3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2018 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
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
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
38 * @copyright CiviCRM LLC (c) 2004-2018
42 class CRM_Core_Selector_Controller
{
45 * Constants to determine if we should store
46 * the output in the session or template
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;
54 * A CRM Object that implements CRM_Core_Selector_API.
65 * The current column to sort on
74 protected $_sortOrder;
77 * @var CRM_Utils_Pager
91 protected $_pagerOffset;
94 * Number of rows to return
97 protected $_pagerRowCount;
100 * Total number of rows
106 * The objectAction for the WebObject
111 * This caches the content for the display system
118 * Is this object being embedded in another object. If
119 * so the display routine needs to not do any work. (The
120 * parent object takes care of the display)
124 protected $_embedded = FALSE;
127 * Are we in print mode? if so we need to modify the display
128 * functionality to do a minimal display :)
132 protected $_print = FALSE;
135 * The storage object (typically a form or a page)
142 * Output target, session, template or both?
149 * Prefif for the selector variables
156 * Cache the smarty template for efficiency reasons
158 * @var CRM_Core_Smarty
160 public static $_template;
163 * Array of properties that the controller dumps into the output object
167 public static $_properties = array('columnHeaders', 'rows', 'rowsEmpty');
170 * Should we compute actions dynamically (since they are quite verbose)
174 protected $_dynamicAction = FALSE;
179 * @param CRM_Core_Selector_API $object
180 * An object that implements the selector API.
186 * The actions to potentially support.
187 * @param CRM_Core_Page|CRM_Core_Form $store place in session to store some values
189 * What do we so with the output, session/template//both.
191 * @param null $prefix
194 * @return \CRM_Core_Selector_Controller
196 public function __construct($object, $pageID, $sortID, $action, $store = NULL, $output = self
::TEMPLATE
, $prefix = NULL, $case = NULL) {
198 $this->_object
= $object;
199 $this->_pageID
= $pageID ?
$pageID : 1;
200 $this->_sortID
= $sortID ?
$sortID : NULL;
201 $this->_action
= $action;
202 $this->_store
= $store;
203 $this->_output
= $output;
204 $this->_prefix
= $prefix;
205 $this->_case
= $case;
208 if ($this->_sortID
&& strpos($this->_sortID
, '_') === FALSE) {
209 $this->_sortID
.= '_u';
213 'pageID' => $this->_pageID
,
216 // let the constructor initialize this, should happen only once
217 if (!isset(self
::$_template)) {
218 self
::$_template = CRM_Core_Smarty
::singleton();
221 $this->_sortOrder
= &$this->_object
->getSortOrder($action);
222 $this->_sort
= new CRM_Utils_Sort($this->_sortOrder
, $this->_sortID
);
225 * if we are in transfer mode, do not goto database, use the
226 * session values instead
229 if ($output == self
::TRANSFER
) {
230 $params['total'] = $this->_store
->get($this->_prefix
. 'rowCount');
233 $params['total'] = $this->_object
->getTotalCount($action, $this->_case
);
236 $this->_total
= $params['total'];
237 $this->_object
->getPagerParams($action, $params);
240 * Set the default values of RowsPerPage
243 $storeRowCount = $store->get($this->_prefix
. CRM_Utils_Pager
::PAGE_ROWCOUNT
);
244 if ($storeRowCount) {
245 $params['rowCount'] = $storeRowCount;
247 elseif (!isset($params['rowCount'])) {
248 $params['rowCount'] = CRM_Utils_Pager
::ROWCOUNT
;
251 $this->_pager
= new CRM_Utils_Pager($params);
252 list($this->_pagerOffset
, $this->_pagerRowCount
) = $this->_pager
->getOffsetAndRowCount();
256 * Have the GET vars changed, i.e. pageId or sortId that forces us to recompute the search values
259 * Are we being reset.
262 * if the GET params are different from the session params
264 public function hasChanged($reset) {
267 * if we are in reset state, i.e the store is cleaned out, we return false
268 * we also return if we dont have a record of the sort id or page id
271 $this->_store
->get($this->_prefix
. CRM_Utils_Pager
::PAGE_ID
) == NULL ||
272 $this->_store
->get($this->_prefix
. CRM_Utils_Sort
::SORT_ID
) == NULL
277 if ($this->_store
->get($this->_prefix
. CRM_Utils_Pager
::PAGE_ID
) != $this->_pager
->getCurrentPageID() ||
278 $this->_store
->get($this->_prefix
. CRM_Utils_Sort
::SORT_ID
) != $this->_sort
->getCurrentSortID() ||
279 $this->_store
->get($this->_prefix
. CRM_Utils_Sort
::SORT_DIRECTION
) != $this->_sort
->getCurrentSortDirection()
287 * Heart of the Controller. This is where all the action takes place
289 * - The rows are fetched and stored depending on the type of output needed
291 * - For export/printing all rows are selected.
293 * - for displaying on screen paging parameters are used to display the
296 * - also depending on output type of session or template rows are appropriately stored in session
297 * or template variables are updated.
302 public function run() {
304 // get the column headers
305 $columnHeaders = &$this->_object
->getColumnHeaders($this->_action
, $this->_output
);
307 $contextArray = explode('_', get_class($this->_object
));
309 $contextName = strtolower($contextArray[1]);
311 // fix contribute and member
312 if ($contextName == 'contribute') {
313 $contextName = 'contribution';
315 elseif ($contextName == 'member') {
316 $contextName = 'membership';
319 // we need to get the rows if we are exporting or printing them
320 if ($this->_output
== self
::EXPORT ||
$this->_output
== self
::SCREEN
) {
321 // get rows (without paging criteria)
322 $rows = self
::getRows($this);
323 CRM_Utils_Hook
::searchColumns($contextName, $columnHeaders, $rows, $this);
324 if ($this->_output
== self
::EXPORT
) {
326 CRM_Core_Report_Excel
::writeCSVFile($this->_object
->getExportFileName(),
330 CRM_Utils_System
::civiExit();
333 // assign to template and display them.
334 self
::$_template->assign_by_ref('rows', $rows);
335 self
::$_template->assign_by_ref('columnHeaders', $columnHeaders);
339 // output requires paging/sorting capability
340 $rows = self
::getRows($this);
341 CRM_Utils_Hook
::searchColumns($contextName, $columnHeaders, $rows, $this);
342 $reorderedHeaders = array();
343 $noWeightHeaders = array();
344 foreach ($columnHeaders as $key => $columnHeader) {
345 // So far only contribution selector sets weight, so just use key if not.
346 // Extension writers will need to fix other getColumnHeaders (or add a wrapper)
348 if (isset($columnHeader['weight'])) {
349 $reorderedHeaders[$columnHeader['weight']] = $columnHeader;
352 $noWeightHeaders[$key] = $columnHeader;
355 ksort($reorderedHeaders);
356 // Merge headers not containing weight to ordered headers
357 $finalColumnHeaders = array_merge($reorderedHeaders, $noWeightHeaders);
359 $rowsEmpty = count($rows) ?
FALSE : TRUE;
360 $qill = $this->getQill();
361 $summary = $this->getSummary();
362 // if we need to store in session, lets update session
363 if ($this->_output
& self
::SESSION
) {
364 $this->_store
->set("{$this->_prefix}columnHeaders", $finalColumnHeaders);
365 if ($this->_dynamicAction
) {
366 $this->_object
->removeActions($rows);
368 $this->_store
->set("{$this->_prefix}rows", $rows);
369 $this->_store
->set("{$this->_prefix}rowCount", $this->_total
);
370 $this->_store
->set("{$this->_prefix}rowsEmpty", $rowsEmpty);
371 $this->_store
->set("{$this->_prefix}qill", $qill);
372 $this->_store
->set("{$this->_prefix}summary", $summary);
375 self
::$_template->assign_by_ref("{$this->_prefix}pager", $this->_pager
);
376 self
::$_template->assign_by_ref("{$this->_prefix}sort", $this->_sort
);
378 self
::$_template->assign_by_ref("{$this->_prefix}columnHeaders", $finalColumnHeaders);
379 self
::$_template->assign_by_ref("{$this->_prefix}rows", $rows);
380 self
::$_template->assign("{$this->_prefix}rowsEmpty", $rowsEmpty);
381 self
::$_template->assign("{$this->_prefix}qill", $qill);
382 self
::$_template->assign("{$this->_prefix}summary", $summary);
385 // always store the current pageID and sortID
386 $this->_store
->set($this->_prefix
. CRM_Utils_Pager
::PAGE_ID
,
387 $this->_pager
->getCurrentPageID()
389 $this->_store
->set($this->_prefix
. CRM_Utils_Sort
::SORT_ID
,
390 $this->_sort
->getCurrentSortID()
392 $this->_store
->set($this->_prefix
. CRM_Utils_Sort
::SORT_DIRECTION
,
393 $this->_sort
->getCurrentSortDirection()
395 $this->_store
->set($this->_prefix
. CRM_Utils_Sort
::SORT_ORDER
,
396 $this->_sort
->orderBy()
398 $this->_store
->set($this->_prefix
. CRM_Utils_Pager
::PAGE_ROWCOUNT
,
399 $this->_pager
->_perPage
407 * @param CRM_Core_Form $form
412 public function getRows($form) {
413 if ($form->_output
== self
::EXPORT ||
$form->_output
== self
::SCREEN
) {
414 //get rows (without paging criteria)
415 return $form->_object
->getRows($form->_action
, 0, 0, $form->_sort
, $form->_output
);
418 return $form->_object
->getRows($form->_action
, $form->_pagerOffset
, $form->_pagerRowCount
,
419 $form->_sort
, $form->_output
, $form->_case
425 * Default function for qill, if needed to be implemented, we
426 * expect the subclass to do it
431 public function getQill() {
432 return $this->_object
->getQill();
438 public function getSummary() {
439 return $this->_object
->getSummary();
445 * @return CRM_Utils_Pager
447 public function getPager() {
448 return $this->_pager
;
454 * @return CRM_Utils_Sort
456 public function getSort() {
461 * Move the variables from the session to the template.
465 public function moveFromSessionToTemplate() {
466 self
::$_template->assign_by_ref("{$this->_prefix}pager", $this->_pager
);
468 $rows = $this->_store
->get("{$this->_prefix}rows");
471 if ($this->_dynamicAction
) {
472 $this->_object
->addActions($rows);
475 self
::$_template->assign("{$this->_prefix}aToZ",
476 $this->_store
->get("{$this->_prefix}AToZBar")
480 self
::$_template->assign_by_ref("{$this->_prefix}sort", $this->_sort
);
481 self
::$_template->assign("{$this->_prefix}columnHeaders", $this->_store
->get("{$this->_prefix}columnHeaders"));
482 self
::$_template->assign("{$this->_prefix}rows", $rows);
483 self
::$_template->assign("{$this->_prefix}rowsEmpty", $this->_store
->get("{$this->_prefix}rowsEmpty"));
484 self
::$_template->assign("{$this->_prefix}qill", $this->_store
->get("{$this->_prefix}qill"));
485 self
::$_template->assign("{$this->_prefix}summary", $this->_store
->get("{$this->_prefix}summary"));
487 if ($this->_embedded
) {
491 self
::$_template->assign('tplFile', $this->_object
->getHookedTemplateFileName());
493 $content = self
::$_template->fetch('CRM/common/print.tpl');
496 $config = CRM_Core_Config
::singleton();
497 $content = self
::$_template->fetch('CRM/common/' . strtolower($config->userFramework
) . '.tpl');
499 echo CRM_Utils_System
::theme($content, $this->_print
);
503 * Setter for embedded.
505 * @param bool $embedded
509 public function setEmbedded($embedded) {
510 $this->_embedded
= $embedded;
514 * Getter for embedded.
517 * return the embedded value
519 public function getEmbedded() {
520 return $this->_embedded
;
530 public function setPrint($print) {
531 $this->_print
= $print;
538 * return the print value
540 public function getPrint() {
541 return $this->_print
;
547 public function setDynamicAction($value) {
548 $this->_dynamicAction
= $value;
554 public function getDynamicAction() {
555 return $this->_dynamicAction
;