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