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