8a4979e916b7a9e73398cde960dc7d7309b0b681
[civicrm-core.git] / CRM / Campaign / BAO / Campaign.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.4 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
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-2013
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 (reference ) an assoc array of name/value pairs
45 *
46 * @return object CRM_Campaign_DAO_Campaign object
47 * @access public
48 * @static
49 */
50 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']) && CRM_Utils_Array::value('include', $params['groups']) && 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 (CRM_Utils_Array::value('custom', $params) &&
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 * function to delete the campaign
103 *
104 * @param int $id id of the campaign
105 */
106 public static function del($id) {
107 if (!$id) {
108 return FALSE;
109 }
110 $dao = new CRM_Campaign_DAO_Campaign();
111 $dao->id = $id;
112 return $dao->delete();
113 }
114
115 /**
116 * Takes a bunch of params that are needed to match certain criteria and
117 * retrieves the relevant objects. Typically the valid params are only
118 * campaign_id.
119 *
120 * @param array $params (reference ) an assoc array of name/value pairs
121 * @param array $defaults (reference ) an assoc array to hold the flattened values
122 *
123 * @access public
124 */
125 public function retrieve(&$params, &$defaults) {
126 $campaign = new CRM_Campaign_DAO_Campaign();
127
128 $campaign->copyValues($params);
129
130 if ($campaign->find(TRUE)) {
131 CRM_Core_DAO::storeValues($campaign, $defaults);
132 return $campaign;
133 }
134 return NULL;
135 }
136
137 /**
138 * Return the all eligible campaigns w/ cache.
139 *
140 * @param int $includeId lets inlcude this campaign by force.
141 * @param int $excludeId do not include this campaign.
142 * @param boolean $onlyActive consider only active campaigns.
143 *
144 * @return $campaigns a set of campaigns.
145 * @access public
146 */
147 public static function getCampaigns(
148 $includeId = NULL,
149 $excludeId = NULL,
150 $onlyActive = TRUE,
151 $onlyCurrent = TRUE,
152 $appendDatesToTitle = FALSE,
153 $forceAll = FALSE
154 ) {
155 static $campaigns;
156 $cacheKey = 0;
157 $cacheKeyParams = array(
158 'includeId', 'excludeId', 'onlyActive',
159 'onlyCurrent', 'appendDatesToTitle', 'forceAll',
160 );
161 foreach ($cacheKeyParams as $param) {
162 $cacheParam = $$param;
163 if (!$cacheParam) {
164 $cacheParam = 0;
165 }
166 $cacheKey .= '_' . $cacheParam;
167 }
168
169 if (!isset($campaigns[$cacheKey])) {
170 $where = array('( camp.title IS NOT NULL )');
171 if ($excludeId) {
172 $where[] = "( camp.id != $excludeId )";
173 }
174 if ($onlyActive) {
175 $where[] = '( camp.is_active = 1 )';
176 }
177 if ($onlyCurrent) {
178 $where[] = '( camp.end_date IS NULL OR camp.end_date >= NOW() )';
179 }
180 $whereClause = implode(' AND ', $where);
181 if ($includeId) {
182 $whereClause .= " OR ( camp.id = $includeId )";
183 }
184
185 //lets force all.
186 if ($forceAll) {
187 $whereClause = '( 1 )';
188 }
189
190 $query = "
191 SELECT camp.id,
192 camp.title,
193 camp.start_date,
194 camp.end_date
195 FROM civicrm_campaign camp
196 WHERE {$whereClause}
197 Order By camp.title";
198
199 $campaign = CRM_Core_DAO::executeQuery($query);
200 $campaigns[$cacheKey] = array();
201 $config = CRM_Core_Config::singleton();
202
203 while ($campaign->fetch()) {
204 $title = $campaign->title;
205 if ($appendDatesToTitle) {
206 $dates = array();
207 foreach (array('start_date', 'end_date') as $date) {
208 if ($campaign->$date) {
209 $dates[] = CRM_Utils_Date::customFormat($campaign->$date, $config->dateformatFull);
210 }
211 }
212 if (!empty($dates)) {
213 $title .= ' (' . implode('-', $dates) . ')';
214 }
215 }
216 $campaigns[$cacheKey][$campaign->id] = $title;
217 }
218 }
219
220 return $campaigns[$cacheKey];
221 }
222
223 /**
224 * Wrapper to self::getCampaigns( )
225 * w/ permissions and component check.
226 *
227 */
228 public static function getPermissionedCampaigns($includeId = NULL,
229 $excludeId = NULL,
230 $onlyActive = TRUE,
231 $onlyCurrent = TRUE,
232 $appendDatesToTitle = FALSE,
233 $forceAll = FALSE,
234 $doCheckForComponent = TRUE,
235 $doCheckForPermissions = TRUE
236 ) {
237 $cacheKey = 0;
238 $cachekeyParams = array(
239 'includeId', 'excludeId', 'onlyActive', 'onlyCurrent',
240 'appendDatesToTitle', 'doCheckForComponent', 'doCheckForPermissions', 'forceAll',
241 );
242 foreach ($cachekeyParams as $param) {
243 $cacheKeyParam = $$param;
244 if (!$cacheKeyParam) {
245 $cacheKeyParam = 0;
246 }
247 $cacheKey .= '_' . $cacheKeyParam;
248 }
249
250 static $validCampaigns;
251 if (!isset($validCampaigns[$cacheKey])) {
252 $isValid = TRUE;
253 $campaigns = array('campaigns' => array(),
254 'hasAccessCampaign' => FALSE,
255 'isCampaignEnabled' => FALSE,
256 );
257
258 //do check for component.
259 if ($doCheckForComponent) {
260 $campaigns['isCampaignEnabled'] = $isValid = self::isCampaignEnable();
261 }
262
263 //do check for permissions.
264 if ($doCheckForPermissions) {
265 $campaigns['hasAccessCampaign'] = $isValid = self::accessCampaign();
266 }
267
268 //finally retrieve campaigns from db.
269 if ($isValid) {
270 $campaigns['campaigns'] = self::getCampaigns($includeId,
271 $excludeId,
272 $onlyActive,
273 $onlyCurrent,
274 $appendDatesToTitle,
275 $forceAll
276 );
277 }
278
279 //store in cache.
280 $validCampaigns[$cacheKey] = $campaigns;
281 }
282
283 return $validCampaigns[$cacheKey];
284 }
285
286 /*
287 * Is CiviCampaign enabled.
288 *
289 */
290 public static function isCampaignEnable() {
291 static $isEnable = NULL;
292
293 if (!isset($isEnable)) {
294 $isEnable = FALSE;
295 $config = CRM_Core_Config::singleton();
296 if (in_array('CiviCampaign', $config->enableComponents)) {
297 $isEnable = TRUE;
298 }
299 }
300
301 return $isEnable;
302 }
303
304 /**
305 * Function to retrieve campaigns for dashboard.
306 *
307 * @static
308 */
309 static function getCampaignSummary($params = array(
310 ), $onlyCount = FALSE) {
311 $campaigns = array();
312
313 //build the limit and order clause.
314 $limitClause = $orderByClause = $lookupTableJoins = NULL;
315 if (!$onlyCount) {
316 $sortParams = array(
317 'sort' => 'start_date',
318 'offset' => 0,
319 'rowCount' => 10,
320 'sortOrder' => 'desc',
321 );
322 foreach ($sortParams as $name => $default) {
323 if (CRM_Utils_Array::value($name, $params)) {
324 $sortParams[$name] = $params[$name];
325 }
326 }
327
328
329 //need to lookup tables.
330 $orderOnCampaignTable = TRUE;
331 if ($sortParams['sort'] == 'status') {
332 $orderOnCampaignTable = FALSE;
333 $lookupTableJoins = "
334 LEFT JOIN civicrm_option_value status ON ( status.value = campaign.status_id OR campaign.status_id IS NULL )
335 INNER JOIN civicrm_option_group grp ON ( status.option_group_id = grp.id AND grp.name = 'campaign_status' )";
336 $orderByClause = "ORDER BY status.label {$sortParams['sortOrder']}";
337 }
338 elseif ($sortParams['sort'] == 'campaign_type') {
339 $orderOnCampaignTable = FALSE;
340 $lookupTableJoins = "
341 LEFT JOIN civicrm_option_value campaign_type ON ( campaign_type.value = campaign.campaign_type_id
342 OR campaign.campaign_type_id IS NULL )
343 INNER JOIN civicrm_option_group grp ON ( campaign_type.option_group_id = grp.id AND grp.name = 'campaign_type' )";
344 $orderByClause = "ORDER BY campaign_type.label {$sortParams['sortOrder']}";
345 }
346 elseif ($sortParams['sort'] == 'isActive') {
347 $sortParams['sort'] = 'is_active';
348 }
349 if ($orderOnCampaignTable) {
350 $orderByClause = "ORDER BY campaign.{$sortParams['sort']} {$sortParams['sortOrder']}";
351 }
352 $limitClause = "LIMIT {$sortParams['offset']}, {$sortParams['rowCount']}";
353 }
354
355 //build the where clause.
356 $queryParams = $where = array();
357 if (CRM_Utils_Array::value('id', $params)) {
358 $where[] = "( campaign.id = %1 )";
359 $queryParams[1] = array($params['id'], 'Positive');
360 }
361 if (CRM_Utils_Array::value('name', $params)) {
362 $where[] = "( campaign.name LIKE %2 )";
363 $queryParams[2] = array('%' . trim($params['name']) . '%', 'String');
364 }
365 if (CRM_Utils_Array::value('title', $params)) {
366 $where[] = "( campaign.title LIKE %3 )";
367 $queryParams[3] = array('%' . trim($params['title']) . '%', 'String');
368 }
369 if (CRM_Utils_Array::value('start_date', $params)) {
370 $startDate = CRM_Utils_Date::processDate($params['start_date']);
371 $where[] = "( campaign.start_date >= %4 OR campaign.start_date IS NULL )";
372 $queryParams[4] = array($startDate, 'String');
373 }
374 if (CRM_Utils_Array::value('end_date', $params)) {
375 $endDate = CRM_Utils_Date::processDate($params['end_date'], '235959');
376 $where[] = "( campaign.end_date <= %5 OR campaign.end_date IS NULL )";
377 $queryParams[5] = array($endDate, 'String');
378 }
379 if (CRM_Utils_Array::value('description', $params)) {
380 $where[] = "( campaign.description LIKE %6 )";
381 $queryParams[6] = array('%' . trim($params['description']) . '%', 'String');
382 }
383 if (CRM_Utils_Array::value('campaign_type_id', $params)) {
384 $typeId = $params['campaign_type_id'];
385 if (is_array($params['campaign_type_id'])) {
386 $typeId = implode(' , ', $params['campaign_type_id']);
387 }
388 $where[] = "( campaign.campaign_type_id IN ( {$typeId} ) )";
389 }
390 if (CRM_Utils_Array::value('status_id', $params)) {
391 $statusId = $params['status_id'];
392 if (is_array($params['status_id'])) {
393 $statusId = implode(' , ', $params['status_id']);
394 }
395 $where[] = "( campaign.status_id IN ( {$statusId} ) )";
396 }
397 if (array_key_exists('is_active', $params)) {
398 $active = "( campaign.is_active = 1 )";
399 if (CRM_Utils_Array::value('is_active', $params)) {
400 $active = "( campaign.is_active = 0 OR campaign.is_active IS NULL )";
401 }
402 $where[] = $active;
403 }
404 $whereClause = NULL;
405 if (!empty($where)) {
406 $whereClause = ' WHERE ' . implode(" \nAND ", $where);
407 }
408
409 $properties = array(
410 'id',
411 'name',
412 'title',
413 'start_date',
414 'end_date',
415 'status_id',
416 'is_active',
417 'description',
418 'campaign_type_id',
419 );
420
421 $selectClause = '
422 SELECT campaign.id as id,
423 campaign.name as name,
424 campaign.title as title,
425 campaign.is_active as is_active,
426 campaign.status_id as status_id,
427 campaign.end_date as end_date,
428 campaign.start_date as start_date,
429 campaign.description as description,
430 campaign.campaign_type_id as campaign_type_id';
431 if ($onlyCount) {
432 $selectClause = 'SELECT COUNT(*)';
433 }
434 $fromClause = 'FROM civicrm_campaign campaign';
435
436 $query = "{$selectClause} {$fromClause} {$lookupTableJoins} {$whereClause} {$orderByClause} {$limitClause}";
437
438 //in case of only count.
439 if ($onlyCount) {
440 return (int)CRM_Core_DAO::singleValueQuery($query, $queryParams);
441 }
442
443 $campaign = CRM_Core_DAO::executeQuery($query, $queryParams);
444 while ($campaign->fetch()) {
445 foreach ($properties as $property) {
446 $campaigns[$campaign->id][$property] = $campaign->$property;
447 }
448 }
449
450 return $campaigns;
451 }
452
453 /**
454 * Get the campaign count.
455 *
456 * @static
457 */
458 static function getCampaignCount() {
459 return (int)CRM_Core_DAO::singleValueQuery('SELECT COUNT(*) FROM civicrm_campaign');
460 }
461
462 /**
463 * Function to get Campaigns groups
464 *
465 * @param int $campaignId campaign id
466 *
467 * @static
468 */
469 static function getCampaignGroups($campaignId) {
470 static $campaignGroups;
471 if (!$campaignId) {
472 return array();
473 }
474
475 if (!isset($campaignGroups[$campaignId])) {
476 $campaignGroups[$campaignId] = array();
477
478 $query = "
479 SELECT grp.title, grp.id
480 FROM civicrm_campaign_group campgrp
481 INNER JOIN civicrm_group grp ON ( grp.id = campgrp.entity_id )
482 WHERE campgrp.group_type = 'Include'
483 AND campgrp.entity_table = 'civicrm_group'
484 AND campgrp.campaign_id = %1";
485
486 $groups = CRM_Core_DAO::executeQuery($query, array(1 => array($campaignId, 'Positive')));
487 while ($groups->fetch()) {
488 $campaignGroups[$campaignId][$groups->id] = $groups->title;
489 }
490 }
491
492 return $campaignGroups[$campaignId];
493 }
494
495 /**
496 * update the is_active flag in the db
497 *
498 * @param int $id id of the database record
499 * @param boolean $is_active value we want to set the is_active field
500 *
501 * @return Object DAO object on sucess, null otherwise
502 * @static
503 */
504 static function setIsActive($id, $is_active) {
505 return CRM_Core_DAO::setFieldValue('CRM_Campaign_DAO_Campaign', $id, 'is_active', $is_active);
506 }
507
508 static function accessCampaign() {
509 static $allow = NULL;
510
511 if (!isset($allow)) {
512 $allow = FALSE;
513 if (CRM_Core_Permission::check('manage campaign') ||
514 CRM_Core_Permission::check('administer CiviCampaign')
515 ) {
516 $allow = TRUE;
517 }
518 }
519
520 return $allow;
521 }
522
523 /*
524 * Add select element for campaign
525 * and assign needful info to templates.
526 *
527 */
528 public static function addCampaign(&$form, $connectedCampaignId = NULL) {
529 //some forms do set default and freeze.
530 $appendDates = TRUE;
531 if ($form->get('action') & CRM_Core_Action::VIEW) {
532 $appendDates = FALSE;
533 }
534
535 $campaignDetails = self::getPermissionedCampaigns($connectedCampaignId, NULL, TRUE, TRUE, $appendDates);
536 $fields = array('campaigns', 'hasAccessCampaign', 'isCampaignEnabled');
537 foreach ($fields as $fld)$$fld = CRM_Utils_Array::value($fld, $campaignDetails);
538
539 //lets see do we have past campaigns.
540 $hasPastCampaigns = FALSE;
541 $allActiveCampaigns = CRM_Campaign_BAO_Campaign::getCampaigns(NULL, NULL, TRUE, FALSE);
542 if (count($allActiveCampaigns) > count($campaigns)) {
543 $hasPastCampaigns = TRUE;
544 }
545 $hasCampaigns = FALSE;
546 if (!empty($campaigns)) {
547 $hasCampaigns = TRUE;
548 }
549 if ($hasPastCampaigns) {
550 $hasCampaigns = TRUE;
551 $form->add('hidden', 'included_past_campaigns');
552 }
553
554 $showAddCampaign = FALSE;
555 $alreadyIncludedPastCampaigns = FALSE;
556 if ($connectedCampaignId || ($isCampaignEnabled && $hasAccessCampaign)) {
557 $showAddCampaign = TRUE;
558 //lets add past campaigns as options to quick-form element.
559 if ($hasPastCampaigns && $form->getElementValue('included_past_campaigns')) {
560 $campaigns = $allActiveCampaigns;
561 $alreadyIncludedPastCampaigns = TRUE;
562 }
563 $campaign = &$form->add('select',
564 'campaign_id',
565 ts('Campaign'),
566 array(
567 '' => ts('- select -')) + $campaigns
568 );
569 //lets freeze when user does not has access or campaign is disabled.
570 if (!$isCampaignEnabled || !$hasAccessCampaign) {
571 $campaign->freeze();
572 }
573 }
574
575 $addCampaignURL = NULL;
576 if (empty($campaigns) && $hasAccessCampaign && $isCampaignEnabled) {
577 $addCampaignURL = CRM_Utils_System::url('civicrm/campaign/add', 'reset=1');
578 }
579
580 $includePastCampaignURL = NULL;
581 if ($hasPastCampaigns && $isCampaignEnabled && $hasAccessCampaign) {
582 $includePastCampaignURL = CRM_Utils_System::url('civicrm/ajax/rest',
583 'className=CRM_Campaign_Page_AJAX&fnName=allActiveCampaigns',
584 FALSE, NULL, FALSE
585 );
586 }
587
588 //carry this info to templates.
589 $infoFields = array(
590 'hasCampaigns',
591 'addCampaignURL',
592 'showAddCampaign',
593 'hasPastCampaigns',
594 'hasAccessCampaign',
595 'isCampaignEnabled',
596 'includePastCampaignURL',
597 'alreadyIncludedPastCampaigns',
598 );
599 foreach ($infoFields as $fld) $campaignInfo[$fld] = $$fld;
600 $form->assign('campaignInfo', $campaignInfo);
601 }
602
603 /*
604 * Add campaign in compoent search.
605 * and assign needful info to templates.
606 *
607 */
608 public static function addCampaignInComponentSearch(&$form, $elementName = 'campaign_id') {
609 $campaignInfo = array();
610 $campaignDetails = self::getPermissionedCampaigns(NULL, NULL, FALSE, FALSE, FALSE, TRUE);
611 $fields = array('campaigns', 'hasAccessCampaign', 'isCampaignEnabled');
612 foreach ($fields as $fld)$$fld = CRM_Utils_Array::value($fld, $campaignDetails);
613 $showCampaignInSearch = FALSE;
614 if ($isCampaignEnabled && $hasAccessCampaign && !empty($campaigns)) {
615 //get the current campaign only.
616 $currentCampaigns = self::getCampaigns(NULL, NULL, FALSE);
617 $pastCampaigns = array_diff($campaigns, $currentCampaigns);
618 $allCampaigns = array();
619 if (!empty($currentCampaigns)) {
620 $allCampaigns = array('current_campaign' => ts('Current Campaigns'));
621 foreach ($currentCampaigns as & $camp) $camp = "&nbsp;&nbsp;&nbsp;{$camp}";
622 $allCampaigns += $currentCampaigns;
623 }
624 if (!empty($pastCampaigns)) {
625 $allCampaigns += array('past_campaign' => ts('Past Campaigns'));
626 foreach ($pastCampaigns as & $camp) $camp = "&nbsp;&nbsp;&nbsp;{$camp}";
627 $allCampaigns += $pastCampaigns;
628 }
629
630 $showCampaignInSearch = TRUE;
631 $form->add('select', $elementName, ts('Campaigns'), $allCampaigns, FALSE,
632 array('id' => 'campaigns', 'multiple' => 'multiple', 'title' => ts('- select -'))
633 );
634 }
635 $infoFields = array(
636 'elementName',
637 'hasAccessCampaign',
638 'isCampaignEnabled',
639 'showCampaignInSearch',
640 );
641 foreach ($infoFields as $fld) $campaignInfo[$fld] = $$fld;
642 $form->assign('campaignInfo', $campaignInfo);
643 }
644 }
645