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