Merge pull request #4897 from totten/master-cleanup2
[civicrm-core.git] / CRM / Campaign / BAO / Campaign.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2014
32 * $Id$
33 *
34 */
35 class CRM_Campaign_BAO_Campaign extends CRM_Campaign_DAO_Campaign {
36
37 /**
38 * Takes an associative array and creates a campaign object
39 *
40 * the function extract all the params it needs to initialize the create a
41 * contact object. the params array could contain additional unused name/value
42 * pairs
43 *
44 * @param array $params
45 * (reference ) an assoc array of name/value pairs.
46 *
47 * @return CRM_Campaign_DAO_Campaign object
48 * @static
49 */
50 public static function create(&$params) {
51 if (empty($params)) {
52 return;
53 }
54
55 if (!(CRM_Utils_Array::value('id', $params))) {
56
57 if (!(CRM_Utils_Array::value('created_id', $params))) {
58 $session = CRM_Core_Session::singleton();
59 $params['created_id'] = $session->get('userID');
60 }
61
62 if (!(CRM_Utils_Array::value('created_date', $params))) {
63 $params['created_date'] = date('YmdHis');
64 }
65
66 if (!(CRM_Utils_Array::value('name', $params))) {
67 $params['name'] = CRM_Utils_String::titleToVar($params['title'], 64);
68 }
69 }
70
71 $campaign = new CRM_Campaign_DAO_Campaign();
72 $campaign->copyValues($params);
73 $campaign->save();
74
75 /* Create the campaign group record */
76
77 $groupTableName = CRM_Contact_BAO_Group::getTableName();
78
79 if (isset($params['groups']) && !empty($params['groups']['include']) && is_array($params['groups']['include'])) {
80 foreach ($params['groups']['include'] as $entityId) {
81 $dao = new CRM_Campaign_DAO_CampaignGroup();
82 $dao->campaign_id = $campaign->id;
83 $dao->entity_table = $groupTableName;
84 $dao->entity_id = $entityId;
85 $dao->group_type = 'Include';
86 $dao->save();
87 $dao->free();
88 }
89 }
90
91 //store custom data
92 if (!empty($params['custom']) &&
93 is_array($params['custom'])
94 ) {
95 CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_campaign', $campaign->id);
96 }
97
98 return $campaign;
99 }
100
101 /**
102 * Delete the campaign
103 *
104 * @param int $id
105 * Id of the campaign.
106 *
107 * @return bool|mixed
108 */
109 public static function del($id) {
110 if (!$id) {
111 return FALSE;
112 }
113 $dao = new CRM_Campaign_DAO_Campaign();
114 $dao->id = $id;
115 return $dao->delete();
116 }
117
118 /**
119 * Takes a bunch of params that are needed to match certain criteria and
120 * retrieves the relevant objects. Typically the valid params are only
121 * campaign_id.
122 *
123 * @param array $params
124 * (reference ) an assoc array of name/value pairs.
125 * @param array $defaults
126 * (reference ) an assoc array to hold the flattened values.
127 *
128 * @return \CRM_Campaign_DAO_Campaign|null
129 */
130 public function retrieve(&$params, &$defaults) {
131 $campaign = new CRM_Campaign_DAO_Campaign();
132
133 $campaign->copyValues($params);
134
135 if ($campaign->find(TRUE)) {
136 CRM_Core_DAO::storeValues($campaign, $defaults);
137 return $campaign;
138 }
139 return NULL;
140 }
141
142 /**
143 * Return the all eligible campaigns w/ cache.
144 *
145 * @param int $includeId
146 * Lets inlcude this campaign by force.
147 * @param int $excludeId
148 * Do not include this campaign.
149 * @param bool $onlyActive
150 * Consider only active campaigns.
151 *
152 * @param bool $onlyCurrent
153 * @param bool $appendDatesToTitle
154 * @param bool $forceAll
155 *
156 * @return mixed $campaigns a set of campaigns.
157 * @access public
158 */
159 public static function getCampaigns(
160 $includeId = NULL,
161 $excludeId = NULL,
162 $onlyActive = TRUE,
163 $onlyCurrent = TRUE,
164 $appendDatesToTitle = FALSE,
165 $forceAll = FALSE
166 ) {
167 static $campaigns;
168 $cacheKey = 0;
169 $cacheKeyParams = array(
170 'includeId',
171 'excludeId',
172 'onlyActive',
173 'onlyCurrent',
174 'appendDatesToTitle',
175 'forceAll',
176 );
177 foreach ($cacheKeyParams as $param) {
178 $cacheParam = $$param;
179 if (!$cacheParam) {
180 $cacheParam = 0;
181 }
182 $cacheKey .= '_' . $cacheParam;
183 }
184
185 if (!isset($campaigns[$cacheKey])) {
186 $where = array('( camp.title IS NOT NULL )');
187 if ($excludeId) {
188 $where[] = "( camp.id != $excludeId )";
189 }
190 if ($onlyActive) {
191 $where[] = '( camp.is_active = 1 )';
192 }
193 if ($onlyCurrent) {
194 $where[] = '( camp.end_date IS NULL OR camp.end_date >= NOW() )';
195 }
196 $whereClause = implode(' AND ', $where);
197 if ($includeId) {
198 $whereClause .= " OR ( camp.id = $includeId )";
199 }
200
201 //lets force all.
202 if ($forceAll) {
203 $whereClause = '( 1 )';
204 }
205
206 $query = "
207 SELECT camp.id,
208 camp.title,
209 camp.start_date,
210 camp.end_date
211 FROM civicrm_campaign camp
212 WHERE {$whereClause}
213 Order By camp.title";
214
215 $campaign = CRM_Core_DAO::executeQuery($query);
216 $campaigns[$cacheKey] = array();
217 $config = CRM_Core_Config::singleton();
218
219 while ($campaign->fetch()) {
220 $title = $campaign->title;
221 if ($appendDatesToTitle) {
222 $dates = array();
223 foreach (array('start_date', 'end_date') as $date) {
224 if ($campaign->$date) {
225 $dates[] = CRM_Utils_Date::customFormat($campaign->$date, $config->dateformatFull);
226 }
227 }
228 if (!empty($dates)) {
229 $title .= ' (' . implode('-', $dates) . ')';
230 }
231 }
232 $campaigns[$cacheKey][$campaign->id] = $title;
233 }
234 }
235
236 return $campaigns[$cacheKey];
237 }
238
239 /**
240 * Wrapper to self::getCampaigns( )
241 * w/ permissions and component check.
242 */
243 public static function getPermissionedCampaigns(
244 $includeId = NULL,
245 $excludeId = NULL,
246 $onlyActive = TRUE,
247 $onlyCurrent = TRUE,
248 $appendDatesToTitle = FALSE,
249 $forceAll = FALSE,
250 $doCheckForComponent = TRUE,
251 $doCheckForPermissions = TRUE
252 ) {
253 $cacheKey = 0;
254 $cachekeyParams = array(
255 'includeId',
256 'excludeId',
257 'onlyActive',
258 'onlyCurrent',
259 'appendDatesToTitle',
260 'doCheckForComponent',
261 'doCheckForPermissions',
262 'forceAll',
263 );
264 foreach ($cachekeyParams as $param) {
265 $cacheKeyParam = $$param;
266 if (!$cacheKeyParam) {
267 $cacheKeyParam = 0;
268 }
269 $cacheKey .= '_' . $cacheKeyParam;
270 }
271
272 static $validCampaigns;
273 if (!isset($validCampaigns[$cacheKey])) {
274 $isValid = TRUE;
275 $campaigns = array(
276 'campaigns' => array(),
277 'hasAccessCampaign' => FALSE,
278 'isCampaignEnabled' => FALSE,
279 );
280
281 //do check for component.
282 if ($doCheckForComponent) {
283 $campaigns['isCampaignEnabled'] = $isValid = self::isCampaignEnable();
284 }
285
286 //do check for permissions.
287 if ($doCheckForPermissions) {
288 $campaigns['hasAccessCampaign'] = $isValid = self::accessCampaign();
289 }
290
291 //finally retrieve campaigns from db.
292 if ($isValid) {
293 $campaigns['campaigns'] = self::getCampaigns($includeId,
294 $excludeId,
295 $onlyActive,
296 $onlyCurrent,
297 $appendDatesToTitle,
298 $forceAll
299 );
300 }
301
302 //store in cache.
303 $validCampaigns[$cacheKey] = $campaigns;
304 }
305
306 return $validCampaigns[$cacheKey];
307 }
308
309 /**
310 * Is CiviCampaign enabled.
311 * @return bool
312 */
313 public static function isCampaignEnable() {
314 static $isEnable = NULL;
315
316 if (!isset($isEnable)) {
317 $isEnable = FALSE;
318 $config = CRM_Core_Config::singleton();
319 if (in_array('CiviCampaign', $config->enableComponents)) {
320 $isEnable = TRUE;
321 }
322 }
323
324 return $isEnable;
325 }
326
327 /**
328 * Retrieve campaigns for dashboard.
329 *
330 * @static
331 */
332 public static function getCampaignSummary($params = array(), $onlyCount = FALSE) {
333 $campaigns = array();
334
335 //build the limit and order clause.
336 $limitClause = $orderByClause = $lookupTableJoins = NULL;
337 if (!$onlyCount) {
338 $sortParams = array(
339 'sort' => 'start_date',
340 'offset' => 0,
341 'rowCount' => 10,
342 'sortOrder' => 'desc',
343 );
344 foreach ($sortParams as $name => $default) {
345 if (!empty($params[$name])) {
346 $sortParams[$name] = $params[$name];
347 }
348 }
349
350 //need to lookup tables.
351 $orderOnCampaignTable = TRUE;
352 if ($sortParams['sort'] == 'status') {
353 $orderOnCampaignTable = FALSE;
354 $lookupTableJoins = "
355 LEFT JOIN civicrm_option_value status ON ( status.value = campaign.status_id OR campaign.status_id IS NULL )
356 INNER JOIN civicrm_option_group grp ON ( status.option_group_id = grp.id AND grp.name = 'campaign_status' )";
357 $orderByClause = "ORDER BY status.label {$sortParams['sortOrder']}";
358 }
359 elseif ($sortParams['sort'] == 'campaign_type') {
360 $orderOnCampaignTable = FALSE;
361 $lookupTableJoins = "
362 LEFT JOIN civicrm_option_value campaign_type ON ( campaign_type.value = campaign.campaign_type_id
363 OR campaign.campaign_type_id IS NULL )
364 INNER JOIN civicrm_option_group grp ON ( campaign_type.option_group_id = grp.id AND grp.name = 'campaign_type' )";
365 $orderByClause = "ORDER BY campaign_type.label {$sortParams['sortOrder']}";
366 }
367 elseif ($sortParams['sort'] == 'isActive') {
368 $sortParams['sort'] = 'is_active';
369 }
370 if ($orderOnCampaignTable) {
371 $orderByClause = "ORDER BY campaign.{$sortParams['sort']} {$sortParams['sortOrder']}";
372 }
373 $limitClause = "LIMIT {$sortParams['offset']}, {$sortParams['rowCount']}";
374 }
375
376 //build the where clause.
377 $queryParams = $where = array();
378 if (!empty($params['id'])) {
379 $where[] = "( campaign.id = %1 )";
380 $queryParams[1] = array($params['id'], 'Positive');
381 }
382 if (!empty($params['name'])) {
383 $where[] = "( campaign.name LIKE %2 )";
384 $queryParams[2] = array('%' . trim($params['name']) . '%', 'String');
385 }
386 if (!empty($params['title'])) {
387 $where[] = "( campaign.title LIKE %3 )";
388 $queryParams[3] = array('%' . trim($params['title']) . '%', 'String');
389 }
390 if (!empty($params['start_date'])) {
391 $startDate = CRM_Utils_Date::processDate($params['start_date']);
392 $where[] = "( campaign.start_date >= %4 OR campaign.start_date IS NULL )";
393 $queryParams[4] = array($startDate, 'String');
394 }
395 if (!empty($params['end_date'])) {
396 $endDate = CRM_Utils_Date::processDate($params['end_date'], '235959');
397 $where[] = "( campaign.end_date <= %5 OR campaign.end_date IS NULL )";
398 $queryParams[5] = array($endDate, 'String');
399 }
400 if (!empty($params['description'])) {
401 $where[] = "( campaign.description LIKE %6 )";
402 $queryParams[6] = array('%' . trim($params['description']) . '%', 'String');
403 }
404 if (!empty($params['campaign_type_id'])) {
405 $typeId = $params['campaign_type_id'];
406 if (is_array($params['campaign_type_id'])) {
407 $typeId = implode(' , ', $params['campaign_type_id']);
408 }
409 $where[] = "( campaign.campaign_type_id IN ( {$typeId} ) )";
410 }
411 if (!empty($params['status_id'])) {
412 $statusId = $params['status_id'];
413 if (is_array($params['status_id'])) {
414 $statusId = implode(' , ', $params['status_id']);
415 }
416 $where[] = "( campaign.status_id IN ( {$statusId} ) )";
417 }
418 if (array_key_exists('is_active', $params)) {
419 $active = "( campaign.is_active = 1 )";
420 if (!empty($params['is_active'])) {
421 $active = "( campaign.is_active = 0 OR campaign.is_active IS NULL )";
422 }
423 $where[] = $active;
424 }
425 $whereClause = NULL;
426 if (!empty($where)) {
427 $whereClause = ' WHERE ' . implode(" \nAND ", $where);
428 }
429
430 $properties = array(
431 'id',
432 'name',
433 'title',
434 'start_date',
435 'end_date',
436 'status_id',
437 'is_active',
438 'description',
439 'campaign_type_id',
440 );
441
442 $selectClause = '
443 SELECT campaign.id as id,
444 campaign.name as name,
445 campaign.title as title,
446 campaign.is_active as is_active,
447 campaign.status_id as status_id,
448 campaign.end_date as end_date,
449 campaign.start_date as start_date,
450 campaign.description as description,
451 campaign.campaign_type_id as campaign_type_id';
452 if ($onlyCount) {
453 $selectClause = 'SELECT COUNT(*)';
454 }
455 $fromClause = 'FROM civicrm_campaign campaign';
456
457 $query = "{$selectClause} {$fromClause} {$lookupTableJoins} {$whereClause} {$orderByClause} {$limitClause}";
458
459 //in case of only count.
460 if ($onlyCount) {
461 return (int) CRM_Core_DAO::singleValueQuery($query, $queryParams);
462 }
463
464 $campaign = CRM_Core_DAO::executeQuery($query, $queryParams);
465 while ($campaign->fetch()) {
466 foreach ($properties as $property) {
467 $campaigns[$campaign->id][$property] = $campaign->$property;
468 }
469 }
470
471 return $campaigns;
472 }
473
474 /**
475 * Get the campaign count.
476 *
477 * @static
478 */
479 public static function getCampaignCount() {
480 return (int) CRM_Core_DAO::singleValueQuery('SELECT COUNT(*) FROM civicrm_campaign');
481 }
482
483 /**
484 * Get Campaigns groups
485 *
486 * @param int $campaignId
487 * Campaign id.
488 *
489 * @return array
490 * @static
491 */
492 public static function getCampaignGroups($campaignId) {
493 static $campaignGroups;
494 if (!$campaignId) {
495 return array();
496 }
497
498 if (!isset($campaignGroups[$campaignId])) {
499 $campaignGroups[$campaignId] = array();
500
501 $query = "
502 SELECT grp.title, grp.id
503 FROM civicrm_campaign_group campgrp
504 INNER JOIN civicrm_group grp ON ( grp.id = campgrp.entity_id )
505 WHERE campgrp.group_type = 'Include'
506 AND campgrp.entity_table = 'civicrm_group'
507 AND campgrp.campaign_id = %1";
508
509 $groups = CRM_Core_DAO::executeQuery($query, array(1 => array($campaignId, 'Positive')));
510 while ($groups->fetch()) {
511 $campaignGroups[$campaignId][$groups->id] = $groups->title;
512 }
513 }
514
515 return $campaignGroups[$campaignId];
516 }
517
518 /**
519 * Update the is_active flag in the db
520 *
521 * @param int $id
522 * Id of the database record.
523 * @param bool $is_active
524 * Value we want to set the is_active field.
525 *
526 * @return Object
527 * DAO object on sucess, null otherwise
528 * @static
529 */
530 public static function setIsActive($id, $is_active) {
531 return CRM_Core_DAO::setFieldValue('CRM_Campaign_DAO_Campaign', $id, 'is_active', $is_active);
532 }
533
534 /**
535 * @return bool
536 */
537 public static function accessCampaign() {
538 static $allow = NULL;
539
540 if (!isset($allow)) {
541 $allow = FALSE;
542 if (CRM_Core_Permission::check('manage campaign') ||
543 CRM_Core_Permission::check('administer CiviCampaign')
544 ) {
545 $allow = TRUE;
546 }
547 }
548
549 return $allow;
550 }
551
552 /*
553 * Add select element for campaign
554 * and assign needful info to templates.
555 */
556 /**
557 * @param CRM_Core_Form $form
558 * @param int $connectedCampaignId
559 */
560 public static function addCampaign(&$form, $connectedCampaignId = NULL) {
561 //some forms do set default and freeze.
562 $appendDates = TRUE;
563 if ($form->get('action') & CRM_Core_Action::VIEW) {
564 $appendDates = FALSE;
565 }
566
567 $campaignDetails = self::getPermissionedCampaigns($connectedCampaignId, NULL, TRUE, TRUE, $appendDates);
568 $fields = array('campaigns', 'hasAccessCampaign', 'isCampaignEnabled');
569 foreach ($fields as $fld) {
570 $$fld = CRM_Utils_Array::value($fld, $campaignDetails);
571 }
572
573 //lets see do we have past campaigns.
574 $hasPastCampaigns = FALSE;
575 $allActiveCampaigns = CRM_Campaign_BAO_Campaign::getCampaigns(NULL, NULL, TRUE, FALSE);
576 if (count($allActiveCampaigns) > count($campaigns)) {
577 $hasPastCampaigns = TRUE;
578 }
579 $hasCampaigns = FALSE;
580 if (!empty($campaigns)) {
581 $hasCampaigns = TRUE;
582 }
583 if ($hasPastCampaigns) {
584 $hasCampaigns = TRUE;
585 $form->add('hidden', 'included_past_campaigns');
586 }
587
588 $showAddCampaign = FALSE;
589 $alreadyIncludedPastCampaigns = FALSE;
590 if ($connectedCampaignId || ($isCampaignEnabled && $hasAccessCampaign)) {
591 $showAddCampaign = TRUE;
592 //lets add past campaigns as options to quick-form element.
593 if ($hasPastCampaigns && $form->getElementValue('included_past_campaigns')) {
594 $campaigns = $allActiveCampaigns;
595 $alreadyIncludedPastCampaigns = TRUE;
596 }
597 $campaign = &$form->add('select',
598 'campaign_id',
599 ts('Campaign'),
600 array('' => ts('- select -')) + $campaigns,
601 FALSE,
602 array('class' => 'crm-select2')
603 );
604 //lets freeze when user does not has access or campaign is disabled.
605 if (!$isCampaignEnabled || !$hasAccessCampaign) {
606 $campaign->freeze();
607 }
608 }
609
610 $addCampaignURL = NULL;
611 if (empty($campaigns) && $hasAccessCampaign && $isCampaignEnabled) {
612 $addCampaignURL = CRM_Utils_System::url('civicrm/campaign/add', 'reset=1');
613 }
614
615 $includePastCampaignURL = NULL;
616 if ($hasPastCampaigns && $isCampaignEnabled && $hasAccessCampaign) {
617 $includePastCampaignURL = CRM_Utils_System::url('civicrm/ajax/rest',
618 'className=CRM_Campaign_Page_AJAX&fnName=allActiveCampaigns',
619 FALSE, NULL, FALSE
620 );
621 }
622
623 //carry this info to templates.
624 $infoFields = array(
625 'hasCampaigns',
626 'addCampaignURL',
627 'showAddCampaign',
628 'hasPastCampaigns',
629 'hasAccessCampaign',
630 'isCampaignEnabled',
631 'includePastCampaignURL',
632 'alreadyIncludedPastCampaigns',
633 );
634 foreach ($infoFields as $fld) {
635 $campaignInfo[$fld] = $$fld;
636 }
637 $form->assign('campaignInfo', $campaignInfo);
638 }
639
640 /**
641 * Add campaign in compoent search.
642 * and assign needful info to templates.
643 *
644 * @param CRM_Core_Form $form
645 * @param string $elementName
646 */
647 public static function addCampaignInComponentSearch(&$form, $elementName = 'campaign_id') {
648 $campaignInfo = array();
649 $campaignDetails = self::getPermissionedCampaigns(NULL, NULL, FALSE, FALSE, FALSE, TRUE);
650 $fields = array('campaigns', 'hasAccessCampaign', 'isCampaignEnabled');
651 foreach ($fields as $fld) {
652 $$fld = CRM_Utils_Array::value($fld, $campaignDetails);
653 }
654 $showCampaignInSearch = FALSE;
655 if ($isCampaignEnabled && $hasAccessCampaign && !empty($campaigns)) {
656 //get the current campaign only.
657 $currentCampaigns = self::getCampaigns(NULL, NULL, FALSE);
658 $pastCampaigns = array_diff($campaigns, $currentCampaigns);
659 $allCampaigns = array();
660 if (!empty($currentCampaigns)) {
661 $allCampaigns = array('crm_optgroup_current_campaign' => ts('Current Campaigns')) + $currentCampaigns;
662 }
663 if (!empty($pastCampaigns)) {
664 $allCampaigns += array('crm_optgroup_past_campaign' => ts('Past Campaigns')) + $pastCampaigns;
665 }
666
667 $showCampaignInSearch = TRUE;
668 $form->add('select', $elementName, ts('Campaigns'), $allCampaigns, FALSE,
669 array('id' => 'campaigns', 'multiple' => 'multiple', 'class' => 'crm-select2')
670 );
671 }
672 $infoFields = array(
673 'elementName',
674 'hasAccessCampaign',
675 'isCampaignEnabled',
676 'showCampaignInSearch',
677 );
678 foreach ($infoFields as $fld) {
679 $campaignInfo[$fld] = $$fld;
680 }
681 $form->assign('campaignInfo', $campaignInfo);
682 }
683 }