diff --git a/forms/gridfield/GridFieldPaginator.php b/forms/gridfield/GridFieldPaginator.php index cec0fa668..4f4a0f1ed 100755 --- a/forms/gridfield/GridFieldPaginator.php +++ b/forms/gridfield/GridFieldPaginator.php @@ -131,7 +131,6 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu * @return SS_List */ public function getManipulatedData(GridField $gridField, SS_List $dataList) { - if(!$this->checkDataType($dataList)) return $dataList; $state = $this->getGridPagerState($gridField); @@ -139,11 +138,18 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu // Update item count prior to filter. GridFieldPageCount will rely on this value $this->totalItems = $dataList->count(); + $startRow = $this->itemsPerPage * ($state->currentPage - 1); + + // Prevent visiting a page with an offset higher than the total number of items + if($startRow >= $this->totalItems) { + $state->currentPage = 1; + $startRow = 0; + } + if(!($dataList instanceof SS_Limitable) || ($dataList instanceof UnsavedRelationList)) { return $dataList; } - $startRow = $this->itemsPerPage * ($state->currentPage - 1); return $dataList->limit((int)$this->itemsPerPage, (int)$startRow); } diff --git a/tests/forms/gridfield/GridFieldPaginatorTest.php b/tests/forms/gridfield/GridFieldPaginatorTest.php index 9cb0276cd..4d9c699de 100644 --- a/tests/forms/gridfield/GridFieldPaginatorTest.php +++ b/tests/forms/gridfield/GridFieldPaginatorTest.php @@ -51,4 +51,22 @@ class GridFieldPaginatorTest extends FunctionalTest { // Check that there is still 'View 1 - 4 of 4' part on the left of the paginator $this->assertEquals(2, count($content->getBySelector('.pagination-records-number'))); } + + public function testPaginationAvoidsIllegalOffsets() { + $grid = $this->gridField; + $total = $this->list->count(); + $perPage = $grid->getConfig()->getComponentByType('GridFieldPaginator')->getItemsPerPage(); + // Get the last page that will contain results + $lastPage = ceil($total / $perPage); + // Set the paginator state to point to an 'invalid' page + $grid->State->GridFieldPaginator->currentPage = $lastPage + 1; + + // Get the paginated list + $list = $grid->getManipulatedList(); + + // Assert that the paginator state has been corrected and the list contains items + $this->assertEquals(1, $grid->State->GridFieldPaginator->currentPage); + $this->assertEquals($perPage, $list->count()); + } + }