From 4026f0173ceb14ac2594db8aeb1d9d8250a7348f Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Wed, 24 Jan 2024 13:05:48 +0300 Subject: [PATCH 01/11] implement --- src/Paginator/KeysetPaginator.php | 56 ++++------ src/Paginator/OffsetPaginator.php | 47 ++++---- src/Paginator/PageToken.php | 24 +++++ src/Paginator/PaginatorInterface.php | 28 +++-- tests/Paginator/KeysetPaginatorTest.php | 138 ++++++++++++------------ tests/Paginator/OffsetPaginatorTest.php | 29 +++-- 6 files changed, 168 insertions(+), 154 deletions(-) create mode 100644 src/Paginator/PageToken.php diff --git a/src/Paginator/KeysetPaginator.php b/src/Paginator/KeysetPaginator.php index 983ad66d..96ec71c7 100644 --- a/src/Paginator/KeysetPaginator.php +++ b/src/Paginator/KeysetPaginator.php @@ -61,8 +61,7 @@ final class KeysetPaginator implements PaginatorInterface * @var int Maximum number of items per page. */ private int $pageSize = self::DEFAULT_PAGE_SIZE; - private ?string $firstValue = null; - private ?string $lastValue = null; + private ?PageToken $pageToken = null; private ?string $currentFirstValue = null; private ?string $currentLastValue = null; @@ -139,20 +138,16 @@ public function __clone() $this->currentLastValue = null; } - public function withNextPageToken(?string $token): static + public function withPageToken(?PageToken $pageToken): static { $new = clone $this; - $new->firstValue = null; - $new->lastValue = $token; + $new->pageToken = $pageToken; return $new; } - public function withPreviousPageToken(?string $token): static + public function getPageToken(): ?PageToken { - $new = clone $this; - $new->firstValue = $token; - $new->lastValue = null; - return $new; + return $this->pageToken; } public function withPageSize(int $pageSize): static @@ -201,19 +196,19 @@ public function read(): iterable /** @infection-ignore-all Any value more one in line below will be ignored into `readData()` method */ $dataReader = $this->dataReader->withLimit($this->pageSize + 1); - if ($this->isGoingToPreviousPage()) { + if ($this->pageToken?->isPrevious === true) { $sort = $this->reverseSort($sort); $dataReader = $dataReader->withSort($sort); } - if ($this->isGoingSomewhere()) { + if ($this->pageToken !== null) { $dataReader = $dataReader->withFilter($this->getFilter($sort)); $this->hasPreviousPage = $this->previousPageExist($dataReader, $sort); } $data = $this->readData($dataReader, $sort); - if ($this->isGoingToPreviousPage()) { + if ($this->pageToken?->isPrevious === true) { $data = $this->reverseData($data); } @@ -240,12 +235,12 @@ public function getCurrentPageSize(): int return count($this->readCache); } - public function getPreviousPageToken(): ?string + public function getPreviousPageTokenValue(): ?string { return $this->isOnFirstPage() ? null : $this->currentFirstValue; } - public function getNextPageToken(): ?string + public function getNextPageTokenValue(): ?string { return $this->isOnLastPage() ? null : $this->currentLastValue; } @@ -269,7 +264,7 @@ public function getSort(): ?Sort public function isOnFirstPage(): bool { - if ($this->lastValue === null && $this->firstValue === null) { + if ($this->pageToken === null) { return true; } @@ -354,7 +349,10 @@ private function previousPageExist(ReadableDataInterface $dataReader, Sort $sort private function getFilter(Sort $sort): FilterInterface { - $value = $this->getValue(); + /** + * @psalm-var PageToken $this->pageToken The code calling this method must ensure that page token is not null. + */ + $value = $this->pageToken->value; [$field, $sorting] = $this->getFieldAndSortingFromSort($sort); $filter = $sorting === SORT_ASC ? new GreaterThan($field, $value) : new LessThan($field, $value); @@ -375,7 +373,10 @@ private function getFilter(Sort $sort): FilterInterface private function getReverseFilter(Sort $sort): FilterInterface { - $value = $this->getValue(); + /** + * @psalm-var PageToken $this->pageToken The code calling this method must ensure that page token is not null. + */ + $value = $this->pageToken->value; [$field, $sorting] = $this->getFieldAndSortingFromSort($sort); $filter = $sorting === SORT_ASC ? new LessThanOrEqual($field, $value) : new GreaterThanOrEqual($field, $value); @@ -394,15 +395,6 @@ private function getReverseFilter(Sort $sort): FilterInterface ); } - /** - * @psalm-suppress NullableReturnStatement, InvalidNullableReturnType, PossiblyNullArgument The code calling this - * method must ensure that at least one of the properties `$firstValue` or `$lastValue` is not `null`. - */ - private function getValue(): string - { - return $this->isGoingToPreviousPage() ? $this->firstValue : $this->lastValue; - } - private function reverseSort(Sort $sort): Sort { $order = $sort->getOrder(); @@ -426,14 +418,4 @@ private function getFieldAndSortingFromSort(Sort $sort): array reset($order) === 'asc' ? SORT_ASC : SORT_DESC, ]; } - - private function isGoingToPreviousPage(): bool - { - return $this->firstValue !== null && $this->lastValue === null; - } - - private function isGoingSomewhere(): bool - { - return $this->firstValue !== null || $this->lastValue !== null; - } } diff --git a/src/Paginator/OffsetPaginator.php b/src/Paginator/OffsetPaginator.php index bfe6fb8c..d4ebbbf3 100644 --- a/src/Paginator/OffsetPaginator.php +++ b/src/Paginator/OffsetPaginator.php @@ -40,9 +40,9 @@ final class OffsetPaginator implements PaginatorInterface { /** - * @var int Current page number. + * @var PageToken Current page token */ - private int $currentPage = 1; + private PageToken $pageToken; /** * @var int Maximum number of items per page. @@ -85,16 +85,12 @@ public function __construct(ReadableDataInterface $dataReader) } $this->dataReader = $dataReader; + $this->pageToken = PageToken::next('1'); } - public function withNextPageToken(?string $token): static + public function withPageToken(?PageToken $pageToken): static { - return $this->withCurrentPage((int) $token); - } - - public function withPreviousPageToken(?string $token): static - { - return $this->withCurrentPage((int) $token); + return $this->withCurrentPage($pageToken === null ? 1 : (int)$pageToken->value); } public function withPageSize(int $pageSize): static @@ -124,18 +120,23 @@ public function withCurrentPage(int $page): self } $new = clone $this; - $new->currentPage = $page; + $new->pageToken = PageToken::next((string) $page); return $new; } - public function getNextPageToken(): ?string + public function getPageToken(): PageToken { - return $this->isOnLastPage() ? null : (string) ($this->currentPage + 1); + return $this->pageToken; } - public function getPreviousPageToken(): ?string + public function getNextPageTokenValue(): ?string { - return $this->isOnFirstPage() ? null : (string) ($this->currentPage - 1); + return $this->isOnLastPage() ? null : (string) ($this->getCurrentPage() + 1); + } + + public function getPreviousPageTokenValue(): ?string + { + return $this->isOnFirstPage() ? null : (string) ($this->getCurrentPage() - 1); } public function getPageSize(): int @@ -150,7 +151,7 @@ public function getPageSize(): int */ public function getCurrentPage(): int { - return $this->currentPage; + return (int) $this->pageToken->value; } public function getCurrentPageSize(): int @@ -161,11 +162,13 @@ public function getCurrentPageSize(): int return $this->getTotalItems(); } - if ($this->currentPage < $pages) { + $currentPage = $this->getCurrentPage(); + + if ($currentPage < $pages) { return $this->pageSize; } - if ($this->currentPage === $pages) { + if ($currentPage === $pages) { return $this->getTotalItems() - $this->getOffset(); } @@ -179,7 +182,7 @@ public function getCurrentPageSize(): int */ public function getOffset(): int { - return $this->pageSize * ($this->currentPage - 1); + return $this->pageSize * ($this->getCurrentPage() - 1); } /** @@ -228,7 +231,7 @@ public function getSort(): ?Sort */ public function read(): iterable { - if ($this->currentPage > $this->getInternalTotalPages()) { + if ($this->getCurrentPage() > $this->getInternalTotalPages()) { throw new PaginatorException('Page not found.'); } @@ -248,16 +251,16 @@ public function readOne(): array|object|null public function isOnFirstPage(): bool { - return $this->currentPage === 1; + return $this->pageToken->value === '1'; } public function isOnLastPage(): bool { - if ($this->currentPage > $this->getInternalTotalPages()) { + if ($this->getCurrentPage() > $this->getInternalTotalPages()) { throw new PaginatorException('Page not found.'); } - return $this->currentPage === $this->getInternalTotalPages(); + return $this->getCurrentPage() === $this->getInternalTotalPages(); } public function isPaginationRequired(): bool diff --git a/src/Paginator/PageToken.php b/src/Paginator/PageToken.php new file mode 100644 index 00000000..47a34a75 --- /dev/null +++ b/src/Paginator/PageToken.php @@ -0,0 +1,24 @@ +withOrderString('id'); $dataReader = (new IterableDataReader([]))->withSort($sort); - $paginator = (new KeysetPaginator($dataReader)) - ->withPageSize(1) - ->withNextPageToken('1') - ; + $paginator = (new KeysetPaginator($dataReader))->withPageSize(1); $this->assertTrue($paginator->isOnFirstPage()); $this->assertTrue($paginator->isOnLastPage()); @@ -218,7 +216,7 @@ public function testReadFirstPage(): void $this->assertSame($expected, $this->iterableToArray($paginator->read())); $last = end($expected); - $this->assertSame((string) $last['id'], $paginator->getNextPageToken()); + $this->assertSame((string)$last['id'], $paginator->getNextPageTokenValue()); $this->assertTrue($paginator->isOnFirstPage()); } @@ -235,7 +233,7 @@ public function testReadObjectsWithPublicProperties(): void $paginator = (new KeysetPaginator($dataReader))->withPageSize(2); $this->assertSame([$data[0], $data[1]], $this->iterableToArray($paginator->read())); - $this->assertSame((string) $data[1]->id, $paginator->getNextPageToken()); + $this->assertSame((string)$data[1]->id, $paginator->getNextPageTokenValue()); $this->assertTrue($paginator->isOnFirstPage()); } @@ -261,7 +259,7 @@ public function testReadObjectsWithGetters(string $orderByField, string $getter) $paginator = (new KeysetPaginator($dataReader))->withPageSize(2); $this->assertSame([$data[0], $data[1]], $this->iterableToArray($paginator->read())); - $this->assertSame((string) $data[1]->$getter(), $paginator->getNextPageToken()); + $this->assertSame((string)$data[1]->$getter(), $paginator->getNextPageTokenValue()); $this->assertTrue($paginator->isOnFirstPage()); } @@ -274,13 +272,13 @@ public function testReadSecondPage(): void $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withNextPageToken('2'); + ->withPageToken(new PageToken('2', false)); $expected = self::getDataSet([2, 3]); $this->assertSame($expected, array_values((array) $paginator->read())); $last = end($expected); - $this->assertSame((string)$last['id'], $paginator->getNextPageToken()); + $this->assertSame((string)$last['id'], $paginator->getNextPageTokenValue()); } public function testReadSecondPageOrderedByName(): void @@ -290,14 +288,13 @@ public function testReadSecondPageOrderedByName(): void $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withNextPageToken('Agent J') - ; + ->withPageToken(PageToken::next('Agent J')); $expected = self::getDataSet([2, 0]); $this->assertSame($expected, array_values($this->iterableToArray($paginator->read()))); $last = end($expected); - $this->assertSame((string)$last['name'], $paginator->getNextPageToken()); + $this->assertSame((string)$last['name'], $paginator->getNextPageTokenValue()); } public static function dataReadOne(): array @@ -338,7 +335,7 @@ public function testBackwardPagination(): void $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withPreviousPageToken('5') + ->withPageToken(PageToken::previous('5')) ; $expected = self::getDataSet([1, 2]); @@ -347,8 +344,8 @@ public function testBackwardPagination(): void $this->assertSame($expected, $read); $first = reset($expected); $last = end($expected); - $this->assertSame((string) $last['id'], $paginator->getNextPageToken(), 'Last value fail!'); - $this->assertSame((string) $first['id'], $paginator->getPreviousPageToken(), 'First value fail!'); + $this->assertSame((string)$last['id'], $paginator->getNextPageTokenValue(), 'Last value fail!'); + $this->assertSame((string)$first['id'], $paginator->getPreviousPageTokenValue(), 'First value fail!'); } public function testForwardAndBackwardPagination(): void @@ -357,8 +354,7 @@ public function testForwardAndBackwardPagination(): void $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withNextPageToken('2') - ; + ->withPageToken(PageToken::next('2')); $expected = self::getDataSet([2, 3]); $read = array_values($this->iterableToArray($paginator->read())); @@ -368,20 +364,20 @@ public function testForwardAndBackwardPagination(): void $first = reset($expected); $last = end($expected); - $this->assertSame((string) $last['id'], $paginator->getNextPageToken(), 'Last value fail!'); - $this->assertSame((string) $first['id'], $paginator->getPreviousPageToken(), 'First value fail!'); + $this->assertSame((string)$last['id'], $paginator->getNextPageTokenValue(), 'Last value fail!'); + $this->assertSame((string)$first['id'], $paginator->getPreviousPageTokenValue(), 'First value fail!'); $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withPreviousPageToken($paginator->getPreviousPageToken()); + ->withPageToken(PageToken::previous($paginator->getPreviousPageTokenValue())); $expected = self::getDataSet([0, 1]); $read = array_values($this->iterableToArray($paginator->read())); $this->assertSame($expected, $read); $last = end($expected); - $this->assertSame((string) $last['id'], $paginator->getNextPageToken(), 'Last value fail!'); - $this->assertNull($paginator->getPreviousPageToken(), 'First value fail!'); + $this->assertSame((string)$last['id'], $paginator->getNextPageTokenValue(), 'Last value fail!'); + $this->assertNull($paginator->getPreviousPageTokenValue(), 'First value fail!'); } public function testIsOnFirstPage(): void @@ -400,19 +396,19 @@ public function testIsOnLastPage(): void $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); $paginator = (new KeysetPaginator($dataReader))->withPageSize(2); - $paginator = $paginator->withNextPageToken('6'); + $paginator = $paginator->withPageToken(PageToken::next('6')); $this->assertTrue($paginator->isOnLastPage()); - $paginator = $paginator->withNextPageToken('5'); + $paginator = $paginator->withPageToken(PageToken::next('5')); $this->assertTrue($paginator->isOnLastPage()); - $paginator = $paginator->withNextPageToken('4'); + $paginator = $paginator->withPageToken(PageToken::next('4')); $this->assertTrue($paginator->isOnLastPage()); - $paginator = $paginator->withNextPageToken('3'); + $paginator = $paginator->withPageToken(PageToken::next('3')); $this->assertTrue($paginator->isOnLastPage()); - $paginator = $paginator->withNextPageToken('2'); + $paginator = $paginator->withPageToken(PageToken::next('2')); $this->assertFalse($paginator->isOnLastPage()); $this->assertTrue($paginator->isPaginationRequired()); } @@ -437,22 +433,22 @@ public function testCurrentPageSize(): void $paginator = (new KeysetPaginator($dataReader))->withPageSize(2); $this->assertSame(2, $paginator->getCurrentPageSize()); - $paginator = $paginator->withPreviousPageToken('1'); + $paginator = $paginator->withPageToken(PageToken::previous('1')); $this->assertSame(0, $paginator->getCurrentPageSize()); - $paginator = $paginator->withPreviousPageToken('2'); + $paginator = $paginator->withPageToken(PageToken::previous('2')); $this->assertSame(1, $paginator->getCurrentPageSize()); - $paginator = $paginator->withPreviousPageToken('3'); + $paginator = $paginator->withPageToken(PageToken::previous('3')); $this->assertSame(2, $paginator->getCurrentPageSize()); - $paginator = $paginator->withNextPageToken('6'); + $paginator = $paginator->withPageToken(PageToken::next('6')); $this->assertSame(0, $paginator->getCurrentPageSize()); - $paginator = $paginator->withNextPageToken('5'); + $paginator = $paginator->withPageToken(PageToken::next('5')); $this->assertSame(1, $paginator->getCurrentPageSize()); - $paginator = $paginator->withNextPageToken('4'); + $paginator = $paginator->withPageToken(PageToken::next('4')); $this->assertSame(2, $paginator->getCurrentPageSize()); } @@ -509,45 +505,45 @@ public function testTokenResults(): void $sort = Sort::only(['id'])->withOrderString('id'); $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); $paginator = (new KeysetPaginator($dataReader))->withPageSize(2); - $this->assertNotNull($paginator->getNextPageToken()); + $this->assertNotNull($paginator->getNextPageTokenValue()); - $paginator = $paginator->withPreviousPageToken('1'); + $paginator = $paginator->withPageToken(PageToken::previous('1')); try { - $paginator->getNextPageToken(); + $paginator->getNextPageTokenValue(); $this->fail(); } catch (RuntimeException) { $this->assertTrue(true); } - $this->assertNull($paginator->getPreviousPageToken()); + $this->assertNull($paginator->getPreviousPageTokenValue()); - $paginator = $paginator->withPreviousPageToken('2'); - $this->assertNotNull($paginator->getNextPageToken()); - $this->assertSame('1', $paginator->getNextPageToken()); - $this->assertNull($paginator->getPreviousPageToken()); + $paginator = $paginator->withPageToken(PageToken::previous('2')); + $this->assertNotNull($paginator->getNextPageTokenValue()); + $this->assertSame('1', $paginator->getNextPageTokenValue()); + $this->assertNull($paginator->getPreviousPageTokenValue()); - $paginator = $paginator->withPreviousPageToken('3'); - $this->assertNotNull($paginator->getNextPageToken()); - $this->assertSame('2', $paginator->getNextPageToken()); - $this->assertNull($paginator->getPreviousPageToken()); + $paginator = $paginator->withPageToken(PageToken::previous('3')); + $this->assertNotNull($paginator->getNextPageTokenValue()); + $this->assertSame('2', $paginator->getNextPageTokenValue()); + $this->assertNull($paginator->getPreviousPageTokenValue()); - $paginator = $paginator->withNextPageToken('6'); + $paginator = $paginator->withPageToken(PageToken::next('6')); try { - $paginator->getPreviousPageToken(); + $paginator->getPreviousPageTokenValue(); $this->fail(); } catch (RuntimeException) { $this->assertTrue(true); } - $this->assertNull($paginator->getNextPageToken()); + $this->assertNull($paginator->getNextPageTokenValue()); - $paginator = $paginator->withNextPageToken('5'); - $this->assertNotNull($paginator->getPreviousPageToken()); - $this->assertSame('6', $paginator->getPreviousPageToken()); - $this->assertNull($paginator->getNextPageToken()); + $paginator = $paginator->withPageToken(PageToken::next('5')); + $this->assertNotNull($paginator->getPreviousPageTokenValue()); + $this->assertSame('6', $paginator->getPreviousPageTokenValue()); + $this->assertNull($paginator->getNextPageTokenValue()); - $paginator = $paginator->withNextPageToken('4'); - $this->assertNull($paginator->getNextPageToken()); - $this->assertNotNull($paginator->getPreviousPageToken()); - $this->assertSame('5', $paginator->getPreviousPageToken()); + $paginator = $paginator->withPageToken(PageToken::next('4')); + $this->assertNull($paginator->getNextPageTokenValue()); + $this->assertNotNull($paginator->getPreviousPageTokenValue()); + $this->assertSame('5', $paginator->getPreviousPageTokenValue()); } public function testDefaultPageSize(): void @@ -694,7 +690,7 @@ public function testWithPreviousPageTokenAndIsOnFirstPageSameTrue(): void { $sort = Sort::only(['id'])->withOrderString('id'); $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); - $paginator = (new KeysetPaginator($dataReader))->withPreviousPageToken('1'); + $paginator = (new KeysetPaginator($dataReader))->withPageToken(PageToken::previous('1')); $this->assertTrue($paginator->isOnFirstPage()); } @@ -710,11 +706,11 @@ public function testCloneClearValues(): void $this->assertSame('1', $this->getInaccessibleProperty($paginator, 'currentFirstValue')); $this->assertSame('6', $this->getInaccessibleProperty($paginator, 'currentLastValue')); - $paginator = $paginator->withPreviousPageToken('1'); + $paginator = $paginator->withPageToken(PageToken::previous('1')); $paginator->read(); $this->assertTrue($this->getInaccessibleProperty($paginator, 'hasNextPage')); - $paginator = $paginator->withNextPageToken('3'); + $paginator = $paginator->withPageToken(PageToken::next('3')); $paginator->read(); $this->assertTrue($this->getInaccessibleProperty($paginator, 'hasPreviousPage')); @@ -733,8 +729,8 @@ public function testImmutability(): void $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); $paginator = new KeysetPaginator($dataReader); - $this->assertNotSame($paginator, $paginator->withNextPageToken('1')); - $this->assertNotSame($paginator, $paginator->withPreviousPageToken('1')); + $this->assertNotSame($paginator, $paginator->withPageToken(PageToken::next('1'))); + $this->assertNotSame($paginator, $paginator->withPageToken(PageToken::previous('1'))); $this->assertNotSame($paginator, $paginator->withPageSize(1)); $this->assertNotSame($paginator, $paginator->withFilterCallback(null)); } @@ -743,7 +739,7 @@ public function testGetPreviousPageExistForCoverage(): void { $sort = Sort::only(['id'])->withOrderString('id'); $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); - $paginator = (new KeysetPaginator($dataReader))->withNextPageToken('1'); + $paginator = (new KeysetPaginator($dataReader))->withPageToken(PageToken::next('1')); $this->assertTrue($this->invokeMethod($paginator, 'previousPageExist', [$dataReader, $sort])); @@ -753,7 +749,7 @@ public function testGetFilterForCoverage(): void { $sort = Sort::only(['id'])->withOrderString('id'); $dataReader = (new IterableDataReader([]))->withSort($sort); - $paginator = (new KeysetPaginator($dataReader))->withNextPageToken('1'); + $paginator = (new KeysetPaginator($dataReader))->withPageToken(PageToken::next('1')); $this->assertInstanceOf( GreaterThan::class, @@ -764,7 +760,7 @@ public function testGetFilterForCoverage(): void ->withOrderString('id') ->withOrder(['id' => 'desc']); $dataReader = (new IterableDataReader([]))->withSort($sort); - $paginator = (new KeysetPaginator($dataReader))->withNextPageToken('1'); + $paginator = (new KeysetPaginator($dataReader))->withPageToken(PageToken::next('1')); $this->assertInstanceOf( LessThan::class, @@ -776,7 +772,7 @@ public function testGetReverseFilterForCoverage(): void { $sort = Sort::only(['42'])->withOrderString('42'); $dataReader = (new IterableDataReader([]))->withSort($sort); - $paginator = (new KeysetPaginator($dataReader))->withNextPageToken('1'); + $paginator = (new KeysetPaginator($dataReader))->withPageToken(PageToken::next('1')); $this->assertInstanceOf( LessThanOrEqual::class, @@ -787,7 +783,7 @@ public function testGetReverseFilterForCoverage(): void ->withOrderString('42') ->withOrder(['42' => 'desc']); $dataReader = (new IterableDataReader([]))->withSort($sort); - $paginator = (new KeysetPaginator($dataReader))->withNextPageToken('1'); + $paginator = (new KeysetPaginator($dataReader))->withPageToken(PageToken::next('1')); $this->assertInstanceOf( GreaterThanOrEqual::class, @@ -806,7 +802,7 @@ static function ($item) { ))->withSort(Sort::only(['id'])->withOrderString('id')); $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withPreviousPageToken('5') + ->withPageToken(PageToken::previous('5')) ->withFilterCallback( static function ( GreaterThan|LessThan|GreaterThanOrEqual|LessThanOrEqual $filter, @@ -845,7 +841,7 @@ static function ($item) { ))->withSort(Sort::only(['id'])->withOrderString('id')); $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withPreviousPageToken('2') + ->withPageToken(PageToken::previous('2')) ->withFilterCallback( static function ( GreaterThan|LessThan|GreaterThanOrEqual|LessThanOrEqual $filter, @@ -889,7 +885,7 @@ public function testFilterCallbackWithReverse(): void $dataReader = (new IterableDataReader(self::DEFAULT_DATASET)) ->withSort(Sort::only(['id'])->withOrderString('id')); $paginator = (new KeysetPaginator($dataReader)) - ->withPreviousPageToken('1') + ->withPageToken(PageToken::previous('1')) ->withFilterCallback( static function ( GreaterThan|LessThan|GreaterThanOrEqual|LessThanOrEqual $filter, @@ -966,7 +962,7 @@ public function testPageTypeWithPreviousPageToken( $paginator = (new KeysetPaginator($reader)) ->withPageSize(2) - ->withPreviousPageToken($token); + ->withPageToken(PageToken::previous($token)); $this->assertSame($expectedIsOnFirstPage, $paginator->isOnFirstPage()); $this->assertSame($expectedIsOnLastPage, $paginator->isOnLastPage()); @@ -1029,7 +1025,7 @@ public function testPageTypeWithNextPageToken( $paginator = (new KeysetPaginator($reader)) ->withPageSize(2) - ->withNextPageToken($token); + ->withPageToken(PageToken::next($token)); $this->assertSame($expectedIsOnFirstPage, $paginator->isOnFirstPage()); $this->assertSame($expectedIsOnLastPage, $paginator->isOnLastPage()); diff --git a/tests/Paginator/OffsetPaginatorTest.php b/tests/Paginator/OffsetPaginatorTest.php index 4a2512c1..b027a80a 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\PageToken; use Yiisoft\Data\Paginator\PaginatorException; use Yiisoft\Data\Paginator\PaginatorInterface; use Yiisoft\Data\Reader\CountableDataInterface; @@ -486,33 +487,32 @@ public function testGetSort(): void public function testNextPageToken(): void { $dataReader = new IterableDataReader(self::DEFAULT_DATASET); - $paginator = (new OffsetPaginator($dataReader))->withNextPageToken('1'); + $paginator = (new OffsetPaginator($dataReader))->withPageToken(PageToken::next('1')); - $this->assertNull($paginator->getNextPageToken()); + $this->assertNull($paginator->getNextPageTokenValue()); $paginator = $paginator->withPageSize(2); - $this->assertSame('2', $paginator->getNextPageToken()); + $this->assertSame('2', $paginator->getNextPageTokenValue()); } public function testPreviousPageToken(): void { $dataReader = new IterableDataReader(self::DEFAULT_DATASET); - $paginator = (new OffsetPaginator($dataReader))->withPreviousPageToken('1'); + $paginator = (new OffsetPaginator($dataReader))->withPageToken(PageToken::previous('1')); - $this->assertNull($paginator->getPreviousPageToken()); + $this->assertNull($paginator->getPreviousPageTokenValue()); - $paginator = $paginator->withPreviousPageToken('5'); + $paginator = $paginator->withPageToken(PageToken::previous('5')); - $this->assertSame('4', $paginator->getPreviousPageToken()); + $this->assertSame('4', $paginator->getPreviousPageTokenValue()); } public function testImmutability(): void { $paginator = new OffsetPaginator(new IterableDataReader([])); - $this->assertNotSame($paginator, $paginator->withNextPageToken('1')); - $this->assertNotSame($paginator, $paginator->withPreviousPageToken('1')); + $this->assertNotSame($paginator, $paginator->withPageToken(PageToken::previous('1'))); $this->assertNotSame($paginator, $paginator->withPageSize(1)); $this->assertNotSame($paginator, $paginator->withCurrentPage(1)); } @@ -555,4 +555,15 @@ public function testWithSortNonSortableData(): void $this->expectExceptionMessage('Data reader does not support sorting.'); $paginator->withSort(null); } + + public function testWithNulledPageToken(): void + { + $paginator = (new OffsetPaginator(new StubOffsetData()))->withPageToken(null); + + $token = $paginator->getPageToken(); + + $this->assertNotNull($token); + $this->assertSame('1', $token->value); + $this->assertFalse($token->isPrevious); + } } From a6cc68b6efdc84d7441578ee62c9fb258fc60439 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Wed, 24 Jan 2024 13:11:37 +0300 Subject: [PATCH 02/11] changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ba01879..539051c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ - 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::isSortable()` and `PaginatorInterface::withSort()` (@vjik) +- Chg #159: Rename `PaginatorInterface` methods: `getNextPageToken()` to `getNextPageTokenValue()` + and `getPrevPageToken()` to `getPrevPageTokenValue()` (@vjik) +- Chg #159: Replace `PaginatorInterface` methods `withNextPageToken()` and `withPreviousPageToken` to + single method `withPageToken()`, and add `getPageToken()` method. These methods are used new `PageToken` class (@vjik) ## 1.0.1 January 25, 2023 From ae577cc7752fcf58237de3284dca0e2aa74124ea Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Wed, 24 Jan 2024 13:13:34 +0300 Subject: [PATCH 03/11] readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 38eac5be..9efabf99 100644 --- a/README.md +++ b/README.md @@ -27,14 +27,14 @@ Features are: ## Requirements -- PHP 8.0 or higher. +- PHP 8.1 or higher. ## Installation The package could be installed with composer: ```shell -composer require yiisoft/data --prefer-dist +composer require yiisoft/data ``` ## Concepts @@ -334,7 +334,7 @@ $dataReader = (new MyDataReader(...)) $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(10) - ->withNextPageToken('13'); + ->withPageToken(PageToken::next('13')); ``` When displaying first page ID (or another field name to paginate by) of the item displayed last is used with `withNextPageToken()` From 25a660dfe32cd78ae5f7c282a0a2858488106866 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Wed, 24 Jan 2024 13:18:10 +0300 Subject: [PATCH 04/11] test --- tests/Paginator/KeysetPaginatorTest.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/Paginator/KeysetPaginatorTest.php b/tests/Paginator/KeysetPaginatorTest.php index b9063a55..544908eb 100644 --- a/tests/Paginator/KeysetPaginatorTest.php +++ b/tests/Paginator/KeysetPaginatorTest.php @@ -1041,7 +1041,7 @@ public function testIsSortable(): void $this->assertTrue($paginator->isSortable()); } - public function testWithSort() + public function testWithSort(): void { $sort1 = Sort::only(['id'])->withOrderString('id'); $reader = (new IterableDataReader([]))->withSort($sort1); @@ -1054,4 +1054,18 @@ public function testWithSort() $this->assertSame($sort1, $paginator1->getSort()); $this->assertSame($sort2, $paginator2->getSort()); } + + public function testGetPageToken(): void + { + $sort = Sort::only(['id'])->withOrderString('id'); + $reader = (new IterableDataReader([]))->withSort($sort); + $paginator = new KeysetPaginator($reader); + + $this->assertNull($paginator->getPageToken()); + + $token = PageToken::next('1'); + $paginator = $paginator->withPageToken($token); + + $this->assertSame($token, $paginator->getPageToken()); + } } From 6e8348db0367176b2c01a34029e6c917d252bd80 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Wed, 24 Jan 2024 13:21:23 +0300 Subject: [PATCH 05/11] rename --- CHANGELOG.md | 6 +- README.md | 2 +- src/Paginator/KeysetPaginator.php | 10 +- src/Paginator/OffsetPaginator.php | 10 +- src/Paginator/PaginatorInterface.php | 10 +- tests/Paginator/KeysetPaginatorTest.php | 136 ++++++++++++------------ tests/Paginator/OffsetPaginatorTest.php | 20 ++-- 7 files changed, 97 insertions(+), 97 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 539051c4..1ab8630a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,10 +12,10 @@ - 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::isSortable()` and `PaginatorInterface::withSort()` (@vjik) -- Chg #159: Rename `PaginatorInterface` methods: `getNextPageToken()` to `getNextPageTokenValue()` - and `getPrevPageToken()` to `getPrevPageTokenValue()` (@vjik) +- Chg #159: Rename `PaginatorInterface` methods: `getNextPageToken()` to `getNextTokenValue()` + and `getPreviousPageToken()` to `getPreviousTokenValue()` (@vjik) - Chg #159: Replace `PaginatorInterface` methods `withNextPageToken()` and `withPreviousPageToken` to - single method `withPageToken()`, and add `getPageToken()` method. These methods are used new `PageToken` class (@vjik) + single method `withToken()`, and add `getToken()` method. These methods are used new `PageToken` class (@vjik) ## 1.0.1 January 25, 2023 diff --git a/README.md b/README.md index 9efabf99..d5bfc58a 100644 --- a/README.md +++ b/README.md @@ -334,7 +334,7 @@ $dataReader = (new MyDataReader(...)) $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(10) - ->withPageToken(PageToken::next('13')); + ->withToken(PageToken::next('13')); ``` When displaying first page ID (or another field name to paginate by) of the item displayed last is used with `withNextPageToken()` diff --git a/src/Paginator/KeysetPaginator.php b/src/Paginator/KeysetPaginator.php index 96ec71c7..e858901e 100644 --- a/src/Paginator/KeysetPaginator.php +++ b/src/Paginator/KeysetPaginator.php @@ -138,14 +138,14 @@ public function __clone() $this->currentLastValue = null; } - public function withPageToken(?PageToken $pageToken): static + public function withToken(?PageToken $token): static { $new = clone $this; - $new->pageToken = $pageToken; + $new->pageToken = $token; return $new; } - public function getPageToken(): ?PageToken + public function getToken(): ?PageToken { return $this->pageToken; } @@ -235,12 +235,12 @@ public function getCurrentPageSize(): int return count($this->readCache); } - public function getPreviousPageTokenValue(): ?string + public function getPreviousTokenValue(): ?string { return $this->isOnFirstPage() ? null : $this->currentFirstValue; } - public function getNextPageTokenValue(): ?string + public function getNextTokenValue(): ?string { return $this->isOnLastPage() ? null : $this->currentLastValue; } diff --git a/src/Paginator/OffsetPaginator.php b/src/Paginator/OffsetPaginator.php index d4ebbbf3..47a94964 100644 --- a/src/Paginator/OffsetPaginator.php +++ b/src/Paginator/OffsetPaginator.php @@ -88,9 +88,9 @@ public function __construct(ReadableDataInterface $dataReader) $this->pageToken = PageToken::next('1'); } - public function withPageToken(?PageToken $pageToken): static + public function withToken(?PageToken $token): static { - return $this->withCurrentPage($pageToken === null ? 1 : (int)$pageToken->value); + return $this->withCurrentPage($token === null ? 1 : (int)$token->value); } public function withPageSize(int $pageSize): static @@ -124,17 +124,17 @@ public function withCurrentPage(int $page): self return $new; } - public function getPageToken(): PageToken + public function getToken(): PageToken { return $this->pageToken; } - public function getNextPageTokenValue(): ?string + public function getNextTokenValue(): ?string { return $this->isOnLastPage() ? null : (string) ($this->getCurrentPage() + 1); } - public function getPreviousPageTokenValue(): ?string + public function getPreviousTokenValue(): ?string { return $this->isOnFirstPage() ? null : (string) ($this->getCurrentPage() - 1); } diff --git a/src/Paginator/PaginatorInterface.php b/src/Paginator/PaginatorInterface.php index b1edc588..1dfa3d99 100644 --- a/src/Paginator/PaginatorInterface.php +++ b/src/Paginator/PaginatorInterface.php @@ -28,13 +28,13 @@ interface PaginatorInterface extends ReadableDataInterface /** * Get a new instance with page token. * - * @param PageToken|null $pageToken Page token. `Null` if current page is first. + * @param PageToken|null $token Page token. `Null` if current page is first. * * @return static New instance. * * @see PageToken */ - public function withPageToken(?PageToken $pageToken): static; + public function withToken(?PageToken $token): static; /** * Get a new instance with page size set. @@ -50,21 +50,21 @@ public function withPageSize(int $pageSize): static; /** * @return PageToken|null Current page token or `null` if not set. */ - public function getPageToken(): ?PageToken; + public function getToken(): ?PageToken; /** * Get token for the next page. * * @return string|null Token for the next page. `null` if current page is last. */ - public function getNextPageTokenValue(): ?string; + public function getNextTokenValue(): ?string; /** * Get token for the previous page. * * @return string|null Token for the previous page. `null` if current page is first. */ - public function getPreviousPageTokenValue(): ?string; + public function getPreviousTokenValue(): ?string; /** * Get maximum number of items per page. diff --git a/tests/Paginator/KeysetPaginatorTest.php b/tests/Paginator/KeysetPaginatorTest.php index 544908eb..f74837e4 100644 --- a/tests/Paginator/KeysetPaginatorTest.php +++ b/tests/Paginator/KeysetPaginatorTest.php @@ -216,7 +216,7 @@ public function testReadFirstPage(): void $this->assertSame($expected, $this->iterableToArray($paginator->read())); $last = end($expected); - $this->assertSame((string)$last['id'], $paginator->getNextPageTokenValue()); + $this->assertSame((string)$last['id'], $paginator->getNextTokenValue()); $this->assertTrue($paginator->isOnFirstPage()); } @@ -233,7 +233,7 @@ public function testReadObjectsWithPublicProperties(): void $paginator = (new KeysetPaginator($dataReader))->withPageSize(2); $this->assertSame([$data[0], $data[1]], $this->iterableToArray($paginator->read())); - $this->assertSame((string)$data[1]->id, $paginator->getNextPageTokenValue()); + $this->assertSame((string)$data[1]->id, $paginator->getNextTokenValue()); $this->assertTrue($paginator->isOnFirstPage()); } @@ -259,7 +259,7 @@ public function testReadObjectsWithGetters(string $orderByField, string $getter) $paginator = (new KeysetPaginator($dataReader))->withPageSize(2); $this->assertSame([$data[0], $data[1]], $this->iterableToArray($paginator->read())); - $this->assertSame((string)$data[1]->$getter(), $paginator->getNextPageTokenValue()); + $this->assertSame((string)$data[1]->$getter(), $paginator->getNextTokenValue()); $this->assertTrue($paginator->isOnFirstPage()); } @@ -272,13 +272,13 @@ public function testReadSecondPage(): void $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withPageToken(new PageToken('2', false)); + ->withToken(new PageToken('2', false)); $expected = self::getDataSet([2, 3]); $this->assertSame($expected, array_values((array) $paginator->read())); $last = end($expected); - $this->assertSame((string)$last['id'], $paginator->getNextPageTokenValue()); + $this->assertSame((string)$last['id'], $paginator->getNextTokenValue()); } public function testReadSecondPageOrderedByName(): void @@ -288,13 +288,13 @@ public function testReadSecondPageOrderedByName(): void $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withPageToken(PageToken::next('Agent J')); + ->withToken(PageToken::next('Agent J')); $expected = self::getDataSet([2, 0]); $this->assertSame($expected, array_values($this->iterableToArray($paginator->read()))); $last = end($expected); - $this->assertSame((string)$last['name'], $paginator->getNextPageTokenValue()); + $this->assertSame((string)$last['name'], $paginator->getNextTokenValue()); } public static function dataReadOne(): array @@ -335,7 +335,7 @@ public function testBackwardPagination(): void $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withPageToken(PageToken::previous('5')) + ->withToken(PageToken::previous('5')) ; $expected = self::getDataSet([1, 2]); @@ -344,8 +344,8 @@ public function testBackwardPagination(): void $this->assertSame($expected, $read); $first = reset($expected); $last = end($expected); - $this->assertSame((string)$last['id'], $paginator->getNextPageTokenValue(), 'Last value fail!'); - $this->assertSame((string)$first['id'], $paginator->getPreviousPageTokenValue(), 'First value fail!'); + $this->assertSame((string)$last['id'], $paginator->getNextTokenValue(), 'Last value fail!'); + $this->assertSame((string)$first['id'], $paginator->getPreviousTokenValue(), 'First value fail!'); } public function testForwardAndBackwardPagination(): void @@ -354,7 +354,7 @@ public function testForwardAndBackwardPagination(): void $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withPageToken(PageToken::next('2')); + ->withToken(PageToken::next('2')); $expected = self::getDataSet([2, 3]); $read = array_values($this->iterableToArray($paginator->read())); @@ -364,20 +364,20 @@ public function testForwardAndBackwardPagination(): void $first = reset($expected); $last = end($expected); - $this->assertSame((string)$last['id'], $paginator->getNextPageTokenValue(), 'Last value fail!'); - $this->assertSame((string)$first['id'], $paginator->getPreviousPageTokenValue(), 'First value fail!'); + $this->assertSame((string)$last['id'], $paginator->getNextTokenValue(), 'Last value fail!'); + $this->assertSame((string)$first['id'], $paginator->getPreviousTokenValue(), 'First value fail!'); $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withPageToken(PageToken::previous($paginator->getPreviousPageTokenValue())); + ->withToken(PageToken::previous($paginator->getPreviousTokenValue())); $expected = self::getDataSet([0, 1]); $read = array_values($this->iterableToArray($paginator->read())); $this->assertSame($expected, $read); $last = end($expected); - $this->assertSame((string)$last['id'], $paginator->getNextPageTokenValue(), 'Last value fail!'); - $this->assertNull($paginator->getPreviousPageTokenValue(), 'First value fail!'); + $this->assertSame((string)$last['id'], $paginator->getNextTokenValue(), 'Last value fail!'); + $this->assertNull($paginator->getPreviousTokenValue(), 'First value fail!'); } public function testIsOnFirstPage(): void @@ -396,19 +396,19 @@ public function testIsOnLastPage(): void $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); $paginator = (new KeysetPaginator($dataReader))->withPageSize(2); - $paginator = $paginator->withPageToken(PageToken::next('6')); + $paginator = $paginator->withToken(PageToken::next('6')); $this->assertTrue($paginator->isOnLastPage()); - $paginator = $paginator->withPageToken(PageToken::next('5')); + $paginator = $paginator->withToken(PageToken::next('5')); $this->assertTrue($paginator->isOnLastPage()); - $paginator = $paginator->withPageToken(PageToken::next('4')); + $paginator = $paginator->withToken(PageToken::next('4')); $this->assertTrue($paginator->isOnLastPage()); - $paginator = $paginator->withPageToken(PageToken::next('3')); + $paginator = $paginator->withToken(PageToken::next('3')); $this->assertTrue($paginator->isOnLastPage()); - $paginator = $paginator->withPageToken(PageToken::next('2')); + $paginator = $paginator->withToken(PageToken::next('2')); $this->assertFalse($paginator->isOnLastPage()); $this->assertTrue($paginator->isPaginationRequired()); } @@ -433,22 +433,22 @@ public function testCurrentPageSize(): void $paginator = (new KeysetPaginator($dataReader))->withPageSize(2); $this->assertSame(2, $paginator->getCurrentPageSize()); - $paginator = $paginator->withPageToken(PageToken::previous('1')); + $paginator = $paginator->withToken(PageToken::previous('1')); $this->assertSame(0, $paginator->getCurrentPageSize()); - $paginator = $paginator->withPageToken(PageToken::previous('2')); + $paginator = $paginator->withToken(PageToken::previous('2')); $this->assertSame(1, $paginator->getCurrentPageSize()); - $paginator = $paginator->withPageToken(PageToken::previous('3')); + $paginator = $paginator->withToken(PageToken::previous('3')); $this->assertSame(2, $paginator->getCurrentPageSize()); - $paginator = $paginator->withPageToken(PageToken::next('6')); + $paginator = $paginator->withToken(PageToken::next('6')); $this->assertSame(0, $paginator->getCurrentPageSize()); - $paginator = $paginator->withPageToken(PageToken::next('5')); + $paginator = $paginator->withToken(PageToken::next('5')); $this->assertSame(1, $paginator->getCurrentPageSize()); - $paginator = $paginator->withPageToken(PageToken::next('4')); + $paginator = $paginator->withToken(PageToken::next('4')); $this->assertSame(2, $paginator->getCurrentPageSize()); } @@ -505,45 +505,45 @@ public function testTokenResults(): void $sort = Sort::only(['id'])->withOrderString('id'); $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); $paginator = (new KeysetPaginator($dataReader))->withPageSize(2); - $this->assertNotNull($paginator->getNextPageTokenValue()); + $this->assertNotNull($paginator->getNextTokenValue()); - $paginator = $paginator->withPageToken(PageToken::previous('1')); + $paginator = $paginator->withToken(PageToken::previous('1')); try { - $paginator->getNextPageTokenValue(); + $paginator->getNextTokenValue(); $this->fail(); } catch (RuntimeException) { $this->assertTrue(true); } - $this->assertNull($paginator->getPreviousPageTokenValue()); + $this->assertNull($paginator->getPreviousTokenValue()); - $paginator = $paginator->withPageToken(PageToken::previous('2')); - $this->assertNotNull($paginator->getNextPageTokenValue()); - $this->assertSame('1', $paginator->getNextPageTokenValue()); - $this->assertNull($paginator->getPreviousPageTokenValue()); + $paginator = $paginator->withToken(PageToken::previous('2')); + $this->assertNotNull($paginator->getNextTokenValue()); + $this->assertSame('1', $paginator->getNextTokenValue()); + $this->assertNull($paginator->getPreviousTokenValue()); - $paginator = $paginator->withPageToken(PageToken::previous('3')); - $this->assertNotNull($paginator->getNextPageTokenValue()); - $this->assertSame('2', $paginator->getNextPageTokenValue()); - $this->assertNull($paginator->getPreviousPageTokenValue()); + $paginator = $paginator->withToken(PageToken::previous('3')); + $this->assertNotNull($paginator->getNextTokenValue()); + $this->assertSame('2', $paginator->getNextTokenValue()); + $this->assertNull($paginator->getPreviousTokenValue()); - $paginator = $paginator->withPageToken(PageToken::next('6')); + $paginator = $paginator->withToken(PageToken::next('6')); try { - $paginator->getPreviousPageTokenValue(); + $paginator->getPreviousTokenValue(); $this->fail(); } catch (RuntimeException) { $this->assertTrue(true); } - $this->assertNull($paginator->getNextPageTokenValue()); + $this->assertNull($paginator->getNextTokenValue()); - $paginator = $paginator->withPageToken(PageToken::next('5')); - $this->assertNotNull($paginator->getPreviousPageTokenValue()); - $this->assertSame('6', $paginator->getPreviousPageTokenValue()); - $this->assertNull($paginator->getNextPageTokenValue()); + $paginator = $paginator->withToken(PageToken::next('5')); + $this->assertNotNull($paginator->getPreviousTokenValue()); + $this->assertSame('6', $paginator->getPreviousTokenValue()); + $this->assertNull($paginator->getNextTokenValue()); - $paginator = $paginator->withPageToken(PageToken::next('4')); - $this->assertNull($paginator->getNextPageTokenValue()); - $this->assertNotNull($paginator->getPreviousPageTokenValue()); - $this->assertSame('5', $paginator->getPreviousPageTokenValue()); + $paginator = $paginator->withToken(PageToken::next('4')); + $this->assertNull($paginator->getNextTokenValue()); + $this->assertNotNull($paginator->getPreviousTokenValue()); + $this->assertSame('5', $paginator->getPreviousTokenValue()); } public function testDefaultPageSize(): void @@ -690,7 +690,7 @@ public function testWithPreviousPageTokenAndIsOnFirstPageSameTrue(): void { $sort = Sort::only(['id'])->withOrderString('id'); $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); - $paginator = (new KeysetPaginator($dataReader))->withPageToken(PageToken::previous('1')); + $paginator = (new KeysetPaginator($dataReader))->withToken(PageToken::previous('1')); $this->assertTrue($paginator->isOnFirstPage()); } @@ -706,11 +706,11 @@ public function testCloneClearValues(): void $this->assertSame('1', $this->getInaccessibleProperty($paginator, 'currentFirstValue')); $this->assertSame('6', $this->getInaccessibleProperty($paginator, 'currentLastValue')); - $paginator = $paginator->withPageToken(PageToken::previous('1')); + $paginator = $paginator->withToken(PageToken::previous('1')); $paginator->read(); $this->assertTrue($this->getInaccessibleProperty($paginator, 'hasNextPage')); - $paginator = $paginator->withPageToken(PageToken::next('3')); + $paginator = $paginator->withToken(PageToken::next('3')); $paginator->read(); $this->assertTrue($this->getInaccessibleProperty($paginator, 'hasPreviousPage')); @@ -729,8 +729,8 @@ public function testImmutability(): void $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); $paginator = new KeysetPaginator($dataReader); - $this->assertNotSame($paginator, $paginator->withPageToken(PageToken::next('1'))); - $this->assertNotSame($paginator, $paginator->withPageToken(PageToken::previous('1'))); + $this->assertNotSame($paginator, $paginator->withToken(PageToken::next('1'))); + $this->assertNotSame($paginator, $paginator->withToken(PageToken::previous('1'))); $this->assertNotSame($paginator, $paginator->withPageSize(1)); $this->assertNotSame($paginator, $paginator->withFilterCallback(null)); } @@ -739,7 +739,7 @@ public function testGetPreviousPageExistForCoverage(): void { $sort = Sort::only(['id'])->withOrderString('id'); $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); - $paginator = (new KeysetPaginator($dataReader))->withPageToken(PageToken::next('1')); + $paginator = (new KeysetPaginator($dataReader))->withToken(PageToken::next('1')); $this->assertTrue($this->invokeMethod($paginator, 'previousPageExist', [$dataReader, $sort])); @@ -749,7 +749,7 @@ public function testGetFilterForCoverage(): void { $sort = Sort::only(['id'])->withOrderString('id'); $dataReader = (new IterableDataReader([]))->withSort($sort); - $paginator = (new KeysetPaginator($dataReader))->withPageToken(PageToken::next('1')); + $paginator = (new KeysetPaginator($dataReader))->withToken(PageToken::next('1')); $this->assertInstanceOf( GreaterThan::class, @@ -760,7 +760,7 @@ public function testGetFilterForCoverage(): void ->withOrderString('id') ->withOrder(['id' => 'desc']); $dataReader = (new IterableDataReader([]))->withSort($sort); - $paginator = (new KeysetPaginator($dataReader))->withPageToken(PageToken::next('1')); + $paginator = (new KeysetPaginator($dataReader))->withToken(PageToken::next('1')); $this->assertInstanceOf( LessThan::class, @@ -772,7 +772,7 @@ public function testGetReverseFilterForCoverage(): void { $sort = Sort::only(['42'])->withOrderString('42'); $dataReader = (new IterableDataReader([]))->withSort($sort); - $paginator = (new KeysetPaginator($dataReader))->withPageToken(PageToken::next('1')); + $paginator = (new KeysetPaginator($dataReader))->withToken(PageToken::next('1')); $this->assertInstanceOf( LessThanOrEqual::class, @@ -783,7 +783,7 @@ public function testGetReverseFilterForCoverage(): void ->withOrderString('42') ->withOrder(['42' => 'desc']); $dataReader = (new IterableDataReader([]))->withSort($sort); - $paginator = (new KeysetPaginator($dataReader))->withPageToken(PageToken::next('1')); + $paginator = (new KeysetPaginator($dataReader))->withToken(PageToken::next('1')); $this->assertInstanceOf( GreaterThanOrEqual::class, @@ -802,7 +802,7 @@ static function ($item) { ))->withSort(Sort::only(['id'])->withOrderString('id')); $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withPageToken(PageToken::previous('5')) + ->withToken(PageToken::previous('5')) ->withFilterCallback( static function ( GreaterThan|LessThan|GreaterThanOrEqual|LessThanOrEqual $filter, @@ -841,7 +841,7 @@ static function ($item) { ))->withSort(Sort::only(['id'])->withOrderString('id')); $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withPageToken(PageToken::previous('2')) + ->withToken(PageToken::previous('2')) ->withFilterCallback( static function ( GreaterThan|LessThan|GreaterThanOrEqual|LessThanOrEqual $filter, @@ -885,7 +885,7 @@ public function testFilterCallbackWithReverse(): void $dataReader = (new IterableDataReader(self::DEFAULT_DATASET)) ->withSort(Sort::only(['id'])->withOrderString('id')); $paginator = (new KeysetPaginator($dataReader)) - ->withPageToken(PageToken::previous('1')) + ->withToken(PageToken::previous('1')) ->withFilterCallback( static function ( GreaterThan|LessThan|GreaterThanOrEqual|LessThanOrEqual $filter, @@ -962,7 +962,7 @@ public function testPageTypeWithPreviousPageToken( $paginator = (new KeysetPaginator($reader)) ->withPageSize(2) - ->withPageToken(PageToken::previous($token)); + ->withToken(PageToken::previous($token)); $this->assertSame($expectedIsOnFirstPage, $paginator->isOnFirstPage()); $this->assertSame($expectedIsOnLastPage, $paginator->isOnLastPage()); @@ -1025,7 +1025,7 @@ public function testPageTypeWithNextPageToken( $paginator = (new KeysetPaginator($reader)) ->withPageSize(2) - ->withPageToken(PageToken::next($token)); + ->withToken(PageToken::next($token)); $this->assertSame($expectedIsOnFirstPage, $paginator->isOnFirstPage()); $this->assertSame($expectedIsOnLastPage, $paginator->isOnLastPage()); @@ -1061,11 +1061,11 @@ public function testGetPageToken(): void $reader = (new IterableDataReader([]))->withSort($sort); $paginator = new KeysetPaginator($reader); - $this->assertNull($paginator->getPageToken()); + $this->assertNull($paginator->getToken()); $token = PageToken::next('1'); - $paginator = $paginator->withPageToken($token); + $paginator = $paginator->withToken($token); - $this->assertSame($token, $paginator->getPageToken()); + $this->assertSame($token, $paginator->getToken()); } } diff --git a/tests/Paginator/OffsetPaginatorTest.php b/tests/Paginator/OffsetPaginatorTest.php index b027a80a..372f7818 100644 --- a/tests/Paginator/OffsetPaginatorTest.php +++ b/tests/Paginator/OffsetPaginatorTest.php @@ -487,32 +487,32 @@ public function testGetSort(): void public function testNextPageToken(): void { $dataReader = new IterableDataReader(self::DEFAULT_DATASET); - $paginator = (new OffsetPaginator($dataReader))->withPageToken(PageToken::next('1')); + $paginator = (new OffsetPaginator($dataReader))->withToken(PageToken::next('1')); - $this->assertNull($paginator->getNextPageTokenValue()); + $this->assertNull($paginator->getNextTokenValue()); $paginator = $paginator->withPageSize(2); - $this->assertSame('2', $paginator->getNextPageTokenValue()); + $this->assertSame('2', $paginator->getNextTokenValue()); } public function testPreviousPageToken(): void { $dataReader = new IterableDataReader(self::DEFAULT_DATASET); - $paginator = (new OffsetPaginator($dataReader))->withPageToken(PageToken::previous('1')); + $paginator = (new OffsetPaginator($dataReader))->withToken(PageToken::previous('1')); - $this->assertNull($paginator->getPreviousPageTokenValue()); + $this->assertNull($paginator->getPreviousTokenValue()); - $paginator = $paginator->withPageToken(PageToken::previous('5')); + $paginator = $paginator->withToken(PageToken::previous('5')); - $this->assertSame('4', $paginator->getPreviousPageTokenValue()); + $this->assertSame('4', $paginator->getPreviousTokenValue()); } public function testImmutability(): void { $paginator = new OffsetPaginator(new IterableDataReader([])); - $this->assertNotSame($paginator, $paginator->withPageToken(PageToken::previous('1'))); + $this->assertNotSame($paginator, $paginator->withToken(PageToken::previous('1'))); $this->assertNotSame($paginator, $paginator->withPageSize(1)); $this->assertNotSame($paginator, $paginator->withCurrentPage(1)); } @@ -558,9 +558,9 @@ public function testWithSortNonSortableData(): void public function testWithNulledPageToken(): void { - $paginator = (new OffsetPaginator(new StubOffsetData()))->withPageToken(null); + $paginator = (new OffsetPaginator(new StubOffsetData()))->withToken(null); - $token = $paginator->getPageToken(); + $token = $paginator->getToken(); $this->assertNotNull($token); $this->assertSame('1', $token->value); From 4a0c9ad18b33a4a22648236f44307f2ca7d09b7f Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Wed, 24 Jan 2024 13:24:39 +0300 Subject: [PATCH 06/11] fix --- src/Paginator/KeysetPaginator.php | 22 +++++++++++----------- src/Paginator/OffsetPaginator.php | 12 ++++++------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Paginator/KeysetPaginator.php b/src/Paginator/KeysetPaginator.php index e858901e..9c7b7510 100644 --- a/src/Paginator/KeysetPaginator.php +++ b/src/Paginator/KeysetPaginator.php @@ -61,7 +61,7 @@ final class KeysetPaginator implements PaginatorInterface * @var int Maximum number of items per page. */ private int $pageSize = self::DEFAULT_PAGE_SIZE; - private ?PageToken $pageToken = null; + private ?PageToken $token = null; private ?string $currentFirstValue = null; private ?string $currentLastValue = null; @@ -141,13 +141,13 @@ public function __clone() public function withToken(?PageToken $token): static { $new = clone $this; - $new->pageToken = $token; + $new->token = $token; return $new; } public function getToken(): ?PageToken { - return $this->pageToken; + return $this->token; } public function withPageSize(int $pageSize): static @@ -196,19 +196,19 @@ public function read(): iterable /** @infection-ignore-all Any value more one in line below will be ignored into `readData()` method */ $dataReader = $this->dataReader->withLimit($this->pageSize + 1); - if ($this->pageToken?->isPrevious === true) { + if ($this->token?->isPrevious === true) { $sort = $this->reverseSort($sort); $dataReader = $dataReader->withSort($sort); } - if ($this->pageToken !== null) { + if ($this->token !== null) { $dataReader = $dataReader->withFilter($this->getFilter($sort)); $this->hasPreviousPage = $this->previousPageExist($dataReader, $sort); } $data = $this->readData($dataReader, $sort); - if ($this->pageToken?->isPrevious === true) { + if ($this->token?->isPrevious === true) { $data = $this->reverseData($data); } @@ -264,7 +264,7 @@ public function getSort(): ?Sort public function isOnFirstPage(): bool { - if ($this->pageToken === null) { + if ($this->token === null) { return true; } @@ -350,9 +350,9 @@ private function previousPageExist(ReadableDataInterface $dataReader, Sort $sort private function getFilter(Sort $sort): FilterInterface { /** - * @psalm-var PageToken $this->pageToken The code calling this method must ensure that page token is not null. + * @psalm-var PageToken $this->token The code calling this method must ensure that page token is not null. */ - $value = $this->pageToken->value; + $value = $this->token->value; [$field, $sorting] = $this->getFieldAndSortingFromSort($sort); $filter = $sorting === SORT_ASC ? new GreaterThan($field, $value) : new LessThan($field, $value); @@ -374,9 +374,9 @@ private function getFilter(Sort $sort): FilterInterface private function getReverseFilter(Sort $sort): FilterInterface { /** - * @psalm-var PageToken $this->pageToken The code calling this method must ensure that page token is not null. + * @psalm-var PageToken $this->token The code calling this method must ensure that page token is not null. */ - $value = $this->pageToken->value; + $value = $this->token->value; [$field, $sorting] = $this->getFieldAndSortingFromSort($sort); $filter = $sorting === SORT_ASC ? new LessThanOrEqual($field, $value) : new GreaterThanOrEqual($field, $value); diff --git a/src/Paginator/OffsetPaginator.php b/src/Paginator/OffsetPaginator.php index 47a94964..23254873 100644 --- a/src/Paginator/OffsetPaginator.php +++ b/src/Paginator/OffsetPaginator.php @@ -42,7 +42,7 @@ final class OffsetPaginator implements PaginatorInterface /** * @var PageToken Current page token */ - private PageToken $pageToken; + private PageToken $token; /** * @var int Maximum number of items per page. @@ -85,7 +85,7 @@ public function __construct(ReadableDataInterface $dataReader) } $this->dataReader = $dataReader; - $this->pageToken = PageToken::next('1'); + $this->token = PageToken::next('1'); } public function withToken(?PageToken $token): static @@ -120,13 +120,13 @@ public function withCurrentPage(int $page): self } $new = clone $this; - $new->pageToken = PageToken::next((string) $page); + $new->token = PageToken::next((string) $page); return $new; } public function getToken(): PageToken { - return $this->pageToken; + return $this->token; } public function getNextTokenValue(): ?string @@ -151,7 +151,7 @@ public function getPageSize(): int */ public function getCurrentPage(): int { - return (int) $this->pageToken->value; + return (int) $this->token->value; } public function getCurrentPageSize(): int @@ -251,7 +251,7 @@ public function readOne(): array|object|null public function isOnFirstPage(): bool { - return $this->pageToken->value === '1'; + return $this->token->value === '1'; } public function isOnLastPage(): bool From 4e15e6147f4938914b8f6ed70edaf5f0bdd6ee8c Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Wed, 24 Jan 2024 15:30:07 +0300 Subject: [PATCH 07/11] improve --- CHANGELOG.md | 5 +- src/Paginator/KeysetPaginator.php | 12 ++-- src/Paginator/OffsetPaginator.php | 8 +-- src/Paginator/PaginatorInterface.php | 8 +-- tests/Paginator/KeysetPaginatorTest.php | 76 ++++++++++++------------ tests/Paginator/OffsetPaginatorTest.php | 10 ++-- tests/Paginator/PageTokenAssertTrait.php | 27 +++++++++ 7 files changed, 88 insertions(+), 58 deletions(-) create mode 100644 tests/Paginator/PageTokenAssertTrait.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ab8630a..92af2b06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,10 +12,9 @@ - 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::isSortable()` and `PaginatorInterface::withSort()` (@vjik) -- Chg #159: Rename `PaginatorInterface` methods: `getNextPageToken()` to `getNextTokenValue()` - and `getPreviousPageToken()` to `getPreviousTokenValue()` (@vjik) - Chg #159: Replace `PaginatorInterface` methods `withNextPageToken()` and `withPreviousPageToken` to - single method `withToken()`, and add `getToken()` method. These methods are used new `PageToken` class (@vjik) + single method `withToken()`, `getNextPageToken()` to `getNextToken()`, `getPreviousPageToken()` + to `getPreviousToken()`, and add `getToken()` method. These methods are used new `PageToken` class (@vjik) ## 1.0.1 January 25, 2023 diff --git a/src/Paginator/KeysetPaginator.php b/src/Paginator/KeysetPaginator.php index 9c7b7510..512d6c2c 100644 --- a/src/Paginator/KeysetPaginator.php +++ b/src/Paginator/KeysetPaginator.php @@ -235,14 +235,18 @@ public function getCurrentPageSize(): int return count($this->readCache); } - public function getPreviousTokenValue(): ?string + public function getPreviousToken(): ?PageToken { - return $this->isOnFirstPage() ? null : $this->currentFirstValue; + return $this->isOnFirstPage() + ? null + : ($this->currentFirstValue === null ? null : PageToken::previous($this->currentFirstValue)); } - public function getNextTokenValue(): ?string + public function getNextToken(): ?PageToken { - return $this->isOnLastPage() ? null : $this->currentLastValue; + return $this->isOnLastPage() + ? null + : ($this->currentLastValue === null ? null : PageToken::next($this->currentLastValue)); } public function isSortable(): bool diff --git a/src/Paginator/OffsetPaginator.php b/src/Paginator/OffsetPaginator.php index 23254873..97a595c0 100644 --- a/src/Paginator/OffsetPaginator.php +++ b/src/Paginator/OffsetPaginator.php @@ -129,14 +129,14 @@ public function getToken(): PageToken return $this->token; } - public function getNextTokenValue(): ?string + public function getNextToken(): ?PageToken { - return $this->isOnLastPage() ? null : (string) ($this->getCurrentPage() + 1); + return $this->isOnLastPage() ? null : PageToken::next((string) ($this->getCurrentPage() + 1)); } - public function getPreviousTokenValue(): ?string + public function getPreviousToken(): ?PageToken { - return $this->isOnFirstPage() ? null : (string) ($this->getCurrentPage() - 1); + return $this->isOnFirstPage() ? null : PageToken::next((string) ($this->getCurrentPage() - 1)); } public function getPageSize(): int diff --git a/src/Paginator/PaginatorInterface.php b/src/Paginator/PaginatorInterface.php index 1dfa3d99..65574fe1 100644 --- a/src/Paginator/PaginatorInterface.php +++ b/src/Paginator/PaginatorInterface.php @@ -55,16 +55,16 @@ public function getToken(): ?PageToken; /** * Get token for the next page. * - * @return string|null Token for the next page. `null` if current page is last. + * @return PageToken|null Page token for the next page. `null` if current page is last. */ - public function getNextTokenValue(): ?string; + public function getNextToken(): ?PageToken; /** * Get token for the previous page. * - * @return string|null Token for the previous page. `null` if current page is first. + * @return PageToken|null Page token for the previous page. `null` if current page is first. */ - public function getPreviousTokenValue(): ?string; + public function getPreviousToken(): ?PageToken; /** * Get maximum number of items per page. diff --git a/tests/Paginator/KeysetPaginatorTest.php b/tests/Paginator/KeysetPaginatorTest.php index f74837e4..57b820e8 100644 --- a/tests/Paginator/KeysetPaginatorTest.php +++ b/tests/Paginator/KeysetPaginatorTest.php @@ -35,6 +35,8 @@ final class KeysetPaginatorTest extends Testcase { + use PageTokenAssertTrait; + private const ITEM_1 = [ 'id' => 1, 'name' => 'Codename Boris', @@ -215,8 +217,7 @@ public function testReadFirstPage(): void $expected = self::getDataSet([0, 1]); $this->assertSame($expected, $this->iterableToArray($paginator->read())); - $last = end($expected); - $this->assertSame((string)$last['id'], $paginator->getNextTokenValue()); + $this->assertPageToken((string) end($expected)['id'], false, $paginator->getNextToken()); $this->assertTrue($paginator->isOnFirstPage()); } @@ -233,7 +234,7 @@ public function testReadObjectsWithPublicProperties(): void $paginator = (new KeysetPaginator($dataReader))->withPageSize(2); $this->assertSame([$data[0], $data[1]], $this->iterableToArray($paginator->read())); - $this->assertSame((string)$data[1]->id, $paginator->getNextTokenValue()); + $this->assertPageToken((string) $data[1]->id, false, $paginator->getNextToken()); $this->assertTrue($paginator->isOnFirstPage()); } @@ -259,7 +260,7 @@ public function testReadObjectsWithGetters(string $orderByField, string $getter) $paginator = (new KeysetPaginator($dataReader))->withPageSize(2); $this->assertSame([$data[0], $data[1]], $this->iterableToArray($paginator->read())); - $this->assertSame((string)$data[1]->$getter(), $paginator->getNextTokenValue()); + $this->assertPageToken((string) $data[1]->$getter(), false, $paginator->getNextToken()); $this->assertTrue($paginator->isOnFirstPage()); } @@ -277,8 +278,7 @@ public function testReadSecondPage(): void $expected = self::getDataSet([2, 3]); $this->assertSame($expected, array_values((array) $paginator->read())); - $last = end($expected); - $this->assertSame((string)$last['id'], $paginator->getNextTokenValue()); + $this->assertPageToken((string) end($expected)['id'], false, $paginator->getNextToken()); } public function testReadSecondPageOrderedByName(): void @@ -293,8 +293,7 @@ public function testReadSecondPageOrderedByName(): void $expected = self::getDataSet([2, 0]); $this->assertSame($expected, array_values($this->iterableToArray($paginator->read()))); - $last = end($expected); - $this->assertSame((string)$last['name'], $paginator->getNextTokenValue()); + $this->assertPageToken((string) end($expected)['name'], false, $paginator->getNextToken()); } public static function dataReadOne(): array @@ -342,10 +341,18 @@ public function testBackwardPagination(): void $read = array_values($this->iterableToArray($paginator->read())); $this->assertSame($expected, $read); - $first = reset($expected); - $last = end($expected); - $this->assertSame((string)$last['id'], $paginator->getNextTokenValue(), 'Last value fail!'); - $this->assertSame((string)$first['id'], $paginator->getPreviousTokenValue(), 'First value fail!'); + $this->assertPageToken( + (string) end($expected)['id'], + false, + $paginator->getNextToken(), + 'Last value fail!', + ); + $this->assertPageToken( + (string) reset($expected)['id'], + true, + $paginator->getPreviousToken(), + 'First value fail!', + ); } public function testForwardAndBackwardPagination(): void @@ -360,24 +367,19 @@ public function testForwardAndBackwardPagination(): void $read = array_values($this->iterableToArray($paginator->read())); $this->assertSame($expected, $read); - - $first = reset($expected); - $last = end($expected); - - $this->assertSame((string)$last['id'], $paginator->getNextTokenValue(), 'Last value fail!'); - $this->assertSame((string)$first['id'], $paginator->getPreviousTokenValue(), 'First value fail!'); + $this->assertPageToken((string) end($expected)['id'], false, $paginator->getNextToken()); + $this->assertPageToken((string) reset($expected)['id'], true, $paginator->getPreviousToken()); $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withToken(PageToken::previous($paginator->getPreviousTokenValue())); + ->withToken(PageToken::previous($paginator->getPreviousToken()->value)); $expected = self::getDataSet([0, 1]); $read = array_values($this->iterableToArray($paginator->read())); $this->assertSame($expected, $read); - $last = end($expected); - $this->assertSame((string)$last['id'], $paginator->getNextTokenValue(), 'Last value fail!'); - $this->assertNull($paginator->getPreviousTokenValue(), 'First value fail!'); + $this->assertPageToken((string) end($expected)['id'], false, $paginator->getNextToken(), 'Last value fail!'); + $this->assertNull($paginator->getPreviousToken(), 'First value fail!'); } public function testIsOnFirstPage(): void @@ -505,45 +507,41 @@ public function testTokenResults(): void $sort = Sort::only(['id'])->withOrderString('id'); $dataReader = (new IterableDataReader(self::getDataSet()))->withSort($sort); $paginator = (new KeysetPaginator($dataReader))->withPageSize(2); - $this->assertNotNull($paginator->getNextTokenValue()); + $this->assertNotNull($paginator->getNextToken()); $paginator = $paginator->withToken(PageToken::previous('1')); try { - $paginator->getNextTokenValue(); + $paginator->getNextToken(); $this->fail(); } catch (RuntimeException) { $this->assertTrue(true); } - $this->assertNull($paginator->getPreviousTokenValue()); + $this->assertNull($paginator->getPreviousToken()); $paginator = $paginator->withToken(PageToken::previous('2')); - $this->assertNotNull($paginator->getNextTokenValue()); - $this->assertSame('1', $paginator->getNextTokenValue()); - $this->assertNull($paginator->getPreviousTokenValue()); + $this->assertPageToken('1', false, $paginator->getNextToken()); + $this->assertNull($paginator->getPreviousToken()); $paginator = $paginator->withToken(PageToken::previous('3')); - $this->assertNotNull($paginator->getNextTokenValue()); - $this->assertSame('2', $paginator->getNextTokenValue()); - $this->assertNull($paginator->getPreviousTokenValue()); + $this->assertPageToken('2', false, $paginator->getNextToken()); + $this->assertNull($paginator->getPreviousToken()); $paginator = $paginator->withToken(PageToken::next('6')); try { - $paginator->getPreviousTokenValue(); + $paginator->getPreviousToken(); $this->fail(); } catch (RuntimeException) { $this->assertTrue(true); } - $this->assertNull($paginator->getNextTokenValue()); + $this->assertNull($paginator->getNextToken()); $paginator = $paginator->withToken(PageToken::next('5')); - $this->assertNotNull($paginator->getPreviousTokenValue()); - $this->assertSame('6', $paginator->getPreviousTokenValue()); - $this->assertNull($paginator->getNextTokenValue()); + $this->assertPageToken('6', true, $paginator->getPreviousToken()); + $this->assertNull($paginator->getNextToken()); $paginator = $paginator->withToken(PageToken::next('4')); - $this->assertNull($paginator->getNextTokenValue()); - $this->assertNotNull($paginator->getPreviousTokenValue()); - $this->assertSame('5', $paginator->getPreviousTokenValue()); + $this->assertNull($paginator->getNextToken()); + $this->assertPageToken('5', true, $paginator->getPreviousToken()); } public function testDefaultPageSize(): void diff --git a/tests/Paginator/OffsetPaginatorTest.php b/tests/Paginator/OffsetPaginatorTest.php index 372f7818..24a47f8c 100644 --- a/tests/Paginator/OffsetPaginatorTest.php +++ b/tests/Paginator/OffsetPaginatorTest.php @@ -22,6 +22,8 @@ final class OffsetPaginatorTest extends TestCase { + use PageTokenAssertTrait; + private const ITEM_1 = [ 'id' => 1, 'name' => 'Codename Boris', @@ -489,11 +491,11 @@ public function testNextPageToken(): void $dataReader = new IterableDataReader(self::DEFAULT_DATASET); $paginator = (new OffsetPaginator($dataReader))->withToken(PageToken::next('1')); - $this->assertNull($paginator->getNextTokenValue()); + $this->assertNull($paginator->getNextToken()); $paginator = $paginator->withPageSize(2); - $this->assertSame('2', $paginator->getNextTokenValue()); + $this->assertPageToken('2', false, $paginator->getNextToken()); } public function testPreviousPageToken(): void @@ -501,11 +503,11 @@ public function testPreviousPageToken(): void $dataReader = new IterableDataReader(self::DEFAULT_DATASET); $paginator = (new OffsetPaginator($dataReader))->withToken(PageToken::previous('1')); - $this->assertNull($paginator->getPreviousTokenValue()); + $this->assertNull($paginator->getPreviousToken()); $paginator = $paginator->withToken(PageToken::previous('5')); - $this->assertSame('4', $paginator->getPreviousTokenValue()); + $this->assertPageToken('4', false, $paginator->getPreviousToken()); } public function testImmutability(): void diff --git a/tests/Paginator/PageTokenAssertTrait.php b/tests/Paginator/PageTokenAssertTrait.php new file mode 100644 index 00000000..7f395a1d --- /dev/null +++ b/tests/Paginator/PageTokenAssertTrait.php @@ -0,0 +1,27 @@ +value, new IsIdentical($expectedValue), $message); + static::assertThat($pageToken->isPrevious, new IsIdentical($expectedIsPrevious), $message); + } +} From b1408a6c59d48d3954d3db23e68e1057eaf8c76d Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Thu, 25 Jan 2024 09:51:21 +0300 Subject: [PATCH 08/11] Update CHANGELOG.md Co-authored-by: Alexander Makarov --- CHANGELOG.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92af2b06..29d7b510 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,9 +12,8 @@ - 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::isSortable()` and `PaginatorInterface::withSort()` (@vjik) -- Chg #159: Replace `PaginatorInterface` methods `withNextPageToken()` and `withPreviousPageToken` to - single method `withToken()`, `getNextPageToken()` to `getNextToken()`, `getPreviousPageToken()` - to `getPreviousToken()`, and add `getToken()` method. These methods are used new `PageToken` class (@vjik) +- Chg #159: Replace `withNextPageToken()` and `withPreviousPageToken()` of `PaginatorInterface` with `withToken()`, `getNextPageToken()` with `getNextToken()`, `getPreviousPageToken()` + with `getPreviousToken()`, and add `getToken()`. These methods use new `PageToken` class (@vjik) ## 1.0.1 January 25, 2023 From 0e1a6f9c5d7ddcc89fdab052674255df571f86a6 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Thu, 25 Jan 2024 09:51:34 +0300 Subject: [PATCH 09/11] Update src/Paginator/PageToken.php Co-authored-by: Alexander Makarov --- src/Paginator/PageToken.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Paginator/PageToken.php b/src/Paginator/PageToken.php index 47a34a75..f1f3d770 100644 --- a/src/Paginator/PageToken.php +++ b/src/Paginator/PageToken.php @@ -6,7 +6,7 @@ final class PageToken { - public function __construct( + private function __construct( public readonly string $value, public readonly bool $isPrevious, ) { From b713b7389b8d5a985c6326f52823090ee821cfed Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Thu, 25 Jan 2024 09:56:30 +0300 Subject: [PATCH 10/11] fix --- tests/Paginator/KeysetPaginatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Paginator/KeysetPaginatorTest.php b/tests/Paginator/KeysetPaginatorTest.php index 57b820e8..8b474ead 100644 --- a/tests/Paginator/KeysetPaginatorTest.php +++ b/tests/Paginator/KeysetPaginatorTest.php @@ -273,7 +273,7 @@ public function testReadSecondPage(): void $paginator = (new KeysetPaginator($dataReader)) ->withPageSize(2) - ->withToken(new PageToken('2', false)); + ->withToken(PageToken::next('2')); $expected = self::getDataSet([2, 3]); From e95fc8c4279987dc77179c7199d2e8e30e8ff74a Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Thu, 25 Jan 2024 09:57:47 +0300 Subject: [PATCH 11/11] fix --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29d7b510..2ebc88f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,9 @@ - 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::isSortable()` and `PaginatorInterface::withSort()` (@vjik) -- Chg #159: Replace `withNextPageToken()` and `withPreviousPageToken()` of `PaginatorInterface` with `withToken()`, `getNextPageToken()` with `getNextToken()`, `getPreviousPageToken()` - with `getPreviousToken()`, and add `getToken()`. These methods use new `PageToken` class (@vjik) +- Chg #159: Replace `withNextPageToken()` and `withPreviousPageToken()` of `PaginatorInterface` with `withToken()`, + `getNextPageToken()` with `getNextToken()`, `getPreviousPageToken()` with `getPreviousToken()`, and add `getToken()`. + These methods use new `PageToken` class (@vjik) ## 1.0.1 January 25, 2023