adjust for multiple activities in 5.36+
authordemeritcowboy <demeritcowboy@hotmail.com>
Sat, 27 Mar 2021 13:33:07 +0000 (09:33 -0400)
committerdemeritcowboy <demeritcowboy@hotmail.com>
Sat, 27 Mar 2021 13:33:07 +0000 (09:33 -0400)
CRM/Activity/BAO/Activity.php
CRM/Contact/Form/Task/EmailTrait.php
tests/phpunit/CRM/Activity/BAO/ActivityTest.php

index 7cdca184da2b5ca56887996f3be0aeda74ad0c1e..4fe6e482c52d7b691aa4ead106500ad9e4456dd6 100644 (file)
@@ -1017,7 +1017,9 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
    * @param int $caseId
    *
    * @return array
-   *   ( sent, activityId) if any email is sent and activityId
+   *   bool $sent FIXME: this only indicates the status of the last email sent.
+   *   array $activityIds The activity ids created, one per "To" recipient.
+   *
    * @throws \CRM_Core_Exception
    * @throws \CiviCRM_API3_Exception
    */
@@ -1116,6 +1118,7 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
 
     $sent = $notSent = [];
     $attachmentFileIds = [];
+    $activityIds = [];
     $firstActivityCreated = FALSE;
     foreach ($contactDetails as $values) {
       $contactId = $values['contact_id'];
@@ -1178,6 +1181,7 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
 
       // Create email activity.
       $activityID = self::createEmailActivity($userID, $tokenSubject, $tokenHtml, $tokenText, $additionalDetails, $campaignId, $attachments, $caseId);
+      $activityIds[] = $activityID;
 
       if ($firstActivityCreated == FALSE && !empty($attachments)) {
         $attachmentFileIds = self::getAttachmentFileIds($activityID, $attachments);
@@ -1203,7 +1207,7 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
       }
     }
 
