Commit | Line | Data |
---|---|---|
8a432af6 | 1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
4 | | Copyright CiviCRM LLC. All rights reserved. | | |
5 | | | | |
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 | +--------------------------------------------------------------------+ | |
10 | */ | |
11 | ||
12 | /** | |
13 | * | |
14 | * @package CRM | |
15 | * @copyright CiviCRM LLC https://civicrm.org/licensing | |
16 | */ | |
17 | ||
5b4b9509 | 18 | use Civi\Api4\Email; |
19 | ||
8a432af6 | 20 | /** |
21 | * This class provides the common functionality for tasks that send emails. | |
22 | */ | |
23 | trait CRM_Contact_Form_Task_EmailTrait { | |
24 | ||
25 | /** | |
26 | * Are we operating in "single mode", i.e. sending email to one | |
27 | * specific contact? | |
28 | * | |
29 | * @var bool | |
30 | */ | |
31 | public $_single = FALSE; | |
32 | ||
8a432af6 | 33 | /** |
34 | * All the existing templates in the system. | |
35 | * | |
36 | * @var array | |
37 | */ | |
38 | public $_templates; | |
39 | ||
362e6a63 | 40 | /** |
41 | * Store "to" contact details. | |
42 | * @var array | |
43 | */ | |
44 | public $_toContactDetails = []; | |
45 | ||
46 | /** | |
47 | * Store all selected contact id's, that includes to, cc and bcc contacts | |
48 | * @var array | |
49 | */ | |
50 | public $_allContactIds = []; | |
51 | ||
52 | /** | |
53 | * Store only "to" contact ids. | |
54 | * @var array | |
55 | */ | |
56 | public $_toContactIds = []; | |
57 | ||
58 | /** | |
59 | * Store only "cc" contact ids. | |
60 | * @var array | |
61 | */ | |
62 | public $_ccContactIds = []; | |
63 | ||
64 | /** | |
65 | * Store only "bcc" contact ids. | |
f7869f64 | 66 | * |
362e6a63 | 67 | * @var array |
68 | */ | |
69 | public $_bccContactIds = []; | |
70 | ||
e94f3011 | 71 | /** |
72 | * Is the form being loaded from a search action. | |
73 | * | |
74 | * @var bool | |
75 | */ | |
76 | public $isSearchContext = TRUE; | |
77 | ||
5b4b9509 | 78 | public $contactEmails = []; |
79 | ||
f1781890 | 80 | /** |
81 | * Contacts form whom emails could not be sent. | |
82 | * | |
83 | * An array of contact ids and the relevant message details. | |
84 | * | |
85 | * @var array | |
86 | */ | |
87 | protected $suppressedEmails = []; | |
88 | ||
e94f3011 | 89 | /** |
90 | * Getter for isSearchContext. | |
91 | * | |
92 | * @return bool | |
93 | */ | |
94 | public function isSearchContext(): bool { | |
95 | return $this->isSearchContext; | |
96 | } | |
97 | ||
98 | /** | |
99 | * Setter for isSearchContext. | |
100 | * | |
101 | * @param bool $isSearchContext | |
102 | */ | |
103 | public function setIsSearchContext(bool $isSearchContext) { | |
104 | $this->isSearchContext = $isSearchContext; | |
105 | } | |
106 | ||
e656d97c | 107 | /** |
108 | * Build all the data structures needed to build the form. | |
109 | * | |
110 | * @throws \CiviCRM_API3_Exception | |
111 | * @throws \CRM_Core_Exception | |
112 | */ | |
113 | public function preProcess() { | |
e94f3011 | 114 | $this->traitPreProcess(); |
115 | } | |
116 | ||
117 | /** | |
118 | * Call trait preProcess function. | |
119 | * | |
120 | * This function exists as a transitional arrangement so classes overriding | |
121 | * preProcess can still call it. Ideally it will be melded into preProcess later. | |
122 | * | |
123 | * @throws \CiviCRM_API3_Exception | |
124 | * @throws \CRM_Core_Exception | |
125 | */ | |
126 | protected function traitPreProcess() { | |
e656d97c | 127 | CRM_Contact_Form_Task_EmailCommon::preProcessFromAddress($this); |
e94f3011 | 128 | if ($this->isSearchContext()) { |
129 | // Currently only the contact email form is callable outside search context. | |
130 | parent::preProcess(); | |
131 | } | |
e656d97c | 132 | $this->setContactIDs(); |
133 | $this->assign('single', $this->_single); | |
e94f3011 | 134 | if (CRM_Core_Permission::check('administer CiviCRM')) { |
135 | $this->assign('isAdmin', 1); | |
136 | } | |
e656d97c | 137 | } |
138 | ||
f7869f64 | 139 | /** |
140 | * Build the form object. | |
141 | * | |
142 | * @throws \CRM_Core_Exception | |
143 | */ | |
144 | public function buildQuickForm() { | |
145 | // Suppress form might not be required but perhaps there was a risk some other process had set it to TRUE. | |
146 | $this->assign('suppressForm', FALSE); | |
147 | $this->assign('emailTask', TRUE); | |
148 | ||
a01fb99f | 149 | $toArray = []; |
b68f0d01 | 150 | $suppressedEmails = 0; |
151 | //here we are getting logged in user id as array but we need target contact id. CRM-5988 | |
152 | $cid = $this->get('cid'); | |
153 | if ($cid) { | |
154 | $this->_contactIds = explode(',', $cid); | |
155 | } | |
156 | if (count($this->_contactIds) > 1) { | |
157 | $this->_single = FALSE; | |
158 | } | |
704696b5 | 159 | $this->bounceIfSimpleMailLimitExceeded(count($this->_contactIds)); |
b68f0d01 | 160 | |
161 | $emailAttributes = [ | |
162 | 'class' => 'huge', | |
163 | ]; | |
164 | $to = $this->add('text', 'to', ts('To'), $emailAttributes, TRUE); | |
a01fb99f | 165 | |
166 | $this->addEntityRef('cc_id', ts('CC'), [ | |
167 | 'entity' => 'Email', | |
168 | 'multiple' => TRUE, | |
169 | ]); | |
5b4b9509 | 170 | |
171 | $this->addEntityRef('bcc_id', ts('BCC'), [ | |
172 | 'entity' => 'Email', | |
173 | 'multiple' => TRUE, | |
174 | ]); | |
b68f0d01 | 175 | |
176 | if ($to->getValue()) { | |
177 | $this->_toContactIds = $this->_contactIds = []; | |
178 | } | |
179 | $setDefaults = TRUE; | |
180 | if (property_exists($this, '_context') && $this->_context === 'standalone') { | |
181 | $setDefaults = FALSE; | |
182 | } | |
183 | ||
b68f0d01 | 184 | $this->_allContactIds = $this->_toContactIds = $this->_contactIds; |
b68f0d01 | 185 | |
2067c79f | 186 | if ($to->getValue()) { |
187 | foreach ($this->getEmails($to) as $value) { | |
188 | $contactId = $value['contact_id']; | |
189 | $email = $value['email']; | |
190 | if ($contactId) { | |
191 | $this->_contactIds[] = $this->_toContactIds[] = $contactId; | |
192 | $this->_toContactEmails[] = $email; | |
193 | $this->_allContactIds[] = $contactId; | |
194 | } | |
b68f0d01 | 195 | } |
2067c79f | 196 | $setDefaults = TRUE; |
b68f0d01 | 197 | } |
198 | ||
199 | //get the group of contacts as per selected by user in case of Find Activities | |
200 | if (!empty($this->_activityHolderIds)) { | |
201 | $contact = $this->get('contacts'); | |
202 | $this->_allContactIds = $this->_contactIds = $contact; | |
203 | } | |
204 | ||
205 | // check if we need to setdefaults and check for valid contact emails / communication preferences | |
206 | if (is_array($this->_allContactIds) && $setDefaults) { | |
b68f0d01 | 207 | // get the details for all selected contacts ( to, cc and bcc contacts ) |
33ced9a4 | 208 | $allContactDetails = civicrm_api3('Contact', 'get', [ |
209 | 'id' => ['IN' => $this->_allContactIds], | |
210 | 'return' => ['sort_name', 'email', 'do_not_email', 'is_deceased', 'on_hold', 'display_name', 'preferred_mail_format'], | |
211 | 'options' => ['limit' => 0], | |
212 | ])['values']; | |
b68f0d01 | 213 | |
f942a8b0 | 214 | // The contact task supports passing in email_id in a url. It supports a single email |
215 | // and is marked as having been related to CiviHR. | |
216 | // The array will look like $this->_toEmail = ['email' => 'x', 'contact_id' => 2]) | |
217 | // If it exists we want to use the specified email which might be different to the primary email | |
218 | // that we have. | |
219 | if (!empty($this->_toEmail['contact_id']) && !empty($allContactDetails[$this->_toEmail['contact_id']])) { | |
220 | $allContactDetails[$this->_toEmail['contact_id']]['email'] = $this->_toEmail['email']; | |
221 | } | |
222 | ||
b68f0d01 | 223 | // perform all validations on unique contact Ids |
33ced9a4 | 224 | foreach ($allContactDetails as $contactId => $value) { |
b68f0d01 | 225 | if ($value['do_not_email'] || empty($value['email']) || !empty($value['is_deceased']) || $value['on_hold']) { |
f1781890 | 226 | $this->setSuppressedEmail($contactId, $value); |
b68f0d01 | 227 | } |
f942a8b0 | 228 | elseif (in_array($contactId, $this->_toContactIds)) { |
229 | $this->_toContactDetails[$contactId] = $this->_contactDetails[$contactId] = $value; | |
230 | $toArray[] = [ | |
231 | 'text' => '"' . $value['sort_name'] . '" <' . $value['email'] . '>', | |
232 | 'id' => "$contactId::{$value['email']}", | |
233 | ]; | |
b68f0d01 | 234 | } |
235 | } | |
236 | ||
237 | if (empty($toArray)) { | |
238 | CRM_Core_Error::statusBounce(ts('Selected contact(s) do not have a valid email address, or communication preferences specify DO NOT EMAIL, or they are deceased or Primary email address is On Hold.')); | |
239 | } | |
240 | } | |
241 | ||
242 | $this->assign('toContact', json_encode($toArray)); | |
b68f0d01 | 243 | |
f1781890 | 244 | $this->assign('suppressedEmails', count($this->suppressedEmails)); |
b68f0d01 | 245 | |
246 | $this->assign('totalSelectedContacts', count($this->_contactIds)); | |
247 | ||
4367e964 | 248 | $this->add('text', 'subject', ts('Subject'), ['size' => 50, 'maxlength' => 254], TRUE); |
b68f0d01 | 249 | |
250 | $this->add('select', 'from_email_address', ts('From'), $this->_fromEmails, TRUE); | |
251 | ||
252 | CRM_Mailing_BAO_Mailing::commonCompose($this); | |
253 | ||
254 | // add attachments | |
255 | CRM_Core_BAO_File::buildAttachment($this, NULL); | |
256 | ||
257 | if ($this->_single) { | |
258 | // also fix the user context stack | |
259 | if ($this->_caseId) { | |
260 | $ccid = CRM_Core_DAO::getFieldValue('CRM_Case_DAO_CaseContact', $this->_caseId, | |
261 | 'contact_id', 'case_id' | |
262 | ); | |
263 | $url = CRM_Utils_System::url('civicrm/contact/view/case', | |
264 | "&reset=1&action=view&cid={$ccid}&id={$this->_caseId}" | |
265 | ); | |
266 | } | |
267 | elseif ($this->_context) { | |
268 | $url = CRM_Utils_System::url('civicrm/dashboard', 'reset=1'); | |
269 | } | |
270 | else { | |
271 | $url = CRM_Utils_System::url('civicrm/contact/view', | |
272 | "&show=1&action=browse&cid={$this->_contactIds[0]}&selectedChild=activity" | |
273 | ); | |
274 | } | |
275 | ||
276 | $session = CRM_Core_Session::singleton(); | |
277 | $session->replaceUserContext($url); | |
278 | $this->addDefaultButtons(ts('Send Email'), 'upload', 'cancel'); | |
279 | } | |
280 | else { | |
281 | $this->addDefaultButtons(ts('Send Email'), 'upload'); | |
282 | } | |
283 | ||
284 | $fields = [ | |
285 | 'followup_assignee_contact_id' => [ | |
286 | 'type' => 'entityRef', | |
287 | 'label' => ts('Assigned to'), | |
288 | 'attributes' => [ | |
289 | 'multiple' => TRUE, | |
290 | 'create' => TRUE, | |
291 | 'api' => ['params' => ['is_deceased' => 0]], | |
292 | ], | |
293 | ], | |
294 | 'followup_activity_type_id' => [ | |
295 | 'type' => 'select', | |
296 | 'label' => ts('Followup Activity'), | |
297 | 'attributes' => ['' => '- ' . ts('select activity') . ' -'] + CRM_Core_PseudoConstant::ActivityType(FALSE), | |
298 | 'extra' => ['class' => 'crm-select2'], | |
299 | ], | |
300 | 'followup_activity_subject' => [ | |
301 | 'type' => 'text', | |
302 | 'label' => ts('Subject'), | |
303 | 'attributes' => CRM_Core_DAO::getAttribute('CRM_Activity_DAO_Activity', | |
304 | 'subject' | |
305 | ), | |
306 | ], | |
307 | ]; | |
308 | ||
309 | //add followup date | |
310 | $this->add('datepicker', 'followup_date', ts('in')); | |
311 | ||
312 | foreach ($fields as $field => $values) { | |
313 | if (!empty($fields[$field])) { | |
314 | $attribute = $values['attributes'] ?? NULL; | |
315 | $required = !empty($values['required']); | |
316 | ||
317 | if ($values['type'] === 'select' && empty($attribute)) { | |
318 | $this->addSelect($field, ['entity' => 'activity'], $required); | |
319 | } | |
320 | elseif ($values['type'] === 'entityRef') { | |
321 | $this->addEntityRef($field, $values['label'], $attribute, $required); | |
322 | } | |
323 | else { | |
324 | $this->add($values['type'], $field, $values['label'], $attribute, $required, CRM_Utils_Array::value('extra', $values)); | |
325 | } | |
326 | } | |
327 | } | |
328 | ||
329 | //Added for CRM-15984: Add campaign field | |
330 | CRM_Campaign_BAO_Campaign::addCampaign($this); | |
331 | ||
19f0858d | 332 | $this->addFormRule([__CLASS__, 'saveTemplateFormRule'], $this); |
b68f0d01 | 333 | CRM_Core_Resources::singleton()->addScriptFile('civicrm', 'templates/CRM/Contact/Form/Task/EmailCommon.js', 0, 'html-header'); |
f7869f64 | 334 | } |
335 | ||
8a432af6 | 336 | /** |
337 | * Process the form after the input has been submitted and validated. | |
338 | * | |
339 | * @throws \CRM_Core_Exception | |
340 | * @throws \CiviCRM_API3_Exception | |
341 | * @throws \Civi\API\Exception\UnauthorizedException | |
426b9dec | 342 | * @throws \API_Exception |
8a432af6 | 343 | */ |
344 | public function postProcess() { | |
704696b5 | 345 | $this->bounceIfSimpleMailLimitExceeded(count($this->_contactIds)); |
346 | ||
347 | // check and ensure that | |
348 | $formValues = $this->controller->exportValues($this->getName()); | |
349 | $this->submit($formValues); | |
350 | } | |
351 | ||
352 | /** | |
353 | * Bounce if there are more emails than permitted. | |
354 | * | |
355 | * @param int $count | |
356 | * The number of emails the user is attempting to send | |
357 | */ | |
358 | protected function bounceIfSimpleMailLimitExceeded($count) { | |
359 | $limit = Civi::settings()->get('simple_mail_limit'); | |
360 | if ($count > $limit) { | |
361 | CRM_Core_Error::statusBounce(ts('Please do not use this task to send a lot of emails (greater than %1). Many countries have legal requirements when sending bulk emails and the CiviMail framework has opt out functionality and domain tokens to help meet these.', | |
362 | [1 => $limit] | |
363 | )); | |
364 | } | |
365 | } | |
366 | ||
367 | /** | |
368 | * Submit the form values. | |
369 | * | |
370 | * This is also accessible for testing. | |
371 | * | |
372 | * @param array $formValues | |
373 | * | |
374 | * @throws \CRM_Core_Exception | |
375 | * @throws \CiviCRM_API3_Exception | |
376 | * @throws \Civi\API\Exception\UnauthorizedException | |
5b4b9509 | 377 | * @throws \API_Exception |
704696b5 | 378 | */ |
379 | public function submit($formValues) { | |
380 | $this->saveMessageTemplate($formValues); | |
381 | ||
382 | $from = $formValues['from_email_address'] ?? NULL; | |
383 | // dev/core#357 User Emails are keyed by their id so that the Signature is able to be added | |
384 | // If we have had a contact email used here the value returned from the line above will be the | |
385 | // numerical key where as $from for use in the sendEmail in Activity needs to be of format of "To Name" <toemailaddress> | |
386 | $from = CRM_Utils_Mail::formatFromAddress($from); | |
704696b5 | 387 | |
a01fb99f | 388 | $ccArray = $formValues['cc_id'] ? explode(',', $formValues['cc_id']) : []; |
389 | $cc = $this->getEmailString($ccArray); | |
390 | $additionalDetails = empty($ccArray) ? '' : "\ncc : " . $this->getEmailUrlString($ccArray); | |
704696b5 | 391 | |
a01fb99f | 392 | $bccArray = $formValues['bcc_id'] ? explode(',', $formValues['bcc_id']) : []; |
5b4b9509 | 393 | $bcc = $this->getEmailString($bccArray); |
394 | $additionalDetails .= empty($bccArray) ? '' : "\nbcc : " . $this->getEmailUrlString($bccArray); | |
704696b5 | 395 | |
704696b5 | 396 | // format contact details array to handle multiple emails from same contact |
397 | $formattedContactDetails = []; | |
704696b5 | 398 | foreach ($this->_contactIds as $key => $contactId) { |
399 | // if we dont have details on this contactID, we should ignore | |
400 | // potentially this is due to the contact not wanting to receive email | |
401 | if (!isset($this->_contactDetails[$contactId])) { | |
402 | continue; | |
403 | } | |
404 | $email = $this->_toContactEmails[$key]; | |
405 | // prevent duplicate emails if same email address is selected CRM-4067 | |
406 | // we should allow same emails for different contacts | |
426b9dec | 407 | $details = $this->_contactDetails[$contactId]; |
408 | $details['email'] = $email; | |
409 | unset($details['email_id']); | |
410 | $formattedContactDetails["{$contactId}::{$email}"] = $details; | |
704696b5 | 411 | } |
412 | ||
704696b5 | 413 | // send the mail |
13ecf776 | 414 | list($sent, $activityIds) = CRM_Activity_BAO_Activity::sendEmail( |
704696b5 | 415 | $formattedContactDetails, |
541ad531 | 416 | $this->getSubject($formValues['subject']), |
704696b5 | 417 | $formValues['text_message'], |
418 | $formValues['html_message'], | |
419 | NULL, | |
420 | NULL, | |
421 | $from, | |
192bedd3 | 422 | $this->getAttachments($formValues), |
704696b5 | 423 | $cc, |
424 | $bcc, | |
425 | array_keys($this->_toContactDetails), | |
426 | $additionalDetails, | |
bbd99e79 | 427 | $this->getVar('_contributionIds') ?? [], |
704696b5 | 428 | CRM_Utils_Array::value('campaign_id', $formValues), |
429 | $this->getVar('_caseId') | |
430 | ); | |
431 | ||
704696b5 | 432 | if ($sent) { |
13ecf776 | 433 | // Only use the first activity id if there's multiple. |
434 | // If there's multiple recipients the idea behind multiple activities | |
435 | // is to record the token value replacements separately, but that | |
436 | // has no meaning for followup activities, and this doesn't prevent | |
437 | // creating more manually if desired. | |
438 | $followupStatus = $this->createFollowUpActivities($formValues, $activityIds[0]); | |
704696b5 | 439 | $count_success = count($this->_toContactDetails); |
440 | CRM_Core_Session::setStatus(ts('One message was sent successfully. ', [ | |
441 | 'plural' => '%count messages were sent successfully. ', | |
442 | 'count' => $count_success, | |
443 | ]) . $followupStatus, ts('Message Sent', ['plural' => 'Messages Sent', 'count' => $count_success]), 'success'); | |
444 | } | |
445 | ||
f1781890 | 446 | if (!empty($this->suppressedEmails)) { |
447 | $status = '(' . ts('because no email address on file or communication preferences specify DO NOT EMAIL or Contact is deceased or Primary email address is On Hold') . ')<ul><li>' . implode('</li><li>', $this->suppressedEmails) . '</li></ul>'; | |
704696b5 | 448 | CRM_Core_Session::setStatus($status, ts('One Message Not Sent', [ |
f1781890 | 449 | 'count' => count($this->suppressedEmails), |
704696b5 | 450 | 'plural' => '%count Messages Not Sent', |
451 | ]), 'info'); | |
452 | } | |
704696b5 | 453 | } |
454 | ||
455 | /** | |
456 | * Save the template if update selected. | |
457 | * | |
458 | * @param array $formValues | |
459 | * | |
460 | * @throws \CiviCRM_API3_Exception | |
461 | * @throws \Civi\API\Exception\UnauthorizedException | |
462 | */ | |
463 | protected function saveMessageTemplate($formValues) { | |
464 | if (!empty($formValues['saveTemplate']) || !empty($formValues['updateTemplate'])) { | |
465 | $messageTemplate = [ | |
466 | 'msg_text' => $formValues['text_message'], | |
467 | 'msg_html' => $formValues['html_message'], | |
468 | 'msg_subject' => $formValues['subject'], | |
469 | 'is_active' => TRUE, | |
470 | ]; | |
471 | ||
472 | if (!empty($formValues['saveTemplate'])) { | |
473 | $messageTemplate['msg_title'] = $formValues['saveTemplateName']; | |
474 | CRM_Core_BAO_MessageTemplate::add($messageTemplate); | |
475 | } | |
476 | ||
477 | if (!empty($formValues['template']) && !empty($formValues['updateTemplate'])) { | |
478 | $messageTemplate['id'] = $formValues['template']; | |
479 | unset($messageTemplate['msg_title']); | |
480 | CRM_Core_BAO_MessageTemplate::add($messageTemplate); | |
481 | } | |
482 | } | |
8a432af6 | 483 | } |
484 | ||
b61322fd | 485 | /** |
486 | * List available tokens for this form. | |
487 | * | |
488 | * @return array | |
489 | */ | |
490 | public function listTokens() { | |
491 | return CRM_Core_SelectValues::contactTokens(); | |
492 | } | |
493 | ||
b68f0d01 | 494 | /** |
495 | * Get the emails from the added element. | |
496 | * | |
497 | * @param HTML_QuickForm_Element $element | |
498 | * | |
499 | * @return array | |
500 | */ | |
501 | protected function getEmails($element): array { | |
502 | $allEmails = explode(',', $element->getValue()); | |
503 | $return = []; | |
504 | foreach ($allEmails as $value) { | |
505 | $values = explode('::', $value); | |
506 | $return[] = ['contact_id' => $values[0], 'email' => $values[1]]; | |
507 | } | |
508 | return $return; | |
509 | } | |
510 | ||
5b4b9509 | 511 | /** |
512 | * Get the string for the email IDs. | |
513 | * | |
514 | * @param array $emailIDs | |
515 | * Array of email IDs. | |
516 | * | |
517 | * @return string | |
518 | * e.g. "Smith, Bob<bob.smith@example.com>". | |
519 | * | |
520 | * @throws \API_Exception | |
521 | * @throws \Civi\API\Exception\UnauthorizedException | |
522 | */ | |
523 | protected function getEmailString(array $emailIDs): string { | |
a01fb99f | 524 | if (empty($emailIDs)) { |
525 | return ''; | |
526 | } | |
5b4b9509 | 527 | $emails = Email::get() |
528 | ->addWhere('id', 'IN', $emailIDs) | |
529 | ->setCheckPermissions(FALSE) | |
84ad7693 | 530 | ->setSelect(['contact_id', 'email', 'contact_id.sort_name', 'contact_id.display_name'])->execute(); |
5b4b9509 | 531 | $emailStrings = []; |
532 | foreach ($emails as $email) { | |
533 | $this->contactEmails[$email['id']] = $email; | |
84ad7693 | 534 | $emailStrings[] = '"' . $email['contact_id.sort_name'] . '" <' . $email['email'] . '>'; |
5b4b9509 | 535 | } |
536 | return implode(',', $emailStrings); | |
537 | } | |
538 | ||
539 | /** | |
540 | * Get the url string. | |
541 | * | |
542 | * This is called after the contacts have been retrieved so we don't need to re-retrieve. | |
543 | * | |
544 | * @param array $emailIDs | |
545 | * | |
546 | * @return string | |
547 | * e.g. <a href='{$contactURL}'>Bob Smith</a>' | |
548 | */ | |
549 | protected function getEmailUrlString(array $emailIDs): string { | |
3420384b | 550 | $urls = []; |
5b4b9509 | 551 | foreach ($emailIDs as $email) { |
3420384b | 552 | $contactURL = CRM_Utils_System::url('civicrm/contact/view', ['reset' => 1, 'cid' => $this->contactEmails[$email]['contact_id']], TRUE); |
84ad7693 | 553 | $urls[] = "<a href='{$contactURL}'>" . $this->contactEmails[$email]['contact_id.display_name'] . '</a>'; |
5b4b9509 | 554 | } |
3420384b | 555 | return implode(', ', $urls); |
5b4b9509 | 556 | } |
557 | ||
f1781890 | 558 | /** |
559 | * Set the emails that are not to be sent out. | |
560 | * | |
561 | * @param int $contactID | |
562 | * @param array $values | |
563 | */ | |
564 | protected function setSuppressedEmail($contactID, $values) { | |
565 | $contactViewUrl = CRM_Utils_System::url('civicrm/contact/view', 'reset=1&cid=' . $contactID); | |
566 | $this->suppressedEmails[$contactID] = "<a href='$contactViewUrl' title='{$values['email']}'>{$values['display_name']}</a>" . ($values['on_hold'] ? '(' . ts('on hold') . ')' : ''); | |
567 | } | |
568 | ||
192bedd3 | 569 | /** |
570 | * Get any attachments. | |
571 | * | |
572 | * @param array $formValues | |
573 | * | |
574 | * @return array | |
575 | */ | |
576 | protected function getAttachments(array $formValues): array { | |
577 | $attachments = []; | |
578 | CRM_Core_BAO_File::formatAttachment($formValues, | |
579 | $attachments, | |
580 | NULL, NULL | |
581 | ); | |
582 | return $attachments; | |
583 | } | |
584 | ||
541ad531 | 585 | /** |
586 | * Get the subject for the message. | |
587 | * | |
588 | * The case handling should possibly be on the case form..... | |
589 | * | |
590 | * @param string $subject | |
591 | * | |
592 | * @return string | |
593 | */ | |
594 | protected function getSubject(string $subject):string { | |
595 | // CRM-5916: prepend case id hash to CiviCase-originating emails’ subjects | |
596 | if (isset($this->_caseId) && is_numeric($this->_caseId)) { | |
597 | $hash = substr(sha1(CIVICRM_SITE_KEY . $this->_caseId), 0, 7); | |
598 | $subject = "[case #$hash] $subject"; | |
599 | } | |
600 | return $subject; | |
601 | } | |
602 | ||
dee865af | 603 | /** |
604 | * Create any follow up activities. | |
605 | * | |
606 | * @param array $formValues | |
607 | * @param int $activityId | |
608 | * | |
609 | * @return string | |
610 | * | |
611 | * @throws \CRM_Core_Exception | |
612 | */ | |
613 | protected function createFollowUpActivities($formValues, $activityId): string { | |
614 | $params = []; | |
615 | $followupStatus = ''; | |
616 | $followupActivity = NULL; | |
617 | if (!empty($formValues['followup_activity_type_id'])) { | |
618 | $params['followup_activity_type_id'] = $formValues['followup_activity_type_id']; | |
619 | $params['followup_activity_subject'] = $formValues['followup_activity_subject']; | |
620 | $params['followup_date'] = $formValues['followup_date']; | |
621 | $params['target_contact_id'] = $this->_contactIds; | |
76dcf463 | 622 | $params['followup_assignee_contact_id'] = array_filter(explode(',', $formValues['followup_assignee_contact_id'])); |
dee865af | 623 | $followupActivity = CRM_Activity_BAO_Activity::createFollowupActivity($activityId, $params); |
624 | $followupStatus = ts('A followup activity has been scheduled.'); | |
625 | ||
626 | if (Civi::settings()->get('activity_assignee_notification')) { | |
627 | if ($followupActivity) { | |
628 | $mailToFollowupContacts = []; | |
629 | $assignee = [$followupActivity->id]; | |
630 | $assigneeContacts = CRM_Activity_BAO_ActivityAssignment::getAssigneeNames($assignee, TRUE, FALSE); | |
631 | foreach ($assigneeContacts as $values) { | |
632 | $mailToFollowupContacts[$values['email']] = $values; | |
633 | } | |
634 | ||
635 | $sentFollowup = CRM_Activity_BAO_Activity::sendToAssignee($followupActivity, $mailToFollowupContacts); | |
636 | if ($sentFollowup) { | |
637 | $followupStatus .= '<br />' . ts('A copy of the follow-up activity has also been sent to follow-up assignee contacts(s).'); | |
638 | } | |
639 | } | |
640 | } | |
641 | } | |
642 | return $followupStatus; | |
643 | } | |
644 | ||
19f0858d EM |
645 | /** |
646 | * Form rule. | |
647 | * | |
648 | * @param array $fields | |
649 | * The input form values. | |
650 | * | |
651 | * @return bool|array | |
652 | * true if no errors, else array of errors | |
653 | */ | |
654 | public static function saveTemplateFormRule(array $fields) { | |
655 | $errors = []; | |
656 | //Added for CRM-1393 | |
657 | if (!empty($fields['saveTemplate']) && empty($fields['saveTemplateName'])) { | |
658 | $errors['saveTemplateName'] = ts('Enter name to save message template'); | |
659 | } | |
660 | return empty($errors) ? TRUE : $errors; | |
661 | } | |
662 | ||
8a432af6 | 663 | } |