3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
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 |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
17 class CRM_Campaign_BAO_Campaign
extends CRM_Campaign_DAO_Campaign
{
20 * Takes an associative array and creates a campaign object.
22 * the function extract all the params it needs to initialize the create a
23 * contact object. the params array could contain additional unused name/value
26 * @param array $params
27 * (reference ) an assoc array of name/value pairs.
29 * @return CRM_Campaign_DAO_Campaign
30 * @throws \CRM_Core_Exception
32 public static function create(&$params) {
37 if (empty($params['id'])) {
38 if (empty($params['created_id'])) {
39 $params['created_id'] = CRM_Core_Session
::getLoggedInContactID();
42 if (empty($params['created_date'])) {
43 $params['created_date'] = date('YmdHis');
46 if (empty($params['name'])) {
47 $params['name'] = CRM_Utils_String
::titleToVar($params['title'], 64);
51 /* @var \CRM_Campaign_DAO_Campaign $campaign */
52 $campaign = self
::writeRecord($params);
54 /* Create the campaign group record */
55 $groupTableName = CRM_Contact_BAO_Group
::getTableName();
57 if (isset($params['groups']) && !empty($params['groups']['include']) && is_array($params['groups']['include'])) {
58 foreach ($params['groups']['include'] as $entityId) {
59 $dao = new CRM_Campaign_DAO_CampaignGroup();
60 $dao->campaign_id
= $campaign->id
;
61 $dao->entity_table
= $groupTableName;
62 $dao->entity_id
= $entityId;
63 $dao->group_type
= 'Include';
69 if (!empty($params['custom']) && is_array($params['custom'])) {
70 CRM_Core_BAO_CustomValueTable
::store($params['custom'], 'civicrm_campaign', $campaign->id
);
77 * Delete the campaign.
84 public static function del($id) {
86 self
::deleteRecord(['id' => $id]);
88 catch (CRM_Core_Exception
$e) {
95 * Retrieve DB object based on input parameters.
97 * It also stores all the retrieved values in the default array.
99 * @param array $params
100 * (reference ) an assoc array of name/value pairs.
101 * @param array $defaults
102 * (reference ) an assoc array to hold the flattened values.
104 * @return \CRM_Campaign_DAO_Campaign|null
106 public static function retrieve(&$params, &$defaults) {
107 $campaign = new CRM_Campaign_DAO_Campaign();
109 $campaign->copyValues($params);
111 if ($campaign->find(TRUE)) {
112 CRM_Core_DAO
::storeValues($campaign, $defaults);
119 * Return the all eligible campaigns w/ cache.
121 * @param int $includeId
122 * Lets include this campaign by force.
123 * @param int $excludeId
124 * Do not include this campaign.
125 * @param bool $onlyActive
126 * Consider only active campaigns.
128 * @param bool $onlyCurrent
129 * @param bool $appendDatesToTitle
130 * @param bool $forceAll
133 * $campaigns a set of campaigns.
135 public static function getCampaigns(
140 $appendDatesToTitle = FALSE,
150 'appendDatesToTitle',
153 foreach ($cacheKeyParams as $param) {
154 $cacheParam = $
$param;
158 $cacheKey .= '_' . $cacheParam;
161 if (!isset($campaigns[$cacheKey])) {
162 $where = ['( camp.title IS NOT NULL )'];
164 $where[] = "( camp.id != $excludeId )";
167 $where[] = '( camp.is_active = 1 )';
170 $where[] = '( camp.end_date IS NULL OR camp.end_date >= NOW() )';
172 $whereClause = implode(' AND ', $where);
174 $whereClause .= " OR ( camp.id = $includeId )";
179 $whereClause = '( 1 )';
187 FROM civicrm_campaign camp
189 Order By camp.title";
191 $campaign = CRM_Core_DAO
::executeQuery($query);
192 $campaigns[$cacheKey] = [];
193 $config = CRM_Core_Config
::singleton();
195 while ($campaign->fetch()) {
196 $title = $campaign->title
;
197 if ($appendDatesToTitle) {
199 foreach (['start_date', 'end_date'] as $date) {
200 if ($campaign->$date) {
201 $dates[] = CRM_Utils_Date
::customFormat($campaign->$date, $config->dateformatFull
);
204 if (!empty($dates)) {
205 $title .= ' (' . implode('-', $dates) . ')';
208 $campaigns[$cacheKey][$campaign->id
] = $title;
212 return $campaigns[$cacheKey];
216 * Wrapper to self::getCampaigns( )
217 * w/ permissions and component check.
219 * @param int $includeId
220 * @param int $excludeId
221 * @param bool $onlyActive
222 * @param bool $onlyCurrent
223 * @param bool $appendDatesToTitle
224 * @param bool $forceAll
225 * @param bool $doCheckForComponent
226 * @param bool $doCheckForPermissions
230 public static function getPermissionedCampaigns(
235 $appendDatesToTitle = FALSE,
237 $doCheckForComponent = TRUE,
238 $doCheckForPermissions = TRUE
246 'appendDatesToTitle',
247 'doCheckForComponent',
248 'doCheckForPermissions',
251 foreach ($cachekeyParams as $param) {
252 $cacheKeyParam = $
$param;
253 if (!$cacheKeyParam) {
256 $cacheKey .= '_' . $cacheKeyParam;
259 static $validCampaigns;
260 if (!isset($validCampaigns[$cacheKey])) {
264 'hasAccessCampaign' => FALSE,
265 'isCampaignEnabled' => FALSE,
268 //do check for component.
269 if ($doCheckForComponent) {
270 $campaigns['isCampaignEnabled'] = $isValid = self
::isCampaignEnable();
273 //do check for permissions.
274 if ($doCheckForPermissions) {
275 $campaigns['hasAccessCampaign'] = $isValid = self
::accessCampaign();
278 //finally retrieve campaigns from db.
280 $campaigns['campaigns'] = self
::getCampaigns($includeId,
290 $validCampaigns[$cacheKey] = $campaigns;
293 return $validCampaigns[$cacheKey];
297 * Is CiviCampaign enabled.
301 public static function isCampaignEnable(): bool {
302 return in_array('CiviCampaign', CRM_Core_Config
::singleton()->enableComponents
, TRUE);
306 * Retrieve campaigns for dashboard.
308 * @param array $params
309 * @param bool $onlyCount
313 public static function getCampaignSummary($params = [], $onlyCount = FALSE) {
316 //build the limit and order clause.
317 $limitClause = $orderByClause = $lookupTableJoins = NULL;
320 'sort' => 'start_date',
323 'sortOrder' => 'desc',
325 foreach ($sortParams as $name => $default) {
326 if (!empty($params[$name])) {
327 $sortParams[$name] = $params[$name];
331 //need to lookup tables.
332 $orderOnCampaignTable = TRUE;
333 if ($sortParams['sort'] === 'status') {
334 $orderOnCampaignTable = FALSE;
335 $lookupTableJoins = "
336 LEFT JOIN civicrm_option_value status ON ( status.value = campaign.status_id OR campaign.status_id IS NULL )
337 INNER JOIN civicrm_option_group grp ON ( status.option_group_id = grp.id AND grp.name = 'campaign_status' )";
338 $orderByClause = "ORDER BY status.label {$sortParams['sortOrder']}";
340 elseif ($sortParams['sort'] === 'campaign_type') {
341 $orderOnCampaignTable = FALSE;
342 $lookupTableJoins = "
343 LEFT JOIN civicrm_option_value campaign_type ON ( campaign_type.value = campaign.campaign_type_id
344 OR campaign.campaign_type_id IS NULL )
345 INNER JOIN civicrm_option_group grp ON ( campaign_type.option_group_id = grp.id AND grp.name = 'campaign_type' )";
346 $orderByClause = "ORDER BY campaign_type.label {$sortParams['sortOrder']}";
348 elseif ($sortParams['sort'] === 'isActive') {
349 $sortParams['sort'] = 'is_active';
351 if ($orderOnCampaignTable) {
352 $orderByClause = "ORDER BY campaign.{$sortParams['sort']} {$sortParams['sortOrder']}";
354 $orderByClause = ($orderByClause) ?
$orderByClause . ", campaign.id {$sortParams['sortOrder']}" : $orderByClause;
355 $limitClause = "LIMIT {$sortParams['offset']}, {$sortParams['rowCount']}";
358 //build the where clause.
359 $queryParams = $where = [];
360 if (!empty($params['id'])) {
361 $where[] = "( campaign.id = %1 )";
362 $queryParams[1] = [$params['id'], 'Positive'];
364 if (!empty($params['name'])) {
365 $where[] = "( campaign.name LIKE %2 )";
366 $queryParams[2] = ['%' . trim($params['name']) . '%', 'String'];
368 if (!empty($params['title'])) {
369 $where[] = "( campaign.title LIKE %3 )";
370 $queryParams[3] = ['%' . trim($params['title']) . '%', 'String'];
372 if (!empty($params['start_date'])) {
373 $startDate = CRM_Utils_Date
::processDate($params['start_date']);
374 $where[] = "( campaign.start_date >= %4 OR campaign.start_date IS NULL )";
375 $queryParams[4] = [$startDate, 'String'];
377 if (!empty($params['end_date'])) {
378 $endDate = CRM_Utils_Date
::processDate($params['end_date'], '235959');
379 $where[] = "( campaign.end_date <= %5 OR campaign.end_date IS NULL )";
380 $queryParams[5] = [$endDate, 'String'];
382 if (!empty($params['description'])) {
383 $where[] = "( campaign.description LIKE %6 )";
384 $queryParams[6] = ['%' . trim($params['description']) . '%', 'String'];
386 if (!empty($params['campaign_type_id'])) {
387 $where[] = "( campaign.campaign_type_id IN ( %7 ) )";
388 $queryParams[7] = [implode(',', (array) $params['campaign_type_id']), 'CommaSeparatedIntegers'];
390 if (!empty($params['status_id'])) {
391 $where[] = "( campaign.status_id IN ( %8 ) )";
392 $queryParams[8] = [implode(',', (array) $params['status_id']), 'CommaSeparatedIntegers'];
394 if (array_key_exists('is_active', $params)) {
395 $active = "( campaign.is_active = 1 )";
396 if (!empty($params['is_active'])) {
397 $active = "( campaign.is_active = 0 OR campaign.is_active IS NULL )";
402 if (!empty($where)) {
403 $whereClause = ' WHERE ' . implode(" \nAND ", $where);
419 SELECT campaign.id as id,
420 campaign.name as name,
421 campaign.title as title,
422 campaign.is_active as is_active,
423 campaign.status_id as status_id,
424 campaign.end_date as end_date,
425 campaign.start_date as start_date,
426 campaign.description as description,
427 campaign.campaign_type_id as campaign_type_id';
429 $selectClause = 'SELECT COUNT(*)';
431 $fromClause = 'FROM civicrm_campaign campaign';
433 $query = "{$selectClause} {$fromClause} {$lookupTableJoins} {$whereClause} {$orderByClause} {$limitClause}";
435 //in case of only count.
437 return (int) CRM_Core_DAO
::singleValueQuery($query, $queryParams);
440 $campaign = CRM_Core_DAO
::executeQuery($query, $queryParams);
441 while ($campaign->fetch()) {
442 foreach ($properties as $property) {
443 $campaigns[$campaign->id
][$property] = $campaign->$property;
451 * Get the campaign count.
455 public static function getCampaignCount(): int {
456 return (int) CRM_Core_DAO
::singleValueQuery('SELECT COUNT(*) FROM civicrm_campaign');
460 * Get Campaigns groups.
462 * @param int $campaignId
467 public static function getCampaignGroups($campaignId) {
468 static $campaignGroups;
473 if (!isset($campaignGroups[$campaignId])) {
474 $campaignGroups[$campaignId] = [];
477 SELECT grp.title, grp.id
478 FROM civicrm_campaign_group campgrp
479 INNER JOIN civicrm_group grp ON ( grp.id = campgrp.entity_id )
480 WHERE campgrp.group_type = 'Include'
481 AND campgrp.entity_table = 'civicrm_group'
482 AND campgrp.campaign_id = %1";
484 $groups = CRM_Core_DAO
::executeQuery($query, [1 => [$campaignId, 'Positive']]);
485 while ($groups->fetch()) {
486 $campaignGroups[$campaignId][$groups->id
] = $groups->title
;
490 return $campaignGroups[$campaignId];
494 * Update the is_active flag in the db.
497 * Id of the database record.
498 * @param bool $is_active
499 * Value we want to set the is_active field.
502 * true if we found and updated the object, else false
504 public static function setIsActive($id, $is_active) {
505 return CRM_Core_DAO
::setFieldValue('CRM_Campaign_DAO_Campaign', $id, 'is_active', $is_active);
511 public static function accessCampaign() {
512 static $allow = NULL;
514 if (!isset($allow)) {
516 if (CRM_Core_Permission
::check('manage campaign') ||
517 CRM_Core_Permission
::check('administer CiviCampaign')
527 * Add select element for campaign
528 * and assign needful info to templates.
530 * @param CRM_Core_Form $form
531 * @param int $connectedCampaignId
533 public static function addCampaign(&$form, $connectedCampaignId = NULL) {
534 //some forms do set default and freeze.
536 if ($form->get('action') & CRM_Core_Action
::VIEW
) {
537 $appendDates = FALSE;
540 $campaignDetails = self
::getPermissionedCampaigns($connectedCampaignId, NULL, TRUE, TRUE, $appendDates);
542 $campaigns = $campaignDetails['campaigns'] ??
NULL;
543 $hasAccessCampaign = $campaignDetails['hasAccessCampaign'] ??
NULL;
544 $isCampaignEnabled = $campaignDetails['isCampaignEnabled'] ??
NULL;
546 $showAddCampaign = FALSE;
547 if ($connectedCampaignId ||
($isCampaignEnabled && $hasAccessCampaign)) {
548 $showAddCampaign = TRUE;
549 $campaign = $form->addEntityRef('campaign_id', ts('Campaign'), [
550 'entity' => 'Campaign',
552 'select' => ['minimumInputLength' => 0],
554 //lets freeze when user does not has access or campaign is disabled.
555 if (!$isCampaignEnabled ||
!$hasAccessCampaign) {
560 //carry this info to templates.
562 'showAddCampaign' => $showAddCampaign,
563 'hasAccessCampaign' => $hasAccessCampaign,
564 'isCampaignEnabled' => $isCampaignEnabled,
567 $form->assign('campaignInfo', $campaignInfo);
571 * Add campaign in component search.
572 * and assign needful info to templates.
574 * @param CRM_Core_Form $form
575 * @param string $elementName
577 public static function addCampaignInComponentSearch(&$form, $elementName = 'campaign_id') {
579 $campaignDetails = self
::getPermissionedCampaigns(NULL, NULL, FALSE, FALSE, FALSE, TRUE);
580 $campaigns = $campaignDetails['campaigns'] ??
NULL;
581 $hasAccessCampaign = $campaignDetails['hasAccessCampaign'] ??
NULL;
582 $isCampaignEnabled = $campaignDetails['isCampaignEnabled'] ??
NULL;
584 $showCampaignInSearch = FALSE;
585 if ($isCampaignEnabled && $hasAccessCampaign && !empty($campaigns)) {
586 //get the current campaign only.
587 $currentCampaigns = self
::getCampaigns(NULL, NULL, FALSE);
588 $pastCampaigns = array_diff($campaigns, $currentCampaigns);
590 if (!empty($currentCampaigns)) {
591 $allCampaigns = ['crm_optgroup_current_campaign' => ts('Current Campaigns')] +
$currentCampaigns;
593 if (!empty($pastCampaigns)) {
594 $allCampaigns +
= ['crm_optgroup_past_campaign' => ts('Past Campaigns')] +
$pastCampaigns;
597 $showCampaignInSearch = TRUE;
598 $form->add('select', $elementName, ts('Campaigns'), $allCampaigns, FALSE,
599 ['id' => 'campaigns', 'multiple' => 'multiple', 'class' => 'crm-select2']
603 $form->assign('campaignElementName', $showCampaignInSearch ?
$elementName : '');
609 public static function getEntityRefFilters() {
611 ['key' => 'campaign_type_id', 'value' => ts('Campaign Type')],
612 ['key' => 'status_id', 'value' => ts('Status')],
614 'key' => 'start_date',
615 'value' => ts('Start Date'),
617 ['key' => '{">":"now"}', 'value' => ts('Upcoming')],
619 'key' => '{"BETWEEN":["now - 3 month","now"]}',
620 'value' => ts('Past 3 Months'),
623 'key' => '{"BETWEEN":["now - 6 month","now"]}',
624 'value' => ts('Past 6 Months'),
627 'key' => '{"BETWEEN":["now - 1 year","now"]}',
628 'value' => ts('Past Year'),
634 'value' => ts('End Date'),
636 ['key' => '{">":"now"}', 'value' => ts('In the future')],
637 ['key' => '{"<":"now"}', 'value' => ts('In the past')],
638 ['key' => '{"IS NULL":"1"}', 'value' => ts('Not set')],
645 * Links to create new campaigns from entityRef widget
649 public static function getEntityRefCreateLinks() {
650 if (CRM_Core_Permission
::check([['administer CiviCampaign', 'manage campaign']])) {
653 'label' => ts('New Campaign'),
654 'url' => CRM_Utils_System
::url('civicrm/campaign/add', "reset=1",
655 NULL, NULL, FALSE, FALSE, TRUE),
656 'type' => 'Campaign',