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