/forms/gridfield/GridFieldPaginator.php

https://github.com/silverstripe-scienceninjas/sapphire · PHP · 214 lines · 110 code · 29 blank · 75 comment · 26 complexity · e0ed006b09a0c3477e5861fa2294eabb MD5 · raw file

  1. <?php
  2. /**
  3. * GridFieldPaginator paginates the gridfields list and adds controlls to the
  4. * bottom of the gridfield.
  5. *
  6. * @package framework
  7. * @subpackage fields-relational
  8. */
  9. class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipulator, GridField_ActionProvider {
  10. /**
  11. *
  12. * @var int
  13. */
  14. protected $itemsPerPage = 15;
  15. /**
  16. * Which template to use for rendering
  17. *
  18. * @var string
  19. */
  20. protected $itemClass = 'GridFieldPaginator_Row';
  21. /**
  22. * See {@link setThrowExceptionOnBadDataType()}
  23. */
  24. protected $throwExceptionOnBadDataType = true;
  25. /**
  26. *
  27. * @param int $itemsPerPage - How many items should be displayed per page
  28. */
  29. public function __construct($itemsPerPage=null) {
  30. if($itemsPerPage) $this->itemsPerPage = $itemsPerPage;
  31. }
  32. /**
  33. * Determine what happens when this component is used with a list that isn't {@link SS_Filterable}.
  34. *
  35. * - true: An exception is thrown
  36. * - false: This component will be ignored - it won't make any changes to the GridField.
  37. *
  38. * By default, this is set to true so that it's clearer what's happening, but the predefined
  39. * {@link GridFieldConfig} subclasses set this to false for flexibility.
  40. */
  41. public function setThrowExceptionOnBadDataType($throwExceptionOnBadDataType) {
  42. $this->throwExceptionOnBadDataType = $throwExceptionOnBadDataType;
  43. }
  44. /**
  45. * See {@link setThrowExceptionOnBadDataType()}
  46. */
  47. public function getThrowExceptionOnBadDataType() {
  48. return $this->throwExceptionOnBadDataType;
  49. }
  50. /**
  51. * Check that this dataList is of the right data type.
  52. * Returns false if it's a bad data type, and if appropriate, throws an exception.
  53. */
  54. protected function checkDataType($dataList) {
  55. if($dataList instanceof SS_Limitable) {
  56. return true;
  57. } else {
  58. if($this->throwExceptionOnBadDataType) {
  59. throw new LogicException(get_class($this) . " expects an SS_Limitable list to be passed to the GridField.");
  60. }
  61. return false;
  62. }
  63. }
  64. /**
  65. *
  66. * @param GridField $gridField
  67. * @return array
  68. */
  69. public function getActions($gridField) {
  70. if(!$this->checkDataType($gridField->getList())) return;
  71. return array('paginate');
  72. }
  73. /**
  74. *
  75. * @param GridField $gridField
  76. * @param string $actionName
  77. * @param string $arguments
  78. * @param array $data
  79. * @return void
  80. */
  81. public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
  82. if(!$this->checkDataType($gridField->getList())) return;
  83. if($actionName !== 'paginate') {
  84. return;
  85. }
  86. $state = $gridField->State->GridFieldPaginator;
  87. $state->currentPage = (int)$arguments;
  88. }
  89. protected $totalItems = 0;
  90. /**
  91. *
  92. * @param GridField $gridField
  93. * @param SS_List $dataList
  94. * @return SS_List
  95. */
  96. public function getManipulatedData(GridField $gridField, SS_List $dataList) {
  97. if(!$this->checkDataType($dataList)) return $dataList;
  98. $this->totalItems = $gridField->getList()->count();
  99. $state = $gridField->State->GridFieldPaginator;
  100. if(!is_int($state->currentPage)) {
  101. $state->currentPage = 1;
  102. }
  103. if(!($dataList instanceof SS_Limitable)) {
  104. return $dataList;
  105. }
  106. if(!$state->currentPage) {
  107. return $dataList->limit((int)$this->itemsPerPage);
  108. }
  109. $startRow = $this->itemsPerPage * ($state->currentPage - 1);
  110. return $dataList->limit((int)$this->itemsPerPage, (int)$startRow);
  111. }
  112. /**
  113. *
  114. * @param GridField $gridField
  115. * @return array
  116. */
  117. public function getHTMLFragments($gridField) {
  118. if(!$this->checkDataType($gridField->getList())) return;
  119. $state = $gridField->State->GridFieldPaginator;
  120. if(!is_int($state->currentPage))
  121. $state->currentPage = 1;
  122. // Figure out which page and record range we're on
  123. $totalRows = $this->totalItems;
  124. if(!$totalRows) return array();
  125. $totalPages = ceil($totalRows/$this->itemsPerPage);
  126. if($totalPages == 0)
  127. $totalPages = 1;
  128. $firstShownRecord = ($state->currentPage - 1) * $this->itemsPerPage + 1;
  129. if($firstShownRecord > $totalRows)
  130. $firstShownRecord = $totalRows;
  131. $lastShownRecord = $state->currentPage * $this->itemsPerPage;
  132. if($lastShownRecord > $totalRows)
  133. $lastShownRecord = $totalRows;
  134. // First page button
  135. $firstPage = new GridField_FormAction($gridField, 'pagination_first', 'First', 'paginate', 1);
  136. $firstPage->addExtraClass('ss-gridfield-firstpage');
  137. if($state->currentPage == 1)
  138. $firstPage = $firstPage->performDisabledTransformation();
  139. // Previous page button
  140. $previousPageNum = $state->currentPage <= 1 ? 1 : $state->currentPage - 1;
  141. $previousPage = new GridField_FormAction($gridField, 'pagination_prev', 'Previous', 'paginate', $previousPageNum);
  142. $previousPage->addExtraClass('ss-gridfield-previouspage');
  143. if($state->currentPage == 1)
  144. $previousPage = $previousPage->performDisabledTransformation();
  145. // Next page button
  146. $nextPageNum = $state->currentPage >= $totalPages ? $totalPages : $state->currentPage + 1;
  147. $nextPage = new GridField_FormAction($gridField, 'pagination_next', 'Next', 'paginate', $nextPageNum);
  148. $nextPage->addExtraClass('ss-gridfield-nextpage');
  149. if($state->currentPage == $totalPages)
  150. $nextPage = $nextPage->performDisabledTransformation();
  151. // Last page button
  152. $lastPage = new GridField_FormAction($gridField, 'pagination_last', 'Last', 'paginate', $totalPages);
  153. $lastPage->addExtraClass('ss-gridfield-lastpage');
  154. if($state->currentPage == $totalPages)
  155. $lastPage = $lastPage->performDisabledTransformation();
  156. // Render in template
  157. $forTemplate = new ArrayData(array(
  158. 'FirstPage' => $firstPage,
  159. 'PreviousPage' => $previousPage,
  160. 'CurrentPageNum' => $state->currentPage,
  161. 'NumPages' => $totalPages,
  162. 'NextPage' => $nextPage,
  163. 'LastPage' => $lastPage,
  164. 'FirstShownRecord' => $firstShownRecord,
  165. 'LastShownRecord' => $lastShownRecord,
  166. 'NumRecords' => $totalRows
  167. ));
  168. return array(
  169. 'footer' => $forTemplate->renderWith('GridFieldPaginator_Row', array('Colspan'=>count($gridField->getColumns()))),
  170. );
  171. }
  172. /**
  173. * @param Int
  174. */
  175. public function setItemsPerPage($num) {
  176. $this->itemsPerPage = $num;
  177. return $this;
  178. }
  179. /**
  180. * @return Int
  181. */
  182. public function getItemsPerPage() {
  183. return $this->itemsPerPage;
  184. }
  185. }