Skip to content
Snippets Groups Projects
Unverified Commit 778d3aa9 authored by totten's avatar totten Committed by GitHub
Browse files

Merge pull request #21449 from eileenmcnaughton/compat

#2814 TokenCompatSubscriber - Evaluate tokens during "civi.token.eval" phase
parents 600977fd d8b9f166
Branches
Tags
No related merge requests found
......@@ -615,15 +615,15 @@ FROM civicrm_action_schedule cas
$mailParams = [
'groupName' => 'Scheduled Reminder Sender',
'from' => self::pickFromEmail($schedule),
'toName' => $tokenRow->context['contact']['display_name'],
'toName' => $tokenRow->render('toName'),
'toEmail' => $toEmail,
'subject' => $tokenRow->render('subject'),
'entity' => 'action_schedule',
'entity_id' => $schedule->id,
];
if (!$body_html || $tokenRow->context['contact']['preferred_mail_format'] === 'Text' ||
$tokenRow->context['contact']['preferred_mail_format'] === 'Both'
$preferredMailFormat = $tokenRow->render('preferred_mail_format');
if (!$body_html || $preferredMailFormat === 'Text' || $preferredMailFormat === 'Both'
) {
// render the & entities in text mode, so that the links work
$mailParams['text'] = str_replace('&', '&', $body_text);
......@@ -658,6 +658,10 @@ FROM civicrm_action_schedule cas
$tp->addMessage('body_html', $schedule->body_html, 'text/html');
$tp->addMessage('sms_body_text', $schedule->sms_body_text, 'text/plain');
$tp->addMessage('subject', $schedule->subject, 'text/plain');
// These 2 are not 'real' tokens - but it tells the processor to load them.
$tp->addMessage('toName', '{contact.display_name}', 'text/plain');
$tp->addMessage('preferred_mail_format', '{contact.preferred_mail_format}', 'text/plain');
return $tp;
}
......
......@@ -30,6 +30,7 @@ class TokenCompatSubscriber implements EventSubscriberInterface {
return [
'civi.token.eval' => [
['setupSmartyAliases', 1000],
['evaluateLegacyHookTokens', 500],
['onEvaluate'],
],
'civi.token.render' => 'onRender',
......@@ -242,6 +243,57 @@ class TokenCompatSubscriber implements EventSubscriberInterface {
$proc->addMessage('TokenCompatSubscriber.aliases', $fakeMessage, 'text/plain');
}
/**
* Load token data from legacy hooks.
*
* While our goal is for people to move towards implementing
* toke processors the old-style hooks can extend contact
* token data.
*
* When that is happening we need to load the full contact record
* to send to the hooks (not great for performance but the
* fix is to move away from implementing legacy style hooks).
*
* Consistent with prior behaviour we only load the contact it it
* is already loaded. In that scenario we also load any extra fields
* that might be wanted for the contact tokens.
*
* @param \Civi\Token\Event\TokenValueEvent $e
* @throws TokenException
*/
public function evaluateLegacyHookTokens(TokenValueEvent $e): void {
$messageTokens = $e->getTokenProcessor()->getMessageTokens();
$hookTokens = array_intersect(\CRM_Utils_Token::getTokenCategories(), array_keys($messageTokens));
if (empty($hookTokens)) {
return;
}
foreach ($e->getRows() as $row) {
if (empty($row->context['contactId'])) {
continue;
}
unset($swapLocale);
$swapLocale = empty($row->context['locale']) ? NULL : \CRM_Utils_AutoClean::swapLocale($row->context['locale']);
if (empty($row->context['contact'])) {
// If we don't have the contact already load it now, getting full
// details for hooks and anything the contact token resolution might
// want later.
$row->context['contact'] = $this->getContact($row->context['contactId'], $messageTokens['contact'] ?? [], TRUE);
}
$contactArray = [$row->context['contactId'] => $row->context['contact']];
\CRM_Utils_Hook::tokenValues($contactArray,
[$row->context['contactId']],
empty($row->context['mailingJobId']) ? NULL : $row->context['mailingJobId'],
$messageTokens,
$row->context['controller']
);
foreach ($hookTokens as $hookToken) {
foreach ($messageTokens[$hookToken] as $tokenName) {
$row->format('text/html')->tokens($hookToken, $tokenName, $contactArray[$row->context['contactId']]["{$hookToken}.{$tokenName}"] ?? '');
}
}
}
}
/**
* Load token data.
*
......@@ -255,7 +307,7 @@ class TokenCompatSubscriber implements EventSubscriberInterface {
$e->getTokenProcessor()->context['hookTokenCategories'] = \CRM_Utils_Token::getTokenCategories();
$messageTokens = $e->getTokenProcessor()->getMessageTokens();
$messageTokens = $e->getTokenProcessor()->getMessageTokens()['contact'] ?? [];
foreach ($e->getRows() as $row) {
if (empty($row->context['contactId'])) {
......@@ -268,24 +320,11 @@ class TokenCompatSubscriber implements EventSubscriberInterface {
/** @var int $contactId */
$contactId = $row->context['contactId'];
if (empty($row->context['contact'])) {
$contact = $this->getContact($contactId, $messageTokens['contact'] ?? [], TRUE);
$contact = $this->getContact($contactId, $messageTokens);
}
else {
$contact = $row->context['contact'];
}
$contactArray = [$contactId => $contact];
\CRM_Utils_Hook::tokenValues($contactArray,
[$contactId],
empty($row->context['mailingJobId']) ? NULL : $row->context['mailingJobId'],
$messageTokens,
$row->context['controller']
);
// merge the custom tokens in the $contact array
if (!empty($contactArray[$contactId])) {
$contact = array_merge($contact, $contactArray[$contactId]);
}
$row->context('contact', $contact);
}
}
......
......@@ -338,6 +338,7 @@ London, 90210
// work in combination.
$tokenString = '{$pre_assigned_smarty}{$passed_smarty}
{domain.name}
{important_stuff.favourite_emoticon}
';
foreach (array_keys($tokenData) as $key) {
$tokenString .= "{$key}:{contact.{$key}}\n";
......@@ -355,6 +356,7 @@ London, 90210
]);
$expected = 'weewhoa
Default Domain Name
emo
';
$expected .= $this->getExpectedContactOutput($address['id'], $tokenData, $messageContent['html']);
$this->assertEquals($expected, $messageContent['html']);
......@@ -381,7 +383,7 @@ Default Domain Name
*/
public function hookTokenValues(array &$details): void {
foreach ($details as $index => $detail) {
$details[$index]['favourite_emoticon'] = 'emo';
$details[$index]['important_stuff.favourite_emoticon'] = 'emo';
}
}
......@@ -454,7 +456,12 @@ Default Domain Name
];
}
public function getAdvertisedTokens() {
/**
* Get the tokens we expect to see advertised.
*
* @return string[]
*/
public function getAdvertisedTokens(): array {
return [
'{contact.contact_type}' => 'Contact Type',
'{contact.do_not_email}' => 'Do Not Email',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment