From c949f0d6ecdaaab31a2443723d8ad4aaaa2e1025 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 23 Jan 2024 16:15:11 +0300 Subject: [PATCH 1/5] Add methods `PaginatorInterface::isSupportSorting()` and `PaginatorInterface::withSort()` --- CHANGELOG.md | 1 + src/Paginator/KeysetPaginator.php | 13 +++++++- src/Paginator/OffsetPaginator.php | 17 ++++++++++ src/Paginator/PaginatorInterface.php | 16 ++++++++++ tests/Paginator/KeysetPaginatorTest.php | 23 ++++++++++++++ tests/Paginator/OffsetPaginatorTest.php | 42 +++++++++++++++++++++++++ tests/Support/StubOffsetData.php | 42 +++++++++++++++++++++++++ 7 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 tests/Support/StubOffsetData.php diff --git a/CHANGELOG.md b/CHANGELOG.md index c0b01b8a..ab6c35e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Chg #154: Raise minimum required PHP version to 8.1 (@vjik) - Bug #155: Fix `Sort` configuration preparation (@vjik) - Bug #155: Fix same named order fields in `Sort` were not overriding previous ones (@vjik) +- New #158: Add methods `PaginatorInterface::isSupportSorting()` and `PaginatorInterface::withSort()` (@vjik) ## 1.0.1 January 25, 2023 diff --git a/src/Paginator/KeysetPaginator.php b/src/Paginator/KeysetPaginator.php index e34c8ecf..7a3fc928 100644 --- a/src/Paginator/KeysetPaginator.php +++ b/src/Paginator/KeysetPaginator.php @@ -250,9 +250,20 @@ public function getNextPageToken(): ?string return $this->isOnLastPage() ? null : $this->currentLastValue; } + public function isSupportSorting(): bool + { + return true; + } + + public function withSort(?Sort $sort): static + { + $new = clone $this; + $new->dataReader = $this->dataReader->withSort($sort); + return $new; + } + public function getSort(): ?Sort { - /** @psalm-var SortableDataInterface $this->dataReader */ return $this->dataReader->getSort(); } diff --git a/src/Paginator/OffsetPaginator.php b/src/Paginator/OffsetPaginator.php index 532bfde2..799f0476 100644 --- a/src/Paginator/OffsetPaginator.php +++ b/src/Paginator/OffsetPaginator.php @@ -6,6 +6,7 @@ use Generator; use InvalidArgumentException; +use LogicException; use Yiisoft\Data\Reader\CountableDataInterface; use Yiisoft\Data\Reader\LimitableDataInterface; use Yiisoft\Data\Reader\OffsetableDataInterface; @@ -201,6 +202,22 @@ public function getTotalPages(): int return (int) ceil($this->getTotalItems() / $this->pageSize); } + public function isSupportSorting(): bool + { + return $this->dataReader instanceof SortableDataInterface; + } + + public function withSort(?Sort $sort): static + { + if (!$this->dataReader instanceof SortableDataInterface) { + throw new LogicException('Data reader does not support sorting.'); + } + + $new = clone $this; + $new->dataReader = $this->dataReader->withSort($sort); + return $new; + } + public function getSort(): ?Sort { return $this->dataReader instanceof SortableDataInterface ? $this->dataReader->getSort() : null; diff --git a/src/Paginator/PaginatorInterface.php b/src/Paginator/PaginatorInterface.php index b38ac3d4..ddac77d7 100644 --- a/src/Paginator/PaginatorInterface.php +++ b/src/Paginator/PaginatorInterface.php @@ -92,6 +92,22 @@ public function getPageSize(): int; */ public function getCurrentPageSize(): int; + /** + * @return bool Whether sorting is supported. + */ + public function isSupportSorting(): bool; + + /** + * Get a new instance with sorting set. + * + * @param Sort|null $sort Sorting criteria or null for no sorting. + * + * @return static New instance. + * + * @throw LogicException When sorting is not supported. + */ + public function withSort(?Sort $sort): static; + /** * Get current sort object. * diff --git a/tests/Paginator/KeysetPaginatorTest.php b/tests/Paginator/KeysetPaginatorTest.php index 1b34f86a..32400937 100644 --- a/tests/Paginator/KeysetPaginatorTest.php +++ b/tests/Paginator/KeysetPaginatorTest.php @@ -1035,4 +1035,27 @@ public function testPageTypeWithNextPageToken( $this->assertSame($expectedIsOnLastPage, $paginator->isOnLastPage()); $this->assertSame($expectedIds, ArrayHelper::getColumn($paginator->read(), 'id', keepKeys: false)); } + + public function testIsSupportSorting(): void + { + $sort = Sort::only(['id'])->withOrderString('id'); + $reader = (new IterableDataReader([]))->withSort($sort); + $paginator = new KeysetPaginator($reader); + + $this->assertTrue($paginator->isSupportSorting()); + } + + public function testWithSort() + { + $sort1 = Sort::only(['id'])->withOrderString('id'); + $reader = (new IterableDataReader([]))->withSort($sort1); + $paginator1 = new KeysetPaginator($reader); + + $sort2 = $sort1->withOrderString('-id'); + $paginator2 = $paginator1->withSort($sort2); + + $this->assertNotSame($paginator1, $paginator2); + $this->assertSame($sort1, $paginator1->getSort()); + $this->assertSame($sort2, $paginator2->getSort()); + } } diff --git a/tests/Paginator/OffsetPaginatorTest.php b/tests/Paginator/OffsetPaginatorTest.php index b615494f..90f29fb7 100644 --- a/tests/Paginator/OffsetPaginatorTest.php +++ b/tests/Paginator/OffsetPaginatorTest.php @@ -5,7 +5,9 @@ namespace Yiisoft\Data\Tests\Paginator; use InvalidArgumentException; +use LogicException; use PHPUnit\Framework\Attributes\DataProvider; +use Yiisoft\Data\Paginator\KeysetPaginator; use Yiisoft\Data\Paginator\OffsetPaginator; use Yiisoft\Data\Paginator\PaginatorException; use Yiisoft\Data\Paginator\PaginatorInterface; @@ -15,6 +17,7 @@ use Yiisoft\Data\Reader\OffsetableDataInterface; use Yiisoft\Data\Reader\ReadableDataInterface; use Yiisoft\Data\Reader\Sort; +use Yiisoft\Data\Tests\Support\StubOffsetData; use Yiisoft\Data\Tests\TestCase; final class OffsetPaginatorTest extends TestCase @@ -514,4 +517,43 @@ public function testImmutability(): void $this->assertNotSame($paginator, $paginator->withPageSize(1)); $this->assertNotSame($paginator, $paginator->withCurrentPage(1)); } + + public static function dataIsSupportSorting(): array + { + return [ + [true, new IterableDataReader([])], + [false, new StubOffsetData()], + ]; + } + + #[DataProvider('dataIsSupportSorting')] + public function testIsSupportSorting(bool $expected, ReadableDataInterface $reader): void + { + $paginator = new OffsetPaginator($reader); + + $this->assertSame($expected, $paginator->isSupportSorting()); + } + + public function testWithSort(): void + { + $sort1 = Sort::only(['id'])->withOrderString('id'); + $reader = (new IterableDataReader([]))->withSort($sort1); + $paginator1 = new OffsetPaginator($reader); + + $sort2 = $sort1->withOrderString('-id'); + $paginator2 = $paginator1->withSort($sort2); + + $this->assertNotSame($paginator1, $paginator2); + $this->assertSame($sort1, $paginator1->getSort()); + $this->assertSame($sort2, $paginator2->getSort()); + } + + public function testWithSortNonSortableData(): void + { + $paginator = new OffsetPaginator(new StubOffsetData()); + + $this->expectException(LogicException::class); + $this->expectExceptionMessage('Data reader does not support sorting.'); + $paginator->withSort(null); + } } diff --git a/tests/Support/StubOffsetData.php b/tests/Support/StubOffsetData.php new file mode 100644 index 00000000..2162e57e --- /dev/null +++ b/tests/Support/StubOffsetData.php @@ -0,0 +1,42 @@ + Date: Tue, 23 Jan 2024 13:15:36 +0000 Subject: [PATCH 2/5] Apply fixes from StyleCI --- tests/Paginator/OffsetPaginatorTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Paginator/OffsetPaginatorTest.php b/tests/Paginator/OffsetPaginatorTest.php index 90f29fb7..f22d4771 100644 --- a/tests/Paginator/OffsetPaginatorTest.php +++ b/tests/Paginator/OffsetPaginatorTest.php @@ -7,7 +7,6 @@ use InvalidArgumentException; use LogicException; use PHPUnit\Framework\Attributes\DataProvider; -use Yiisoft\Data\Paginator\KeysetPaginator; use Yiisoft\Data\Paginator\OffsetPaginator; use Yiisoft\Data\Paginator\PaginatorException; use Yiisoft\Data\Paginator\PaginatorInterface; From 9db515643238aa7623fd5cbf84c293a63d5d1c3d Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Wed, 24 Jan 2024 09:47:18 +0300 Subject: [PATCH 3/5] rename --- src/Paginator/KeysetPaginator.php | 2 +- src/Paginator/OffsetPaginator.php | 2 +- src/Paginator/PaginatorInterface.php | 2 +- src/Reader/Sort.php | 22 ++++++++++++++++++++++ tests/Paginator/KeysetPaginatorTest.php | 4 ++-- tests/Paginator/OffsetPaginatorTest.php | 4 ++-- 6 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/Paginator/KeysetPaginator.php b/src/Paginator/KeysetPaginator.php index 7a3fc928..983ad66d 100644 --- a/src/Paginator/KeysetPaginator.php +++ b/src/Paginator/KeysetPaginator.php @@ -250,7 +250,7 @@ public function getNextPageToken(): ?string return $this->isOnLastPage() ? null : $this->currentLastValue; } - public function isSupportSorting(): bool + public function isSortable(): bool { return true; } diff --git a/src/Paginator/OffsetPaginator.php b/src/Paginator/OffsetPaginator.php index 799f0476..bfe6fb8c 100644 --- a/src/Paginator/OffsetPaginator.php +++ b/src/Paginator/OffsetPaginator.php @@ -202,7 +202,7 @@ public function getTotalPages(): int return (int) ceil($this->getTotalItems() / $this->pageSize); } - public function isSupportSorting(): bool + public function isSortable(): bool { return $this->dataReader instanceof SortableDataInterface; } diff --git a/src/Paginator/PaginatorInterface.php b/src/Paginator/PaginatorInterface.php index ddac77d7..3d728c5b 100644 --- a/src/Paginator/PaginatorInterface.php +++ b/src/Paginator/PaginatorInterface.php @@ -95,7 +95,7 @@ public function getCurrentPageSize(): int; /** * @return bool Whether sorting is supported. */ - public function isSupportSorting(): bool; + public function isSortable(): bool; /** * Get a new instance with sorting set. diff --git a/src/Reader/Sort.php b/src/Reader/Sort.php index d71d79bf..44b6519e 100644 --- a/src/Reader/Sort.php +++ b/src/Reader/Sort.php @@ -267,6 +267,28 @@ public function withoutDefaultSorting(): self return $new; } + /** + * Returns default order of logical fields' directions. + * + * Example of result: + * + * ``` + * [ + * 'id' => 'asc', + * 'name' => 'desc', + * ] + * ``` + * + * @psalm-return TOrder + */ + public function getDefaults(): array + { + return array_map( + static fn($fieldConfig) => $fieldConfig['default'], + $this->config, + ); + } + /** * Get current logical fields order. * diff --git a/tests/Paginator/KeysetPaginatorTest.php b/tests/Paginator/KeysetPaginatorTest.php index 32400937..4e3e96ba 100644 --- a/tests/Paginator/KeysetPaginatorTest.php +++ b/tests/Paginator/KeysetPaginatorTest.php @@ -1036,13 +1036,13 @@ public function testPageTypeWithNextPageToken( $this->assertSame($expectedIds, ArrayHelper::getColumn($paginator->read(), 'id', keepKeys: false)); } - public function testIsSupportSorting(): void + public function testIsSortable(): void { $sort = Sort::only(['id'])->withOrderString('id'); $reader = (new IterableDataReader([]))->withSort($sort); $paginator = new KeysetPaginator($reader); - $this->assertTrue($paginator->isSupportSorting()); + $this->assertTrue($paginator->isSortable()); } public function testWithSort() diff --git a/tests/Paginator/OffsetPaginatorTest.php b/tests/Paginator/OffsetPaginatorTest.php index 90f29fb7..fa9dfc69 100644 --- a/tests/Paginator/OffsetPaginatorTest.php +++ b/tests/Paginator/OffsetPaginatorTest.php @@ -527,11 +527,11 @@ public static function dataIsSupportSorting(): array } #[DataProvider('dataIsSupportSorting')] - public function testIsSupportSorting(bool $expected, ReadableDataInterface $reader): void + public function testIsSortable(bool $expected, ReadableDataInterface $reader): void { $paginator = new OffsetPaginator($reader); - $this->assertSame($expected, $paginator->isSupportSorting()); + $this->assertSame($expected, $paginator->isSortable()); } public function testWithSort(): void From 79c6e5fcb34265418c0d10063381b12b6a05f535 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Wed, 24 Jan 2024 09:49:01 +0300 Subject: [PATCH 4/5] Fix changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab6c35e4..6ba01879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ - Chg #154: Raise minimum required PHP version to 8.1 (@vjik) - Bug #155: Fix `Sort` configuration preparation (@vjik) - Bug #155: Fix same named order fields in `Sort` were not overriding previous ones (@vjik) -- New #158: Add methods `PaginatorInterface::isSupportSorting()` and `PaginatorInterface::withSort()` (@vjik) +- New #158: Add methods `PaginatorInterface::isSortable()` and `PaginatorInterface::withSort()` (@vjik) ## 1.0.1 January 25, 2023 From 59dd2439f0608d8407e5e99810808cde126e4127 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Wed, 24 Jan 2024 09:50:48 +0300 Subject: [PATCH 5/5] fix --- src/Reader/Sort.php | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/Reader/Sort.php b/src/Reader/Sort.php index 44b6519e..d71d79bf 100644 --- a/src/Reader/Sort.php +++ b/src/Reader/Sort.php @@ -267,28 +267,6 @@ public function withoutDefaultSorting(): self return $new; } - /** - * Returns default order of logical fields' directions. - * - * Example of result: - * - * ``` - * [ - * 'id' => 'asc', - * 'name' => 'desc', - * ] - * ``` - * - * @psalm-return TOrder - */ - public function getDefaults(): array - { - return array_map( - static fn($fieldConfig) => $fieldConfig['default'], - $this->config, - ); - } - /** * Get current logical fields order. *