diff --git a/composer.json b/composer.json index e068fae7..817637df 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ ], "require": { "php": ">= 8.1", - "loophp/iterators": "^3.1" + "loophp/iterators": "^3.1.1" }, "require-dev": { "ext-pcov": "*", diff --git a/docs/pages/api.rst b/docs/pages/api.rst index acb9b845..08b3209a 100644 --- a/docs/pages/api.rst +++ b/docs/pages/api.rst @@ -2136,7 +2136,7 @@ sort ~~~~ Sort a collection using a callback. If no callback is provided, it will sort -using natural order, ascending. +using natural order. The direction by default match the PHP `usort` function. By default, it will sort by values and using the default callback. If you want to sort by keys, you can pass a parameter to change the behaviour. diff --git a/src/Operation/Matching.php b/src/Operation/Matching.php index e3f68065..70fb00d5 100644 --- a/src/Operation/Matching.php +++ b/src/Operation/Matching.php @@ -43,7 +43,7 @@ static function (Criteria $criteria): Closure { $next = null; foreach (array_reverse($orderings) as $field => $ordering) { - $next = ClosureExpressionVisitor::sortByField($field, Criteria::ASC === $ordering ? -1 : 1, $next); + $next = ClosureExpressionVisitor::sortByField($field, Criteria::DESC === $ordering ? -1 : 1, $next); } $pipes[] = (new Sort())()(Sortable::BY_VALUES)($next); diff --git a/src/Operation/Sort.php b/src/Operation/Sort.php index 54a44ef1..08fcf5e5 100644 --- a/src/Operation/Sort.php +++ b/src/Operation/Sort.php @@ -45,7 +45,7 @@ static function (null|callable|Closure $callback = null) use ($type): Closure { * @param TKey $leftKey * @param TKey $rightKey */ - static fn (mixed $left, mixed $right, mixed $leftKey, mixed $rightKey): int => $right <=> $left; + static fn (mixed $left, mixed $right, mixed $leftKey, mixed $rightKey): int => $left <=> $right; if (!($callback instanceof Closure)) { trigger_deprecation( diff --git a/tests/unit/IssuesTest.php b/tests/unit/IssuesTest.php index c7b4b770..9721caff 100644 --- a/tests/unit/IssuesTest.php +++ b/tests/unit/IssuesTest.php @@ -56,4 +56,51 @@ public function __construct( self::assertEquals([1, 2, 3], $input->all()); } + + private static function createValueObject(int $id, int $weight): object + { + return new class($id, $weight) { + public function __construct( + public int $id, + public int $weight, + ) { + } + }; + } + + public function testPhpSorting(): void + { + $input = [ + self::createValueObject(id: 1, weight: 2), + self::createValueObject(id: 160, weight: 1), + self::createValueObject(id: 1600, weight: 3), + self::createValueObject(id: 2, weight: 2), + self::createValueObject(id: 150, weight: 1), + self::createValueObject(id: 1500, weight: 3), + self::createValueObject(id: 3, weight: 2), + ]; + + usort($input, static fn (object $a, object $b): int => $a->weight <=> $b->weight); + + $collection = Collection::fromIterable($input)->map(static fn (object $item): int => $item->id); + + self::assertEquals([160, 150, 1, 2, 3, 1600, 1500], $collection->all()); + } + + public function testCollectionSorting(): void + { + $input = Collection::fromIterable([ + self::createValueObject(id: 1, weight: 2), + self::createValueObject(id: 160, weight: 1), + self::createValueObject(id: 1600, weight: 3), + self::createValueObject(id: 2, weight: 2), + self::createValueObject(id: 150, weight: 1), + self::createValueObject(id: 1500, weight: 3), + self::createValueObject(id: 3, weight: 2), + ]) + ->sort(callback: static fn (object $a, object $b): int => $a->weight <=> $b->weight) + ->map(static fn (object $item): int => $item->id); + + self::assertEquals([160, 150, 1, 2, 3, 1600, 1500], $input->all()); + } } diff --git a/tests/unit/Traits/GenericCollectionProviders.php b/tests/unit/Traits/GenericCollectionProviders.php index 0e9b3e48..b3a1b938 100644 --- a/tests/unit/Traits/GenericCollectionProviders.php +++ b/tests/unit/Traits/GenericCollectionProviders.php @@ -4071,7 +4071,7 @@ public static function sortOperationProvider() static fn (string $left, string $right): int => $left <=> $right, ], $input, - array_combine(range('A', 'E'), range('E', 'A')), + array_combine(range('E', 'A'), range('A', 'E')), ]; $inputGen = static function () {