From c06f174feaa0e82fac89c3709e6fe0ca36f3b9b4 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 10 Aug 2021 17:52:13 -0700 Subject: [PATCH] ActionSchedule - Fill TokenProcessor will real batches Background: `ActionSchedule::sendMailings()` fetches a batch of pending reminders (per some specific schedule/rule). Then it composes and sends a message for each. Before: For each item in the batch, it makes a new `TokenProcessor`. This means that the `TokenProcessor` only sees one pending reminder. Therefore, the `TokenProcessor` cannot meaningfully fetch batched data. After: It creates one `TokenProcessor` and adds rows for each pending reminder. This means that `TokenProcessor` can fetch batched data.# On branch master-action-batch Comments: This part of a longer plot to simplify the `CRM_*_Tokens`. Currently, `CRM_*_Tokens` implements duplicate prefetch mechanisms -- the general-purpose `prefetch()` and the special-purpose `alterActionScheduleQuery()`. This patch makes it possible to use `prefetch()` for all the real work of prefetching (and phasing-out `alterActionScheduleQuery()`). --- CRM/Core/BAO/ActionSchedule.php | 37 ++++++++++++++++++--------------- Civi/Token/TokenProcessor.php | 2 +- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/CRM/Core/BAO/ActionSchedule.php b/CRM/Core/BAO/ActionSchedule.php index 014978230e..5821fced06 100644 --- a/CRM/Core/BAO/ActionSchedule.php +++ b/CRM/Core/BAO/ActionSchedule.php @@ -267,9 +267,8 @@ FROM civicrm_action_schedule cas ); $multilingual = CRM_Core_I18n::isMultilingual(); + $tokenProcessor = self::createTokenProcessor($actionSchedule, $mapping); while ($dao->fetch()) { - $errors = []; - $tokenProcessor = self::createTokenProcessor($actionSchedule, $mapping); $row = $tokenProcessor->addRow() ->context('contactId', $dao->contactID) ->context('actionSearchResult', (object) $dao->toArray()); @@ -279,27 +278,31 @@ FROM civicrm_action_schedule cas $preferred_language = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $dao->contactID, 'preferred_language'); $row->context('locale', CRM_Core_BAO_ActionSchedule::pickLocale($actionSchedule->communication_language, $preferred_language)); } + } - foreach ($tokenProcessor->evaluate()->getRows() as $tokenRow) { - // It's possible, eg, that sendReminderEmail fires Hook::alterMailParams() and that some listener use ts(). - $swapLocale = empty($row->context['locale']) ? NULL : \CRM_Utils_AutoClean::swapLocale($row->context['locale']); + $tokenProcessor->evaluate(); + foreach ($tokenProcessor->getRows() as $tokenRow) { + $dao = $tokenRow->context['actionSearchResult']; + $errors = []; - if ($actionSchedule->mode === 'SMS' || $actionSchedule->mode === 'User_Preference') { - CRM_Utils_Array::extend($errors, self::sendReminderSms($tokenRow, $actionSchedule, $dao->contactID)); - } + // It's possible, eg, that sendReminderEmail fires Hook::alterMailParams() and that some listener use ts(). + $swapLocale = empty($row->context['locale']) ? NULL : \CRM_Utils_AutoClean::swapLocale($row->context['locale']); - if ($actionSchedule->mode === 'Email' || $actionSchedule->mode === 'User_Preference') { - CRM_Utils_Array::extend($errors, self::sendReminderEmail($tokenRow, $actionSchedule, $dao->contactID)); - } - // insert activity log record if needed - if ($actionSchedule->record_activity && empty($errors)) { - $caseID = empty($dao->case_id) ? NULL : $dao->case_id; - CRM_Core_BAO_ActionSchedule::createMailingActivity($tokenRow, $mapping, $dao->contactID, $dao->entityID, $caseID); - } + if ($actionSchedule->mode === 'SMS' || $actionSchedule->mode === 'User_Preference') { + CRM_Utils_Array::extend($errors, self::sendReminderSms($tokenRow, $actionSchedule, $dao->contactID)); + } - unset($swapLocale); + if ($actionSchedule->mode === 'Email' || $actionSchedule->mode === 'User_Preference') { + CRM_Utils_Array::extend($errors, self::sendReminderEmail($tokenRow, $actionSchedule, $dao->contactID)); + } + // insert activity log record if needed + if ($actionSchedule->record_activity && empty($errors)) { + $caseID = empty($dao->case_id) ? NULL : $dao->case_id; + CRM_Core_BAO_ActionSchedule::createMailingActivity($tokenRow, $mapping, $dao->contactID, $dao->entityID, $caseID); } + unset($swapLocale); + // update action log record $logParams = [ 'id' => $dao->reminderID, diff --git a/Civi/Token/TokenProcessor.php b/Civi/Token/TokenProcessor.php index 7ad2ec7b58..d434a1a139 100644 --- a/Civi/Token/TokenProcessor.php +++ b/Civi/Token/TokenProcessor.php @@ -256,7 +256,7 @@ class TokenProcessor { * Each row is presented with a fluent, OOP facade. */ public function getRows() { - return new TokenRowIterator($this, new \ArrayIterator($this->rowContexts)); + return new TokenRowIterator($this, new \ArrayIterator($this->rowContexts ?: [])); } /** -- 2.25.1