diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d5039d4..3a6a0fde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,11 @@ `getNextPageToken()` with `getNextToken()`, `getPreviousPageToken()` with `getPreviousToken()`, and add `getToken()`. These methods use new `PageToken` class (@vjik) - New #160: Add `Sort::hasFieldInConfig()` method that checks for the presence of a field in the sort config (@vjik) +- New #161: Add `PageNotFoundException` (@vjik) +- Chg #161: `PaginatorInterface::getCurrentPageSize()` returns 0 instead throws exception if page specified is + not found (@vjik) +- Enh #161: Add more specified psalm annotations to `CountableDataInterface::count()`, + `PaginatorInterface::getCurrentPageSize()` and `OffsetPaginator::getTotalItems()` (@vjik) ## 1.0.1 January 25, 2023 diff --git a/src/Paginator/OffsetPaginator.php b/src/Paginator/OffsetPaginator.php index 97a595c0..85fe4933 100644 --- a/src/Paginator/OffsetPaginator.php +++ b/src/Paginator/OffsetPaginator.php @@ -46,6 +46,7 @@ final class OffsetPaginator implements PaginatorInterface /** * @var int Maximum number of items per page. + * @psalm-var positive-int */ private int $pageSize = self::DEFAULT_PAGE_SIZE; @@ -169,10 +170,11 @@ public function getCurrentPageSize(): int } if ($currentPage === $pages) { + /** @psalm-var positive-int Because total items is more than offset */ return $this->getTotalItems() - $this->getOffset(); } - throw new PaginatorException('Page not found.'); + return 0; } /** @@ -189,6 +191,8 @@ public function getOffset(): int * Get total number of items in the whole data reader being paginated. * * @return int Total items number. + * + * @psalm-return non-negative-int */ public function getTotalItems(): int { @@ -232,7 +236,7 @@ public function getSort(): ?Sort public function read(): iterable { if ($this->getCurrentPage() > $this->getInternalTotalPages()) { - throw new PaginatorException('Page not found.'); + throw new PageNotFoundException(); } yield from $this->dataReader @@ -257,7 +261,7 @@ public function isOnFirstPage(): bool public function isOnLastPage(): bool { if ($this->getCurrentPage() > $this->getInternalTotalPages()) { - throw new PaginatorException('Page not found.'); + throw new PageNotFoundException(); } return $this->getCurrentPage() === $this->getInternalTotalPages(); @@ -268,6 +272,9 @@ public function isPaginationRequired(): bool return $this->getTotalPages() > 1; } + /** + * @psalm-return non-negative-int + */ private function getInternalTotalPages(): int { return max(1, $this->getTotalPages()); diff --git a/src/Paginator/PageNotFoundException.php b/src/Paginator/PageNotFoundException.php new file mode 100644 index 00000000..279967fb --- /dev/null +++ b/src/Paginator/PageNotFoundException.php @@ -0,0 +1,13 @@ + @@ -126,7 +126,7 @@ public function read(): iterable; /** * Get whether current page is the last one. * - * @throws PaginatorException If page specified is not found. + * @throws PageNotFoundException If page specified is not found. * * @return bool Whether current page is the last one. */ diff --git a/src/Reader/CountableDataInterface.php b/src/Reader/CountableDataInterface.php index 72335189..605d7602 100644 --- a/src/Reader/CountableDataInterface.php +++ b/src/Reader/CountableDataInterface.php @@ -13,6 +13,8 @@ interface CountableDataInterface extends Countable { /** * @return int Number of items in the data. + * + * @psalm-return non-negative-int */ public function count(): int; } diff --git a/tests/Paginator/OffsetPaginatorTest.php b/tests/Paginator/OffsetPaginatorTest.php index 24a47f8c..6411d433 100644 --- a/tests/Paginator/OffsetPaginatorTest.php +++ b/tests/Paginator/OffsetPaginatorTest.php @@ -8,6 +8,7 @@ use LogicException; use PHPUnit\Framework\Attributes\DataProvider; use Yiisoft\Data\Paginator\OffsetPaginator; +use Yiisoft\Data\Paginator\PageNotFoundException; use Yiisoft\Data\Paginator\PageToken; use Yiisoft\Data\Paginator\PaginatorException; use Yiisoft\Data\Paginator\PaginatorInterface; @@ -222,7 +223,7 @@ public function testReadCurrentPageCannotBeLargerThanMaxPages(): void ; $this->assertSame(3, $paginator->getTotalPages()); - $this->expectException(PaginatorException::class); + $this->expectException(PageNotFoundException::class); $this->expectExceptionMessage('Page not found.'); $this->iterableToArray($paginator->read()); @@ -397,7 +398,7 @@ public function testIsLastPageBeyondMaxPages(): void ; $this->assertSame(3, $paginator->getTotalPages()); - $this->expectException(PaginatorException::class); + $this->expectException(PageNotFoundException::class); $this->expectExceptionMessage('Page not found.'); $paginator->isOnLastPage(); @@ -446,14 +447,10 @@ public function testGetCurrentPageCannotBeLargerThanMaxPages(): void $dataReader = new IterableDataReader(self::DEFAULT_DATASET); $paginator = (new OffsetPaginator($dataReader)) ->withPageSize(2) - ->withCurrentPage(4) - ; + ->withCurrentPage(4); $this->assertSame(5, $paginator->getTotalItems()); - $this->expectException(PaginatorException::class); - $this->expectExceptionMessage('Page not found.'); - - $paginator->getCurrentPageSize(); + $this->assertSame(0, $paginator->getCurrentPageSize()); } public function testEmptyDataSet(): void