Merge pull request #13837 from eileenmcnaughton/event_conf
[civicrm-core.git] / CRM / PCP / BAO / PCP.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
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-2019
32 */
33 class CRM_PCP_BAO_PCP extends CRM_PCP_DAO_PCP {
34
35 /**
36 * The action links that we need to display for the browse screen.
37 *
38 * @var array
39 */
40 public static $_pcpLinks = NULL;
41
42 /**
43 * Class constructor.
44 */
45 public function __construct() {
46 parent::__construct();
47 }
48
49 /**
50 * Add or update either a Personal Campaign Page OR a PCP Block.
51 *
52 * @param array $params
53 * Values to create the pcp.
54 *
55 * @return object
56 */
57 public static function create($params) {
58
59 $dao = new CRM_PCP_DAO_PCP();
60 $dao->copyValues($params);
61
62 // ensure we set status_id since it is a not null field
63 // we should change the schema and allow this to be null
64 if (!$dao->id && !isset($dao->status_id)) {
65 $dao->status_id = 0;
66 }
67
68 // set currency for CRM-1496
69 if (!isset($dao->currency)) {
70 $dao->currency = CRM_Core_Config::singleton()->defaultCurrency;
71 }
72
73 $dao->save();
74 return $dao;
75 }
76
77 /**
78 * Get the Display name of a contact for a PCP.
79 *
80 * @param int $id
81 * Id for the PCP.
82 *
83 * @return null|string
84 * Dispaly name of the contact if found
85 */
86 public static function displayName($id) {
87 $id = CRM_Utils_Type::escape($id, 'Integer');
88
89 $query = "
90 SELECT civicrm_contact.display_name
91 FROM civicrm_pcp, civicrm_contact
92 WHERE civicrm_pcp.contact_id = civicrm_contact.id
93 AND civicrm_pcp.id = {$id}
94 ";
95 return CRM_Core_DAO::singleValueQuery($query);
96 }
97
98 /**
99 * Return PCP Block info for dashboard.
100 *
101 * @param int $contactId
102 *
103 * @return array
104 * array of Pcp if found
105 */
106 public static function getPcpDashboardInfo($contactId) {
107 $links = self::pcpLinks();
108
109 $query = "
110 SELECT pcp.*, block.is_tellfriend_enabled FROM civicrm_pcp pcp
111 LEFT JOIN civicrm_pcp_block block ON block.id = pcp.pcp_block_id
112 WHERE pcp.is_active = 1
113 AND pcp.contact_id = %1
114 ORDER BY page_type, page_id";
115
116 $params = [1 => [$contactId, 'Integer']];
117
118 $pcpInfoDao = CRM_Core_DAO::executeQuery($query, $params);
119 $pcpInfo = [];
120 $hide = $mask = array_sum(array_keys($links['all']));
121 $contactPCPPages = [];
122
123 $event = CRM_Event_PseudoConstant::event(NULL, FALSE, "( is_template IS NULL OR is_template != 1 )");
124 $contribute = CRM_Contribute_PseudoConstant::contributionPage();
125 $pcpStatus = CRM_Contribute_PseudoConstant::pcpStatus();
126 $approved = CRM_Utils_Array::key('Approved', $pcpStatus);
127
128 while ($pcpInfoDao->fetch()) {
129 $mask = $hide;
130 if ($links) {
131 $replace = [
132 'pcpId' => $pcpInfoDao->id,
133 'pcpBlock' => $pcpInfoDao->pcp_block_id,
134 'pageComponent' => $pcpInfoDao->page_type,
135 ];
136 }
137
138 $pcpLink = $links['all'];
139 $class = '';
140
141 if ($pcpInfoDao->status_id != $approved || $pcpInfoDao->is_active != 1) {
142 $class = 'disabled';
143 if (!$pcpInfoDao->is_tellfriend_enabled) {
144 $mask -= CRM_Core_Action::DETACH;
145 }
146 }
147
148 if ($pcpInfoDao->is_active == 1) {
149 $mask -= CRM_Core_Action::ENABLE;
150 }
151 else {
152 $mask -= CRM_Core_Action::DISABLE;
153 }
154 $action = CRM_Core_Action::formLink($pcpLink, $mask, $replace, ts('more'),
155 FALSE, 'pcp.dashboard.active', 'PCP', $pcpInfoDao->id);
156 $component = $pcpInfoDao->page_type;
157 $pageTitle = CRM_Utils_Array::value($pcpInfoDao->page_id, $$component);
158
159 $pcpInfo[] = [
160 'pageTitle' => $pageTitle,
161 'pcpId' => $pcpInfoDao->id,
162 'pcpTitle' => $pcpInfoDao->title,
163 'pcpStatus' => $pcpStatus[$pcpInfoDao->status_id],
164 'action' => $action,
165 'class' => $class,
166 ];
167 $contactPCPPages[$pcpInfoDao->page_type][] = $pcpInfoDao->page_id;
168 }
169
170 $excludePageClause = $clause = NULL;
171 if (!empty($contactPCPPages)) {
172 foreach ($contactPCPPages as $component => $entityIds) {
173 $excludePageClause[] = "
174 ( target_entity_type = '{$component}'
175 AND target_entity_id NOT IN ( " . implode(',', $entityIds) . ") )";
176 }
177
178 $clause = ' AND ' . implode(' OR ', $excludePageClause);
179 }
180
181 $query = "
182 SELECT *
183 FROM civicrm_pcp_block block
184 LEFT JOIN civicrm_pcp pcp ON pcp.pcp_block_id = block.id
185 WHERE block.is_active = 1
186 {$clause}
187 GROUP BY block.id, pcp.id
188 ORDER BY target_entity_type, target_entity_id
189 ";
190 $pcpBlockDao = CRM_Core_DAO::executeQuery($query);
191 $pcpBlock = [];
192 $mask = 0;
193
194 while ($pcpBlockDao->fetch()) {
195 if ($links) {
196 $replace = [
197 'pageId' => $pcpBlockDao->target_entity_id,
198 'pageComponent' => $pcpBlockDao->target_entity_type,
199 ];
200 }
201 $pcpLink = $links['add'];
202 $action = CRM_Core_Action::formLink($pcpLink, $mask, $replace, ts('more'),
203 FALSE, 'pcp.dashboard.other', "{$pcpBlockDao->target_entity_type}_PCP", $pcpBlockDao->target_entity_id);
204 $component = $pcpBlockDao->target_entity_type;
205 if ($pageTitle = CRM_Utils_Array::value($pcpBlockDao->target_entity_id, $$component)) {
206 $pcpBlock[] = [
207 'pageId' => $pcpBlockDao->target_entity_id,
208 'pageTitle' => $pageTitle,
209 'action' => $action,
210 ];
211 }
212 }
213
214 return [$pcpBlock, $pcpInfo];
215 }
216
217 /**
218 * Show the total amount for Personal Campaign Page on thermometer.
219 *
220 * @param array $pcpId
221 * Contains the pcp ID.
222 *
223 * @return float
224 * Total amount
225 */
226 public static function thermoMeter($pcpId) {
227 $query = "
228 SELECT SUM(cc.total_amount) as total
229 FROM civicrm_pcp pcp
230 LEFT JOIN civicrm_contribution_soft cs ON ( pcp.id = cs.pcp_id )
231 LEFT JOIN civicrm_contribution cc ON ( cs.contribution_id = cc.id)
232 WHERE pcp.id = %1 AND cc.contribution_status_id =1 AND cc.is_test = 0";
233
234 $params = [1 => [$pcpId, 'Integer']];
235 return CRM_Core_DAO::singleValueQuery($query, $params);
236 }
237
238 /**
239 * Show the amount, nickname on honor roll.
240 *
241 * @param array $pcpId
242 * Contains the pcp ID.
243 *
244 * @return array
245 */
246 public static function honorRoll($pcpId) {
247 $query = "
248 SELECT cc.id, cs.pcp_roll_nickname, cs.pcp_personal_note,
249 cc.total_amount, cc.currency
250 FROM civicrm_contribution cc
251 LEFT JOIN civicrm_contribution_soft cs ON cc.id = cs.contribution_id
252 WHERE cs.pcp_id = {$pcpId}
253 AND cs.pcp_display_in_roll = 1
254 AND contribution_status_id = 1
255 AND is_test = 0";
256 $dao = CRM_Core_DAO::executeQuery($query);
257 $honor = [];
258 while ($dao->fetch()) {
259 $honor[$dao->id]['nickname'] = ucwords($dao->pcp_roll_nickname);
260 $honor[$dao->id]['total_amount'] = CRM_Utils_Money::format($dao->total_amount, $dao->currency);
261 $honor[$dao->id]['personal_note'] = $dao->pcp_personal_note;
262 }
263 return $honor;
264 }
265
266 /**
267 * Get action links.
268 *
269 * @return array
270 * (reference) of action links
271 */
272 public static function &pcpLinks() {
273 if (!(self::$_pcpLinks)) {
274 $deleteExtra = ts('Are you sure you want to delete this Personal Campaign Page?') . '\n' . ts('This action cannot be undone.');
275
276 self::$_pcpLinks['add'] = [
277 CRM_Core_Action::ADD => [
278 'name' => ts('Create a Personal Campaign Page'),
279 'class' => 'no-popup',
280 'url' => 'civicrm/contribute/campaign',
281 'qs' => 'action=add&reset=1&pageId=%%pageId%%&component=%%pageComponent%%',
282 'title' => ts('Configure'),
283 ],
284 ];
285
286 self::$_pcpLinks['all'] = [
287 CRM_Core_Action::UPDATE => [
288 'name' => ts('Edit Your Page'),
289 'url' => 'civicrm/pcp/info',
290 'qs' => 'action=update&reset=1&id=%%pcpId%%&component=%%pageComponent%%',
291 'title' => ts('Configure'),
292 ],
293 CRM_Core_Action::DETACH => [
294 'name' => ts('Tell Friends'),
295 'url' => 'civicrm/friend',
296 'qs' => 'eid=%%pcpId%%&blockId=%%pcpBlock%%&reset=1&pcomponent=pcp&component=%%pageComponent%%',
297 'title' => ts('Tell Friends'),
298 ],
299 CRM_Core_Action::VIEW => [
300 'name' => ts('URL for this Page'),
301 'url' => 'civicrm/pcp/info',
302 'qs' => 'reset=1&id=%%pcpId%%&component=%%pageComponent%%',
303 'title' => ts('URL for this Page'),
304 ],
305 CRM_Core_Action::BROWSE => [
306 'name' => ts('Update Contact Information'),
307 'url' => 'civicrm/pcp/info',
308 'qs' => 'action=browse&reset=1&id=%%pcpId%%&component=%%pageComponent%%',
309 'title' => ts('Update Contact Information'),
310 ],
311 CRM_Core_Action::ENABLE => [
312 'name' => ts('Enable'),
313 'url' => 'civicrm/pcp',
314 'qs' => 'action=enable&reset=1&id=%%pcpId%%&component=%%pageComponent%%',
315 'title' => ts('Enable'),
316 ],
317 CRM_Core_Action::DISABLE => [
318 'name' => ts('Disable'),
319 'url' => 'civicrm/pcp',
320 'qs' => 'action=disable&reset=1&id=%%pcpId%%&component=%%pageComponent%%',
321 'title' => ts('Disable'),
322 ],
323 CRM_Core_Action::DELETE => [
324 'name' => ts('Delete'),
325 'url' => 'civicrm/pcp',
326 'qs' => 'action=delete&reset=1&id=%%pcpId%%&component=%%pageComponent%%',
327 'extra' => 'onclick = "return confirm(\'' . $deleteExtra . '\');"',
328 'title' => ts('Delete'),
329 ],
330 ];
331 }
332 return self::$_pcpLinks;
333 }
334
335 /**
336 * Delete the campaign page.
337 *
338 * @param int $id
339 * Campaign page id.
340 */
341 public static function deleteById($id) {
342 CRM_Utils_Hook::pre('delete', 'Campaign', $id, CRM_Core_DAO::$_nullArray);
343
344 $transaction = new CRM_Core_Transaction();
345
346 // delete from pcp table
347 $pcp = new CRM_PCP_DAO_PCP();
348 $pcp->id = $id;
349 $pcp->delete();
350
351 $transaction->commit();
352
353 CRM_Utils_Hook::post('delete', 'Campaign', $id, $pcp);
354 }
355
356 /**
357 * Build the form object.
358 *
359 * @param CRM_Core_Form $form
360 * Form object.
361 */
362 public static function buildPCPForm($form) {
363 $form->addElement('checkbox', 'pcp_active', ts('Enable Personal Campaign Pages?'), NULL, ['onclick' => "return showHideByValue('pcp_active',true,'pcpFields','block','radio',false);"]);
364
365 $form->addElement('checkbox', 'is_approval_needed', ts('Approval required'));
366
367 $profile = [];
368 $isUserRequired = NULL;
369 $config = CRM_Core_Config::singleton();
370 if ($config->userFramework != 'Standalone') {
371 $isUserRequired = 2;
372 }
373 CRM_Core_DAO::commonRetrieveAll('CRM_Core_DAO_UFGroup', 'is_cms_user', $isUserRequired, $profiles, [
374 'title',
375 'is_active',
376 ]);
377 if (!empty($profiles)) {
378 foreach ($profiles as $key => $value) {
379 if ($value['is_active']) {
380 $profile[$key] = $value['title'];
381 }
382 }
383 $form->assign('profile', $profile);
384 }
385
386 $form->add('select', 'supporter_profile_id', ts('Supporter Profile'), ['' => ts('- select -')] + $profile, TRUE);
387
388 //CRM-15821 - To add new option for PCP "Owner" notification
389 $ownerNotifications = CRM_Core_OptionGroup::values('pcp_owner_notify');
390 $form->addRadio('owner_notify_id', ts('Owner Email Notification'), $ownerNotifications, NULL, '<br/>', TRUE);
391
392 $form->addElement('checkbox', 'is_tellfriend_enabled', ts("Allow 'Tell a friend' functionality"), NULL, ['onclick' => "return showHideByValue('is_tellfriend_enabled',true,'tflimit','table-row','radio',false);"]);
393
394 $form->add('number',
395 'tellfriend_limit',
396 ts("'Tell a friend' maximum recipients limit"),
397 CRM_Core_DAO::getAttribute('CRM_PCP_DAO_PCPBlock', 'tellfriend_limit')
398 );
399 $form->addRule('tellfriend_limit', ts('Please enter a valid limit.'), 'integer');
400
401 $form->add('text',
402 'link_text',
403 ts("'Create Personal Campaign Page' link text"),
404 CRM_Core_DAO::getAttribute('CRM_PCP_DAO_PCPBlock', 'link_text')
405 );
406
407 $form->add('text', 'notify_email', ts('Notify Email'), CRM_Core_DAO::getAttribute('CRM_PCP_DAO_PCPBlock', 'notify_email'));
408 }
409
410 /**
411 * Add PCP form elements to a form.
412 *
413 * @param int $pcpId
414 * @param CRM_Core_Form $page
415 * @param null $elements
416 */
417 public static function buildPcp($pcpId, &$page, &$elements = NULL) {
418
419 $prms = ['id' => $pcpId];
420 CRM_Core_DAO::commonRetrieve('CRM_PCP_DAO_PCP', $prms, $pcpInfo);
421 if ($pcpSupporter = CRM_PCP_BAO_PCP::displayName($pcpId)) {
422 if ($pcpInfo['page_type'] == 'event') {
423 $pcp_supporter_text = ts('This event registration is being made thanks to the efforts of <strong>%1</strong>, who supports our campaign. ', [1 => $pcpSupporter]);
424 $text = CRM_PCP_BAO_PCP::getPcpBlockStatus($pcpInfo['page_id'], 'event');
425 if (!empty($text)) {
426 $pcp_supporter_text .= "You can support it as well - once you complete the registration, you will be able to create your own Personal Campaign Page!";
427 }
428 }
429 else {
430 $pcp_supporter_text = ts('This contribution is being made thanks to the efforts of <strong>%1</strong>, who supports our campaign. ', [1 => $pcpSupporter]);
431 $text = CRM_PCP_BAO_PCP::getPcpBlockStatus($pcpInfo['page_id'], 'contribute');
432 if (!empty($text)) {
433 $pcp_supporter_text .= "You can support it as well - once you complete the donation, you will be able to create your own Personal Campaign Page!";
434 }
435 }
436
437 $page->assign('pcpSupporterText', $pcp_supporter_text);
438 }
439 $page->assign('pcp', TRUE);
440
441 // build honor roll fields for registration form if supporter has honor roll enabled for their PCP
442 if ($pcpInfo['is_honor_roll']) {
443 $page->assign('is_honor_roll', TRUE);
444 $page->add('checkbox', 'pcp_display_in_roll', ts('Show my support in the public honor roll'), NULL, NULL,
445 ['onclick' => "showHideByValue('pcp_display_in_roll','','nameID|nickID|personalNoteID','block','radio',false); pcpAnonymous( );"]
446 );
447 $extraOption = ['onclick' => "return pcpAnonymous( );"];
448 $elements = [];
449 $elements[] = &$page->createElement('radio', NULL, '', ts('Include my name and message'), 0, $extraOption);
450 $elements[] = &$page->createElement('radio', NULL, '', ts('List my support anonymously'), 1, $extraOption);
451 $page->addGroup($elements, 'pcp_is_anonymous', NULL, '&nbsp;&nbsp;&nbsp;');
452 $page->_defaults['pcp_is_anonymous'] = 0;
453
454 $page->add('text', 'pcp_roll_nickname', ts('Name'), ['maxlength' => 30]);
455 $page->addField('pcp_personal_note', ['entity' => 'ContributionSoft', 'context' => 'create', 'style' => 'height: 3em; width: 40em;']);
456 }
457 else {
458 $page->assign('is_honor_roll', FALSE);
459 }
460 }
461
462 /**
463 * Process a PCP contribution.
464 *
465 * @param int $pcpId
466 * @param string $component
467 * @param string $entity
468 *
469 * @return array
470 */
471 public static function handlePcp($pcpId, $component, $entity) {
472
473 self::getPcpEntityTable($component);
474
475 if (!$pcpId) {
476 return FALSE;
477 }
478
479 $pcpStatus = CRM_Core_PseudoConstant::get('CRM_PCP_BAO_PCP', 'status_id');
480 $approvedId = array_search('Approved', $pcpStatus);
481
482 $params = ['id' => $pcpId];
483 CRM_Core_DAO::commonRetrieve('CRM_PCP_DAO_PCP', $params, $pcpInfo);
484
485 $params = ['id' => $pcpInfo['pcp_block_id']];
486 CRM_Core_DAO::commonRetrieve('CRM_PCP_DAO_PCPBlock', $params, $pcpBlock);
487
488 $params = ['id' => $pcpInfo['page_id']];
489 $now = time();
490
491 if ($component == 'event') {
492 // figure out where to redirect if an exception occurs below based on target entity
493 $urlBase = 'civicrm/event/register';
494
495 // ignore startDate for events - PCP's can be active long before event start date
496 $startDate = 0;
497 $endDate = CRM_Utils_Date::unixTime(CRM_Utils_Array::value('end_date', $entity));
498 }
499 elseif ($component == 'contribute') {
500 $urlBase = 'civicrm/contribute/transact';
501 //start and end date of the contribution page
502 $startDate = CRM_Utils_Date::unixTime(CRM_Utils_Array::value('start_date', $entity));
503 $endDate = CRM_Utils_Date::unixTime(CRM_Utils_Array::value('end_date', $entity));
504 }
505
506 // define redirect url back to contrib page or event if needed
507 $url = CRM_Utils_System::url($urlBase, "reset=1&id={$pcpBlock['entity_id']}", FALSE, NULL, FALSE, TRUE);
508 $currentPCPStatus = CRM_Core_PseudoConstant::getName('CRM_PCP_BAO_PCP', 'status_id', $pcpInfo['status_id']);
509
510 if ($pcpBlock['target_entity_id'] != $entity['id']) {
511 $statusMessage = ts('This page is not related to the Personal Campaign Page you have just visited. However you can still make a contribution here.');
512 CRM_Core_Error::statusBounce($statusMessage, $url);
513 }
514 elseif ($currentPCPStatus !== 'Approved') {
515 $statusMessage = ts('The Personal Campaign Page you have just visited is currently %1. However you can still support the campaign here.', [1 => $pcpStatus[$pcpInfo['status_id']]]);
516 CRM_Core_Error::statusBounce($statusMessage, $url);
517 }
518 elseif (empty($pcpBlock['is_active'])) {
519 $statusMessage = ts('Personal Campaign Pages are currently not enabled for this contribution page. However you can still support the campaign here.');
520 CRM_Core_Error::statusBounce($statusMessage, $url);
521 }
522 elseif (empty($pcpInfo['is_active'])) {
523 $statusMessage = ts('The Personal Campaign Page you have just visited is currently inactive. However you can still support the campaign here.');
524 CRM_Core_Error::statusBounce($statusMessage, $url);
525 }
526 // Check if we're in range for contribution page start and end dates. for events, check if after event end date
527 elseif (($startDate && $startDate > $now) || ($endDate && $endDate < $now)) {
528 $customStartDate = CRM_Utils_Date::customFormat(CRM_Utils_Array::value('start_date', $entity));
529 $customEndDate = CRM_Utils_Date::customFormat(CRM_Utils_Array::value('end_date', $entity));
530 if ($startDate && $endDate) {
531 $statusMessage = ts('The Personal Campaign Page you have just visited is only active from %1 to %2. However you can still support the campaign here.',
532 [1 => $customStartDate, 2 => $customEndDate]
533 );
534 CRM_Core_Error::statusBounce($statusMessage, $url);
535 }
536 elseif ($startDate) {
537 $statusMessage = ts('The Personal Campaign Page you have just visited will be active beginning on %1. However you can still support the campaign here.', [1 => $customStartDate]);
538 CRM_Core_Error::statusBounce($statusMessage, $url);
539 }
540 elseif ($endDate) {
541 if ($component == 'event') {
542 // Target_entity is an event and the event is over, redirect to event info instead of event registration page.
543 $url = CRM_Utils_System::url('civicrm/event/info',
544 "reset=1&id={$pcpBlock['entity_id']}",
545 FALSE, NULL, FALSE, TRUE
546 );
547 $statusMessage = ts('The event linked to the Personal Campaign Page you have just visited is over (as of %1).', [1 => $customEndDate]);
548 CRM_Core_Error::statusBounce($statusMessage, $url);
549 }
550 else {
551 $statusMessage = ts('The Personal Campaign Page you have just visited is no longer active (as of %1). However you can still support the campaign here.', [1 => $customEndDate]);
552 CRM_Core_Error::statusBounce($statusMessage, $url);
553 }
554 }
555 }
556
557 return [
558 'pcpId' => $pcpId,
559 'pcpBlock' => $pcpBlock,
560 'pcpInfo' => $pcpInfo,
561 ];
562 }
563
564 /**
565 * Approve / Reject the campaign page.
566 *
567 * @param int $id
568 * Campaign page id.
569 *
570 * @param bool $is_active
571 */
572 public static function setIsActive($id, $is_active) {
573 switch ($is_active) {
574 case 0:
575 $is_active = 3;
576 break;
577
578 case 1:
579 $is_active = 2;
580 break;
581 }
582
583 CRM_Core_DAO::setFieldValue('CRM_PCP_DAO_PCP', $id, 'status_id', $is_active);
584
585 $pcpTitle = CRM_Core_DAO::getFieldValue('CRM_PCP_DAO_PCP', $id, 'title');
586 $pcpPageType = CRM_Core_DAO::getFieldValue('CRM_PCP_DAO_PCP', $id, 'page_type');
587
588 $pcpStatus = CRM_Core_OptionGroup::values("pcp_status");
589 $pcpStatus = $pcpStatus[$is_active];
590
591 CRM_Core_Session::setStatus(ts("%1 status has been updated to %2.", [
592 1 => $pcpTitle,
593 2 => $pcpStatus,
594 ]), 'Status Updated', 'success');
595
596 // send status change mail
597 $result = self::sendStatusUpdate($id, $is_active, FALSE, $pcpPageType);
598
599 if ($result) {
600 CRM_Core_Session::setStatus(ts("A notification email has been sent to the supporter."), ts('Email Sent'), 'success');
601 }
602 }
603
604 /**
605 * Send notification email to supporter.
606 *
607 * 1. when their PCP status is changed by site admin.
608 * 2. when supporter initially creates a Personal Campaign Page ($isInitial set to true).
609 *
610 * @param int $pcpId
611 * Campaign page id.
612 * @param int $newStatus
613 * Pcp status id.
614 * @param bool|int $isInitial is it the first time, campaign page has been created by the user
615 *
616 * @param string $component
617 *
618 * @throws Exception
619 * @return null
620 */
621 public static function sendStatusUpdate($pcpId, $newStatus, $isInitial = FALSE, $component = 'contribute') {
622 $pcpStatusName = CRM_Core_OptionGroup::values("pcp_status", FALSE, FALSE, FALSE, NULL, 'name');
623 $pcpStatus = CRM_Core_OptionGroup::values("pcp_status");
624 $config = CRM_Core_Config::singleton();
625
626 if (!isset($pcpStatus[$newStatus])) {
627 return FALSE;
628 }
629
630 require_once 'Mail/mime.php';
631
632 //set loginUrl
633 $loginURL = $config->userSystem->getLoginURL();
634
635 // used in subject templates
636 $contribPageTitle = self::getPcpPageTitle($pcpId, $component);
637
638 $tplParams = [
639 'loginUrl' => $loginURL,
640 'contribPageTitle' => $contribPageTitle,
641 'pcpId' => $pcpId,
642 ];
643
644 //get the default domain email address.
645 list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail();
646
647 if (!$domainEmailAddress || $domainEmailAddress == 'info@EXAMPLE.ORG') {
648 $fixUrl = CRM_Utils_System::url("civicrm/admin/domain", 'action=update&reset=1');
649 CRM_Core_Error::fatal(ts('The site administrator needs to enter a valid \'FROM Email Address\' in <a href="%1">Administer CiviCRM &raquo; Communications &raquo; FROM Email Addresses</a>. The email address used may need to be a valid mail account with your email service provider.', [1 => $fixUrl]));
650 }
651
652 $receiptFrom = '"' . $domainEmailName . '" <' . $domainEmailAddress . '>';
653
654 // get recipient (supporter) name and email
655 $params = ['id' => $pcpId];
656 CRM_Core_DAO::commonRetrieve('CRM_PCP_DAO_PCP', $params, $pcpInfo);
657 list($name, $address) = CRM_Contact_BAO_Contact_Location::getEmailDetails($pcpInfo['contact_id']);
658
659 // get pcp block info
660 list($blockId, $eid) = self::getPcpBlockEntityId($pcpId, $component);
661 $params = ['id' => $blockId];
662 CRM_Core_DAO::commonRetrieve('CRM_PCP_DAO_PCPBlock', $params, $pcpBlockInfo);
663
664 // assign urls required in email template
665 if ($pcpStatusName[$newStatus] == 'Approved') {
666 $tplParams['isTellFriendEnabled'] = $pcpBlockInfo['is_tellfriend_enabled'];
667 if ($pcpBlockInfo['is_tellfriend_enabled']) {
668 $pcpTellFriendURL = CRM_Utils_System::url('civicrm/friend',
669 "reset=1&eid=$pcpId&blockId=$blockId&pcomponent=pcp",
670 TRUE, NULL, FALSE, TRUE
671 );
672 $tplParams['pcpTellFriendURL'] = $pcpTellFriendURL;
673 }
674 }
675 $pcpInfoURL = CRM_Utils_System::url('civicrm/pcp/info',
676 "reset=1&id=$pcpId",
677 TRUE, NULL, FALSE, TRUE
678 );
679 $tplParams['pcpInfoURL'] = $pcpInfoURL;
680 $tplParams['contribPageTitle'] = $contribPageTitle;
681 if ($emails = CRM_Utils_Array::value('notify_email', $pcpBlockInfo)) {
682 $emailArray = explode(',', $emails);
683 $tplParams['pcpNotifyEmailAddress'] = $emailArray[0];
684 }
685 // get appropriate message based on status
686 $tplParams['pcpStatus'] = $pcpStatus[$newStatus];
687
688 $tplName = $isInitial ? 'pcp_supporter_notify' : 'pcp_status_change';
689
690 list($sent, $subject, $message, $html) = CRM_Core_BAO_MessageTemplate::sendTemplate(
691 [
692 'groupName' => 'msg_tpl_workflow_contribution',
693 'valueName' => $tplName,
694 'contactId' => $pcpInfo['contact_id'],
695 'tplParams' => $tplParams,
696 'from' => $receiptFrom,
697 'toName' => $name,
698 'toEmail' => $address,
699 ]
700 );
701 return $sent;
702 }
703
704 /**
705 * Enable / Disable the campaign page.
706 *
707 * @param int $id
708 * Campaign page id.
709 *
710 * @param bool $is_active
711 *
712 * @return bool
713 * true if we found and updated the object, else false
714 */
715 public static function setDisable($id, $is_active) {
716 return CRM_Core_DAO::setFieldValue('CRM_PCP_DAO_PCP', $id, 'is_active', $is_active);
717 }
718
719 /**
720 * Get pcp block is active.
721 *
722 * @param int $pcpId
723 * @param $component
724 *
725 * @return int
726 */
727 public static function getStatus($pcpId, $component) {
728 $query = "
729 SELECT pb.is_active
730 FROM civicrm_pcp pcp
731 LEFT JOIN civicrm_pcp_block pb ON ( pcp.page_id = pb.entity_id )
732 WHERE pcp.id = %1
733 AND pb.entity_table = %2";
734
735 $entity_table = self::getPcpEntityTable($component);
736
737 $params = [1 => [$pcpId, 'Integer'], 2 => [$entity_table, 'String']];
738 return CRM_Core_DAO::singleValueQuery($query, $params);
739 }
740
741 /**
742 * Get pcp block is enabled for component page.
743 *
744 * @param int $pageId
745 * @param $component
746 *
747 * @return string
748 */
749 public static function getPcpBlockStatus($pageId, $component) {
750 $query = "
751 SELECT pb.link_text as linkText
752 FROM civicrm_pcp_block pb
753 WHERE pb.is_active = 1 AND
754 pb.entity_id = %1 AND
755 pb.entity_table = %2";
756
757 $entity_table = self::getPcpEntityTable($component);
758
759 $params = [1 => [$pageId, 'Integer'], 2 => [$entity_table, 'String']];
760 return CRM_Core_DAO::singleValueQuery($query, $params);
761 }
762
763 /**
764 * Find out if the PCP block is in use by one or more PCP page.
765 *
766 * @param int $id
767 * Pcp block id.
768 *
769 * @return Bool
770 */
771 public static function getPcpBlockInUse($id) {
772 $query = "
773 SELECT count(*)
774 FROM civicrm_pcp pcp
775 WHERE pcp.pcp_block_id = %1";
776
777 $params = [1 => [$id, 'Integer']];
778 $result = CRM_Core_DAO::singleValueQuery($query, $params);
779 return $result > 0;
780 }
781
782 /**
783 * Get email is enabled for supporter's profile
784 *
785 * @param int $profileId
786 * Supporter's profile id.
787 *
788 * @return bool
789 */
790 public static function checkEmailProfile($profileId) {
791 $query = "
792 SELECT field_name
793 FROM civicrm_uf_field
794 WHERE field_name like 'email%' And is_active = 1 And uf_group_id = %1";
795
796 $params = [1 => [$profileId, 'Integer']];
797 $dao = CRM_Core_DAO::executeQuery($query, $params);
798 if (!$dao->fetch()) {
799 return TRUE;
800 }
801 return FALSE;
802 }
803
804 /**
805 * Obtain the title of page associated with a pcp.
806 *
807 * @param int $pcpId
808 * @param $component
809 *
810 * @return int
811 */
812 public static function getPcpPageTitle($pcpId, $component) {
813 if ($component == 'contribute') {
814 $query = "
815 SELECT cp.title
816 FROM civicrm_pcp pcp
817 LEFT JOIN civicrm_contribution_page as cp ON ( cp.id = pcp.page_id )
818 WHERE pcp.id = %1";
819 }
820 elseif ($component == 'event') {
821 $query = "
822 SELECT ce.title
823 FROM civicrm_pcp pcp
824 LEFT JOIN civicrm_event as ce ON ( ce.id = pcp.page_id )
825 WHERE pcp.id = %1";
826 }
827
828 $params = [1 => [$pcpId, 'Integer']];
829 return CRM_Core_DAO::singleValueQuery($query, $params);
830 }
831
832 /**
833 * Get pcp block & entity id given pcp id
834 *
835 * @param int $pcpId
836 * @param $component
837 *
838 * @return string
839 */
840 public static function getPcpBlockEntityId($pcpId, $component) {
841 $entity_table = self::getPcpEntityTable($component);
842
843 $query = "
844 SELECT pb.id as pcpBlockId, pb.entity_id
845 FROM civicrm_pcp pcp
846 LEFT JOIN civicrm_pcp_block pb ON ( pb.entity_id = pcp.page_id AND pb.entity_table = %2 )
847 WHERE pcp.id = %1";
848
849 $params = [1 => [$pcpId, 'Integer'], 2 => [$entity_table, 'String']];
850 $dao = CRM_Core_DAO::executeQuery($query, $params);
851 if ($dao->fetch()) {
852 return [$dao->pcpBlockId, $dao->entity_id];
853 }
854
855 return [];
856 }
857
858 /**
859 * Get pcp entity table given a component.
860 *
861 * @param $component
862 *
863 * @return string
864 */
865 public static function getPcpEntityTable($component) {
866 $entity_table_map = [
867 'event' => 'civicrm_event',
868 'civicrm_event' => 'civicrm_event',
869 'contribute' => 'civicrm_contribution_page',
870 'civicrm_contribution_page' => 'civicrm_contribution_page',
871 ];
872 return isset($entity_table_map[$component]) ? $entity_table_map[$component] : FALSE;
873 }
874
875 /**
876 * Get supporter profile id.
877 *
878 * @param int $component_id
879 * @param string $component
880 *
881 * @return int
882 */
883 public static function getSupporterProfileId($component_id, $component = 'contribute') {
884 $entity_table = self::getPcpEntityTable($component);
885
886 $query = "
887 SELECT pcp.supporter_profile_id
888 FROM civicrm_pcp_block pcp
889 INNER JOIN civicrm_uf_group ufgroup
890 ON pcp.supporter_profile_id = ufgroup.id
891 WHERE pcp.entity_id = %1
892 AND pcp.entity_table = %2
893 AND ufgroup.is_active = 1";
894
895 $params = [1 => [$component_id, 'Integer'], 2 => [$entity_table, 'String']];
896 if (!$supporterProfileId = CRM_Core_DAO::singleValueQuery($query, $params)) {
897 CRM_Core_Error::fatal(ts('Supporter profile is not set for this Personal Campaign Page or the profile is disabled. Please contact the site administrator if you need assistance.'));
898 }
899 else {
900 return $supporterProfileId;
901 }
902 }
903
904 /**
905 * Get owner notification id.
906 *
907 * @param int $component_id
908 * @param $component
909 *
910 * @return int
911 */
912 public static function getOwnerNotificationId($component_id, $component = 'contribute') {
913 $entity_table = self::getPcpEntityTable($component);
914 $query = "
915 SELECT pb.owner_notify_id
916 FROM civicrm_pcp_block pb
917 WHERE pb.entity_id = %1 AND pb.entity_table = %2";
918 $params = [1 => [$component_id, 'Integer'], 2 => [$entity_table, 'String']];
919 if (!$ownerNotificationId = CRM_Core_DAO::singleValueQuery($query, $params)) {
920 CRM_Core_Error::fatal(ts('Owner Notification is not set for this Personal Campaign Page. Please contact the site administrator if you need assistance.'));
921 }
922 else {
923 return $ownerNotificationId;
924 }
925 }
926
927 }