Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
06b69b18 | 4 | | CiviCRM version 4.5 | |
6a488035 | 5 | +--------------------------------------------------------------------+ |
06b69b18 | 6 | | Copyright CiviCRM LLC (c) 2004-2014 | |
6a488035 TO |
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 | * This class is a generic class to be used when we want to display | |
31 | * a list of rows along with a set of associated actions | |
32 | * | |
33 | * Centralizing this code enables us to write a generic lister and enables | |
34 | * us to automate the export process. To use this class, the object has to | |
35 | * implement the Selector/Api.interface.php class | |
36 | * | |
37 | * @package CRM | |
06b69b18 | 38 | * @copyright CiviCRM LLC (c) 2004-2014 |
6a488035 TO |
39 | * $Id$ |
40 | * | |
41 | */ | |
42 | class CRM_Core_Selector_Controller { | |
43 | ||
44 | /** | |
45 | * constants to determine if we should store | |
46 | * the output in the session or template | |
47 | * @var int | |
48 | */ | |
49 | // move the values from the session to the template | |
50 | CONST SESSION = 1, TEMPLATE = 2, | |
51 | TRANSFER = 4, EXPORT = 8, SCREEN = 16, PDF = 32; | |
52 | ||
53 | /** | |
54 | * a CRM Object that implements CRM_Core_Selector_API | |
55 | * @var object | |
56 | */ | |
57 | protected $_object; | |
58 | ||
59 | /* | |
60 | * the CRM_Utils_Sort object | |
61 | * @var object | |
62 | */ | |
63 | ||
64 | protected $_sort; | |
65 | ||
66 | /* | |
67 | * the current column to sort on | |
68 | * @var int | |
69 | */ | |
70 | ||
71 | protected $_sortID; | |
72 | ||
73 | /* | |
74 | * the sortOrder array | |
75 | * @var array | |
76 | */ | |
77 | ||
78 | protected $_sortOrder; | |
79 | ||
80 | /* | |
81 | * the CRM_Utils_Pager object | |
82 | * @var object | |
83 | */ | |
84 | ||
85 | protected $_pager; | |
86 | ||
87 | /* | |
88 | * the pageID | |
89 | * @var int | |
90 | */ | |
91 | ||
92 | protected $_pageID; | |
93 | ||
94 | /* | |
95 | * offset | |
96 | * @var int | |
97 | */ | |
98 | ||
99 | protected $_pagerOffset; | |
100 | ||
101 | /** | |
102 | * number of rows to return | |
103 | * @var int | |
104 | */ | |
105 | protected $_pagerRowCount; | |
106 | ||
107 | /** | |
108 | * total number of rows | |
109 | * @var int | |
110 | */ | |
111 | protected $_total; | |
112 | ||
113 | /* the objectAction for the WebObject */ | |
114 | ||
115 | protected $_action; | |
116 | ||
117 | /** | |
118 | * This caches the content for the display system | |
119 | * | |
120 | * @var string | |
121 | */ | |
122 | protected $_content; | |
123 | ||
124 | /** | |
125 | * Is this object being embedded in another object. If | |
126 | * so the display routine needs to not do any work. (The | |
127 | * parent object takes care of the display) | |
128 | * | |
129 | * @var boolean | |
130 | */ | |
131 | protected $_embedded = FALSE; | |
132 | ||
133 | /** | |
134 | * Are we in print mode? if so we need to modify the display | |
135 | * functionality to do a minimal display :) | |
136 | * | |
137 | * @var boolean | |
138 | */ | |
139 | protected $_print = FALSE; | |
140 | ||
141 | /** | |
142 | * The storage object (typically a form or a page) | |
143 | * | |
144 | * @var Object | |
145 | */ | |
146 | protected $_store; | |
147 | ||
148 | /** | |
149 | * Output target, session, template or both? | |
150 | * | |
151 | * @var int | |
152 | */ | |
153 | protected $_output; | |
154 | ||
155 | /** | |
156 | * Prefif for the selector variables | |
157 | * | |
158 | * @var int | |
159 | */ | |
160 | protected $_prefix; | |
161 | ||
162 | /** | |
163 | * cache the smarty template for efficiency reasons | |
164 | * | |
165 | * @var CRM_Core_Smarty | |
166 | */ | |
167 | public static $_template; | |
168 | ||
169 | /** | |
170 | * Array of properties that the controller dumps into the output object | |
171 | * | |
172 | * @var array | |
173 | * @static | |
174 | */ | |
175 | public static $_properties = array('columnHeaders', 'rows', 'rowsEmpty'); | |
176 | ||
177 | /** | |
178 | * Should we compute actions dynamically (since they are quite verbose) | |
179 | * | |
180 | * @var boolean | |
181 | */ | |
182 | protected $_dynamicAction = FALSE; | |
183 | ||
184 | /** | |
185 | * Class constructor | |
186 | * | |
da6b46f4 EM |
187 | * @param CRM_Core_Selector_API $object an object that implements the selector API |
188 | * @param int $pageID default pageID | |
189 | * @param int $sortID default sortID | |
190 | * @param int $action the actions to potentially support | |
191 | * @param CRM_Core_Page|CRM_Core_Form $store place in session to store some values | |
192 | * @param int $output what do we so with the output, session/template//both | |
6a488035 | 193 | * |
da6b46f4 EM |
194 | * @param null $prefix |
195 | * @param null $case | |
196 | * | |
197 | * @return \CRM_Core_Selector_Controller | |
198 | @access public | |
199 | */ | |
200 | function __construct($object, $pageID, $sortID, $action, $store = NULL, $output = self::TEMPLATE, $prefix = NULL, $case = NULL) { | |
6a488035 TO |
201 | |
202 | $this->_object = $object; | |
203 | $this->_pageID = $pageID ? $pageID : 1; | |
204 | $this->_sortID = $sortID ? $sortID : NULL; | |
205 | $this->_action = $action; | |
206 | $this->_store = $store; | |
207 | $this->_output = $output; | |
208 | $this->_prefix = $prefix; | |
209 | $this->_case = $case; | |
210 | ||
211 | // fix sortID | |
212 | if ($this->_sortID && strpos($this->_sortID, '_') === FALSE) { | |
213 | $this->_sortID .= '_u'; | |
214 | } | |
215 | ||
216 | $params = array( | |
217 | 'pageID' => $this->_pageID, | |
218 | ); | |
219 | ||
220 | // let the constructor initialize this, should happen only once | |
221 | if (!isset(self::$_template)) { | |
222 | self::$_template = CRM_Core_Smarty::singleton(); | |
223 | } | |
224 | ||
225 | $this->_sortOrder = &$this->_object->getSortOrder($action); | |
226 | $this->_sort = new CRM_Utils_Sort($this->_sortOrder, $this->_sortID); | |
227 | ||
228 | /* | |
f4bff68a CW |
229 | * if we are in transfer mode, do not goto database, use the |
230 | * session values instead | |
231 | */ | |
6a488035 TO |
232 | |
233 | if ($output == self::TRANSFER) { | |
234 | $params['total'] = $this->_store->get($this->_prefix . 'rowCount'); | |
235 | } | |
236 | else { | |
237 | $params['total'] = $this->_object->getTotalCount($action, $this->_case); | |
238 | } | |
239 | ||
240 | $this->_total = $params['total']; | |
241 | $this->_object->getPagerParams($action, $params); | |
242 | ||
243 | /* | |
f4bff68a CW |
244 | * Set the default values of RowsPerPage |
245 | */ | |
6a488035 TO |
246 | |
247 | $storeRowCount = $store->get($this->_prefix . CRM_Utils_Pager::PAGE_ROWCOUNT); | |
248 | if ($storeRowCount) { | |
249 | $params['rowCount'] = $storeRowCount; | |
250 | } | |
251 | elseif (!isset($params['rowCount'])) { | |
252 | $params['rowCount'] = CRM_Utils_Pager::ROWCOUNT; | |
253 | } | |
254 | ||
255 | $this->_pager = new CRM_Utils_Pager($params); | |
256 | list($this->_pagerOffset, $this->_pagerRowCount) = $this->_pager->getOffsetAndRowCount(); | |
257 | } | |
258 | ||
259 | /** | |
260 | * have the GET vars changed, i.e. pageId or sortId that forces us to recompute the search values | |
261 | * | |
262 | * @param int $reset are we being reset | |
263 | * | |
264 | * @return boolean if the GET params are different from the session params | |
265 | * @access public | |
266 | */ | |
267 | function hasChanged($reset) { | |
268 | ||
269 | /** | |
270 | * if we are in reset state, i.e the store is cleaned out, we return false | |
271 | * we also return if we dont have a record of the sort id or page id | |
272 | */ | |
273 | if ($reset || | |
274 | $this->_store->get($this->_prefix . CRM_Utils_Pager::PAGE_ID) == NULL || | |
275 | $this->_store->get($this->_prefix . CRM_Utils_Sort::SORT_ID) == NULL | |
276 | ) { | |
277 | return FALSE; | |
278 | } | |
279 | ||
280 | if ($this->_store->get($this->_prefix . CRM_Utils_Pager::PAGE_ID) != $this->_pager->getCurrentPageID() || | |
281 | $this->_store->get($this->_prefix . CRM_Utils_Sort::SORT_ID) != $this->_sort->getCurrentSortID() || | |
282 | $this->_store->get($this->_prefix . CRM_Utils_Sort::SORT_DIRECTION) != $this->_sort->getCurrentSortDirection() | |
283 | ) { | |
284 | return TRUE; | |
285 | } | |
286 | return FALSE; | |
287 | } | |
288 | ||
289 | /** | |
290 | * Heart of the Controller. This is where all the action takes place | |
291 | * | |
292 | * - The rows are fetched and stored depending on the type of output needed | |
293 | * | |
294 | * - For export/printing all rows are selected. | |
295 | * | |
296 | * - for displaying on screen paging parameters are used to display the | |
297 | * required rows. | |
298 | * | |
299 | * - also depending on output type of session or template rows are appropriately stored in session | |
300 | * or template variables are updated. | |
301 | * | |
302 | * | |
303 | * @return void | |
304 | * | |
305 | */ | |
306 | function run() { | |
307 | ||
308 | // get the column headers | |
309 | $columnHeaders = &$this->_object->getColumnHeaders($this->_action, $this->_output); | |
310 | ||
311 | $contextArray = explode('_', get_class($this->_object)); | |
312 | ||
313 | $contextName = strtolower($contextArray[1]); | |
314 | ||
315 | // fix contribute and member | |
316 | if ($contextName == 'contribute') { | |
317 | $contextName = 'contribution'; | |
318 | } | |
319 | elseif ($contextName == 'member') { | |
320 | $contextName = 'membership'; | |
321 | } | |
322 | ||
323 | // we need to get the rows if we are exporting or printing them | |
324 | if ($this->_output == self::EXPORT || $this->_output == self::SCREEN) { | |
325 | // get rows (without paging criteria) | |
326 | $rows = self::getRows($this); | |
327 | CRM_Utils_Hook::searchColumns($contextName, $columnHeaders, $rows, $this); | |
328 | if ($this->_output == self::EXPORT) { | |
329 | // export the rows. | |
330 | CRM_Core_Report_Excel::writeCSVFile($this->_object->getExportFileName(), | |
331 | $columnHeaders, | |
332 | $rows | |
333 | ); | |
334 | CRM_Utils_System::civiExit(); | |
335 | } | |
336 | else { | |
337 | // assign to template and display them. | |
338 | self::$_template->assign_by_ref('rows', $rows); | |
339 | self::$_template->assign_by_ref('columnHeaders', $columnHeaders); | |
340 | } | |
341 | } | |
342 | else { | |
343 | // output requires paging/sorting capability | |
344 | $rows = self::getRows($this); | |
345 | CRM_Utils_Hook::searchColumns($contextName, $columnHeaders, $rows, $this); | |
346 | $rowsEmpty = count($rows) ? FALSE : TRUE; | |
347 | $qill = $this->getQill(); | |
348 | $summary = $this->getSummary(); | |
349 | // if we need to store in session, lets update session | |
350 | if ($this->_output & self::SESSION) { | |
351 | $this->_store->set("{$this->_prefix}columnHeaders", $columnHeaders); | |
352 | if ($this->_dynamicAction) { | |
353 | $this->_object->removeActions($rows); | |
354 | } | |
355 | $this->_store->set("{$this->_prefix}rows", $rows); | |
356 | $this->_store->set("{$this->_prefix}rowCount", $this->_total); | |
357 | $this->_store->set("{$this->_prefix}rowsEmpty", $rowsEmpty); | |
358 | $this->_store->set("{$this->_prefix}qill", $qill); | |
359 | $this->_store->set("{$this->_prefix}summary", $summary); | |
360 | } | |
361 | else { | |
362 | self::$_template->assign_by_ref("{$this->_prefix}pager", $this->_pager); | |
363 | self::$_template->assign_by_ref("{$this->_prefix}sort", $this->_sort); | |
364 | ||
365 | self::$_template->assign_by_ref("{$this->_prefix}columnHeaders", $columnHeaders); | |
366 | self::$_template->assign_by_ref("{$this->_prefix}rows", $rows); | |
367 | self::$_template->assign("{$this->_prefix}rowsEmpty", $rowsEmpty); | |
368 | self::$_template->assign("{$this->_prefix}qill", $qill); | |
369 | self::$_template->assign("{$this->_prefix}summary", $summary); | |
370 | } | |
371 | ||
372 | ||
373 | // always store the current pageID and sortID | |
374 | $this->_store->set($this->_prefix . CRM_Utils_Pager::PAGE_ID, | |
375 | $this->_pager->getCurrentPageID() | |
376 | ); | |
377 | $this->_store->set($this->_prefix . CRM_Utils_Sort::SORT_ID, | |
378 | $this->_sort->getCurrentSortID() | |
379 | ); | |
380 | $this->_store->set($this->_prefix . CRM_Utils_Sort::SORT_DIRECTION, | |
381 | $this->_sort->getCurrentSortDirection() | |
382 | ); | |
383 | $this->_store->set($this->_prefix . CRM_Utils_Sort::SORT_ORDER, | |
384 | $this->_sort->orderBy() | |
385 | ); | |
386 | $this->_store->set($this->_prefix . CRM_Utils_Pager::PAGE_ROWCOUNT, | |
387 | $this->_pager->_perPage | |
388 | ); | |
389 | } | |
390 | } | |
391 | ||
392 | /** | |
393 | * function to retrieve rows. | |
394 | * | |
2a6da8d7 EM |
395 | * @param $form |
396 | * | |
6a488035 TO |
397 | * @return array of rows |
398 | * @access public | |
399 | */ | |
400 | public function getRows($form) { | |
401 | if ($form->_output == self::EXPORT || $form->_output == self::SCREEN) { | |
402 | //get rows (without paging criteria) | |
403 | return $form->_object->getRows($form->_action, 0, 0, $form->_sort, $form->_output); | |
404 | } | |
405 | else { | |
406 | return $form->_object->getRows($form->_action, $form->_pagerOffset, $form->_pagerRowCount, | |
407 | $form->_sort, $form->_output, $form->_case | |
408 | ); | |
409 | } | |
410 | } | |
411 | ||
412 | /** | |
413 | * default function for qill, if needed to be implemented, we | |
414 | * expect the subclass to do it | |
415 | * | |
416 | * @return string the status message | |
417 | * @access public | |
418 | */ | |
419 | public function getQill() { | |
420 | return $this->_object->getQill(); | |
421 | } | |
422 | ||
a0ee3941 EM |
423 | /** |
424 | * @return mixed | |
425 | */ | |
6a488035 TO |
426 | public function getSummary() { |
427 | return $this->_object->getSummary(); | |
428 | } | |
429 | ||
430 | /** | |
431 | * getter for pager | |
432 | * | |
433 | * @return object CRM_Utils_Pager | |
434 | * @access public | |
435 | */ | |
436 | function getPager() { | |
437 | return $this->_pager; | |
438 | } | |
439 | ||
440 | /** | |
441 | * getter for sort | |
442 | * | |
443 | * @return object CRM_Utils_Sort | |
444 | * @access public | |
445 | */ | |
446 | function getSort() { | |
447 | return $this->_sort; | |
448 | } | |
449 | ||
450 | /** | |
451 | * Move the variables from the session to the template | |
452 | * | |
453 | * @return void | |
454 | * @access public | |
455 | */ | |
456 | function moveFromSessionToTemplate() { | |
457 | self::$_template->assign_by_ref("{$this->_prefix}pager", $this->_pager); | |
458 | ||
459 | $rows = $this->_store->get("{$this->_prefix}rows"); | |
460 | ||
461 | if ($rows) { | |
462 | if ($this->_dynamicAction) { | |
463 | $this->_object->addActions($rows); | |
464 | } | |
465 | ||
466 | self::$_template->assign("{$this->_prefix}aToZ", | |
467 | $this->_store->get("{$this->_prefix}AToZBar") | |
468 | ); | |
469 | } | |
470 | ||
471 | self::$_template->assign_by_ref("{$this->_prefix}sort", $this->_sort); | |
472 | self::$_template->assign("{$this->_prefix}columnHeaders", $this->_store->get("{$this->_prefix}columnHeaders")); | |
473 | self::$_template->assign("{$this->_prefix}rows", $rows); | |
474 | self::$_template->assign("{$this->_prefix}rowsEmpty", $this->_store->get("{$this->_prefix}rowsEmpty")); | |
475 | self::$_template->assign("{$this->_prefix}qill", $this->_store->get("{$this->_prefix}qill")); | |
476 | self::$_template->assign("{$this->_prefix}summary", $this->_store->get("{$this->_prefix}summary")); | |
477 | ||
478 | if ($this->_embedded) { | |
479 | return; | |
480 | } | |
481 | ||
8aac22c8 | 482 | self::$_template->assign('tplFile', $this->_object->getHookedTemplateFileName()); |
6a488035 TO |
483 | if ($this->_print) { |
484 | $content = self::$_template->fetch('CRM/common/print.tpl'); | |
485 | } | |
486 | else { | |
487 | $config = CRM_Core_Config::singleton(); | |
488 | $content = self::$_template->fetch('CRM/common/' . strtolower($config->userFramework) . '.tpl'); | |
489 | } | |
490 | echo CRM_Utils_System::theme($content, $this->_print); | |
491 | } | |
492 | ||
493 | /** | |
494 | * setter for embedded | |
495 | * | |
496 | * @param boolean $embedded | |
497 | * | |
498 | * @return void | |
499 | * @access public | |
500 | */ | |
501 | function setEmbedded($embedded) { | |
502 | $this->_embedded = $embedded; | |
503 | } | |
504 | ||
505 | /** | |
506 | * getter for embedded | |
507 | * | |
508 | * @return boolean return the embedded value | |
509 | * @access public | |
510 | */ | |
511 | function getEmbedded() { | |
512 | return $this->_embedded; | |
513 | } | |
514 | ||
515 | /** | |
516 | * setter for print | |
517 | * | |
518 | * @param boolean $print | |
519 | * | |
520 | * @return void | |
521 | * @access public | |
522 | */ | |
523 | function setPrint($print) { | |
524 | $this->_print = $print; | |
525 | } | |
526 | ||
527 | /** | |
528 | * getter for print | |
529 | * | |
530 | * @return boolean return the print value | |
531 | * @access public | |
532 | */ | |
533 | function getPrint() { | |
534 | return $this->_print; | |
535 | } | |
536 | ||
a0ee3941 EM |
537 | /** |
538 | * @param $value | |
539 | */ | |
6a488035 TO |
540 | function setDynamicAction($value) { |
541 | $this->_dynamicAction = $value; | |
542 | } | |
543 | ||
a0ee3941 EM |
544 | /** |
545 | * @return bool | |
546 | */ | |
6a488035 TO |
547 | function getDynamicAction() { |
548 | return $this->_dynamicAction; | |
549 | } | |
550 | } | |
551 |