Skip to content

Commit

Permalink
Fix #52: IteratorDataReader does not reset numeric keys when sorting …
Browse files Browse the repository at this point in the history
…anymore
  • Loading branch information
roxblnfk committed Feb 8, 2021
1 parent 6c99d77 commit bd6ebf2
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 286 deletions.
18 changes: 14 additions & 4 deletions src/Reader/Iterable/IterableDataReader.php
Expand Up @@ -6,7 +6,7 @@

use Generator;
use Traversable;
use Yiisoft\Arrays\ArraySorter;
use Yiisoft\Arrays\ArrayHelper;
use Yiisoft\Data\Reader\DataReaderInterface;
use Yiisoft\Data\Reader\Filter\FilterInterface;
use Yiisoft\Data\Reader\Filter\FilterProcessorInterface;
Expand Down Expand Up @@ -90,7 +90,17 @@ private function sortItems(iterable $items, Sort $sort): iterable
$criteria = $sort->getCriteria();
if ($criteria !== []) {
$items = $this->iterableToArray($items);
ArraySorter::multisort($items, array_keys($criteria), array_values($criteria));
uasort($items, static function ($itemA, $itemB) use ($criteria) {
foreach ($criteria as $key => $order) {
$valueA = ArrayHelper::getValue($itemA, $key);
$valueB = ArrayHelper::getValue($itemB, $key);
if ($valueB === $valueA) {
continue;
}
return ($valueA > $valueB xor $order === SORT_DESC) ? 1 : -1;
}
return 0;
});
}

return $items;
Expand Down Expand Up @@ -146,7 +156,7 @@ public function read(): array
? $this->data
: $this->sortItems($this->data, $this->sort);

foreach ($sortedData as $item) {
foreach ($sortedData as $key => $item) {
// do not return more than limit items
if ($this->limit > 0 && count($data) === $this->limit) {
break;
Expand All @@ -160,7 +170,7 @@ public function read(): array

// filter items
if ($filter === null || $this->matchFilter($item, $filter)) {
$data[] = $item;
$data[$key] = $item;
}
}

Expand Down
49 changes: 27 additions & 22 deletions tests/Paginator/KeysetPaginatorTest.php
Expand Up @@ -16,27 +16,32 @@

final class KeysetPaginatorTest extends Testcase
{
private const ITEM_1 = [
'id' => 1,
'name' => 'Codename Boris',
];
private const ITEM_2 = [
'id' => 2,
'name' => 'Codename Doris',
];
private const ITEM_3 = [
'id' => 3,
'name' => 'Agent K',
];
private const ITEM_4 = [
'id' => 5,
'name' => 'Agent J',
];
private const ITEM_5 = [
'id' => 6,
'name' => '007',
];
private const DEFAULT_DATASET = [
[
'id' => 1,
'name' => 'Codename Boris',
],
[
'id' => 2,
'name' => 'Codename Doris',
],
[
'id' => 3,
'name' => 'Agent K',
],
[
'id' => 5,
'name' => 'Agent J',
],
[
'id' => 6,
'name' => '007',
],
0 => self::ITEM_1,
1 => self::ITEM_2,
2 => self::ITEM_3,
3 => self::ITEM_4,
4 => self::ITEM_5,
];

public function testDataReaderWithoutFilterableInterface(): void
Expand Down Expand Up @@ -211,7 +216,7 @@ public function testReadSecondPage(): void

$expected = $this->getDataSet([2, 3]);

$this->assertSame($expected, $paginator->read());
$this->assertSame($expected, array_values($paginator->read()));
$last = end($expected);
$this->assertSame((string)$last['id'], $paginator->getNextPageToken());
}
Expand All @@ -229,7 +234,7 @@ public function testReadSecondPageOrderedByName(): void

$expected = $this->getDataSet([2, 0]);

$this->assertSame($expected, $this->iterableToArray($paginator->read()));
$this->assertSame($expected, array_values($this->iterableToArray($paginator->read())));
$last = end($expected);
$this->assertSame((string)$last['name'], $paginator->getNextPageToken());
}
Expand Down

0 comments on commit bd6ebf2

Please sign in to comment.