-    return [$sent, $activityID];
+    return [$sent, $activityIds];
   }
 
   /**
index 3b2bcc97636b948872ae80463d663b97c3db2f2e..dc7771acfbc158d40f01c41dfc5723979ab015a5 100644 (file)
@@ -413,7 +413,7 @@ trait CRM_Contact_Form_Task_EmailTrait {
     }
 
     // send the mail
-    list($sent, $activityId) = CRM_Activity_BAO_Activity::sendEmail(
+    list($sent, $activityIds) = CRM_Activity_BAO_Activity::sendEmail(
       $formattedContactDetails,
       $this->getSubject($formValues['subject']),
       $formValues['text_message'],
@@ -432,7 +432,12 @@ trait CRM_Contact_Form_Task_EmailTrait {
     );
 
     if ($sent) {
-      $followupStatus = $this->createFollowUpActivities($formValues, $activityId);
+      // Only use the first activity id if there's multiple.
+      // If there's multiple recipients the idea behind multiple activities
+      // is to record the token value replacements separately, but that
+      // has no meaning for followup activities, and this doesn't prevent
+      // creating more manually if desired.
+      $followupStatus = $this->createFollowUpActivities($formValues, $activityIds[0]);
       $count_success = count($this->_toContactDetails);
       CRM_Core_Session::setStatus(ts('One message was sent successfully. ', [
         'plural' => '%count messages were sent successfully. ',
index 6e0a62a6abc7348842a90e18eea3ed8dfb5cd5ee..10c6ec2ac76fcd1d3bb9e5e441a776d2bbdfcceb 100644 (file)
@@ -1221,7 +1221,7 @@ class CRM_Activity_BAO_ActivityTest extends CiviUnitTestCase {
     $text = __FUNCTION__ . ' text';
     $userID = $loggedInUser;
 
-    list($sent, $activity_id) = $email_result = CRM_Activity_BAO_Activity::sendEmail(
+    list($sent, $activity_ids) = $email_result = CRM_Activity_BAO_Activity::sendEmail(
       $contactDetails,
       $subject,
       $text,
@@ -1231,7 +1231,7 @@ class CRM_Activity_BAO_ActivityTest extends CiviUnitTestCase {
       $from = __FUNCTION__ . '@example.com'
     );
 
-    $activity = $this->civicrm_api('activity', 'getsingle', ['id' => $activity_id, 'version' => $this->_apiversion]);
+    $activity = $this->civicrm_api('activity', 'getsingle', ['id' => $activity_ids[0], 'version' => $this->_apiversion]);
     $details = "-ALTERNATIVE ITEM 0-
 $html
 -ALTERNATIVE ITEM 1-
@@ -1278,7 +1278,7 @@ $text
     $text = __FUNCTION__ . ' text';
     $userID = $loggedInUser;
 
-    list($sent, $activity_id) = $email_result = CRM_Activity_BAO_Activity::sendEmail(
+    list($sent, $activity_ids) = $email_result = CRM_Activity_BAO_Activity::sendEmail(
       $contactDetails,
       $subject,
       $text,
@@ -1294,7 +1294,7 @@ $text
       NULL,
       $campaign_id
     );
-    $activity = $this->civicrm_api('activity', 'getsingle', ['id' => $activity_id, 'version' => $this->_apiversion]);
+    $activity = $this->civicrm_api('activity', 'getsingle', ['id' => $activity_ids[0], 'version' => $this->_apiversion]);
     $this->assertEquals($activity['campaign_id'], $campaign_id, 'Activity campaign_id does not match.');
   }
 
@@ -1543,7 +1543,7 @@ $text
     $text = __FUNCTION__ . ' text';
 
     $mut = new CiviMailUtils($this, TRUE);
-    list($sent, $activity_id) = $email_result = CRM_Activity_BAO_Activity::sendEmail(
+    list($sent, $activity_ids) = $email_result = CRM_Activity_BAO_Activity::sendEmail(
       $contact['values'],
       $subject,
       $text,
@@ -1560,7 +1560,7 @@ $text
       NULL,
       $caseId
     );
-    $activity = $this->callAPISuccess('Activity', 'getsingle', ['id' => $activity_id, 'return' => ['case_id']]);
+    $activity = $this->callAPISuccess('Activity', 'getsingle', ['id' => $activity_ids[0], 'return' => ['case_id']]);
     $this->assertEquals($caseId, $activity['case_id'][0], 'Activity case_id does not match.');
     $mut->checkMailLog(['subject my case']);
     $mut->stop();
@@ -2451,4 +2451,61 @@ $textValue
     ];
   }
 
+  /**
+   * Test the returned activity ids when there are multiple "To" recipients.
+   * Similar to testSendEmailWillReplaceTokensUniquelyForEachContact but we're
+   * checking the activity ids returned from sendEmail.
+   */
+  public function testSendEmailWithMultipleToRecipients() {
+    $contactId1 = $this->individualCreate(['first_name' => 'Aaaa', 'last_name' => 'Bbbb']);
+    $contactId2 = $this->individualCreate(['first_name' => 'Cccc', 'last_name' => 'Dddd']);
+
+    // create a logged in USER since the code references it for sendEmail user.
+    $loggedInUser = $this->createLoggedInUser();
+    $contacts = $this->callAPISuccess('Contact', 'get', [
+      'sequential' => 1,
+      'id' => ['IN' => [$contactId1, $contactId2]],
+    ]);
+
+    list($sent, $activityIds) = CRM_Activity_BAO_Activity::sendEmail(
+      $contacts['values'],
+      'a subject',
+      'here is some text',
+      '<p>here is some html</p>',
+      $contacts['values'][0]['email'],
+      $loggedInUser,
+      $from = __FUNCTION__ . '@example.com',
+      $attachments = NULL,
+      $cc = NULL,
+      $bcc = NULL,
+      $contactIds = array_column($contacts['values'], 'id'),
+      $additionalDetails = NULL,
+      NULL,
+     $campaign_id = NULL
+    );
+
+    // Get all activities for these contacts
+    $result = $this->callAPISuccess('activity', 'get', [
+      'sequential' => 1,
+      'return' => ['target_contact_id'],
+      'target_contact_id' => ['IN' => [$contactId1, $contactId2]],
+    ]);
+
+    // There should be one activity created for each of the two contacts
+    $this->assertEquals(2, $result['count']);
+
+    // Activity ids returned from sendEmail should match the ones returned from api call.
+    $this->assertEquals($activityIds, array_column($result['values'], 'id'));
+
+    // Is it the right contacts?
+    $this->assertEquals(
+      [0 => [0 => $contactId1], 1 => [0 => $contactId2]],
+      array_column($result['values'], 'target_contact_id')
+    );
+    $this->assertEquals(
+      [0 => [$contactId1 => 'Bbbb, Aaaa'], 1 => [$contactId2 => 'Dddd, Cccc']],
+      array_column($result['values'], 'target_contact_sort_name')
+    );
+  }
+
 }