3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
14 * @copyright CiviCRM LLC https://civicrm.org/licensing
18 * This class extends the PEAR pager object by substituting standard default pager arguments
19 * We also extract the pageId from either the GET variables or the POST variable (since we
20 * use a POST to jump to a specific page). At some point we should evaluate if we want
21 * to use Pager_Jumping instead. We've changed the format to allow navigation by jumping
22 * to a page and also First, Prev CURRENT Next Last
25 require_once 'Pager/Sliding.php';
28 * Class CRM_Utils_Pager
30 class CRM_Utils_Pager
extends Pager_Sliding
{
33 * Constants for static parameters of the pager
35 const PAGE_ID
= 'crmPID', PAGE_ID_TOP
= 'crmPID', PAGE_ID_BOTTOM
= 'crmPID_B', PAGE_ROWCOUNT
= 'crmRowCount';
38 * Deprecated constants that might still be used by extensions but no longer by core
44 * The output of the pager. This is a name/value array with various keys
45 * that an application could use to display the pager
52 * The pager constructor. Takes a few values, and then assigns a lot of defaults
53 * to the PEAR pager class
54 * We have embedded some html in this class. Need to figure out how to export this
55 * to the top level at some point in time
57 * @param array $params
59 * @return \CRM_Utils_Pager the newly created and initialized pager object
61 public function __construct($params) {
62 if ($params['status'] === NULL) {
63 $params['status'] = ts('Contacts %%StatusMessage%%');
66 $this->initialize($params);
68 parent
::__construct($params);
70 list($offset, $limit) = $this->getOffsetAndRowCount();
72 $end = $offset +
$limit;
73 if ($end > $params['total']) {
74 $end = $params['total'];
77 if ($params['total'] == 0) {
81 $statusMessage = ts('%1 - %2 of %3', [1 => $start, 2 => $end, 3 => $params['total']]);
83 $params['status'] = str_replace('%%StatusMessage%%', $statusMessage, $params['status']);
86 'first' => $this->getFirstPageLink(),
87 'back' => $this->getBackPageLink(),
88 'next' => $this->getNextPageLink(),
89 'last' => $this->getLastPageLink(),
90 'currentPage' => $this->getCurrentPageID(),
91 'numPages' => $this->numPages(),
92 'csvString' => $params['csvString'] ??
NULL,
93 'status' => $params['status'] ??
NULL,
94 'buttonTop' => $params['buttonTop'] ??
NULL,
95 'buttonBottom' => $params['buttonBottom'] ??
NULL,
96 'currentLocation' => $this->getCurrentLocation(),
100 * A page cannot have two variables with the same form name. Hence in the
101 * pager display, we have a form submission at the top with the normal
102 * page variable, but a different form element for one at the bottom.
104 $this->_response
['titleTop'] = ts('Page %1 of %2', [
105 1 => '<input size="2" maxlength="4" name="' . self
::PAGE_ID
. '" type="text" value="' . $this->_response
['currentPage'] . '" />',
106 2 => $this->_response
['numPages'],
108 $this->_response
['titleBottom'] = ts('Page %1 of %2', [
109 1 => '<input size="2" maxlength="4" name="' . self
::PAGE_ID_BOTTOM
. '" type="text" value="' . $this->_response
['currentPage'] . '" />',
110 2 => $this->_response
['numPages'],
115 * Helper function to assign remaining pager options as good default
118 * @param array $params
119 * The set of options needed to initialize the parent constructor.
123 public function initialize(&$params) {
124 // set the mode for the pager to Sliding
126 $params['mode'] = 'Sliding';
128 // also set the urlVar to be a crm specific get variable.
130 $params['urlVar'] = self
::PAGE_ID
;
132 // set this to a small value, since we dont use this functionality
134 $params['delta'] = 1;
136 $params['totalItems'] = $params['total'];
137 $params['append'] = TRUE;
138 $params['separator'] = '';
139 $params['spacesBeforeSeparator'] = 1;
140 $params['spacesAfterSeparator'] = 1;
141 $params['extraVars'] = ['force' => 1];
142 $params['excludeVars'] = ['reset', 'snippet', 'section'];
144 // set previous and next text labels
145 $params['prevImg'] = ' ' . ts('< Previous');
146 $params['nextImg'] = ts('Next >') . ' ';
148 // set first and last text fragments
149 $params['firstPagePre'] = '';
150 $params['firstPageText'] = ' ' . ts('<< First');
151 $params['firstPagePost'] = '';
153 $params['lastPagePre'] = '';
154 $params['lastPageText'] = ts('Last >>') . ' ';
155 $params['lastPagePost'] = '';
157 if (isset($params['pageID'])) {
158 $params['currentPage'] = $this->getPageID($params['pageID'], $params);
161 $params['perPage'] = $this->getPageRowCount($params['rowCount']);
167 * Figure out the current page number based on value of
168 * GET / POST variables. Hierarchy rules are followed,
169 * POST over-rides a GET, a POST at the top overrides
170 * a POST at the bottom (of the page)
172 * @param int $defaultPageId
173 * DefaultPageId current pageId.
175 * @param array $params
178 * new pageId to display to the user
180 public function getPageID($defaultPageId, &$params) {
181 // POST has higher priority than GET vars
182 // else if a value is set that has higher priority and finally the GET var
183 $currentPage = $defaultPageId;
184 if (!empty($_POST)) {
185 if (isset($_POST[CRM_Utils_Array
::value('buttonTop', $params)]) && isset($_POST[self
::PAGE_ID
])) {
186 $currentPage = max((int ) @$_POST[self
::PAGE_ID
], 1);
188 elseif (isset($_POST[$params['buttonBottom']]) && isset($_POST[self
::PAGE_ID_BOTTOM
])) {
189 $currentPage = max((int ) @$_POST[self
::PAGE_ID_BOTTOM
], 1);
191 elseif (isset($_POST[self
::PAGE_ID
])) {
192 $currentPage = max((int ) @$_POST[self
::PAGE_ID
], 1);
194 elseif (isset($_POST[self
::PAGE_ID_BOTTOM
])) {
195 $currentPage = max((int ) @$_POST[self
::PAGE_ID_BOTTOM
], 1);
198 elseif (isset($_GET[self
::PAGE_ID
])) {
199 $currentPage = max((int ) @$_GET[self
::PAGE_ID
], 1);
205 * Get the number of rows to display from either a GET / POST variable
207 * @param int|null $defaultPageRowCount
208 * The default value if not set.
211 * the rowCount value to use
213 public function getPageRowCount($defaultPageRowCount = NULL) {
214 // POST has higher priority than GET vars
215 if (isset($_POST[self
::PAGE_ROWCOUNT
])) {
216 $rowCount = max((int ) @$_POST[self
::PAGE_ROWCOUNT
], 1);
218 elseif (isset($_GET[self
::PAGE_ROWCOUNT
])) {
219 $rowCount = max((int ) @$_GET[self
::PAGE_ROWCOUNT
], 1);
222 if (empty($defaultPageRowCount)) {
223 $rowCount = Civi
::settings()->get('default_pager_size');
226 $rowCount = $defaultPageRowCount;
233 * Use the pager class to get the pageId and Offset.
236 * an array of the pageID and offset
238 public function getOffsetAndRowCount() {
239 $pageId = $this->getCurrentPageID();
244 $offset = ($pageId - 1) * $this->_perPage
;
246 return [$offset, $this->_perPage
];
252 public function getCurrentLocation() {
253 $path = CRM_Utils_System
::currentPath();
254 return CRM_Utils_System
::url($path, CRM_Utils_System
::getLinksUrl(self
::PAGE_ID
, FALSE, TRUE), FALSE, NULL, FALSE) . $this->getCurrentPageID();
260 public function getFirstPageLink() {
261 if ($this->isFirstPage()) {
264 $href = $this->makeURL(self
::PAGE_ID
, 1);
265 return $this->formatLink($href, str_replace('%d', 1, $this->_altFirst
), $this->_firstPagePre
. $this->_firstPageText
. $this->_firstPagePost
) .
266 $this->_spacesBefore
. $this->_spacesAfter
;
272 public function getLastPageLink() {
273 if ($this->isLastPage()) {
276 $href = $this->makeURL(self
::PAGE_ID
, $this->_totalPages
);
277 return $this->formatLink($href, str_replace('%d', $this->_totalPages
, $this->_altLast
), $this->_lastPagePre
. $this->_lastPageText
. $this->_lastPagePost
);
283 public function getBackPageLink() {
284 if ($this->_currentPage
> 1) {
285 $href = $this->makeURL(self
::PAGE_ID
, $this->getPreviousPageID());
286 return $this->formatLink($href, $this->_altPrev
, $this->_prevImg
) . $this->_spacesBefore
. $this->_spacesAfter
;
294 public function getNextPageLink() {
295 if ($this->_currentPage
< $this->_totalPages
) {
296 $href = $this->makeURL(self
::PAGE_ID
, $this->getNextPageID());
297 return $this->_spacesAfter
.
298 $this->formatLink($href, $this->_altNext
, $this->_nextImg
) .
299 $this->_spacesBefore
. $this->_spacesAfter
;
305 * Build a url for pager links.
308 * @param string $value
312 public function makeURL($key, $value) {
313 $href = CRM_Utils_System
::makeURL($key, TRUE);
314 // CRM-12212 Remove alpha sort param
315 if (strpos($href, '&sortByCharacter=')) {
316 $href = preg_replace('#(.*)\&sortByCharacter=[^&]*(.*)#', '\1\2', $href);
318 return $href . $value;
322 * Output the html pager link.
323 * @param string $href
324 * @param string $title
325 * @param string $image
328 private function formatLink($href, $title, $image) {
329 return sprintf('<a class="crm-pager-link action-item crm-hover-button" href="%s" title="%s">%s</a>', $href, $title, $image);