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