CRM-13809, prevent sending emails to deceased contacts, also code clean up/optimizations
authorkurund <kurund@civicrm.org>
Fri, 29 Nov 2013 08:15:31 +0000 (13:45 +0530)
committerkurund <kurund@civicrm.org>
Fri, 29 Nov 2013 08:15:31 +0000 (13:45 +0530)
----------------------------------------
* CRM-13809: send email activity: cc may go to wrong contact
  http://issues.civicrm.org/jira/browse/CRM-13809

CRM/Contact/Form/Task/EmailCommon.php
templates/CRM/Contact/Form/Task/Email.tpl

index ca503ddb90609cd4442b8608306e961b4ba4f4dd..aaf247dc63cfcba08ab26a6a19aaf410f6b5d1fc 100644 (file)
@@ -42,10 +42,15 @@ class CRM_Contact_Form_Task_EmailCommon {
   CONST MAX_EMAILS_KILL_SWITCH = 50;
 
   public $_contactDetails = array();
-  public $_additionalContactDetails = array();
   public $_allContactDetails = array();
   public $_toContactEmails = array();
 
+  public $_toContactDetails = array();
+  public $_allContactIds = array();
+  public $_toContactIds = array();
+  public $_ccContactIds = array();
+  public $_bccContactIds = array();
+
   static function preProcessFromAddress(&$form) {
     $form->_single = FALSE;
     $className = CRM_Utils_System::getClassName($form);
@@ -136,42 +141,41 @@ class CRM_Contact_Form_Task_EmailCommon {
     $cc  = $form->add('text', 'cc_id', ts('CC'));
     $bcc = $form->add('text', 'bcc_id', ts('BCC'));
 
-    $elements = array('cc', 'bcc');
+    $setDefaults = TRUE;
+    if (property_exists($form, '_context') && $form->_context == 'standalone') {
+      $setDefaults = FALSE;
+    }
+
+    $elements = array('to', 'cc', 'bcc');
     foreach ($elements as $element) {
       if ($$element->getValue()) {
-        preg_match_all('!"(.*?)"\s+<\s*(.*?)\s*>!', $$element->getValue(), $matches);
-        $elementValues = array();
-        for ($i = 0; $i < count($matches[0]); $i++) {
-          $name = '"' . $matches[1][$i] . '" &lt;' . $matches[2][$i] . '&gt;';
-          $elementValues[] = array(
-            'name' => $name,
-            'id' => $matches[0][$i],
-          );
-          $id = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Email', $matches[2][$i] , 'contact_id', 'email');
-          $form->_additionalContactDetails[$element][$id] = CRM_Contact_BAO_Contact::displayName($id);
+        $allEmails = explode(',', $$element->getValue());
+        if ($element == 'to') {
+          $form->_contactIds = array();
         }
-        $var = "{$element}Contact";
-        $form->assign($var, json_encode($elementValues));
-      }
-    }
 
-    $toSetDefault = TRUE;
-    if (property_exists($form, '_context') && $form->_context == 'standalone') {
-      $toSetDefault = FALSE;
-    }
-    // when form is submitted recompute contactIds
-    $allToEmails = array();
-    if ($to->getValue()) {
-      $allToEmails = explode(',', $to->getValue());
-      $form->_contactIds = array();
-      foreach ($allToEmails as $value) {
-        list($contactId, $email) = explode('::', $value);
-        if ($contactId) {
-          $form->_contactIds[] = $contactId;
-          $form->_toContactEmails[] = $email;
+        foreach ($allEmails as $value) {
+          list($contactId, $email) = explode('::', $value);
+          if ($contactId) {
+            switch ($element) {
+              case 'to':
+                $form->_contactIds[] = $form->_toContactIds[] = $contactId;
+                $form->_toContactEmails[] = $email;
+                break;
+              case 'cc':
+                $form->_ccContactIds[] = $contactId;
+                break;
+              case 'bcc':
+                $form->_bccContactIds[] = $contactId;
+                break;
+            }
+
+            $form->_allContactIds[] = $contactId;
+          }
         }
+
+        $setDefaults = TRUE;
       }
-      $toSetDefault = TRUE;
     }
 
     //get the group of contacts as per selected by user in case of Find Activities
@@ -180,7 +184,9 @@ class CRM_Contact_Form_Task_EmailCommon {
       $form->_contactIds = $contact;
     }
 
-    if (is_array($form->_contactIds) && $toSetDefault) {
+
+    // check if we need to setdefaults and check for valid contact emails / communication preferences
+    if (is_array($form->_contactIds) && $setDefaults) {
       $returnProperties = array(
         'sort_name' => 1,
         'email' => 1,
@@ -191,7 +197,8 @@ class CRM_Contact_Form_Task_EmailCommon {
         'preferred_mail_format' => 1,
       );
 
-      list($form->_contactDetails) = CRM_Utils_Token::getTokenDetails($form->_contactIds,
+      // get the details for all selected contacts ( to, cc and bcc contacts )
+      list($form->_contactDetails) = CRM_Utils_Token::getTokenDetails($form->_allContactIds,
         $returnProperties,
         FALSE,
         FALSE
@@ -200,7 +207,8 @@ class CRM_Contact_Form_Task_EmailCommon {
       // make a copy of all contact details
       $form->_allContactDetails = $form->_contactDetails;
 
-      foreach ($form->_contactIds as $key => $contactId) {
+      // perform all validations
+      foreach ($form->_allContactIds as $key => $contactId) {
         $value = $form->_contactDetails[$contactId];
         if ($value['do_not_email'] || empty($value['email']) || CRM_Utils_Array::value('is_deceased', $value) || $value['on_hold']) {
           $suppressedEmails++;
@@ -210,16 +218,28 @@ class CRM_Contact_Form_Task_EmailCommon {
           unset($form->_contactDetails[$contactId]);
         }
         else {
-          if (empty($form->_toContactEmails)) {
-            $email = $value['email'];
+          $email = $value['email'];
+
+          // build array's which are used to setdefaults
+          if (in_array($contactId, $form->_toContactIds)) {
+            $form->_toContactDetails[$contactId] = $form->_contactDetails[$contactId];
+            $toArray[] = array(
+              'name' => '"' . $value['sort_name'] . '" &lt;' . $email . '&gt;',
+              'id' => "$contactId::{$email}",
+            );
+          }
+          elseif (in_array($contactId, $form->_ccContactIds)) {
+            $ccArray[] = array(
+              'name' => '"' . $value['sort_name'] . '" &lt;' . $email . '&gt;',
+              'id' => "$contactId::{$email}",
+            );
           }
-          else {
-            $email = $form->_toContactEmails[$key];
+          elseif (in_array($contactId, $form->_bccContactIds)) {
+            $bccArray[] = array(
+              'name' => '"' . $value['sort_name'] . '" &lt;' . $email . '&gt;',
+              'id' => "$contactId::{$email}",
+            );
           }
-          $toArray[] = array(
-            'name' => '"' . $value['sort_name'] . '" &lt;' . $email . '&gt;',
-            'id' => "$contactId::{$email}",
-          );
         }
       }
 
@@ -229,6 +249,9 @@ class CRM_Contact_Form_Task_EmailCommon {
     }
 
     $form->assign('toContact', json_encode($toArray));
+    $form->assign('ccContact', json_encode($ccArray));
+    $form->assign('bccContact', json_encode($bccArray));
+
     $form->assign('suppressedEmails', $suppressedEmails);
 
     $form->assign('totalSelectedContacts', count($form->_contactIds));
@@ -321,25 +344,42 @@ class CRM_Contact_Form_Task_EmailCommon {
 
     $fromEmail = $formValues['fromEmailAddress'];
     $from      = CRM_Utils_Array::value($fromEmail, $form->_emails);
-    $cc        = CRM_Utils_Array::value('cc_id', $formValues);
-    $bcc       = CRM_Utils_Array::value('bcc_id', $formValues);
     $subject   = $formValues['subject'];
 
-
-    // CRM-13378: Append CC and BCC information at the end of Activity Details
-    $elements = array('cc', 'bcc');
+    // CRM-13378: Append CC and BCC information at the end of Activity Details and format cc and bcc fields
+    $elements = array('cc_id', 'bcc_id');
     $additionalDetails = NULL;
+    $ccValues = $bccValues = array();
     foreach ($elements as $element) {
-      if (isset($form->_additionalContactDetails[$element])) {
-        foreach ($form->_additionalContactDetails[$element] as $id => $display_name) {
-          $url = CRM_Utils_System::url('civicrm/contact/view', "reset=1&force=1&cid={$id}");
-          $form->_additionalContactDetails[$element][$id] = "<a href=$url>$display_name</a>";
+      if (CRM_Utils_Array::value($element, $formValues)) {
+        $allEmails = explode(',', $formValues[$element]);
+        foreach ($allEmails as $value) {
+          list($contactId, $email) = explode('::', $value);
+          $contactURL = CRM_Utils_System::url('civicrm/contact/view', "reset=1&force=1&cid={$contactId}", true);
+          switch ($element) {
+            case 'cc_id':
+              $ccValues['email'][] = '"' . $form->_contactDetails[$contactId]['sort_name'] . '" <' . $email . '>';
+              $ccValues['details'][] = "<a href='{$contactURL}'>" . $form->_contactDetails[$contactId]['display_name'] . "</a>";
+              break;
+            case 'bcc_id':
+              $bccValues['email'][]= '"' . $form->_contactDetails[$contactId]['sort_name'] . '" <' . $email . '>';
+              $bccValues['details'][] = "<a href='{$contactURL}'>" . $form->_contactDetails[$contactId]['display_name'] . "</a>";
+              break;
+          }
         }
-        $additionalDetails .= "\n$element : " . implode(", ", $form->_additionalContactDetails[$element]);
-        unset($form->_additionalContactDetails[$element]);
       }
     }
 
+    $cc = $bcc = '';
+    if (!empty($ccValues)) {
+      $cc = implode(',', $ccValues['email']);
+      $additionalDetails .= "\ncc : " . implode(", ", $ccValues['details']);
+    }
+    if (!empty($bccValues)) {
+      $bcc = implode(',', $bccValues['email']);
+      $additionalDetails .= "\nbcc : " . implode(", ", $bccValues['details']);
+    }
+
     // CRM-5916: prepend case id hash to CiviCase-originating emails’ subjects
     if (isset($form->_caseId) && is_numeric($form->_caseId)) {
       $hash = substr(sha1(CIVICRM_SITE_KEY . $form->_caseId), 0, 7);
@@ -412,12 +452,12 @@ class CRM_Contact_Form_Task_EmailCommon {
       $attachments,
       $cc,
       $bcc,
-      array_keys($form->_contactDetails),
+      array_keys($form->_toContactDetails),
       $additionalDetails
     );
 
     if ($sent) {
-      $count_success = count($form->_contactDetails);
+      $count_success = count($form->_toContactDetails);
       CRM_Core_Session::setStatus(ts('One message was sent successfully.', array('plural' => '%count messages were sent successfully.', 'count' => $count_success)), ts('Message Sent', array('plural' => 'Messages Sent', 'count' => $count_success)), 'success');
     }
 
index 6d48e932e7ae97d2cc5f74eb2d3ebe849763894a..ab3e1d02c3f6f161e0ab6f4ba0c09a2c97ce17a5 100644 (file)
@@ -109,7 +109,7 @@ cj('#addbcc').toggle( function() { cj(this).text('Remove BCC');
 });
 
 var hintText = "{/literal}{ts escape='js'}Type in a partial or complete name or email address of an existing contact.{/ts}{literal}";
-var sourceDataUrl = "{/literal}{crmURL p='civicrm/ajax/checkemail' h=0 }{literal}";
+var sourceDataUrl = "{/literal}{crmURL p='civicrm/ajax/checkemail' q='id=1' h=0 }{literal}";
 var toDataUrl     = "{/literal}{crmURL p='civicrm/ajax/checkemail' q='id=1' h=0 }{literal}";
 
 cj( "#to"     ).tokenInput( toDataUrl,     { prePopulate: toContact,  theme: 'facebook', hintText: hintText });