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_Mailing_Event_BAO_Forward
extends CRM_Mailing_Event_DAO_Forward
{
20 * Create a new forward event, create a new contact if necessary
25 * @param $forward_email
26 * @param string|null $fromEmail
27 * @param array|null $comment
31 public static function &forward($job_id, $queue_id, $hash, $forward_email, $fromEmail = NULL, $comment = NULL) {
32 $q = CRM_Mailing_Event_BAO_Queue
::verify($job_id, $queue_id, $hash);
34 $successfulForward = FALSE;
37 return $successfulForward;
40 // Find the email address/contact, if it exists.
42 $contact = CRM_Contact_BAO_Contact
::getTableName();
43 $email = CRM_Core_BAO_Email
::getTableName();
44 $queueTable = CRM_Mailing_Event_BAO_Queue
::getTableName();
45 $job = CRM_Mailing_BAO_MailingJob
::getTableName();
47 $dao = new CRM_Core_DAO();
49 SELECT $contact.id as contact_id,
50 $email.id as email_id,
51 $contact.do_not_email as do_not_email,
52 $queueTable.id as queue_id
53 FROM ($email, $job as temp_job)
55 ON $email.contact_id = $contact.id
57 ON $email.id = $queueTable.email_id
59 ON $queueTable.job_id = $job.id
60 AND temp_job.mailing_id = $job.mailing_id
61 WHERE $queueTable.job_id = $job_id
62 AND $email.email = '" .
63 CRM_Utils_Type
::escape($forward_email, 'String') . "'"
68 $transaction = new CRM_Core_Transaction();
70 if (isset($dao->queue_id
) ||
71 (isset($dao->do_not_email
) && $dao->do_not_email
== 1)
73 // We already sent this mailing to $forward_email, or we should
74 // never email this contact. Give up.
76 return $successfulForward;
79 require_once 'api/api.php';
81 'email' => $forward_email,
84 $contactValues = civicrm_api('contact', 'get', $contactParams);
85 $count = $contactValues['count'];
88 // If the contact does not exist, create one.
91 'contact_type' => 'Individual',
94 $locationType = CRM_Core_BAO_LocationType
::getDefault();
96 'email' => $forward_email,
97 'location_type_id' => $locationType->id
,
99 self
::_civicrm_api3_deprecated_add_formatted_param($value, $formatted);
100 $formatted['onDuplicate'] = CRM_Import_Parser
::DUPLICATE_SKIP
;
101 $formatted['fixAddress'] = TRUE;
102 $contact = civicrm_api('contact', 'create', $formatted);
103 if (civicrm_error($contact)) {
104 return $successfulForward;
106 $contact_id = $contact['id'];
108 $email = new CRM_Core_DAO_Email();
109 $email->email
= $forward_email;
111 $email_id = $email->id
;
113 $contact_id = $email->contact_id
;
116 // Create a new queue event.
119 'email_id' => $email_id,
120 'contact_id' => $contact_id,
124 $queue = CRM_Mailing_Event_BAO_Queue
::create($queue_params);
126 $forward = new CRM_Mailing_Event_BAO_Forward();
127 $forward->time_stamp
= date('YmdHis');
128 $forward->event_queue_id
= $queue_id;
129 $forward->dest_queue_id
= $queue->id
;
133 $dao->query(" SELECT $job.mailing_id as mailing_id
136 CRM_Utils_Type
::escape($job_id, 'Integer')
139 $mailing_obj = new CRM_Mailing_BAO_Mailing();
140 $mailing_obj->id
= $dao->mailing_id
;
141 $mailing_obj->find(TRUE);
143 $config = CRM_Core_Config
::singleton();
144 $mailer = \Civi
::service('pear_mail');
148 $message = $mailing_obj->compose($job_id, $queue->id
, $queue->hash
,
149 $queue->contact_id
, $forward_email, $recipient, FALSE, NULL, $attachments, TRUE, $fromEmail
151 //append comment if added while forwarding.
152 if (count($comment)) {
153 $message->_txtbody
= CRM_Utils_Array
::value('body_text', $comment) . $message->_txtbody
;
154 if (!empty($comment['body_html'])) {
155 $message->_htmlbody
= $comment['body_html'] . '<br />---------------Original message---------------------<br />' . $message->_htmlbody
;
159 $body = $message->get();
160 $headers = $message->headers();
163 if (is_object($mailer)) {
164 $errorScope = CRM_Core_TemporaryErrorScope
::ignoreException();
165 $result = $mailer->send($recipient, $headers, $body);
170 'event_queue_id' => $queue->id
,
172 'hash' => $queue->hash
,
174 if (is_a($result, 'PEAR_Error')) {
175 // Register the bounce event.
177 $params = array_merge($params,
178 CRM_Mailing_BAO_BouncePattern
::match($result->getMessage())
180 CRM_Mailing_Event_BAO_Bounce
::create($params);
183 $successfulForward = TRUE;
184 // Register the delivery event.
186 CRM_Mailing_Event_BAO_Delivered
::create($params);
189 $transaction->commit();
191 return $successfulForward;
195 * This function adds the contact variable in $values to the
196 * parameter list $params. For most cases, $values should have length 1. If
197 * the variable being added is a child of Location, a location_type_id must
198 * also be included. If it is a child of phone, a phone_type must be included.
200 * @param array $values
201 * The variable(s) to be added.
202 * @param array $params
203 * The structured parameter list.
205 * @return bool|CRM_Utils_Error
207 protected static function _civicrm_api3_deprecated_add_formatted_param(&$values, &$params) {
208 // @todo - most of this code is UNREACHABLE.
209 // Crawl through the possible classes:
222 // Cache the various object fields
223 static $fields = NULL;
225 if ($fields == NULL) {
229 // first add core contact values since for other Civi modules they are not added
230 require_once 'CRM/Contact/BAO/Contact.php';
231 $contactFields = CRM_Contact_DAO_Contact
::fields();
232 _civicrm_api3_store_values($contactFields, $values, $params);
234 // get the formatted location blocks into params - w/ 3.0 format, CRM-4605
235 if (!empty($values['location_type_id'])) {
236 static $fields = NULL;
237 if ($fields == NULL) {
241 foreach (['Phone', 'Email', 'IM', 'OpenID', 'Phone_Ext'] as $block) {
242 $name = strtolower($block);
243 if (!array_key_exists($name, $values)) {
247 if ($name === 'phone_ext') {
251 // block present in value array.
252 if (!array_key_exists($name, $params) ||
!is_array($params[$name])) {
256 if (!array_key_exists($block, $fields)) {
257 $className = "CRM_Core_DAO_$block";
258 $fields[$block] =& $className::fields();
261 $blockCnt = count($params[$name]);
263 // copy value to dao field name.
265 $values['name'] = $values[$name];
268 _civicrm_api3_store_values($fields[$block], $values,
269 $params[$name][++
$blockCnt]
272 if (empty($params['id']) && ($blockCnt == 1)) {
273 $params[$name][$blockCnt]['is_primary'] = TRUE;
276 // we only process single block at a time.
280 // handle address fields.
281 if (!array_key_exists('address', $params) ||
!is_array($params['address'])) {
282 $params['address'] = [];
286 foreach ($params['address'] as $cnt => $addressBlock) {
287 if (CRM_Utils_Array
::value('location_type_id', $values) ==
288 CRM_Utils_Array
::value('location_type_id', $addressBlock)
296 if (!array_key_exists('Address', $fields)) {
297 $fields['Address'] = CRM_Core_DAO_Address
::fields();
300 // Note: we doing multiple value formatting here for address custom fields, plus putting into right format.
301 // The actual formatting (like date, country ..etc) for address custom fields is taken care of while saving
302 // the address in CRM_Core_BAO_Address::create method
303 if (!empty($values['location_type_id'])) {
304 static $customFields = [];
305 if (empty($customFields)) {
306 $customFields = CRM_Core_BAO_CustomField
::getFields('Address');
308 // make a copy of values, as we going to make changes
309 $newValues = $values;
310 foreach ($values as $key => $val) {
311 $customFieldID = CRM_Core_BAO_CustomField
::getKeyID($key);
312 if ($customFieldID && array_key_exists($customFieldID, $customFields)) {
313 // mark an entry in fields array since we want the value of custom field to be copied
314 $fields['Address'][$key] = NULL;
316 $htmlType = $customFields[$customFieldID]['html_type'] ??
NULL;
317 if (CRM_Core_BAO_CustomField
::isSerialized($customFields[$customFieldID]) && $val) {
318 $mulValues = explode(',', $val);
319 $customOption = CRM_Core_BAO_CustomOption
::getCustomOption($customFieldID, TRUE);
320 $newValues[$key] = [];
321 foreach ($mulValues as $v1) {
322 foreach ($customOption as $v2) {
323 if ((strtolower($v2['label']) == strtolower(trim($v1))) ||
324 (strtolower($v2['value']) == strtolower(trim($v1)))
326 if ($htmlType == 'CheckBox') {
327 $newValues[$key][$v2['value']] = 1;
330 $newValues[$key][] = $v2['value'];
338 // consider new values
339 $values = $newValues;
342 _civicrm_api3_store_values($fields['Address'], $values, $params['address'][$addressCnt]);
348 'supplemental_address_1',
349 'supplemental_address_2',
350 'supplemental_address_3',
351 'StateProvince.name',
354 foreach ($addressFields as $field) {
355 if (array_key_exists($field, $values)) {
356 if (!array_key_exists('address', $params)) {
357 $params['address'] = [];
359 $params['address'][$addressCnt][$field] = $values[$field];
363 if ($addressCnt == 1) {
365 $params['address'][$addressCnt]['is_primary'] = TRUE;
372 * Get row count for the event selector.
374 * @param int $mailing_id
377 * Optional ID of a job to filter on.
378 * @param bool $is_distinct
379 * Group by queue ID?.
382 * Number of rows in result set
384 public static function getTotalCount(
385 $mailing_id, $job_id = NULL,
388 $dao = new CRM_Core_DAO();
390 $forward = self
::getTableName();
391 $queue = CRM_Mailing_Event_BAO_Queue
::getTableName();
392 $mailing = CRM_Mailing_BAO_Mailing
::getTableName();
393 $job = CRM_Mailing_BAO_MailingJob
::getTableName();
396 SELECT COUNT($forward.id) as forward
399 ON $forward.event_queue_id = $queue.id
401 ON $queue.job_id = $job.id
403 ON $job.mailing_id = $mailing.id
405 WHERE $mailing.id = " . CRM_Utils_Type
::escape($mailing_id, 'Integer');
407 if (!empty($job_id)) {
408 $query .= " AND $job.id = " . CRM_Utils_Type
::escape($job_id, 'Integer');
412 $query .= " GROUP BY $queue.id ";
419 return $dao->forward
;
426 * Get rows for the event browser.
428 * @param int $mailing_id
431 * Optional ID of the job.
432 * @param bool $is_distinct
433 * Group by queue id?.
436 * @param int $rowCount
444 public static function &getRows(
445 $mailing_id, $job_id = NULL,
446 $is_distinct = FALSE, $offset = NULL, $rowCount = NULL, $sort = NULL
449 $dao = new CRM_Core_DAO();
451 $forward = self
::getTableName();
452 $queue = CRM_Mailing_Event_BAO_Queue
::getTableName();
453 $mailing = CRM_Mailing_BAO_Mailing
::getTableName();
454 $job = CRM_Mailing_BAO_MailingJob
::getTableName();
455 $contact = CRM_Contact_BAO_Contact
::getTableName();
456 $email = CRM_Core_BAO_Email
::getTableName();
459 SELECT $contact.display_name as from_name,
460 $contact.id as from_id,
461 $email.email as from_email,
462 dest_contact.id as dest_id,
463 dest_email.email as dest_email,
464 $forward.time_stamp as date
467 ON $queue.contact_id = $contact.id
469 ON $queue.email_id = $email.id
471 ON $forward.event_queue_id = $queue.id
472 INNER JOIN $queue as dest_queue
473 ON $forward.dest_queue_id = dest_queue.id
474 INNER JOIN $contact as dest_contact
475 ON dest_queue.contact_id = dest_contact.id
476 INNER JOIN $email as dest_email
477 ON dest_queue.email_id = dest_email.id
479 ON $queue.job_id = $job.id
481 ON $job.mailing_id = $mailing.id
483 WHERE $mailing.id = " . CRM_Utils_Type
::escape($mailing_id, 'Integer');
485 if (!empty($job_id)) {
486 $query .= " AND $job.id = " . CRM_Utils_Type
::escape($job_id, 'Integer');
490 $query .= " GROUP BY $queue.id, dest_contact.id, dest_email.email, $forward.time_stamp ";
493 $orderBy = "$contact.sort_name ASC, {$forward}.time_stamp DESC";
495 if (is_string($sort)) {
496 $sort = CRM_Utils_Type
::escape($sort, 'String');
500 $orderBy = trim($sort->orderBy());
504 $query .= " ORDER BY {$orderBy} ";
506 if ($offset ||
$rowCount) {
507 //Added "||$rowCount" to avoid displaying all records on first page
508 $query .= ' LIMIT ' . CRM_Utils_Type
::escape($offset, 'Integer') . ', ' . CRM_Utils_Type
::escape($rowCount, 'Integer');
515 while ($dao->fetch()) {
516 $from_url = CRM_Utils_System
::url('civicrm/contact/view',
517 "reset=1&cid={$dao->from_id}"
519 $dest_url = CRM_Utils_System
::url('civicrm/contact/view',
520 "reset=1&cid={$dao->dest_id}"
523 'from_name' => "<a href=\"$from_url\">{$dao->from_name}</a>",
524 'from_email' => $dao->from_email
,
525 'dest_email' => "<a href=\"$dest_url\">{$dao->dest_email}</a>",
526 'date' => CRM_Utils_Date
::customFormat($dao->date
),