diff --git a/core/PaginatedList.php b/core/PaginatedList.php index 9addc8e48de..5886182eb79 100644 --- a/core/PaginatedList.php +++ b/core/PaginatedList.php @@ -13,6 +13,7 @@ class PaginatedList extends SS_ListDecorator { protected $pageLength = 10; protected $pageStart; protected $totalItems; + protected $limitItems = true; /** * Constructs a new paginated list instance around a list. @@ -144,13 +145,39 @@ public function setPaginationFromQuery(SQLQuery $query) { } } + /** + * Returns whether or not the underlying list is limited to the current + * pagination range when iterating. + * + * By default the limit method will be called on the underlying list to + * extract the subset for the current page. In some situations, if the list + * is custom generated and already paginated you don't want to additionally + * limit the list. You can use {@link setLimitItems} to control this. + * + * @return bool + */ + public function getLimitItems() { + return $this->limitItems; + } + + /** + * @param bool $limit + */ + public function setLimitItems($limit) { + $this->limitItems = (bool) $limit; + } + /** * @return IteratorIterator */ public function getIterator() { - return new IteratorIterator( - $this->list->limit($this->pageLength, $this->getPageStart()) - ); + if($this->limitItems) { + return new IteratorIterator( + $this->list->limit($this->pageLength, $this->getPageStart()) + ); + } else { + return new IteratorIterator($this->list); + } } /** diff --git a/docs/en/howto/pagination.md b/docs/en/howto/pagination.md index 195b6adeeef..cf61691eadb 100644 --- a/docs/en/howto/pagination.md +++ b/docs/en/howto/pagination.md @@ -6,7 +6,7 @@ care of fetching a sub-set of the total list and presenting it to the template. In order to create a paginated list, you can create a method on your controller that first creates a `DataList` that will return all pages, and then wraps it -in a `[api:PaginatedSet]` object. The `PaginatedList` object is also passed the +in a `[api:PaginatedList]` object. The `PaginatedList` object is also passed the HTTP request object so it can read the current page information from the "?start=" GET var. @@ -26,7 +26,7 @@ information. Now all that remains is to render this list into a template, along with pagination controls. There are two ways to generate pagination controls: -`[api:PaginatedSet->Pages()]` and `[api:PaginatedSet->PaginationSummary()]`. In +`[api:PaginatedList->Pages()]` and `[api:PaginatedList->PaginationSummary()]`. In this example we will use `PaginationSummary()`. The first step is to simply list the objects in the template: @@ -63,4 +63,12 @@ controls below this so the user can switch between pages: <% end_if %> If there is more than one page, this block will render a set of pagination -controls in the form `[1] ... [3] [4] [[5]] [6] [7] ... [10]`. \ No newline at end of file +controls in the form `[1] ... [3] [4] [[5]] [6] [7] ... [10]`. + +## Paginating Custom Lists + +In some situations where you are generating the list yourself, the underlying +list will already contain only the items that you wish to display on the current +page. In this situation the automatic limiting done by `[api:PaginatedList]` +will break the pagination. You can disable automatic limiting using the +`[api:PaginatedList->setLimitItems()]` method when using custom lists. diff --git a/tests/model/PaginatedListTest.php b/tests/model/PaginatedListTest.php index 64a1f7c00f6..0bed6b70cdb 100644 --- a/tests/model/PaginatedListTest.php +++ b/tests/model/PaginatedListTest.php @@ -135,6 +135,17 @@ public function testPaginationSummary() { $this->assertDOSEquals($expect, $list->PaginationSummary(4)); } + public function testLimitItems() { + $list = new ArrayList(range(1, 50)); + $list = new PaginatedList($list); + + $list->setCurrentPage(3); + $this->assertEquals(10, count($list->getIterator()->getInnerIterator())); + + $list->setLimitItems(false); + $this->assertEquals(50, count($list->getIterator()->getInnerIterator())); + } + public function testCurrentPage() { $list = new PaginatedList(new ArrayList()); $list->setTotalItems(50);