assertEquals($expected, $sorted->toList()); $sorted = new SortIterator($items, $identity, SORT_ASC); $expected = range(1, 5); $this->assertEquals($expected, $sorted->toList()); } /** * Tests sorting numbers with custom callback */ public function testSortNumbersCustom(): void { $items = new ArrayObject([3, 5, 1, 2, 4]); $callback = function ($a) { return $a * -1; }; $sorted = new SortIterator($items, $callback); $expected = range(1, 5); $this->assertEquals($expected, $sorted->toList()); $sorted = new SortIterator($items, $callback, SORT_ASC); $expected = range(5, 1); $this->assertEquals($expected, $sorted->toList()); } /** * Tests sorting a complex structure with numeric sort */ public function testSortComplexNumeric(): void { $items = new ArrayObject([ ['foo' => 1, 'bar' => 'a'], ['foo' => 10, 'bar' => 'a'], ['foo' => 2, 'bar' => 'a'], ['foo' => 13, 'bar' => 'a'], ]); $callback = function ($a) { return $a['foo']; }; $sorted = new SortIterator($items, $callback, SORT_DESC, SORT_NUMERIC); $expected = [ ['foo' => 13, 'bar' => 'a'], ['foo' => 10, 'bar' => 'a'], ['foo' => 2, 'bar' => 'a'], ['foo' => 1, 'bar' => 'a'], ]; $this->assertEquals($expected, $sorted->toList()); $sorted = new SortIterator($items, $callback, SORT_ASC, SORT_NUMERIC); $expected = [ ['foo' => 1, 'bar' => 'a'], ['foo' => 2, 'bar' => 'a'], ['foo' => 10, 'bar' => 'a'], ['foo' => 13, 'bar' => 'a'], ]; $this->assertEquals($expected, $sorted->toList()); } /** * Tests sorting a complex structure with natural sort */ public function testSortComplexNatural(): void { $items = new ArrayObject([ ['foo' => 'foo_1', 'bar' => 'a'], ['foo' => 'foo_10', 'bar' => 'a'], ['foo' => 'foo_2', 'bar' => 'a'], ['foo' => 'foo_13', 'bar' => 'a'], ]); $callback = function ($a) { return $a['foo']; }; $sorted = new SortIterator($items, $callback, SORT_DESC, SORT_NATURAL); $expected = [ ['foo' => 'foo_13', 'bar' => 'a'], ['foo' => 'foo_10', 'bar' => 'a'], ['foo' => 'foo_2', 'bar' => 'a'], ['foo' => 'foo_1', 'bar' => 'a'], ]; $this->assertEquals($expected, $sorted->toList()); $sorted = new SortIterator($items, $callback, SORT_ASC, SORT_NATURAL); $expected = [ ['foo' => 'foo_1', 'bar' => 'a'], ['foo' => 'foo_2', 'bar' => 'a'], ['foo' => 'foo_10', 'bar' => 'a'], ['foo' => 'foo_13', 'bar' => 'a'], ]; $this->assertEquals($expected, $sorted->toList()); $this->assertEquals($expected, $sorted->toList(), 'Iterator should rewind'); } /** * Tests sorting a complex structure with natural sort with string callback */ public function testSortComplexNaturalWithPath(): void { $items = new ArrayObject([ ['foo' => 'foo_1', 'bar' => 'a'], ['foo' => 'foo_10', 'bar' => 'a'], ['foo' => 'foo_2', 'bar' => 'a'], ['foo' => 'foo_13', 'bar' => 'a'], ]); $sorted = new SortIterator($items, 'foo', SORT_DESC, SORT_NATURAL); $expected = [ ['foo' => 'foo_13', 'bar' => 'a'], ['foo' => 'foo_10', 'bar' => 'a'], ['foo' => 'foo_2', 'bar' => 'a'], ['foo' => 'foo_1', 'bar' => 'a'], ]; $this->assertEquals($expected, $sorted->toList()); $sorted = new SortIterator($items, 'foo', SORT_ASC, SORT_NATURAL); $expected = [ ['foo' => 'foo_1', 'bar' => 'a'], ['foo' => 'foo_2', 'bar' => 'a'], ['foo' => 'foo_10', 'bar' => 'a'], ['foo' => 'foo_13', 'bar' => 'a'], ]; $this->assertEquals($expected, $sorted->toList()); $this->assertEquals($expected, $sorted->toList(), 'Iterator should rewind'); } /** * Tests sorting a complex structure with a deep path */ public function testSortComplexDeepPath(): void { $items = new ArrayObject([ ['foo' => ['bar' => 1], 'bar' => 'a'], ['foo' => ['bar' => 12], 'bar' => 'a'], ['foo' => ['bar' => 10], 'bar' => 'a'], ['foo' => ['bar' => 2], 'bar' => 'a'], ]); $sorted = new SortIterator($items, 'foo.bar', SORT_ASC, SORT_NUMERIC); $expected = [ ['foo' => ['bar' => 1], 'bar' => 'a'], ['foo' => ['bar' => 2], 'bar' => 'a'], ['foo' => ['bar' => 10], 'bar' => 'a'], ['foo' => ['bar' => 12], 'bar' => 'a'], ]; $this->assertEquals($expected, $sorted->toList()); } /** * Tests sorting datetime */ public function testSortDateTime(): void { $items = new ArrayObject([ new DateTime('2014-07-21'), new DateTime('2015-06-30'), new DateTimeImmutable('2013-08-12'), ]); $callback = function ($a) { return $a->add(new DateInterval('P1Y')); }; $sorted = new SortIterator($items, $callback); $expected = [ new DateTime('2016-06-30'), new DateTime('2015-07-21'), new DateTimeImmutable('2013-08-12'), ]; $this->assertEquals($expected, $sorted->toList()); $items = new ArrayObject([ new DateTime('2014-07-21'), new DateTime('2015-06-30'), new DateTimeImmutable('2013-08-12'), ]); $sorted = new SortIterator($items, $callback, SORT_ASC); $expected = [ new DateTimeImmutable('2013-08-12'), new DateTime('2015-07-21'), new DateTime('2016-06-30'), ]; $this->assertEquals($expected, $sorted->toList()); } /** * Tests sorting with Chronos datetime */ public function testSortWithChronosDateTime(): void { $items = new ArrayObject([ new Chronos('2014-07-21'), new ChronosDate('2015-06-30'), new DateTimeImmutable('2013-08-12'), ]); $callback = fn ($d) => $d; $sorted = new SortIterator($items, $callback); $expected = [ new ChronosDate('2015-06-30'), new Chronos('2014-07-21'), new DateTimeImmutable('2013-08-12'), ]; $this->assertEquals($expected, $sorted->toList()); $items = new ArrayObject([ new Chronos('2014-07-21'), new ChronosDate('2015-06-30'), new DateTimeImmutable('2013-08-12'), ]); $sorted = new SortIterator($items, $callback, SORT_ASC); $expected = [ new DateTimeImmutable('2013-08-12'), new Chronos('2014-07-21'), new ChronosDate('2015-06-30'), ]; $this->assertEquals($expected, $sorted->toList()); } }