diff --git a/CRM/Activity/Tokens.php b/CRM/Activity/Tokens.php index 66663dd7c497..2f3268d0a727 100644 --- a/CRM/Activity/Tokens.php +++ b/CRM/Activity/Tokens.php @@ -145,7 +145,7 @@ public function evaluateToken(TokenRow $row, $entity, $field, $prefetch = NULL) ]; // 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]; diff --git a/CRM/Admin/Form/ScheduleReminders.php b/CRM/Admin/Form/ScheduleReminders.php index 15a7a24a5afd..c0eda3b5dca1 100644 --- a/CRM/Admin/Form/ScheduleReminders.php +++ b/CRM/Admin/Form/ScheduleReminders.php @@ -690,8 +690,14 @@ public function parseActionSchedule($values) { * @return array */ public function listTokens() { - $tokens = CRM_Core_SelectValues::contactTokens(); - $tokens = array_merge(CRM_Core_SelectValues::activityTokens(), $tokens); + $tokenProcessor = new \Civi\Token\TokenProcessor(\Civi::dispatcher(), [ + 'controller' => get_class(), + 'smarty' => FALSE, + 'schema' => ['activityId'], + ]); + $tokens = $tokenProcessor->listTokens(); + + $tokens = array_merge(CRM_Core_SelectValues::contactTokens(), $tokens); $tokens = array_merge(CRM_Core_SelectValues::eventTokens(), $tokens); $tokens = array_merge(CRM_Core_SelectValues::membershipTokens(), $tokens); $tokens = array_merge(CRM_Core_SelectValues::contributionTokens(), $tokens); diff --git a/CRM/Core/BAO/ActionSchedule.php b/CRM/Core/BAO/ActionSchedule.php index e804f3bc7657..7afd667e9990 100644 --- a/CRM/Core/BAO/ActionSchedule.php +++ b/CRM/Core/BAO/ActionSchedule.php @@ -276,10 +276,13 @@ public static function sendMailings($mappingID, $now) { $errors = []; try { - $tokenProcessor = self::createTokenProcessor($actionSchedule, $mapping); + $entityContextId = \Civi\Token\TokenProcessor::getEntityTableToSchemaMapping($mapping->getEntity()); + $schema = ['contactId', $entityContextId]; + $tokenProcessor = self::createTokenProcessor($actionSchedule, $mapping, $schema); $tokenProcessor->addRow() ->context('contactId', $dao->contactID) - ->context('actionSearchResult', (object) $dao->toArray()); + ->context('actionSearchResult', (object) $dao->toArray()) + ->context($entityContextId, $dao->id); foreach ($tokenProcessor->evaluate()->getRows() as $tokenRow) { if ($actionSchedule->mode === 'SMS' || $actionSchedule->mode === 'User_Preference') { CRM_Utils_Array::extend($errors, self::sendReminderSms($tokenRow, $actionSchedule, $dao->contactID)); @@ -641,14 +644,17 @@ protected static function sendReminderEmail($tokenRow, $schedule, $toContactID): /** * @param CRM_Core_DAO_ActionSchedule $schedule * @param \Civi\ActionSchedule\Mapping $mapping + * @param array $schema (eg. ['contactId', 'activityId']) + * * @return \Civi\Token\TokenProcessor */ - protected static function createTokenProcessor($schedule, $mapping) { + protected static function createTokenProcessor($schedule, $mapping, $schema) { $tp = new \Civi\Token\TokenProcessor(\Civi::dispatcher(), [ 'controller' => __CLASS__, 'actionSchedule' => $schedule, 'actionMapping' => $mapping, 'smarty' => TRUE, + 'schema' => $schema, ]); $tp->addMessage('body_text', $schedule->body_text, 'text/plain'); $tp->addMessage('body_html', $schedule->body_html, 'text/html'); diff --git a/Civi/Token/TokenProcessor.php b/Civi/Token/TokenProcessor.php index e8ee1b8f73f5..509ec1b74aa0 100644 --- a/Civi/Token/TokenProcessor.php +++ b/Civi/Token/TokenProcessor.php @@ -111,6 +111,25 @@ class TokenProcessor { protected $next = 0; + /** + * Get a mapping from entity_table to context (currently used by actionSchedule to map parameters) + * + * @param string $entityTable eg. civicrm_activity + * + * @return string|null + */ + public static function getEntityTableToSchemaMapping($entityTable) { + $mapping = [ + 'civicrm_activity' => 'activityId', + 'civicrm_contact' => 'contactId', + 'civicrm_contribution' => 'contributionId', + ]; + if (array_key_exists($entityTable, $mapping)) { + return $mapping[$entityTable]; + } + return NULL; + } + /** * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher * @param array $context diff --git a/tests/phpunit/CRM/Core/BAO/ActionScheduleTest.php b/tests/phpunit/CRM/Core/BAO/ActionScheduleTest.php index f78853cb7310..250d250d4b5e 100644 --- a/tests/phpunit/CRM/Core/BAO/ActionScheduleTest.php +++ b/tests/phpunit/CRM/Core/BAO/ActionScheduleTest.php @@ -112,6 +112,8 @@ public function setUp(): void { 'activity_date_time' => '20120615100000', 'is_current_revision' => 1, 'is_deleted' => 0, + 'subject' => 'Phone call', + 'details' => 'A phone call about a bear', ]; $this->fixtures['contact'] = [ 'is_deceased' => 0, @@ -952,6 +954,27 @@ public function mailerExamples(): array { ], ]; + // In this example, we test activity tokens + $activityTokens = '{activity.subject};;{activity.details};;{activity.activity_date_time}'; + $activity = $this->fixtures['phonecall']; + $activityTokensExpected = "Phone call;;A phone call about a bear;;June 15th, 2012 10:00 AM"; + $cases[4] = [ + // Schedule definition. + [ + 'subject' => "subj $someTokensTmpl", + 'body_html' => "html {$activityTokens}", + 'body_text' => "text {$activityTokens}", + ], + // Assertions (regex). + [ + 'from_name' => '/^FIXME$/', + 'from_email' => '/^info@EXAMPLE.ORG$/', + 'subject' => "/^subj $someTokensExpected\$/", + 'body_html' => "/^html $activityTokensExpected\$/", + 'body_text' => "/^text $activityTokensExpected\$/", + ], + ]; + return $cases; }