Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change exceptions usage in paginator #219

Merged
merged 14 commits into from
Jan 8, 2025
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@
- Enh #214: Improved interface hierarchy (@samdark)
- Enh #207: More specific Psalm type for `OffsetPaginator::withCurrentPage()` parameter (@samdark)
- Enh #210: More specific Psalm type for `PaginatorInterface::getPageSize()` result (@vjik)
- Chg #219: Narrow type of page size in `PaginatorInterface::withPageSize()` method to positive int by psalm
annotation and throw `InvalidArgumentException` if non-positive value is passed (@vjik)
- Enh #219: Add page to message of `PageNotFoundException` exception (@vjik)
- Chg #219: Throw `InvalidArgumentException` instead of `PaginatorException` in `OffsetPaginator::withCurrentPage()`
method when non-positive value is passed (@vjik)
- Chg #219: Don't check correctness of current page in `PaginatorInterface::isOnLastPage()` method (@vjik)
- Chg #219: Rename `PaginatorException` to `InvalidPageException` (@vjik)

## 1.0.1 January 25, 2023

Expand Down
14 changes: 14 additions & 0 deletions src/Paginator/InvalidPageException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Data\Paginator;

use LogicException;

/**
* Thrown when the page is invalid.
*/
class InvalidPageException extends LogicException
{
}
1 change: 1 addition & 0 deletions src/Paginator/KeysetPaginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ public function getToken(): ?PageToken

