CRM-13244 - Split prepareMailingQuery() into entity-specific pieces.
[civicrm-core.git] / CRM / Core / BAO / ActionSchedule.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
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-2015
32 * $Id$
33 *
34 */
35
36 /**
37 * This class contains functions for managing Scheduled Reminders
38 */
39 class CRM_Core_BAO_ActionSchedule extends CRM_Core_DAO_ActionSchedule {
40
41 /**
42 * @param array $filters
43 * Filter by property (e.g. 'id').
44 * @return array
45 * Array(scalar $id => Mapping $mapping).
46 */
47 public static function getMappings($filters = NULL) {
48 static $_action_mapping;
49
50 if ($_action_mapping === NULL) {
51 $event = \Civi\Core\Container::singleton()->get('dispatcher')
52 ->dispatch(\Civi\ActionSchedule\Events::MAPPINGS,
53 new \Civi\ActionSchedule\Event\MappingRegisterEvent());
54 $_action_mapping = $event->getMappings();
55 }
56
57 if (empty($filters)) {
58 return $_action_mapping;
59 }
60 elseif (isset($filters['id'])) {
61 return array(
62 $filters['id'] => $_action_mapping[$filters['id']],
63 );
64 }
65 else {
66 throw new CRM_Core_Exception("getMappings() called with unsupported filter: " . implode(', ', array_keys($filters)));
67 }
68 }
69
70 /**
71 * Retrieve list of selections/drop downs for Scheduled Reminder form
72 *
73 * @param bool $id
74 * Mapping id.
75 *
76 * @return array
77 * associated array of all the drop downs in the form
78 */
79 public static function getSelection($id = NULL) {
80 $mappings = CRM_Core_BAO_ActionSchedule::getMappings();
81
82 $entityValueLabels = $entityStatusLabels = $dateFieldLabels = array();
83 $entityRecipientLabels = $entityRecipientNames = array();
84
85 if (!$id) {
86 $id = 1;
87 }
88
89 foreach ($mappings as $mapping) {
90 /** @var \Civi\ActionSchedule\Mapping $mapping */
91
92 $mappingId = $mapping->getId();
93 $entityValueLabels[$mappingId] = $mapping->getValueLabels();
94 // Not sure why: everything *except* contact-dates have a $valueLabel.
95 if ($mapping->getId() !== CRM_Contact_ActionMapping::CONTACT_MAPPING_ID) {
96 $valueLabel = array('- ' . strtolower($mapping->getValueHeader()) . ' -');
97 $entityValueLabels[$mapping->getId()] = $valueLabel + $entityValueLabels[$mapping->getId()];
98 }
99
100 if ($mapping->getId() == $id) {
101 $dateFieldLabels = $mapping->getDateFields();
102 $entityRecipientLabels = $mapping->getRecipientTypes();
103 $entityRecipientNames = array_combine(array_keys($entityRecipientLabels), array_keys($entityRecipientLabels));
104 }
105
106 $statusLabel = array('- ' . strtolower($mapping->getStatusHeader()) . ' -');
107 $entityStatusLabels[$mapping->getId()] = $entityValueLabels[$mapping->getId()];
108 foreach ($entityStatusLabels[$mapping->getId()] as $kkey => & $vval) {
109 $vval = $statusLabel + $mapping->getStatusLabels($kkey);
110 }
111 }
112
113 $entityLabels = array_map(function ($v) {
114 return $v->getLabel();
115 }, $mappings);
116 $entityNames = array_map(function ($v) {
117 return $v->getEntity();
118 }, $mappings);
119
120 return array(
121 'sel1' => $entityLabels,
122 'sel2' => $entityValueLabels,
123 'sel3' => $entityStatusLabels,
124 'sel4' => $dateFieldLabels,
125 'sel5' => $entityRecipientLabels,
126 'entityMapping' => $entityNames,
127 'recipientMapping' => $entityRecipientNames,
128 );
129 }
130
131 /**
132 * @param int $mappingId
133 * @param int $isLimit
134 *
135 * @return array
136 */
137 public static function getSelection1($mappingId = NULL, $isLimit = NULL) {
138 $mappings = CRM_Core_BAO_ActionSchedule::getMappings(array(
139 'id' => $mappingId,
140 ));
141 $dateFieldLabels = $entityRecipientLabels = array();
142
143 foreach ($mappings as $mapping) {
144 /** @var \Civi\ActionSchedule\Mapping $mapping */
145 $dateFieldLabels = $mapping->getDateFields();
146 $entityRecipientLabels = $mapping->getRecipientTypes(!$isLimit);
147 }
148
149 return array(
150 'sel4' => $dateFieldLabels,
151 'sel5' => $entityRecipientLabels,
152 'recipientMapping' => array_combine(array_keys($entityRecipientLabels), array_keys($entityRecipientLabels)),
153 );
154 }
155
156 /**
157 * Retrieve list of Scheduled Reminders.
158 *
159 * @param bool $namesOnly
160 * Return simple list of names.
161 *
162 * @param \Civi\ActionSchedule\Mapping|NULL $filterMapping
163 * Filter by the schedule's mapping type.
164 * @param int $filterValue
165 * Filter by the schedule's entity_value.
166 *
167 * @return array
168 * (reference) reminder list
169 */
170 public static function &getList($namesOnly = FALSE, $filterMapping = NULL, $filterValue = NULL) {
171 $query = "
172 SELECT
173 title,
174 cas.id as id,
175 cas.mapping_id,
176 cas.entity_value as entityValueIds,
177 cas.entity_status as entityStatusIds,
178 cas.start_action_date as entityDate,
179 cas.start_action_offset,
180 cas.start_action_unit,
181 cas.start_action_condition,
182 cas.absolute_date,
183 is_repeat,
184 is_active
185
186 FROM civicrm_action_schedule cas
187 ";
188 $queryParams = array();
189 $where = " WHERE 1 ";
190 if ($filterMapping and $filterValue) {
191 $where .= " AND cas.entity_value = %1 AND cas.mapping_id = %2";
192 $queryParams[1] = array($filterValue, 'Integer');
193 $queryParams[2] = array($filterMapping->getId(), 'Integer');
194 }
195 $where .= " AND cas.used_for IS NULL";
196 $query .= $where;
197 $dao = CRM_Core_DAO::executeQuery($query, $queryParams);
198 while ($dao->fetch()) {
199 /** @var Civi\ActionSchedule\Mapping $filterMapping */
200 $filterMapping = CRM_Utils_Array::first(self::getMappings(array(
201 'id' => $dao->mapping_id,
202 )));
203 $list[$dao->id]['id'] = $dao->id;
204 $list[$dao->id]['title'] = $dao->title;
205 $list[$dao->id]['start_action_offset'] = $dao->start_action_offset;
206 $list[$dao->id]['start_action_unit'] = $dao->start_action_unit;
207 $list[$dao->id]['start_action_condition'] = $dao->start_action_condition;
208 $list[$dao->id]['entityDate'] = ucwords(str_replace('_', ' ', $dao->entityDate));
209 $list[$dao->id]['absolute_date'] = $dao->absolute_date;
210 $list[$dao->id]['entity'] = $filterMapping->getLabel();
211 $list[$dao->id]['value'] = implode(', ', CRM_Utils_Array::subset(
212 $filterMapping->getValueLabels(),
213 explode(CRM_Core_DAO::VALUE_SEPARATOR, $dao->entityValueIds)
214 ));
215 $list[$dao->id]['status'] = implode(', ', CRM_Utils_Array::subset(
216 $filterMapping->getStatusLabels($dao->entityValueIds),
217 explode(CRM_Core_DAO::VALUE_SEPARATOR, $dao->entityStatusIds)
218 ));
219 $list[$dao->id]['is_repeat'] = $dao->is_repeat;
220 $list[$dao->id]['is_active'] = $dao->is_active;
221 }
222
223 return $list;
224 }
225
226 /**
227 * Add the schedules reminders in the db.
228 *
229 * @param array $params
230 * (reference ) an assoc array of name/value pairs.
231 * @param array $ids
232 * Unused variable.
233 *
234 * @return CRM_Core_DAO_ActionSchedule
235 */
236 public static function add(&$params, $ids = array()) {
237 $actionSchedule = new CRM_Core_DAO_ActionSchedule();
238 $actionSchedule->copyValues($params);
239
240 return $actionSchedule->save();
241 }
242
243 /**
244 * Retrieve DB object based on input parameters.
245 *
246 * It also stores all the retrieved values in the default array.
247 *
248 * @param array $params
249 * (reference ) an assoc array of name/value pairs.
250 * @param array $values
251 * (reference ) an assoc array to hold the flattened values.
252 *
253 * @return CRM_Core_DAO_ActionSchedule|null
254 * object on success, null otherwise
255 */
256 public static function retrieve(&$params, &$values) {
257 if (empty($params)) {
258 return NULL;
259 }
260 $actionSchedule = new CRM_Core_DAO_ActionSchedule();
261
262 $actionSchedule->copyValues($params);
263
264 if ($actionSchedule->find(TRUE)) {
265 $ids['actionSchedule'] = $actionSchedule->id;
266
267 CRM_Core_DAO::storeValues($actionSchedule, $values);
268
269 return $actionSchedule;
270 }
271 return NULL;
272 }
273
274 /**
275 * Delete a Reminder.
276 *
277 * @param int $id
278 * ID of the Reminder to be deleted.
279 *
280 */
281 public static function del($id) {
282 if ($id) {
283 $dao = new CRM_Core_DAO_ActionSchedule();
284 $dao->id = $id;
285 if ($dao->find(TRUE)) {
286 $dao->delete();
287 return;
288 }
289 }
290 CRM_Core_Error::fatal(ts('Invalid value passed to delete function.'));
291 }
292
293 /**
294 * Update the is_active flag in the db.
295 *
296 * @param int $id
297 * Id of the database record.
298 * @param bool $is_active
299 * Value we want to set the is_active field.
300 *
301 * @return Object
302 * DAO object on success, null otherwise
303 */
304 public static function setIsActive($id, $is_active) {
305 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_ActionSchedule', $id, 'is_active', $is_active);
306 }
307
308 /**
309 * @param int $mappingID
310 * @param $now
311 *
312 * @throws CRM_Core_Exception
313 */
314 public static function sendMailings($mappingID, $now) {
315 $mapping = CRM_Utils_Array::first(self::getMappings(array(
316 'id' => $mappingID,
317 )));
318
319 $actionSchedule = new CRM_Core_DAO_ActionSchedule();
320 $actionSchedule->mapping_id = $mappingID;
321 $actionSchedule->is_active = 1;
322 $actionSchedule->find(FALSE);
323
324 while ($actionSchedule->fetch()) {
325 $query = CRM_Core_BAO_ActionSchedule::prepareMailingQuery($mapping, $actionSchedule);
326 $dao = CRM_Core_DAO::executeQuery($query,
327 array(1 => array($actionSchedule->id, 'Integer'))
328 );
329
330 $multilingual = CRM_Core_I18n::isMultilingual();
331 while ($dao->fetch()) {
332 // switch language if necessary
333 if ($multilingual) {
334 $preferred_language = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $dao->contactID, 'preferred_language');
335 CRM_Core_BAO_ActionSchedule::setCommunicationLanguage($actionSchedule->communication_language, $preferred_language);
336 }
337
338 $errors = array();
339 try {
340 $tokenProcessor = self::createTokenProcessor($actionSchedule, $mapping);
341 $tokenProcessor->addRow()
342 ->context('contactId', $dao->contactID)
343 ->context('actionSearchResult', (object) $dao->toArray());
344 foreach ($tokenProcessor->evaluate()->getRows() as $tokenRow) {
345 if ($actionSchedule->mode == 'SMS' or $actionSchedule->mode == 'User_Preference') {
346 CRM_Utils_Array::extend($errors, self::sendReminderSms($tokenRow, $actionSchedule, $dao->contactID));
347 }
348
349 if ($actionSchedule->mode == 'Email' or $actionSchedule->mode == 'User_Preference') {
350 CRM_Utils_Array::extend($errors, self::sendReminderEmail($tokenRow, $actionSchedule, $dao->contactID));
351 }
352 }
353 }
354 catch (\Civi\Token\TokenException $e) {
355 $errors['token_exception'] = $e->getMessage();
356 }
357
358 // update action log record
359 $logParams = array(
360 'id' => $dao->reminderID,
361 'is_error' => !empty($errors),
362 'message' => empty($errors) ? "null" : implode(' ', $errors),
363 'action_date_time' => $now,
364 );
365 CRM_Core_BAO_ActionLog::create($logParams);
366
367 // insert activity log record if needed
368 if ($actionSchedule->record_activity && empty($errors)) {
369 $caseID = empty($dao->case_id) ? NULL : $dao->case_id;
370 CRM_Core_BAO_ActionSchedule::createMailingActivity($actionSchedule, $mapping, $dao->contactID, $dao->entityID, $caseID);
371 }
372 }
373
374 $dao->free();
375 }
376 }
377
378 /**
379 * @param int $mappingID
380 * @param $now
381 * @param array $params
382 *
383 * @throws API_Exception
384 */
385 public static function buildRecipientContacts($mappingID, $now, $params = array()) {
386 $actionSchedule = new CRM_Core_DAO_ActionSchedule();
387 $actionSchedule->mapping_id = $mappingID;
388 $actionSchedule->is_active = 1;
389 if (!empty($params)) {
390 _civicrm_api3_dao_set_filter($actionSchedule, $params, FALSE);
391 }
392 $actionSchedule->find();
393
394 while ($actionSchedule->fetch()) {
395 /** @var \Civi\ActionSchedule\Mapping $mapping */
396 $mapping = CRM_Utils_Array::first(self::getMappings(array(
397 'id' => $mappingID,
398 )));
399 $builder = new \Civi\ActionSchedule\RecipientBuilder($now, $actionSchedule, $mapping);
400 $builder->build();
401 }
402 }
403
404 /**
405 * @param null $now
406 * @param array $params
407 *
408 * @return array
409 */
410 public static function processQueue($now = NULL, $params = array()) {
411 $now = $now ? CRM_Utils_Time::setTime($now) : CRM_Utils_Time::getTime();
412
413 $mappings = CRM_Core_BAO_ActionSchedule::getMappings();
414 foreach ($mappings as $mappingID => $mapping) {
415 CRM_Core_BAO_ActionSchedule::buildRecipientContacts($mappingID, $now, $params);
416 CRM_Core_BAO_ActionSchedule::sendMailings($mappingID, $now);
417 }
418
419 $result = array(
420 'is_error' => 0,
421 'messages' => ts('Sent all scheduled reminders successfully'),
422 );
423 return $result;
424 }
425
426 /**
427 * @param int $id
428 * @param int $mappingID
429 *
430 * @return null|string
431 */
432 public static function isConfigured($id, $mappingID) {
433 $queryString = "SELECT count(id) FROM civicrm_action_schedule
434 WHERE mapping_id = %1 AND
435 entity_value = %2";
436
437 $params = array(
438 1 => array($mappingID, 'Integer'),
439 2 => array($id, 'Integer'),
440 );
441 return CRM_Core_DAO::singleValueQuery($queryString, $params);
442 }
443
444 /**
445 * @param int $mappingID
446 * @param $recipientType
447 *
448 * @return array
449 */
450 public static function getRecipientListing($mappingID, $recipientType) {
451 if (!$mappingID) {
452 return array();
453 }
454
455 /** @var \Civi\ActionSchedule\Mapping $mapping */
456 $mapping = CRM_Utils_Array::first(CRM_Core_BAO_ActionSchedule::getMappings(array(
457 'id' => $mappingID,
458 )));
459 return $mapping->getRecipientListing($recipientType);
460 }
461
462 /**
463 * @param $communication_language
464 * @param $preferred_language
465 */
466 public static function setCommunicationLanguage($communication_language, $preferred_language) {
467 $config = CRM_Core_Config::singleton();
468 $language = $config->lcMessages;
469
470 // prepare the language for the email
471 if ($communication_language == CRM_Core_I18n::AUTO) {
472 if (!empty($preferred_language)) {
473 $language = $preferred_language;
474 }
475 }
476 else {
477 $language = $communication_language;
478 }
479
480 // language not in the existing language, use default
481 $languages = CRM_Core_I18n::languages(TRUE);
482 if (!in_array($language, $languages)) {
483 $language = $config->lcMessages;
484 }
485
486 // change the language
487 $i18n = CRM_Core_I18n::singleton();
488 $i18n->setLanguage($language);
489 }
490
491 /**
492 * Save a record about the delivery of a reminder email.
493 *
494 * WISHLIST: Instead of saving $actionSchedule->body_html, call this immediately after
495 * sending the message and pass in the fully rendered text of the message.
496 *
497 * @param CRM_Core_DAO_ActionSchedule $actionSchedule
498 * @param Civi\ActionSchedule\Mapping $mapping
499 * @param int $contactID
500 * @param int $entityID
501 * @param int|NULL $caseID
502 * @throws CRM_Core_Exception
503 */
504 protected static function createMailingActivity($actionSchedule, $mapping, $contactID, $entityID, $caseID) {
505 $session = CRM_Core_Session::singleton();
506
507 if ($mapping->getEntity() == 'civicrm_membership') {
508 $activityTypeID
509 = CRM_Core_OptionGroup::getValue('activity_type', 'Membership Renewal Reminder', 'name');
510 }
511 else {
512 $activityTypeID
513 = CRM_Core_OptionGroup::getValue('activity_type', 'Reminder Sent', 'name');
514 }
515
516 $activityParams = array(
517 'subject' => $actionSchedule->title,
518 'details' => $actionSchedule->body_html,
519 'source_contact_id' => $session->get('userID') ? $session->get('userID') : $contactID,
520 'target_contact_id' => $contactID,
521 'activity_date_time' => CRM_Utils_Time::getTime('YmdHis'),
522 'status_id' => CRM_Core_OptionGroup::getValue('activity_status', 'Completed', 'name'),
523 'activity_type_id' => $activityTypeID,
524 'source_record_id' => $entityID,
525 );
526 $activity = CRM_Activity_BAO_Activity::create($activityParams);
527
528 //file reminder on case if source activity is a case activity
529 if (!empty($caseID)) {
530 $caseActivityParams = array();
531 $caseActivityParams['case_id'] = $caseID;
532 $caseActivityParams['activity_id'] = $activity->id;
533 CRM_Case_BAO_Case::processCaseActivity($caseActivityParams);
534 }
535 }
536
537 /**
538 * @param \Civi\ActionSchedule\MappingInterface $mapping
539 * @param \CRM_Core_DAO_ActionSchedule $actionSchedule
540 * @return string
541 */
542 protected static function prepareMailingQuery($mapping, $actionSchedule) {
543 $select = CRM_Utils_SQL_Select::from('civicrm_action_log reminder')
544 ->select("reminder.id as reminderID, reminder.contact_id as contactID, reminder.entity_table as entityTable, reminder.*, e.id AS entityID")
545 ->join('e', "!casMailingJoinType !casMappingEntity e ON !casEntityJoinExpr")
546 ->select("e.id as entityID, e.*")
547 ->where("reminder.action_schedule_id = #casActionScheduleId")
548 ->where("reminder.action_date_time IS NULL")
549 ->param(array(
550 'casActionScheduleId' => $actionSchedule->id,
551 'casMailingJoinType' => ($actionSchedule->limit_to == 0) ? 'LEFT JOIN' : 'INNER JOIN',
552 'casMappingId' => $mapping->getId(),
553 'casMappingEntity' => $mapping->getEntity(),
554 'casEntityJoinExpr' => 'e.id = reminder.entity_id',
555 ));
556
557 if ($actionSchedule->limit_to == 0) {
558 $select->where("e.id = reminder.entity_id OR reminder.entity_table = 'civicrm_contact'");
559 }
560
561 \Civi\Core\Container::singleton()->get('dispatcher')
562 ->dispatch(
563 \Civi\ActionSchedule\Events::MAILING_QUERY,
564 new \Civi\ActionSchedule\Event\MailingQueryEvent($actionSchedule, $mapping, $select)
565 );
566
567 return $select->toSQL();
568 }
569
570 /**
571 * @param TokenRow $tokenRow
572 * @param CRM_Core_DAO_ActionSchedule $schedule
573 * @param int $toContactID
574 * @throws CRM_Core_Exception
575 * @return array
576 * List of error messages.
577 */
578 protected static function sendReminderSms($tokenRow, $schedule, $toContactID) {
579 $toPhoneNumber = self::pickSmsPhoneNumber($toContactID);
580 if (!$toPhoneNumber) {
581 return array("sms_phone_missing" => "Couldn't find recipient's phone number.");
582 }
583
584 $messageSubject = $tokenRow->render('subject');
585 $sms_body_text = $tokenRow->render('sms_body_text');
586
587 $session = CRM_Core_Session::singleton();
588 $userID = $session->get('userID') ? $session->get('userID') : $tokenRow->context['contactId'];
589 $smsParams = array(
590 'To' => $toPhoneNumber,
591 'provider_id' => $schedule->sms_provider_id,
592 'activity_subject' => $messageSubject,
593 );
594 $activityTypeID = CRM_Core_OptionGroup::getValue('activity_type',
595 'SMS',
596 'name'
597 );
598 $activityParams = array(
599 'source_contact_id' => $userID,
600 'activity_type_id' => $activityTypeID,
601 'activity_date_time' => date('YmdHis'),
602 'subject' => $messageSubject,
603 'details' => $sms_body_text,
604 'status_id' => CRM_Core_OptionGroup::getValue('activity_status', 'Completed', 'name'),
605 );
606
607 $activity = CRM_Activity_BAO_Activity::create($activityParams);
608
609 CRM_Activity_BAO_Activity::sendSMSMessage($tokenRow->context['contactId'],
610 $sms_body_text,
611 $smsParams,
612 $activity->id,
613 $userID
614 );
615
616 return array();
617 }
618
619 /**
620 * @param CRM_Core_DAO_ActionSchedule $actionSchedule
621 * @return string
622 * Ex: "Alice <alice@example.org>".
623 */
624 protected static function pickFromEmail($actionSchedule) {
625 $domainValues = CRM_Core_BAO_Domain::getNameAndEmail();
626 $fromEmailAddress = "$domainValues[0] <$domainValues[1]>";
627 if ($actionSchedule->from_email) {
628 $fromEmailAddress = "$actionSchedule->from_name <$actionSchedule->from_email>";
629 return $fromEmailAddress;
630 }
631 return $fromEmailAddress;
632 }
633
634 /**
635 * @param TokenRow $tokenRow
636 * @param CRM_Core_DAO_ActionSchedule $schedule
637 * @param int $toContactID
638 * @return array
639 * List of error messages.
640 */
641 protected static function sendReminderEmail($tokenRow, $schedule, $toContactID) {
642 $toEmail = CRM_Contact_BAO_Contact::getPrimaryEmail($toContactID);
643 if (!$toEmail) {
644 return array("email_missing" => "Couldn't find recipient's email address.");
645 }
646
647 $body_text = $tokenRow->render('body_text');
648 $body_html = $tokenRow->render('body_html');
649 if (!$schedule->body_text) {
650 $body_text = CRM_Utils_String::htmlToText($body_html);
651 }
652
653 // set up the parameters for CRM_Utils_Mail::send
654 $mailParams = array(
655 'groupName' => 'Scheduled Reminder Sender',
656 'from' => self::pickFromEmail($schedule),
657 'toName' => $tokenRow->context['contact']['display_name'],
658 'toEmail' => $toEmail,
659 'subject' => $tokenRow->render('subject'),
660 'entity' => 'action_schedule',
661 'entity_id' => $schedule->id,
662 );
663
664 if (!$body_html || $tokenRow->context['contact']['preferred_mail_format'] == 'Text' ||
665 $tokenRow->context['contact']['preferred_mail_format'] == 'Both'
666 ) {
667 // render the &amp; entities in text mode, so that the links work
668 $mailParams['text'] = str_replace('&amp;', '&', $body_text);
669 }
670 if ($body_html && ($tokenRow->context['contact']['preferred_mail_format'] == 'HTML' ||
671 $tokenRow->context['contact']['preferred_mail_format'] == 'Both'
672 )
673 ) {
674 $mailParams['html'] = $body_html;
675 }
676 $result = CRM_Utils_Mail::send($mailParams);
677 if (!$result || is_a($result, 'PEAR_Error')) {
678 return array('email_fail' => 'Failed to send message');
679 }
680
681 return array();
682 }
683
684 /**
685 * @param CRM_Core_DAO_ActionSchedule $schedule
686 * @param \Civi\ActionSchedule\Mapping $mapping
687 * @return \Civi\Token\TokenProcessor
688 */
689 protected static function createTokenProcessor($schedule, $mapping) {
690 $tp = new \Civi\Token\TokenProcessor(\Civi\Core\Container::singleton()->get('dispatcher'), array(
691 'controller' => __CLASS__,
692 'actionSchedule' => $schedule,
693 'actionMapping' => $mapping,
694 'smarty' => TRUE,
695 ));
696 $tp->addMessage('body_text', $schedule->body_text, 'text/plain');
697 $tp->addMessage('body_html', $schedule->body_html, 'text/html');
698 $tp->addMessage('sms_body_text', $schedule->sms_body_text, 'text/plain');
699 $tp->addMessage('subject', $schedule->subject, 'text/plain');
700 return $tp;
701 }
702
703 /**
704 * @param $dao
705 * @return string|NULL
706 */
707 protected static function pickSmsPhoneNumber($smsToContactId) {
708 $toPhoneNumbers = CRM_Core_BAO_Phone::allPhones($smsToContactId, FALSE, 'Mobile', array(
709 'is_deceased' => 0,
710 'is_deleted' => 0,
711 'do_not_sms' => 0,
712 ));
713 //to get primary mobile ph,if not get a first mobile phONE
714 if (!empty($toPhoneNumbers)) {
715 $toPhoneNumberDetails = reset($toPhoneNumbers);
716 $toPhoneNumber = CRM_Utils_Array::value('phone', $toPhoneNumberDetails);
717 return $toPhoneNumber;
718 }
719 return NULL;
720 }
721
722 }