diff --git a/CHANGELOG.md b/CHANGELOG.md index 9506c84..4ede54c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ - Enh #190: Use `str_contains` for case-sensitive match in `LikeHandler` (@samdark) - Enh #194: Improve psalm annotations in `LimitableDataInterface` (@vjik) - Bug #195: Fix invalid count in `IterableDataReader` when limit or/and offset used (@vjik) +- Enh #202: Check that correct sort is passed to `withSort()` of keyset paginator (@samdark) - Enh #207: More secific Psalm type for OffsetPaginator::withCurrentPage() (@samdark) ## 1.0.1 January 25, 2023 diff --git a/src/Paginator/KeysetPaginator.php b/src/Paginator/KeysetPaginator.php index 6945ee5..c42a945 100644 --- a/src/Paginator/KeysetPaginator.php +++ b/src/Paginator/KeysetPaginator.php @@ -6,7 +6,6 @@ use Closure; use InvalidArgumentException; -use RuntimeException; use Yiisoft\Arrays\ArrayHelper; use Yiisoft\Data\Reader\Filter\GreaterThan; use Yiisoft\Data\Reader\Filter\GreaterThanOrEqual; @@ -123,14 +122,7 @@ public function __construct(ReadableDataInterface $dataReader) } $sort = $dataReader->getSort(); - - if ($sort === null) { - throw new RuntimeException('Data sorting should be configured to work with keyset pagination.'); - } - - if (empty($sort->getOrder())) { - throw new RuntimeException('Data should be always sorted to work with keyset pagination.'); - } + $this->assertSort($sort); $this->dataReader = $dataReader; } @@ -262,6 +254,8 @@ public function isSortable(): bool public function withSort(?Sort $sort): static { + $this->assertSort($sort); + $new = clone $this; $new->dataReader = $this->dataReader->withSort($sort); return $new; @@ -440,4 +434,15 @@ private function getFieldAndSortingFromSort(Sort $sort): array reset($order) === 'asc' ? SORT_ASC : SORT_DESC, ]; } + + private function assertSort(?Sort $sort): void + { + if ($sort === null) { + throw new InvalidArgumentException('Data sorting should be configured to work with keyset pagination.'); + } + + if (empty($sort->getOrder())) { + throw new InvalidArgumentException('Data should be always sorted to work with keyset pagination.'); + } + } } diff --git a/tests/Paginator/KeysetPaginatorTest.php b/tests/Paginator/KeysetPaginatorTest.php index 1a3317e..088bed8 100644 --- a/tests/Paginator/KeysetPaginatorTest.php +++ b/tests/Paginator/KeysetPaginatorTest.php @@ -149,23 +149,45 @@ public function testThrowsExceptionWhenReaderHasNoSort(): void { $dataReader = new IterableDataReader(self::getDataSet()); - $this->expectException(RuntimeException::class); + $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Data sorting should be configured to work with keyset pagination.'); new KeysetPaginator($dataReader); } + public function testThrowsExceptionForWithSortNull(): void + { + $sort = Sort::only(['id', 'name'])->withOrderString('id'); + $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Data sorting should be configured to work with keyset pagination.'); + + (new KeysetPaginator($dataReader))->withSort(null); + } + public function testThrowsExceptionWhenNotSorted(): void { $sort = Sort::only(['id', 'name']); $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); - $this->expectException(RuntimeException::class); + $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Data should be always sorted to work with keyset pagination.'); new KeysetPaginator($dataReader); } + public function testThrowsExceptionForWithSortNotSorted(): void + { + $sort = Sort::only(['id', 'name'])->withOrderString('id'); + $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Data should be always sorted to work with keyset pagination.'); + + (new KeysetPaginator($dataReader))->withSort(Sort::only(['id', 'name'])); + } + public function testPageSizeCannotBeLessThanOne(): void { $sort = Sort::only(['id', 'name'])->withOrderString('id');