From f661784daee80c03cfd24f26bac0da6ebaccc947 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Sun, 31 Mar 2024 05:30:45 +0000 Subject: [PATCH] feat: calling `slice()` on a LazyMatchingReadableCollection` now should not trigger initialization of the underlying collection. (#12) * feat: calling `slice()` on a LazyMatchingReadableCollection` now should not trigger initialization of the underlying collection. * remove order to pass test --- CHANGELOG.md | 2 ++ .../LazyMatchingReadableCollection.php | 13 +++++++ ...tchingReadableCollectionFromSelectable.php | 9 +++++ tests/LazyMatchingTest.php | 35 +++++++++++++++++++ tests/Model/SliceInterceptor.php | 35 +++++++++++++++++++ 5 files changed, 94 insertions(+) create mode 100644 tests/Model/SliceInterceptor.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ab0197..5891f9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## 2.3.0 +* feat: calling `slice()` on a `LazyMatchingReadableCollection` now should not + trigger initialization of the underlying collection. * test: improve `LazyMatchingTest` ## 2.2.0 diff --git a/src/LazyMatching/LazyMatchingReadableCollection.php b/src/LazyMatching/LazyMatchingReadableCollection.php index 5e46e98..c4a76a3 100644 --- a/src/LazyMatching/LazyMatchingReadableCollection.php +++ b/src/LazyMatching/LazyMatchingReadableCollection.php @@ -79,4 +79,17 @@ public function matching(Criteria $criteria): ReadableCollection&Selectable return $clone; } + + public function slice(int $offset, ?int $length = null): array + { + if ($this->criteria === null) { + return parent::slice($offset, $length); + } + + $criteria = (clone $this->criteria) + ->setFirstResult($offset) + ->setMaxResults($length); + + return $this->matching($criteria)->toArray(); + } } diff --git a/src/LazyMatching/LazyMatchingReadableCollectionFromSelectable.php b/src/LazyMatching/LazyMatchingReadableCollectionFromSelectable.php index 0b37179..c867b94 100644 --- a/src/LazyMatching/LazyMatchingReadableCollectionFromSelectable.php +++ b/src/LazyMatching/LazyMatchingReadableCollectionFromSelectable.php @@ -63,4 +63,13 @@ public function matching(Criteria $criteria): ReadableCollection&Selectable return $clone; } + + public function slice(int $offset, ?int $length = null): array + { + $criteria = (clone $this->criteria) + ->setFirstResult($offset) + ->setMaxResults($length); + + return $this->matching($criteria)->toArray(); + } } diff --git a/tests/LazyMatchingTest.php b/tests/LazyMatchingTest.php index f361196..ac2f397 100644 --- a/tests/LazyMatchingTest.php +++ b/tests/LazyMatchingTest.php @@ -15,12 +15,14 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Criteria; +use Doctrine\Common\Collections\Order; use PHPUnit\Framework\TestCase; use Rekalogika\Collections\Decorator\LazyMatching\LazyMatchingCollection; use Rekalogika\Collections\Decorator\LazyMatching\LazyMatchingReadableCollection; use Rekalogika\Collections\Decorator\Tests\Model\Book; use Rekalogika\Collections\Decorator\Tests\Model\BookShelf; use Rekalogika\Collections\Decorator\Tests\Model\SelectableInterceptor; +use Rekalogika\Collections\Decorator\Tests\Model\SliceInterceptor; class LazyMatchingTest extends TestCase { @@ -122,4 +124,37 @@ public function testCriteria(): void $result->toArray() ); } + + public function testSlice(): void + { + $bookshelf = new BookShelf(); + $bookshelf->set('a', new Book('A', 100, 'Author A')); + $bookshelf->set('b', new Book('B', 200, 'Author B')); + $bookshelf->set('c', new Book('C', 300, 'Author C')); + $bookshelf->set('d', new Book('D', 50, 'Author C')); + $bookshelf->set('e', new Book('E', 20, 'Author C')); + $bookshelf->set('f', new Book('F', 500, 'Author C')); + + $bookshelf = new SliceInterceptor($bookshelf); + $realBookShelf = $bookshelf; + + $bookshelf = new LazyMatchingCollection($bookshelf); + $criteria = Criteria::create() + ->where(Criteria::expr()->gt('numOfPages', 60)); + + $filtered = $bookshelf->matching($criteria); + $count = $filtered->count(); + $this->assertSame(4, $count); + + $sliced = $filtered->slice(1, 2); + $this->assertEquals( + [ + 'b' => new Book('B', 200, 'Author B'), + 'c' => new Book('C', 300, 'Author C'), + ], + $sliced + ); + + $this->assertEquals(0, $realBookShelf->getSliceCount()); + } } diff --git a/tests/Model/SliceInterceptor.php b/tests/Model/SliceInterceptor.php new file mode 100644 index 0000000..4577b4b --- /dev/null +++ b/tests/Model/SliceInterceptor.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\Collections\Decorator\Tests\Model; + +use Rekalogika\Collections\Decorator\Decorator\SelectableCollectionDecorator; + +/** + * @extends SelectableCollectionDecorator + */ +class SliceInterceptor extends SelectableCollectionDecorator +{ + private int $sliceCount = 0; + + public function count(): int + { + $this->sliceCount++; + return $this->getWrapped()->count(); + } + + public function getSliceCount(): int + { + return $this->sliceCount; + } +}