Merge pull request #4696 from colemanw/CRM-15669
[civicrm-core.git] / CRM / Contribute / Page / ContributionPage.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
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-2014
32 * $Id$
33 *
34 */
35
36 /**
37 * Create a page for displaying Contribute Pages
38 * Contribute Pages are pages that are used to display
39 * contributions of different types. Pages consist
40 * of many customizable sections which can be
41 * accessed.
42 *
43 * This page provides a top level browse view
44 * of all the contribution pages in the system.
45 *
46 */
47 class CRM_Contribute_Page_ContributionPage extends CRM_Core_Page {
48
49 /**
50 * The action links that we need to display for the browse screen
51 *
52 * @var array
53 */
54 private static $_actionLinks;
55 private static $_contributionLinks;
56 private static $_configureActionLinks;
57 private static $_onlineContributionLinks;
58
59 /**
60 * @var CRM_Utils_Pager
61 */
62 protected $_pager = NULL;
63
64 /**
65 * @var string
66 */
67 protected $_sortByCharacter;
68
69 /**
70 * Get the action links for this page.
71 *
72 * @return array
73 */
74 function &actionLinks() {
75 // check if variable _actionsLinks is populated
76 if (!isset(self::$_actionLinks)) {
77 // helper variable for nicer formatting
78 $deleteExtra = ts('Are you sure you want to delete this Contribution page?');
79 $copyExtra = ts('Are you sure you want to make a copy of this Contribution page?');
80
81 self::$_actionLinks = array(
82 CRM_Core_Action::COPY => array(
83 'name' => ts('Make a Copy'),
84 'url' => CRM_Utils_System::currentPath(),
85 'qs' => 'action=copy&gid=%%id%%',
86 'title' => ts('Make a Copy of CiviCRM Contribution Page'),
87 'extra' => 'onclick = "return confirm(\'' . $copyExtra . '\');"',
88 ),
89 CRM_Core_Action::DISABLE => array(
90 'name' => ts('Disable'),
91 'title' => ts('Disable'),
92 'ref' => 'crm-enable-disable',
93 ),
94 CRM_Core_Action::ENABLE => array(
95 'name' => ts('Enable'),
96 'ref' => 'crm-enable-disable',
97 'title' => ts('Enable'),
98 ),
99 CRM_Core_Action::DELETE => array(
100 'name' => ts('Delete'),
101 'url' => CRM_Utils_System::currentPath(),
102 'qs' => 'action=delete&reset=1&id=%%id%%',
103 'title' => ts('Delete Custom Field'),
104 'extra' => 'onclick = "return confirm(\'' . $deleteExtra . '\');"',
105 ),
106 );
107 }
108 return self::$_actionLinks;
109 }
110
111 /**
112 * Get the configure action links for this page.
113 *
114 * @return array
115 */
116 public function &configureActionLinks() {
117 // check if variable _actionsLinks is populated
118 if (!isset(self::$_configureActionLinks)) {
119 $urlString = 'civicrm/admin/contribute/';
120 $urlParams = 'reset=1&action=update&id=%%id%%';
121
122 self::$_configureActionLinks = array(
123 CRM_Core_Action::ADD => array(
124 'name' => ts('Title and Settings'),
125 'title' => ts('Title and Settings'),
126 'url' => $urlString . 'settings',
127 'qs' => $urlParams,
128 'uniqueName' => 'settings',
129 ),
130 CRM_Core_Action::UPDATE => array(
131 'name' => ts('Contribution Amounts'),
132 'title' => ts('Contribution Amounts'),
133 'url' => $urlString . 'amount',
134 'qs' => $urlParams,
135 'uniqueName' => 'amount',
136 ),
137 CRM_Core_Action::VIEW => array(
138 'name' => ts('Membership Settings'),
139 'title' => ts('Membership Settings'),
140 'url' => $urlString . 'membership',
141 'qs' => $urlParams,
142 'uniqueName' => 'membership',
143 ),
144 CRM_Core_Action::EXPORT => array(
145 'name' => ts('Thank-you and Receipting'),
146 'title' => ts('Thank-you and Receipting'),
147 'url' => $urlString . 'thankyou',
148 'qs' => $urlParams,
149 'uniqueName' => 'thankyou',
150 ),
151 CRM_Core_Action::BASIC => array(
152 'name' => ts('Tell a Friend'),
153 'title' => ts('Tell a Friend'),
154 'url' => $urlString . 'friend',
155 'qs' => $urlParams,
156 'uniqueName' => 'friend',
157 ),
158 CRM_Core_Action::PROFILE => array(
159 'name' => ts('Include Profiles'),
160 'title' => ts('Include Profiles'),
161 'url' => $urlString . 'custom',
162 'qs' => $urlParams,
163 'uniqueName' => 'custom',
164 ),
165 CRM_Core_Action::MAP => array(
166 'name' => ts('Contribution Widget'),
167 'title' => ts('Contribution Widget'),
168 'url' => $urlString . 'widget',
169 'qs' => $urlParams,
170 'uniqueName' => 'widget',
171 ),
172 CRM_Core_Action::FOLLOWUP => array(
173 'name' => ts('Premiums'),
174 'title' => ts('Premiums'),
175 'url' => $urlString . 'premium',
176 'qs' => $urlParams,
177 'uniqueName' => 'premium',
178 ),
179 CRM_Core_Action::ADVANCED => array(
180 'name' => ts('Personal Campaign Pages'),
181 'title' => ts('Personal Campaign Pages'),
182 'url' => $urlString . 'pcp',
183 'qs' => $urlParams,
184 'uniqueName' => 'pcp',
185 ),
186 );
187 }
188
189 return self::$_configureActionLinks;
190 }
191
192 /**
193 * Get the online contribution links.
194 *
195 * @return array
196 */
197 public function &onlineContributionLinks() {
198 if (!isset(self::$_onlineContributionLinks)) {
199 $urlString = 'civicrm/contribute/transact';
200 $urlParams = 'reset=1&id=%%id%%';
201 self::$_onlineContributionLinks = array(
202 CRM_Core_Action::RENEW => array(
203 'name' => ts('Live Page'),
204 'title' => ts('Live Page'),
205 'url' => $urlString,
206 'qs' => $urlParams,
207 'fe' => TRUE,
208 'uniqueName' => 'live_page',
209 ),
210 CRM_Core_Action::PREVIEW => array(
211 'name' => ts('Test-drive'),
212 'title' => ts('Test-drive'),
213 'url' => $urlString,
214 'qs' => $urlParams . '&action=preview',
215 'uniqueName' => 'test_drive',
216 ),
217 );
218 }
219
220 return self::$_onlineContributionLinks;
221 }
222
223 /**
224 * Get the contributions links.
225 *
226 * @return array
227 */
228 public function &contributionLinks() {
229 if (!isset(self::$_contributionLinks)) {
230 //get contribution dates.
231 $dates = CRM_Contribute_BAO_Contribution::getContributionDates();
232 $now = $dates['now'];
233 $yearDate = $dates['yearDate'];
234 $monthDate = $dates['monthDate'];
235 $yearNow = $yearDate + 10000;
236
237 $urlString = 'civicrm/contribute/search';
238 $urlParams = 'reset=1&pid=%%id%%&force=1&test=0';
239
240 self::$_contributionLinks = array(
241 CRM_Core_Action::DETACH => array(
242 'name' => ts('Current Month-To-Date'),
243 'title' => ts('Current Month-To-Date'),
244 'url' => $urlString,
245 'qs' => "{$urlParams}&start={$monthDate}&end={$now}",
246 'uniqueName' => 'current_month_to_date',
247 ),
248 CRM_Core_Action::REVERT => array(
249 'name' => ts('Fiscal Year-To-Date'),
250 'title' => ts('Fiscal Year-To-Date'),
251 'url' => $urlString,
252 'qs' => "{$urlParams}&start={$yearDate}&end={$yearNow}",
253 'uniqueName' => 'fiscal_year_to_date',
254 ),
255 CRM_Core_Action::BROWSE => array(
256 'name' => ts('Cumulative'),
257 'title' => ts('Cumulative'),
258 'url' => $urlString,
259 'qs' => "{$urlParams}&start=&end=$now",
260 'uniqueName' => 'cumulative',
261 ),
262 );
263 }
264
265 return self::$_contributionLinks;
266 }
267
268 /**
269 * Run the page.
270 *
271 * This method is called after the page is created. It checks for the
272 * type of action and executes that action.
273 * Finally it calls the parent's run method.
274 *
275 * @return mixed
276 */
277 public function run() {
278 // get the requested action
279 $action = CRM_Utils_Request::retrieve('action', 'String',
280 // default to 'browse'
281 $this, FALSE, 'browse'
282 );
283
284 // assign vars to templates
285 $this->assign('action', $action);
286 $id = CRM_Utils_Request::retrieve('id', 'Positive',
287 $this, FALSE, 0
288 );
289
290 // set breadcrumb to append to 2nd layer pages
291 $breadCrumb = array(array('title' => ts('Manage Contribution Pages'),
292 'url' => CRM_Utils_System::url(CRM_Utils_System::currentPath(),
293 'reset=1'
294 ),
295 ));
296
297 // what action to take ?
298 if ($action & CRM_Core_Action::ADD) {
299 $session = CRM_Core_Session::singleton();
300 $session->pushUserContext(CRM_Utils_System::url(CRM_Utils_System::currentPath(),
301 'action=browse&reset=1'
302 ));
303
304 $controller = new CRM_Contribute_Controller_ContributionPage(NULL, $action);
305 CRM_Utils_System::setTitle(ts('Manage Contribution Page'));
306 CRM_Utils_System::appendBreadCrumb($breadCrumb);
307 return $controller->run();
308 }
309 elseif ($action & CRM_Core_Action::UPDATE) {
310 $config = CRM_Core_Config::singleton();
311
312 // assign vars to templates
313 $this->assign('id', $id);
314 $this->assign('title', CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_ContributionPage', $id, 'title'));
315 $this->assign('is_active', CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_ContributionPage', $id, 'is_active'));
316 if (in_array('CiviMember', $config->enableComponents)) {
317 $this->assign('CiviMember', TRUE);
318 }
319 }
320 elseif ($action & CRM_Core_Action::COPY) {
321 // @todo Unused local variable can be safely removed.
322 // But are there any side effects of CRM_Core_Session::singleton() that we
323 // need to preserve?
324 $session = CRM_Core_Session::singleton();
325 CRM_Core_Session::setStatus(ts('A copy of the contribution page has been created'), ts('Successfully Copied'), 'success');
326 $this->copy();
327 }
328 elseif ($action & CRM_Core_Action::DELETE) {
329 CRM_Utils_System::appendBreadCrumb($breadCrumb);
330
331 $session = CRM_Core_Session::singleton();
332 $session->pushUserContext(CRM_Utils_System::url(CRM_Utils_System::currentPath(),
333 'reset=1&action=browse'
334 ));
335
336 $id = CRM_Utils_Request::retrieve('id', 'Positive',
337 $this, FALSE, 0
338 );
339 $query = "
340 SELECT ccp.title
341 FROM civicrm_contribution_page ccp
342 JOIN civicrm_pcp cp ON ccp.id = cp.page_id
343 WHERE cp.page_id = {$id}
344 AND cp.page_type = 'contribute'
345 ";
346
347 if ($pageTitle = CRM_Core_DAO::singleValueQuery($query)) {
348 CRM_Core_Session::setStatus(ts('The \'%1\' cannot be deleted! You must Delete all Personal Campaign Page(s) related with this contribution page prior to deleting the page.', array(1 => $pageTitle)), ts('Deletion Error'), 'error');
349
350 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/admin/contribute', 'reset=1'));
351 }
352
353 $controller = new CRM_Core_Controller_Simple('CRM_Contribute_Form_ContributionPage_Delete',
354 'Delete Contribution Page',
355 CRM_Core_Action::DELETE
356 );
357 $controller->set('id', $id);
358 $controller->process();
359 return $controller->run();
360 }
361 else {
362 // finally browse the contribution pages
363 $this->browse();
364
365 CRM_Utils_System::setTitle(ts('Manage Contribution Pages'));
366 }
367
368 return parent::run();
369 }
370
371 /**
372 * This function is to make a copy of a contribution page, including
373 * all the fields in the page
374 *
375 * @return void
376 */
377 public function copy() {
378 $gid = CRM_Utils_Request::retrieve('gid', 'Positive',
379 $this, TRUE, 0, 'GET'
380 );
381
382 CRM_Contribute_BAO_ContributionPage::copy($gid);
383
384 CRM_Utils_System::redirect(CRM_Utils_System::url(CRM_Utils_System::currentPath(), 'reset=1'));
385 }
386
387 /**
388 * Browse all contribution pages
389 *
390 * @param mixed $action
391 * Unused parameter.
392 * @static
393 */
394 public function browse($action = NULL) {
395 $this->_sortByCharacter = CRM_Utils_Request::retrieve('sortByCharacter',
396 'String',
397 $this
398 );
399 // @todo Unused local variable can be safely removed.
400 // But are there any side effects of CRM_Utils_Request::retrieve() that we
401 // need to preserve?
402 $createdId = CRM_Utils_Request::retrieve('cid', 'Positive',
403 $this, FALSE, 0
404 );
405
406 if ($this->_sortByCharacter == 1 ||
407 !empty($_POST)
408 ) {
409 $this->_sortByCharacter = '';
410 $this->set('sortByCharacter', '');
411 }
412
413 $this->search();
414
415 $params = array();
416
417 $whereClause = $this->whereClause($params, FALSE);
418 $this->pagerAToZ($whereClause, $params);
419
420 $params = array();
421 $whereClause = $this->whereClause($params, TRUE);
422 $this->pager($whereClause, $params);
423
424 list($offset, $rowCount) = $this->_pager->getOffsetAndRowCount();
425
426 //check for delete CRM-4418
427 $allowToDelete = CRM_Core_Permission::check('delete in CiviContribute');
428
429 $query = "
430 SELECT id
431 FROM civicrm_contribution_page
432 WHERE $whereClause
433 LIMIT $offset, $rowCount";
434 $contribPage = CRM_Core_DAO::executeQuery($query, $params, TRUE, 'CRM_Contribute_DAO_ContributionPage');
435 $contribPageIds = array();
436 while ($contribPage->fetch()) {
437 $contribPageIds[$contribPage->id] = $contribPage->id;
438 }
439 //get all section info.
440 $contriPageSectionInfo = CRM_Contribute_BAO_ContributionPage::getSectionInfo($contribPageIds);
441
442 $query = "
443 SELECT *
444 FROM civicrm_contribution_page
445 WHERE $whereClause
446 ORDER BY title asc
447 LIMIT $offset, $rowCount";
448
449 $dao = CRM_Core_DAO::executeQuery($query, $params, TRUE, 'CRM_Contribute_DAO_ContributionPage');
450
451 //get all campaigns.
452 $allCampaigns = CRM_Campaign_BAO_Campaign::getCampaigns(NULL, NULL, FALSE, FALSE, FALSE, TRUE);
453
454 //get configure actions links.
455 $configureActionLinks = self::configureActionLinks();
456
457 while ($dao->fetch()) {
458 $contribution[$dao->id] = array();
459 CRM_Core_DAO::storeValues($dao, $contribution[$dao->id]);
460
461 // form all action links
462 $action = array_sum(array_keys($this->actionLinks()));
463
464 //add configure actions links.
465 $action += array_sum(array_keys($configureActionLinks));
466
467 //add online contribution links.
468 $action += array_sum(array_keys(self::onlineContributionLinks()));
469
470 //add contribution search links.
471 $action += array_sum(array_keys(self::contributionLinks()));
472
473 if ($dao->is_active) {
474 $action -= (int)CRM_Core_Action::ENABLE;
475 }
476 else {
477 $action -= (int)CRM_Core_Action::DISABLE;
478 }
479
480 //CRM-4418
481 if (!$allowToDelete) {
482 $action -= (int)CRM_Core_Action::DELETE;
483 }
484
485 //build the configure links.
486 $sectionsInfo = CRM_Utils_Array::value($dao->id, $contriPageSectionInfo, array());
487 $contribution[$dao->id]['configureActionLinks'] = CRM_Core_Action::formLink(self::formatConfigureLinks($sectionsInfo),
488 $action,
489 array('id' => $dao->id),
490 ts('Configure'),
491 TRUE,
492 'contributionpage.configure.actions',
493 'ContributionPage',
494 $dao->id
495 );
496
497 //build the contributions links.
498 $contribution[$dao->id]['contributionLinks'] = CRM_Core_Action::formLink(self::contributionLinks(),
499 $action,
500 array('id' => $dao->id),
501 ts('Contributions'),
502 TRUE,
503 'contributionpage.contributions.search',
504 'ContributionPage',
505 $dao->id
506 );
507
508 //build the online contribution links.
509 $contribution[$dao->id]['onlineContributionLinks'] = CRM_Core_Action::formLink(self::onlineContributionLinks(),
510 $action,
511 array('id' => $dao->id),
512 ts('Links'),
513 TRUE,
514 'contributionpage.online.links',
515 'ContributionPage',
516 $dao->id
517 );
518
519 //build the normal action links.
520 $contribution[$dao->id]['action'] = CRM_Core_Action::formLink(self::actionLinks(),
521 $action,
522 array('id' => $dao->id),
523 ts('more'),
524 TRUE,
525 'contributionpage.action.links',
526 'ContributionPage',
527 $dao->id
528 );
529
530 //show campaigns on selector.
531 $contribution[$dao->id]['campaign'] = CRM_Utils_Array::value($dao->campaign_id, $allCampaigns);
532 }
533
534 if (isset($contribution)) {
535 $this->assign('rows', $contribution);
536 }
537 }
538
539 public function search() {
540 if (isset($this->_action) &
541 (CRM_Core_Action::ADD |
542 CRM_Core_Action::UPDATE |
543 CRM_Core_Action::DELETE
544 )
545 ) {
546 return;
547 }
548
549 $form = new CRM_Core_Controller_Simple('CRM_Contribute_Form_SearchContribution',
550 ts('Search Contribution'),
551 CRM_Core_Action::ADD
552 );
553 $form->setEmbedded(TRUE);
554 $form->setParent($this);
555 $form->process();
556 $form->run();
557 }
558
559 /**
560 * @param array $params
561 * @param bool $sortBy
562 *
563 * @return int|string
564 */
565 public function whereClause(&$params, $sortBy = TRUE) {
566 // @todo Unused local variable can be safely removed.
567 $values = $clauses = array();
568 $title = $this->get('title');
569 $createdId = $this->get('cid');
570
571 if ($createdId) {
572 $clauses[] = "(created_id = {$createdId})";
573 }
574
575 if ($title) {
576 $clauses[] = "title LIKE %1";
577 if (strpos($title, '%') !== FALSE) {
578 $params[1] = array(trim($title), 'String', FALSE);
579 }
580 else {
581 $params[1] = array(trim($title), 'String', TRUE);
582 }
583 }
584
585 $value = $this->get( 'financial_type_id' );
586 $val = array();
587 if ($value) {
588 if (is_array($value)) {
589 foreach ($value as $k => $v) {
590 if ($v) {
591 $val[$k] = $k;
592 }
593 }
594 $type = implode(',', $val);
595 }
596 // @todo Variable 'type' might not have been defined.
597 $clauses[] = "financial_type_id IN ({$type})";
598 }
599
600 if ($sortBy && $this->_sortByCharacter !== NULL) {
601 $clauses[] = "title LIKE '" . strtolower(CRM_Core_DAO::escapeWildCardString($this->_sortByCharacter)) . "%'";
602 }
603
604 $campaignIds = $this->getCampaignIds();
605 if (count($campaignIds) >= 1) {
606 $clauses[] = '( campaign_id IN ( ' . implode(' , ', $campaignIds) . ' ) )';
607 }
608
609 if (empty($clauses)) {
610 // Let template know if user has run a search or not
611 $this->assign('isSearch', 0);
612 return 1;
613 }
614 else {
615 $this->assign('isSearch', 1);
616 }
617
618 return implode(' AND ', $clauses);
619 }
620
621 /**
622 * Gets the campaign ids from the session.
623 *
624 * @return int[]
625 */
626 function getCampaignIds() {
627 // The unfiltered value from the session cannot be trusted, it needs to be
628 // processed to get a clean array of positive integers.
629 $ids = array();
630 foreach ((array)$this->get('campaign_id') as $id) {
631 if ((string)(int)$id === (string)$id && $id > 0) {
632 $ids[] = $id;
633 }
634 }
635 return $ids;
636 }
637
638 /**
639 * @param $whereClause
640 * @param array $whereParams
641 */
642 function pager($whereClause, $whereParams) {
643
644 $params['status'] = ts('Contribution %%StatusMessage%%');
645 $params['csvString'] = NULL;
646 $params['buttonTop'] = 'PagerTopButton';
647 $params['buttonBottom'] = 'PagerBottomButton';
648 $params['rowCount'] = $this->get(CRM_Utils_Pager::PAGE_ROWCOUNT);
649 if (!$params['rowCount']) {
650 $params['rowCount'] = CRM_Utils_Pager::ROWCOUNT;
651 }
652
653 $query = "
654 SELECT count(id)
655 FROM civicrm_contribution_page
656 WHERE $whereClause";
657
658 $params['total'] = CRM_Core_DAO::singleValueQuery($query, $whereParams);
659
660 $this->_pager = new CRM_Utils_Pager($params);
661 $this->assign_by_ref('pager', $this->_pager);
662 }
663
664 /**
665 * @param $whereClause
666 * @param array $whereParams
667 */
668 public function pagerAtoZ($whereClause, $whereParams) {
669
670 $query = "
671 SELECT DISTINCT UPPER(LEFT(title, 1)) as sort_name
672 FROM civicrm_contribution_page
673 WHERE $whereClause
674 ORDER BY LEFT(title, 1)
675 ";
676 $dao = CRM_Core_DAO::executeQuery($query, $whereParams);
677
678 $aToZBar = CRM_Utils_PagerAToZ::getAToZBar($dao, $this->_sortByCharacter, TRUE);
679 $this->assign('aToZ', $aToZBar);
680 }
681
682 /**
683 * @param array $sectionsInfo
684 *
685 * @return array
686 */
687 public function formatConfigureLinks($sectionsInfo) {
688 // build the formatted configure links.
689 $formattedConfLinks = self::configureActionLinks();
690 foreach ($formattedConfLinks as $act => & $link) {
691 $sectionName = CRM_Utils_Array::value('uniqueName', $link);
692 if (!$sectionName) {
693 continue;
694 }
695
696 if (empty($sectionsInfo[$sectionName])) {
697 $classes = array();
698 if (isset($link['class'])) {
699 $classes = $link['class'];
700 }
701 $link['class'] = array_merge($classes, array('disabled'));
702 }
703 }
704
705 return $formattedConfLinks;
706 }
707 }