Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ActionSchedule - Pass real batches into TokenProcessor. Simplify CRM_Activity_Tokens. #21088

Merged
merged 4 commits into from
Aug 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions CRM/Activity/Tokens.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,15 @@ public function alterActionScheduleQuery(\Civi\ActionSchedule\Event\MailingQuery
// Multiple revisions of the activity.
// Q: Could we simplify & move the extra AND clauses into `where(...)`?
$e->query->param('casEntityJoinExpr', 'e.id = reminder.entity_id AND e.is_current_revision = 1 AND e.is_deleted = 0');
$e->query->select('e.id AS tokenContext_' . $this->getEntityContextSchema());
}

/**
* @inheritDoc
*/
public function prefetch(TokenValueEvent $e) {
// Find all the entity IDs
$entityIds
= $e->getTokenProcessor()->getContextValues('actionSearchResult', 'entityID')
+ $e->getTokenProcessor()->getContextValues($this->getEntityContextSchema());
$entityIds = $e->getTokenProcessor()->getContextValues($this->getEntityContextSchema());

if (!$entityIds) {
return NULL;
Expand Down Expand Up @@ -144,8 +143,7 @@ public function evaluateToken(TokenRow $row, $entity, $field, $prefetch = NULL)
'activity_id' => 'id',
];

// Get ActivityID either from actionSearchResult (for scheduled reminders) if exists
$activityId = $row->context['actionSearchResult']->entityID ?? $row->context[$this->getEntityContextSchema()];
$activityId = $row->context[$this->getEntityContextSchema()];

$activity = $prefetch['activity'][$activityId];

Expand Down
65 changes: 36 additions & 29 deletions CRM/Core/BAO/ActionSchedule.php
Original file line number Diff line number Diff line change
Expand Up @@ -267,44 +267,51 @@ public static function sendMailings($mappingID, $now) {
);

$multilingual = CRM_Core_I18n::isMultilingual();
$tokenProcessor = self::createTokenProcessor($actionSchedule, $mapping);
while ($dao->fetch()) {
$errors = [];
try {
$tokenProcessor = self::createTokenProcessor($actionSchedule, $mapping);
$row = $tokenProcessor->addRow()
->context('contactId', $dao->contactID)
->context('actionSearchResult', (object) $dao->toArray());

// switch language if necessary
if ($multilingual) {
$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));
$row = $tokenProcessor->addRow()
->context('contactId', $dao->contactID)
->context('actionSearchResult', (object) $dao->toArray());

// switch language if necessary
if ($multilingual) {
$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 ($dao->toArray() as $key => $value) {
if (preg_match('/^tokenContext_(.*)/', $key, $m)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So really this is the meaningful change in here - I think some comments around it would help. The fact this still passes tests means it must still work for contribution tokens - but I'm quite sure how

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eileenmcnaughton Agree about comments. Added PR for that: #21098

For contribution tokens, this PR doesn't actually change anything. CRM_Contribution_Tokens::alterActionScheduleQuery() still does the same prefetch that it did before. That'll be the subsequent PR.

For this PR, I only touched CRM_Activity_Tokens::alterActionScheduleQuery() because that was the simplest one - a way to demonstrate the mechanism.

if (!in_array($m[1], $tokenProcessor->context['schema'])) {
$tokenProcessor->context['schema'][] = $m[1];
}
$row->context($m[1], $value);
}
}
}

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));
}
catch (\Civi\Token\TokenException $e) {
$errors['token_exception'] = $e->getMessage();
// 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,
Expand Down
2 changes: 1 addition & 1 deletion Civi/Token/TokenProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ public function getRow($key) {
* 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 ?: []));
}

/**
Expand Down