From 795acfbb4bb5a3097e1a01c7294cd7424a1e3e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9=20Costa?= Date: Mon, 15 Apr 2024 13:40:02 +0200 Subject: [PATCH] feat,refactor(add-paging-to-result-set): added test cases for ResultSet paging, fixed PHPStan configuration, rebuilt baseline, refactored return type annotation --- phpstan-baseline.neon | 30 +++++----------------------- phpstan.neon | 2 +- src/ResultSet.php | 17 +++++++++++----- tests/ResultSetTest.php | 44 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 31 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 3fc5ac7..ce70d7a 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -756,12 +756,12 @@ parameters: path: src/Resolver.php - - message: "#^Class ipl\\\\Orm\\\\ResultSet implements generic interface Iterator but does not specify its types\\: TKey, TValue$#" + message: "#^Cannot assign offset mixed to ArrayIterator\\.$#" count: 1 path: src/ResultSet.php - - message: "#^Method ipl\\\\Orm\\\\ResultSet\\:\\:__construct\\(\\) has parameter \\$limit with no type specified\\.$#" + message: "#^Class ipl\\\\Orm\\\\ResultSet implements generic interface Iterator but does not specify its types\\: TKey, TValue$#" count: 1 path: src/ResultSet.php @@ -776,17 +776,7 @@ parameters: path: src/ResultSet.php - - message: "#^Method ipl\\\\Orm\\\\ResultSet\\:\\:hasMore\\(\\) has no return type specified\\.$#" - count: 1 - path: src/ResultSet.php - - - - message: "#^Method ipl\\\\Orm\\\\ResultSet\\:\\:hasResult\\(\\) has no return type specified\\.$#" - count: 1 - path: src/ResultSet.php - - - - message: "#^Method ipl\\\\Orm\\\\ResultSet\\:\\:yieldTraversable\\(\\) has no return type specified\\.$#" + message: "#^Method ipl\\\\Orm\\\\ResultSet\\:\\:key\\(\\) should return int\\|null but returns mixed\\.$#" count: 1 path: src/ResultSet.php @@ -796,22 +786,12 @@ parameters: path: src/ResultSet.php - - message: "#^Property ipl\\\\Orm\\\\ResultSet\\:\\:\\$cache has no type specified\\.$#" - count: 1 - path: src/ResultSet.php - - - - message: "#^Property ipl\\\\Orm\\\\ResultSet\\:\\:\\$generator has no type specified\\.$#" - count: 1 - path: src/ResultSet.php - - - - message: "#^Property ipl\\\\Orm\\\\ResultSet\\:\\:\\$limit has no type specified\\.$#" + message: "#^Parameter \\#1 \\$offset of method ArrayIterator\\<\\(int\\|string\\),mixed\\>\\:\\:seek\\(\\) expects int, mixed given\\.$#" count: 1 path: src/ResultSet.php - - message: "#^Property ipl\\\\Orm\\\\ResultSet\\:\\:\\$position has no type specified\\.$#" + message: "#^Property ipl\\\\Orm\\\\ResultSet\\:\\:\\$cache with generic class ArrayIterator does not specify its types\\: TKey, TValue$#" count: 1 path: src/ResultSet.php diff --git a/phpstan.neon b/phpstan.neon index d3bd084..07a3a97 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -11,7 +11,7 @@ parameters: - src scanDirectories: - - vendor + - /usr/share/icinga-php/vendor ignoreErrors: - diff --git a/src/ResultSet.php b/src/ResultSet.php index 94811da..74b2aec 100644 --- a/src/ResultSet.php +++ b/src/ResultSet.php @@ -35,7 +35,7 @@ class ResultSet implements Iterator protected $pageSize; /** - * Construct the {@see self::class class} object + * Construct the ResultSet object * * @param Traversable $traversable * @param ?int $limit @@ -62,9 +62,10 @@ public function getCurrentPage(): int { if ($this->pageSize) { $offset = $this->offset ?: 0; - if ($this->position && ($this->position + $offset) > $this->pageSize) { + $position = $this->position + 1; + if ($position && ($position + $offset) > $this->pageSize) { // we are not on the first page anymore, calculating proper page - return intval(floor(($this->position + $offset) / $this->pageSize)); + return intval(ceil(($position + $offset) / $this->pageSize)); } // still on the first page @@ -77,7 +78,7 @@ public function getCurrentPage(): int /** * Set the amount of entries a page should contain (needed for pagination) * - * @param ?int $size entries per page + * @param ?int $size entries per page * @return $this */ public function setPageSize(?int $size) @@ -157,7 +158,13 @@ public function next(): void } } - public function key(): ?int + /** + * Return the current item's key + * + * @return ?int + */ + #[\ReturnTypeWillChange] + public function key() { if ($this->position === null) { $this->advance(); diff --git a/tests/ResultSetTest.php b/tests/ResultSetTest.php index c0c1413..78b1bc5 100644 --- a/tests/ResultSetTest.php +++ b/tests/ResultSetTest.php @@ -3,6 +3,7 @@ namespace ipl\Tests\Orm; use ArrayIterator; +use BadMethodCallException; use ipl\Orm\ResultSet; use PHPUnit\Framework\TestCase; @@ -81,4 +82,47 @@ public function testResultWithCacheEnabledWithLimit() ['a', 'b', 'a', 'b'] ); } + + public function testResultPaging() + { + $set = (new ResultSet(new ArrayIterator(['a', 'b', 'c', 'd', 'e', 'f', 'g']))) + ->setPageSize(2); + + $count = 0; + foreach ($set as $item) { + ++$count; + + if ($count > 2) { + if ($count % 2 === 0) { + // a multiple of two, page should equal to count / 2 + $this->assertEquals( + $set->getCurrentPage(), + $count / 2 + ); + } elseif ($count % 2 === 1) { + $this->assertEquals( + $set->getCurrentPage(), + intval(ceil($count / 2)) + ); + } + } else { + $this->assertEquals( + $set->getCurrentPage(), + 1 + ); + } + } + } + + public function testResultPagingWithoutPageSize() + { + $this->expectException(BadMethodCallException::class); + + $set = (new ResultSet(new ArrayIterator(['a', 'b', 'c', 'd', 'e', 'f', 'g']))); + + foreach ($set as $item) { + // this raises an exception as no page size has been set + $set->getCurrentPage(); + } + } }