province abbreviation patch - issue 724
[civicrm-core.git] / CRM / Utils / Pager.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 5 | |
bc77d7c0
TO
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 |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035
TO
11
12/**
6a488035 13 * @package CRM
ca5cec67 14 * @copyright CiviCRM LLC https://civicrm.org/licensing
6a488035
TO
15 */
16
17/**
6a488035
TO
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
6a488035
TO
23 */
24
25require_once 'Pager/Sliding.php';
5bc392e6
EM
26
27/**
28 * Class CRM_Utils_Pager
29 */
6a488035
TO
30class CRM_Utils_Pager extends Pager_Sliding {
31
32 /**
100fef9d 33 * Constants for static parameters of the pager
6a488035 34 */
7fa7c084
SL
35 const PAGE_ID = 'crmPID', PAGE_ID_TOP = 'crmPID', PAGE_ID_BOTTOM = 'crmPID_B', PAGE_ROWCOUNT = 'crmRowCount';
36
37 /**
38 * Deprecated constants that might still be used by extensions but no longer by core
39 * @deprecated
40 */
41 const ROWCOUNT = 50;
6a488035
TO
42
43 /**
100fef9d 44 * The output of the pager. This is a name/value array with various keys
6a488035 45 * that an application could use to display the pager
50bfb460 46 *
6a488035
TO
47 * @var array
48 */
49 public $_response;
50
51 /**
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
56 *
c490a46a 57 * @param array $params
f4aaa82a 58 *
e0b82b44 59 * @return \CRM_Utils_Pager the newly created and initialized pager object
6a488035 60 */
00be9182 61 public function __construct($params) {
6a488035
TO
62 if ($params['status'] === NULL) {
63 $params['status'] = ts('Contacts %%StatusMessage%%');
64 }
65
66 $this->initialize($params);
67
6ef04c72 68 parent::__construct($params);
6a488035
TO
69
70 list($offset, $limit) = $this->getOffsetAndRowCount();
71 $start = $offset + 1;
72 $end = $offset + $limit;
73 if ($end > $params['total']) {
74 $end = $params['total'];
75 }
76
77 if ($params['total'] == 0) {
78 $statusMessage = '';
79 }
80 else {
be2fb01f 81 $statusMessage = ts('%1 - %2 of %3', [1 => $start, 2 => $end, 3 => $params['total']]);
6a488035
TO
82 }
83 $params['status'] = str_replace('%%StatusMessage%%', $statusMessage, $params['status']);
84
be2fb01f 85 $this->_response = [
6a488035
TO
86 'first' => $this->getFirstPageLink(),
87 'back' => $this->getBackPageLink(),
88 'next' => $this->getNextPageLink(),
89 'last' => $this->getLastPageLink(),
90 'currentPage' => $this->getCurrentPageID(),
91 'numPages' => $this->numPages(),
6b409353
CW
92 'csvString' => $params['csvString'] ?? NULL,
93 'status' => $params['status'] ?? NULL,
94 'buttonTop' => $params['buttonTop'] ?? NULL,
95 'buttonBottom' => $params['buttonBottom'] ?? NULL,
fe010227 96 'currentLocation' => $this->getCurrentLocation(),
be2fb01f 97 ];
6a488035
TO
98
99 /**
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
50bfb460 102 * page variable, but a different form element for one at the bottom.
6a488035 103 */
be2fb01f 104 $this->_response['titleTop'] = ts('Page %1 of %2', [
6714d8d2
SL
105 1 => '<input size="2" maxlength="4" name="' . self::PAGE_ID . '" type="text" value="' . $this->_response['currentPage'] . '" />',
106 2 => $this->_response['numPages'],
107 ]);
be2fb01f 108 $this->_response['titleBottom'] = ts('Page %1 of %2', [
6714d8d2
SL
109 1 => '<input size="2" maxlength="4" name="' . self::PAGE_ID_BOTTOM . '" type="text" value="' . $this->_response['currentPage'] . '" />',
110 2 => $this->_response['numPages'],
111 ]);
6a488035
TO
112 }
113
114 /**
100fef9d 115 * Helper function to assign remaining pager options as good default
4d429319 116 * values.
6a488035 117 *
77855840 118 * @param array $params
b8c71ffa 119 * The set of options needed to initialize the parent constructor.
6a488035 120 *
b8c71ffa 121 * @return array
6a488035 122 */
00be9182 123 public function initialize(&$params) {
50bfb460 124 // set the mode for the pager to Sliding
6a488035
TO
125
126 $params['mode'] = 'Sliding';
127
50bfb460 128 // also set the urlVar to be a crm specific get variable.
6a488035
TO
129
130 $params['urlVar'] = self::PAGE_ID;
131
50bfb460 132 // set this to a small value, since we dont use this functionality
6a488035
TO
133
134 $params['delta'] = 1;
135
136 $params['totalItems'] = $params['total'];
137 $params['append'] = TRUE;
138 $params['separator'] = '';
139 $params['spacesBeforeSeparator'] = 1;
140 $params['spacesAfterSeparator'] = 1;
be2fb01f
CW
141 $params['extraVars'] = ['force' => 1];
142 $params['excludeVars'] = ['reset', 'snippet', 'section'];
6a488035
TO
143
144 // set previous and next text labels
145 $params['prevImg'] = ' ' . ts('&lt; Previous');
146 $params['nextImg'] = ts('Next &gt;') . ' ';
147
6a488035
TO
148 // set first and last text fragments
149 $params['firstPagePre'] = '';
150 $params['firstPageText'] = ' ' . ts('&lt;&lt; First');
151 $params['firstPagePost'] = '';
152
153 $params['lastPagePre'] = '';
154 $params['lastPageText'] = ts('Last &gt;&gt;') . ' ';
155 $params['lastPagePost'] = '';
156
157 if (isset($params['pageID'])) {
158 $params['currentPage'] = $this->getPageID($params['pageID'], $params);
159 }
160
161 $params['perPage'] = $this->getPageRowCount($params['rowCount']);
162
163 return $params;
164 }
165
166 /**
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)
171 *
77855840
TO
172 * @param int $defaultPageId
173 * DefaultPageId current pageId.
f4aaa82a 174 *
c490a46a 175 * @param array $params
6a488035 176 *
a6c01b45
CW
177 * @return int
178 * new pageId to display to the user
6a488035 179 */
47eea6b6 180 public function getPageID($defaultPageId, &$params) {
6a488035
TO
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])) {
e7292422 186 $currentPage = max((int ) @$_POST[self::PAGE_ID], 1);
6a488035
TO
187 }
188 elseif (isset($_POST[$params['buttonBottom']]) && isset($_POST[self::PAGE_ID_BOTTOM])) {
e7292422 189 $currentPage = max((int ) @$_POST[self::PAGE_ID_BOTTOM], 1);
6a488035
TO
190 }
191 elseif (isset($_POST[self::PAGE_ID])) {
e7292422 192 $currentPage = max((int ) @$_POST[self::PAGE_ID], 1);
6a488035
TO
193 }
194 elseif (isset($_POST[self::PAGE_ID_BOTTOM])) {
b208d4d5 195 $currentPage = max((int ) @$_POST[self::PAGE_ID_BOTTOM], 1);
6a488035
TO
196 }
197 }
198 elseif (isset($_GET[self::PAGE_ID])) {
e7292422 199 $currentPage = max((int ) @$_GET[self::PAGE_ID], 1);
6a488035
TO
200 }
201 return $currentPage;
202 }
203
204 /**
205 * Get the number of rows to display from either a GET / POST variable
206 *
7fa7c084 207 * @param int|null $defaultPageRowCount
77855840 208 * The default value if not set.
6a488035 209 *
a6c01b45
CW
210 * @return int
211 * the rowCount value to use
6a488035 212 */
7fa7c084 213 public function getPageRowCount($defaultPageRowCount = NULL) {
6a488035
TO
214 // POST has higher priority than GET vars
215 if (isset($_POST[self::PAGE_ROWCOUNT])) {
e7292422 216 $rowCount = max((int ) @$_POST[self::PAGE_ROWCOUNT], 1);
6a488035
TO
217 }
218 elseif (isset($_GET[self::PAGE_ROWCOUNT])) {
e7292422 219 $rowCount = max((int ) @$_GET[self::PAGE_ROWCOUNT], 1);
6a488035
TO
220 }
221 else {
7fa7c084 222 if (empty($defaultPageRowCount)) {
9f3d3f19 223 $rowCount = Civi::settings()->get('default_pager_size');
7fa7c084
SL
224 }
225 else {
226 $rowCount = $defaultPageRowCount;
227 }
6a488035
TO
228 }
229 return $rowCount;
230 }
231
232 /**
fe482240 233 * Use the pager class to get the pageId and Offset.
6a488035 234 *
a6c01b45
CW
235 * @return array
236 * an array of the pageID and offset
6a488035 237 */
00be9182 238 public function getOffsetAndRowCount() {
6a488035
TO
239 $pageId = $this->getCurrentPageID();
240 if (!$pageId) {
241 $pageId = 1;
242 }
243
244 $offset = ($pageId - 1) * $this->_perPage;
245
be2fb01f 246 return [$offset, $this->_perPage];
6a488035
TO
247 }
248
5bc392e6
EM
249 /**
250 * @return string
251 */
00be9182 252 public function getCurrentLocation() {
13594d55 253 $path = CRM_Utils_System::currentPath();
fe010227 254 return CRM_Utils_System::url($path, CRM_Utils_System::getLinksUrl(self::PAGE_ID, FALSE, TRUE), FALSE, NULL, FALSE) . $this->getCurrentPageID();
6a488035
TO
255 }
256
5bc392e6
EM
257 /**
258 * @return string
259 */
00be9182 260 public function getFirstPageLink() {
6a488035
TO
261 if ($this->isFirstPage()) {
262 return '';
263 }
10824c72 264 $href = $this->makeURL(self::PAGE_ID, 1);
c5d647c1 265 return $this->formatLink($href, str_replace('%d', 1, $this->_altFirst), $this->_firstPagePre . $this->_firstPageText . $this->_firstPagePost) .
353ffa53 266 $this->_spacesBefore . $this->_spacesAfter;
6a488035
TO
267 }
268
5bc392e6
EM
269 /**
270 * @return string
271 */
00be9182 272 public function getLastPageLink() {
6a488035
TO
273 if ($this->isLastPage()) {
274 return '';
275 }
10824c72 276 $href = $this->makeURL(self::PAGE_ID, $this->_totalPages);
c5d647c1 277 return $this->formatLink($href, str_replace('%d', $this->_totalPages, $this->_altLast), $this->_lastPagePre . $this->_lastPageText . $this->_lastPagePost);
6a488035
TO
278 }
279
5bc392e6
EM
280 /**
281 * @return string
282 */
00be9182 283 public function getBackPageLink() {
6a488035 284 if ($this->_currentPage > 1) {
10824c72 285 $href = $this->makeURL(self::PAGE_ID, $this->getPreviousPageID());
c5d647c1 286 return $this->formatLink($href, $this->_altPrev, $this->_prevImg) . $this->_spacesBefore . $this->_spacesAfter;
6a488035
TO
287 }
288 return '';
289 }
290
5bc392e6
EM
291 /**
292 * @return string
293 */
00be9182 294 public function getNextPageLink() {
6a488035 295 if ($this->_currentPage < $this->_totalPages) {
10824c72 296 $href = $this->makeURL(self::PAGE_ID, $this->getNextPageID());
c5d647c1 297 return $this->_spacesAfter .
353ffa53
TO
298 $this->formatLink($href, $this->_altNext, $this->_nextImg) .
299 $this->_spacesBefore . $this->_spacesAfter;
6a488035
TO
300 }
301 return '';
302 }
10824c72
CW
303
304 /**
fe482240 305 * Build a url for pager links.
54957108 306 *
307 * @param string $key
308 * @param string $value
309 *
310 * @return string
10824c72 311 */
00be9182 312 public function makeURL($key, $value) {
e6add384 313 $href = CRM_Utils_System::makeURL($key, TRUE);
10824c72
CW
314 // CRM-12212 Remove alpha sort param
315 if (strpos($href, '&amp;sortByCharacter=')) {
316 $href = preg_replace('#(.*)\&amp;sortByCharacter=[^&]*(.*)#', '\1\2', $href);
317 }
318 return $href . $value;
319 }
c5d647c1
CW
320
321 /**
fe482240 322 * Output the html pager link.
c5d647c1
CW
323 * @param string $href
324 * @param string $title
325 * @param string $image
326 * @return string
327 */
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);
330 }
96025800 331
6a488035 332}