Open Monograph Press  1.1
 All Classes Namespaces Functions Variables Groups Pages
PagingFeature.inc.php
1 <?php
2 
17 import('lib.pkp.classes.controllers.grid.feature.GridFeature');
18 
19 class PagingFeature extends GridFeature{
20 
22  private $_itemIterator;
23 
27  function PagingFeature() {
28  parent::GridFeature('paging');
29  }
30 
31  //
32  // Getters and setters.
33  //
38  function getItemIterator() {
39  return $this->_itemIterator;
40  }
41 
42 
43  //
44  // Extended methods from GridFeature.
45  //
49  function getJSClass() {
50  return '$.pkp.classes.features.PagingFeature';
51  }
52 
58  function setOptions($request, $grid) {
59  // Get the default items per page setting value.
60  $rangeInfo = PKPHandler::getRangeInfo($request, $grid->getId());
61  $defaultItemsPerPage = $rangeInfo->getCount();
62 
63  // Check for a component level items per page setting.
64  $componentItemsPerPage = $request->getUserVar($this->_getItemsPerPageParamName($grid->getId()));
65  if ($componentItemsPerPage) {
66  $currentItemsPerPage = $componentItemsPerPage;
67  } else {
68  $currentItemsPerPage = $defaultItemsPerPage;
69  }
70 
71  $iterator = $this->getItemIterator();
72 
73  $options = array(
74  'itemsPerPageParamName' => $this->_getItemsPerPageParamName($grid->getId()),
75  'defaultItemsPerPage' => $defaultItemsPerPage,
76  'currentItemsPerPage' => $currentItemsPerPage,
77  'itemsTotal' => $iterator->getCount(),
78  'pageParamName' => PKPHandler::getPageParamName($grid->getId()),
79  'currentPage' => $iterator->getPage()
80  );
81 
82  $this->addOptions($options);
83 
84  parent::setOptions($request, $grid);
85  }
86 
92  function fetchUIElements($request, $grid) {
93  $iterator = $this->getItemIterator();
94  $options = $this->getOptions();
95 
96  $templateMgr = TemplateManager::getManager($request);
97  $templateMgr->assign('iterator', $iterator);
98  $templateMgr->assign('currentItemsPerPage', $options['currentItemsPerPage']);
99  $templateMgr->assign('grid', $grid);
100 
101  return array('pagingMarkup' => $templateMgr->fetch('controllers/grid/feature/gridPaging.tpl'));
102  }
103 
104 
105  //
106  // Hooks implementation.
107  //
108  /*
109  * @see GridFeature::gridInitialize()
110  * The feature will know about the current filter
111  * value so it can request grid refreshes keeping
112  * the filter.
113  * @param $args array
114  */
115  function getGridDataElements($args) {
116  $filter = $args['filter'];
117 
118  if (is_array($filter) && !empty($filter)) {
119  $this->addOptions(array('filter' => json_encode($filter)));
120  }
121  }
122 
123 
128  function setGridDataElements($args) {
129  $grid =& $args['grid'];
130  $data =& $args['data'];
132  if (is_array($data)) {
133  import('lib.pkp.classes.core.ArrayItemIterator');
134  $request = Application::getRequest();
135  $rangeInfo = $grid->getGridRangeInfo($request, $grid->getId());
136  $itemIterator = new ArrayItemIterator($data, $rangeInfo->getPage(), $rangeInfo->getCount());
137  $this->_itemIterator = $itemIterator;
138  $data = $itemIterator->toArray();
139  } elseif (is_a($data, 'ItemIterator')) {
140  $this->_itemIterator = $data;
141  }
142  }
143 
148  function getRequestArgs($args) {
149  $grid = $args['grid'];
150  $requestArgs =& $args['requestArgs'];
152  // Add paging info so grid actions will not loose paging context.
153  // Only works if grid link actions use the getRequestArgs
154  // returned content.
155  $request = Application::getRequest();
156  $rangeInfo = $grid->getGridRangeInfo($request, $grid->getId());
157  $requestArgs[GridHandler::getPageParamName($grid->getId())] = $rangeInfo->getPage();
158  $requestArgs[$this->_getItemsPerPageParamName($grid->getId())] = $rangeInfo->getCount();
159  }
160 
165  function getGridRangeInfo($args) {
166  $request = $args['request'];
167  $grid = $args['grid'];
168  $rangeInfo = $args['rangeInfo'];
169 
170  // Add grid level items per page setting, if any.
171  $itemsPerPage = $request->getUserVar($this->_getItemsPerPageParamName($grid->getId()));
172  if ($itemsPerPage) {
173  $rangeInfo->setCount($itemsPerPage);
174  }
175  }
176 
192  function fetchRow($args) {
193  $request = $args['request'];
194  $grid = $args['grid'];
195  $row = $args['row'];
196  $jsonMessage = $args['jsonMessage'];
197  $pagingAttributes = array();
198 
199  if (is_null($row)) {
200  $gridData = $grid->getGridDataElements($request);
201  $iterator = $this->getItemIterator();
202  $rangeInfo = $grid->getGridRangeInfo($request, $grid->getId());
203 
204  // Check if row was really deleted or if the requested row is
205  // just not inside the requested range.
206  $deleted = true;
207  $topLimitRowId = (int) $request->getUserVar('topLimitRowId');
208  $bottomLimitRowId = (int) $request->getUserVar('bottomLimitRowId');
209 
210  reset($gridData);
211  $firstDataId = key($gridData);
212  next($gridData);
213  $secondDataId = key($gridData);
214  end($gridData);
215  $lastDataId = key($gridData);
216 
217  if ($secondDataId == $topLimitRowId) {
218  $deleted = false;
219  // Case 1.
220  // Row was added but it's on previous pages, so the first
221  // item of the grid was moved to the second place by the added
222  // row. Render the first one that's currently not visible yet in
223  // grid.
224  $args = array('rowId' => $firstDataId);
225  $row = $grid->getRequestedRow($request, $args);
226  $pagingAttributes['newTopRow'] = $grid->renderRow($request, $row);
227  }
228 
229  if ($firstDataId == $topLimitRowId && $lastDataId == $bottomLimitRowId) {
230  $deleted = false;
231  }
232 
233  if ($deleted) {
234  if ((empty($gridData) ||
235  // When DAOResultFactory, it seems that if no items were found for the current
236  // range information, the last page is fetched, which give us grid data even if
237  // the current page is empty. So we check for iterator and rangeInfo current pages.
238  $iterator->getPage() != $rangeInfo->getPage())
239  && $iterator->getPageCount() >= 1) {
240  // Case 3.
241  $pagingAttributes['loadLastPage'] = true;
242  } else {
243  if (count($gridData) >= $rangeInfo->getCount()) {
244  // Case 2.
245  // Get the last data element id of the current page.
246  end($gridData);
247  $firstRowId = key($gridData);
248 
249  // Get the row and render it.
250  $args = array('rowId' => $firstRowId);
251  $row = $grid->getRequestedRow($request, $args);
252  $pagingAttributes['deletedRowReplacement'] = $grid->renderRow($request, $row);
253  }
254  }
255  }
256  }
257 
258  // Render the paging options, including updated markup.
259  $this->setOptions($request, $grid);
260  $pagingAttributes['pagingInfo'] = $this->getOptions();
261 
262  // Add paging attributes to json so grid can update UI.
263  $additionalAttributes = $jsonMessage->getAdditionalAttributes();
264  $jsonMessage->setAdditionalAttributes(array_merge(
265  $pagingAttributes,
266  $additionalAttributes)
267  );
268  }
269 
270 
271  //
272  // Private helper methods.
273  //
279  private function _getItemsPerPageParamName($rangeName) {
280  return $rangeName . 'ItemsPerPage';
281  }
282 }
283 
284 ?>
setOptions($request, $grid)
Provides paging and iteration for arrays.
fetchUIElements($request, $grid)
static getPageParamName($rangeName)
addOptions($options)
Add paging functionality to grids.
Base grid feature class. A feature is a type of plugin specific to the grid widgets. It provides several hooks to allow injection of additional grid functionality. This class implements template methods to be extendeded by subclasses.
static getRangeInfo($request, $rangeName, $contextData=null)