public function withPageSize(int $pageSize): static
{
/** @psalm-suppress DocblockTypeContradiction We don't believe in psalm types */
if ($pageSize < 1) {
throw new InvalidArgumentException('Page size should be at least 1.');
}
Expand Down
33 changes: 20 additions & 13 deletions src/Paginator/OffsetPaginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,23 @@ public function __construct(ReadableDataInterface $dataReader)

public function withToken(?PageToken $token): static
{
/** @psalm-suppress ArgumentTypeCoercion */
return $this->withCurrentPage($token === null ? 1 : (int)$token->value);
if ($token === null) {
$page = 1;
} else {
$page = (int) $token->value;
if ($page < 1) {
throw new InvalidPageException('Current page should be at least 1.');
}
}

return $this->withCurrentPage($page);
}

public function withPageSize(int $pageSize): static
{
/** @psalm-suppress DocblockTypeContradiction We don't believe in psalm types */
if ($pageSize < 1) {
throw new PaginatorException('Page size should be at least 1.');
throw new InvalidArgumentException('Page size should be at least 1.');
}

$new = clone $this;
Expand All @@ -113,17 +122,18 @@ public function withPageSize(int $pageSize): static
* Get a new instance with the given current page number set.
*
* @param int $page Page number.
* @psalm-param positive-int $page
*
* @throws PaginatorException If the current page is incorrect.
* @throws InvalidArgumentException If page is not a positive number.
*
* @return self New instance.
*
* @psalm-param positive-int $page
*/
public function withCurrentPage(int $page): self
{
/** @psalm-suppress DocblockTypeContradiction */
if ($page < 1) {
throw new PaginatorException('Current page should be at least 1.');
throw new InvalidArgumentException('Current page should be at least 1.');
samdark marked this conversation as resolved.
Show resolved Hide resolved
}

$new = clone $this;
Expand Down Expand Up @@ -276,8 +286,9 @@ public function withFilter(FilterInterface $filter): static
*/
public function read(): iterable
{
if ($this->getCurrentPage() > $this->getInternalTotalPages()) {
throw new PageNotFoundException();
$currentPage = $this->getCurrentPage();
if ($currentPage > $this->getInternalTotalPages()) {
throw new PageNotFoundException($currentPage);
}

$limit = $this->pageSize;
Expand Down Expand Up @@ -316,11 +327,7 @@ public function isOnFirstPage(): bool

public function isOnLastPage(): bool
{
if ($this->getCurrentPage() > $this->getInternalTotalPages()) {
throw new PageNotFoundException();
}

return $this->getCurrentPage() === $this->getInternalTotalPages();
return $this->getCurrentPage() >= $this->getInternalTotalPages();
}

public function isPaginationRequired(): bool
Expand Down
10 changes: 7 additions & 3 deletions src/Paginator/PageNotFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@

namespace Yiisoft\Data\Paginator;

final class PageNotFoundException extends PaginatorException
use function sprintf;

final class PageNotFoundException extends InvalidPageException
{
public function __construct()
public function __construct(int $page)
{
parent::__construct('Page not found.');
parent::__construct(
sprintf('Page %d not found.', $page)
);
}
}
16 changes: 0 additions & 16 deletions src/Paginator/PaginatorException.php

This file was deleted.

9 changes: 5 additions & 4 deletions src/Paginator/PaginatorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yiisoft\Data\Paginator;

use InvalidArgumentException;
use LogicException;
use Yiisoft\Data\Reader\FilterInterface;
use Yiisoft\Data\Reader\ReadableDataInterface;
Expand Down Expand Up @@ -34,7 +35,7 @@ interface PaginatorInterface extends ReadableDataInterface
*
* @param PageToken|null $token Page token. `Null` if current page is first.
*
* @throws PaginatorException If page token is incorrect.
* @throws InvalidPageException If page token is incorrect.
*
* @return static New instance.
*
Expand All @@ -47,9 +48,11 @@ public function withToken(?PageToken $token): static;
*
* @param int $pageSize Maximum number of items per page.
*
* @throws PaginatorException If page size is incorrect.
* @throws InvalidArgumentException If page size is not a positive number.
*
* @return static New instance.
*
* @psalm-param positive-int $pageSize
*/
public function withPageSize(int $pageSize): static;

Expand Down Expand Up @@ -148,8 +151,6 @@ public function read(): iterable;
/**
* Get whether the current page is the last one.
*
* @throws PageNotFoundException If the page specified isn't found.
*
* @return bool Whether the current page is the last one.
*/
public function isOnLastPage(): bool;
Expand Down
22 changes: 3 additions & 19 deletions tests/Paginator/OffsetPaginatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
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;
use Yiisoft\Data\Reader\CountableDataInterface;
use Yiisoft\Data\Reader\Filter\Equals;
Expand Down Expand Up @@ -219,7 +218,7 @@ public function testCurrentPageCannotBeLessThanOne(): void
$dataReader = new IterableDataReader(self::DEFAULT_DATASET);
$paginator = new OffsetPaginator($dataReader);

$this->expectException(PaginatorException::class);
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Current page should be at least 1.');

$paginator->withCurrentPage(0);
Expand All @@ -235,7 +234,7 @@ public function testReadCurrentPageCannotBeLargerThanMaxPages(): void

$this->assertSame(3, $paginator->getTotalPages());
$this->expectException(PageNotFoundException::class);
$this->expectExceptionMessage('Page not found.');
$this->expectExceptionMessage('Page 4 not found.');

$this->iterableToArray($paginator->read());
}
Expand All @@ -255,7 +254,7 @@ public function testPageSizeCannotBeLessThanOne(): void
$dataReader = new IterableDataReader(self::DEFAULT_DATASET);
$paginator = new OffsetPaginator($dataReader);

$this->expectException(PaginatorException::class);
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Page size should be at least 1.');

$paginator->withPageSize(0);
Expand Down Expand Up @@ -400,21 +399,6 @@ public function testIsLastPageOnLastPage(): void
$this->assertTrue($paginator->isOnLastPage());
}

public function testIsLastPageBeyondMaxPages(): void
{
$dataReader = new IterableDataReader(self::DEFAULT_DATASET);
$paginator = (new OffsetPaginator($dataReader))
->withPageSize(2)
->withCurrentPage(4)
;

$this->assertSame(3, $paginator->getTotalPages());
$this->expectException(PageNotFoundException::class);
$this->expectExceptionMessage('Page not found.');

$paginator->isOnLastPage();
}

public function testGetCurrentPageSizeFirstFullPage(): void
{
$dataReader = new IterableDataReader(self::DEFAULT_DATASET);
Expand Down
Loading