From 67728476ecff8d45cbe09ac4dd7ff25fc4449816 Mon Sep 17 00:00:00 2001 From: Bizley Date: Sun, 20 Sep 2020 23:18:52 +0200 Subject: [PATCH] Fix #16418: Fixed `yii\data\Pagination::getLinks()` to return links to the first and the last pages regardless of the current page --- framework/CHANGELOG.md | 2 +- framework/data/Pagination.php | 17 +- tests/framework/data/PaginationTest.php | 321 +++++++++++++++++++++++- 3 files changed, 329 insertions(+), 11 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index ca6a0e46ab..92254999f4 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,7 +4,7 @@ Yii Framework 2 Change Log 2.0.39 under development ------------------------ -- no changes in this release. +- Bug #16418: Fixed `yii\data\Pagination::getLinks()` to return links to the first and the last pages regardless of the current page (ptz-nerf, bizley) 2.0.38 September 14, 2020 diff --git a/framework/data/Pagination.php b/framework/data/Pagination.php index 5006d9ea0b..32078b1c7e 100644 --- a/framework/data/Pagination.php +++ b/framework/data/Pagination.php @@ -319,16 +319,17 @@ class Pagination extends BaseObject implements Linkable { $currentPage = $this->getPage(); $pageCount = $this->getPageCount(); - $links = [ - Link::REL_SELF => $this->createUrl($currentPage, null, $absolute), - ]; - if ($currentPage > 0) { + + $links = [Link::REL_SELF => $this->createUrl($currentPage, null, $absolute)]; + if ($pageCount > 0) { $links[self::LINK_FIRST] = $this->createUrl(0, null, $absolute); - $links[self::LINK_PREV] = $this->createUrl($currentPage - 1, null, $absolute); - } - if ($currentPage < $pageCount - 1) { - $links[self::LINK_NEXT] = $this->createUrl($currentPage + 1, null, $absolute); $links[self::LINK_LAST] = $this->createUrl($pageCount - 1, null, $absolute); + if ($currentPage > 0) { + $links[self::LINK_PREV] = $this->createUrl($currentPage - 1, null, $absolute); + } + if ($currentPage < $pageCount - 1) { + $links[self::LINK_NEXT] = $this->createUrl($currentPage + 1, null, $absolute); + } } return $links; diff --git a/tests/framework/data/PaginationTest.php b/tests/framework/data/PaginationTest.php index 98bc9ecfbc..5f2d3488f8 100644 --- a/tests/framework/data/PaginationTest.php +++ b/tests/framework/data/PaginationTest.php @@ -8,6 +8,7 @@ namespace yiiunit\framework\data; use yii\data\Pagination; +use yii\web\Link; use yiiunit\TestCase; /** @@ -58,6 +59,13 @@ class PaginationTest extends TestCase '/index.php?r=item%2Flist&q=test&page=3&per-page=5', ['q' => 'test'], ], + [ + 1, + 10, + '/index.php?r=item%2Flist&page=2&per-page=10', + null, + true, + ], ]; } @@ -68,13 +76,14 @@ class PaginationTest extends TestCase * @param int $pageSize * @param string $expectedUrl * @param array $params + * @param bool $absolute */ - public function testCreateUrl($page, $pageSize, $expectedUrl, $params) + public function testCreateUrl($page, $pageSize, $expectedUrl, $params, $absolute = false) { $pagination = new Pagination(); $pagination->route = 'item/list'; $pagination->params = $params; - $this->assertEquals($expectedUrl, $pagination->createUrl($page, $pageSize)); + $this->assertEquals($expectedUrl, $pagination->createUrl($page, $pageSize, $absolute)); } /** @@ -105,4 +114,312 @@ class PaginationTest extends TestCase $pagination->setPage(999, false); $this->assertEquals(999, $pagination->getPage()); } + + public function dataProviderPageCount() + { + return [ + [0, 0, 0], + [0, 1, 1], + [-1, 0, 0], + [-1, 1, 1], + [1, -1, 0], + [1, 0, 0], + [1, 1, 1], + [10, 10, 1], + [10, 20, 2], + [2, 15, 8], + ]; + } + + /** + * @dataProvider dataProviderPageCount + * + * @param int $pageSize + * @param int $totalCount + * @param int $pageCount + */ + public function testPageCount($pageSize, $totalCount, $pageCount) + { + $pagination = new Pagination(); + $pagination->setPageSize($pageSize); + $pagination->totalCount = $totalCount; + + $this->assertEquals($pageCount, $pagination->getPageCount()); + } + + public function testGetDefaultPage() + { + $this->assertEquals(0, (new Pagination())->getPage()); + } + + public function dataProviderSetPage() + { + return [ + [null, false, 0, null], + [null, true, 0, null], + [0, false, 0, 0], + [0, true, 0, 0], + [-1, false, 0, 0], + [-1, true, 0, 0], + [1, false, 0, 1], + [1, true, 0, 0], + [2, false, 10, 2], + [2, true, 10, 0], + [2, false, 40, 2], + [2, true, 40, 1], + ]; + } + + /** + * @dataProvider dataProviderSetPage + * + * @param int|null $value + * @param bool $validate + * @param int $totalCount + * @param int $page + */ + public function testSetPage($value, $validate, $totalCount, $page) + { + $pagination = new Pagination(); + $pagination->totalCount = $totalCount; + $pagination->setPage($value, $validate); + + $this->assertEquals($page, $pagination->getPage()); + } + + public function dataProviderGetPageSize() + { + return [ + [[1, 50], 20], + [[], 20], + [[1], 20], + [['a' => 1, 50], 20], + [['a' => 1, 'b' => 50], 20], + [[2, 10], 10], + [[30, 100], 30], + ]; + } + + /** + * @dataProvider dataProviderGetPageSize + * + * @param array|bool $pageSizeLimit + * @param int $pageSize + */ + public function testGetPageSize($pageSizeLimit, $pageSize) + { + $pagination = new Pagination(); + $pagination->pageSizeLimit = $pageSizeLimit; + + $this->assertEquals($pageSize, $pagination->getPageSize()); + } + + public function dataProviderSetPageSize() + { + return [ + [null, false, false, 20], + [null, true, false, 20], + [null, false, [1, 50], 20], + [null, true, [1, 50], 20], + [1, false, false, 1], + [1, true, false, 1], + [1, false, [1, 50], 1], + [1, true, [1, 50], 1], + [10, false, [20, 50], 10], + [10, true, [20, 50], 20], + [40, false, [1, 20], 40], + [40, true, [1, 20], 20], + ]; + } + + /** + * @dataProvider dataProviderSetPageSize + * + * @param int|null $value + * @param bool $validate + * @param array|false $pageSizeLimit + * @param int $pageSize + */ + public function testSetPageSize($value, $validate, $pageSizeLimit, $pageSize) + { + $pagination = new Pagination(); + $pagination->pageSizeLimit = $pageSizeLimit; + $pagination->setPageSize($value, $validate); + + $this->assertEquals($pageSize, $pagination->getPageSize()); + } + + public function dataProviderGetOffset() + { + return [ + [0, 0, 0], + [0, 1, 0], + [1, 1, 1], + [1, 2, 2], + [10, 2, 20], + ]; + } + + /** + * @dataProvider dataProviderGetOffset + * + * @param int $pageSize + * @param int $page + * @param int $offset + */ + public function testGetOffset($pageSize, $page, $offset) + { + $pagination = new Pagination(); + $pagination->setPageSize($pageSize); + $pagination->setPage($page); + + $this->assertEquals($offset, $pagination->getOffset()); + } + + public function dataProviderGetLimit() + { + return [ + [0, -1], + [1, 1], + [2, 2], + ]; + } + + /** + * @dataProvider dataProviderGetLimit + * + * @param int $pageSize + * @param int $limit + */ + public function testGetLimit($pageSize, $limit) + { + $pagination = new Pagination(); + $pagination->setPageSize($pageSize); + + $this->assertEquals($limit, $pagination->getLimit()); + } + + public function dataProviderGetLinks() + { + return [ + [0, 0, 0, '/index.php?r=list&page=1&per-page=0', null, null, null, null], + [1, 0, 0, '/index.php?r=list&page=1&per-page=0', null, null, null, null], + [ + 0, + 0, + 1, + '/index.php?r=list&page=1&per-page=0', + '/index.php?r=list&page=1&per-page=0', + '/index.php?r=list&page=1&per-page=0', + null, + null, + ], + [ + 1, + 0, + 1, + '/index.php?r=list&page=1&per-page=0', + '/index.php?r=list&page=1&per-page=0', + '/index.php?r=list&page=1&per-page=0', + null, + null, + ], + [ + 0, + 1, + 1, + '/index.php?r=list&page=1&per-page=1', + '/index.php?r=list&page=1&per-page=1', + '/index.php?r=list&page=1&per-page=1', + null, + null, + ], + [ + 1, + 1, + 1, + '/index.php?r=list&page=1&per-page=1', + '/index.php?r=list&page=1&per-page=1', + '/index.php?r=list&page=1&per-page=1', + null, + null, + ], + [ + 0, + 5, + 10, + '/index.php?r=list&page=1&per-page=5', + '/index.php?r=list&page=1&per-page=5', + '/index.php?r=list&page=2&per-page=5', + null, + '/index.php?r=list&page=2&per-page=5', + ], + [ + 1, + 5, + 10, + '/index.php?r=list&page=2&per-page=5', + '/index.php?r=list&page=1&per-page=5', + '/index.php?r=list&page=2&per-page=5', + '/index.php?r=list&page=1&per-page=5', + null, + ], + [ + 1, + 5, + 15, + '/index.php?r=list&page=2&per-page=5', + '/index.php?r=list&page=1&per-page=5', + '/index.php?r=list&page=3&per-page=5', + '/index.php?r=list&page=1&per-page=5', + '/index.php?r=list&page=3&per-page=5', + ], + ]; + } + + /** + * @dataProvider dataProviderGetLinks + * + * @param int $page + * @param int $pageSize + * @param int $totalCount + * @param string $self + * @param string|null $first + * @param string|null $last + * @param string|null $prev + * @param string|null $next + */ + public function testGetLinks($page, $pageSize, $totalCount, $self, $first, $last, $prev, $next) + { + $pagination = new Pagination(); + $pagination->totalCount = $totalCount; + $pagination->route = 'list'; + $pagination->setPageSize($pageSize); + $pagination->setPage($page, true); + + $links = $pagination->getLinks(); + + $this->assertSame($self, $links[Link::REL_SELF]); + + if ($first) { + $this->assertSame($first, $links[Pagination::LINK_FIRST]); + } else { + $this->assertArrayNotHasKey(Pagination::LINK_FIRST, $links); + } + if ($last) { + $this->assertSame($last, $links[Pagination::LINK_LAST]); + } else { + $this->assertArrayNotHasKey(Pagination::LINK_LAST, $links); + } + if ($prev) { + $this->assertSame($prev, $links[Pagination::LINK_PREV]); + } else { + $this->assertArrayNotHasKey(Pagination::LINK_PREV, $links); + } + if ($next) { + $this->assertSame($next, $links[Pagination::LINK_NEXT]); + } else { + $this->assertArrayNotHasKey(Pagination::LINK_NEXT, $links); + } + } }