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