From 4f5f985c08cf579b7bea6a752a868acce248c4f1 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Wed, 13 Oct 2021 08:46:39 +1300 Subject: [PATCH] dev/core#2907 fix for gdpr clobering contact tokens This is a fix for contact tokens not rendering when gdpr tokens is installed. Gdpr declares some addtional tokens with the namespace 'contact'. I am inclined to agree this counts as 'naughty' and so while I have fixed the clobbering by not processing contact-metadata tokens I have not fixed the enotices. If we think it is non-naughty I can kill those - but I've already loosened some strictness that I think had benefits in order to facilitate this --- CRM/Contact/Tokens.php | 47 ++++++++++++++++++++++++++++++++------- CRM/Core/EntityTokens.php | 2 +- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/CRM/Contact/Tokens.php b/CRM/Contact/Tokens.php index 7134b01aa8..40e2028a4a 100644 --- a/CRM/Contact/Tokens.php +++ b/CRM/Contact/Tokens.php @@ -32,6 +32,13 @@ class CRM_Contact_Tokens extends CRM_Core_EntityTokens { return 'Contact'; } + /** + * Tokens defined by the legacy hook. + * + * @var array + */ + protected $hookTokens; + /** * @inheritDoc */ @@ -112,9 +119,8 @@ class CRM_Contact_Tokens extends CRM_Core_EntityTokens { */ protected function getLegacyHookTokens(): array { $tokens = []; - $hookTokens = []; - \CRM_Utils_Hook::tokens($hookTokens); - foreach ($hookTokens as $tokenValues) { + + foreach ($this->getHookTokens() as $tokenValues) { foreach ($tokenValues as $key => $value) { if (is_numeric($key)) { // This appears to be an attempt to compensate for @@ -243,10 +249,10 @@ class CRM_Contact_Tokens extends CRM_Core_EntityTokens { */ public function evaluateLegacyHookTokens(TokenValueEvent $e): void { $messageTokens = $e->getTokenProcessor()->getMessageTokens(); - $hookTokens = array_intersect(\CRM_Utils_Token::getTokenCategories(), array_keys($messageTokens)); - if (empty($hookTokens)) { + if (!array_intersect(array_keys($this->getHookTokens()), array_keys($messageTokens))) { return; } + foreach ($e->getRows() as $row) { if (empty($row->context['contactId'])) { continue; @@ -266,9 +272,15 @@ class CRM_Contact_Tokens extends CRM_Core_EntityTokens { $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}"] ?? ''); + foreach ($this->getHookTokens() as $category => $hookToken) { + if (!empty($messageTokens[$category])) { + foreach (array_keys($hookToken) as $tokenName) { + $tokenPartOnly = str_replace($category . '.', '', $tokenName); + if (in_array($tokenPartOnly, $messageTokens[$category], TRUE)) { + $row->format('text/html') + ->tokens($category, str_replace($category . '.', '', $tokenName), $contactArray[$row->context['contactId']][$tokenName] ?? ($contactArray[$row->context['contactId']][$category . '.' . $tokenName] ?? '')); + } + } } } } @@ -676,4 +688,23 @@ class CRM_Contact_Tokens extends CRM_Core_EntityTokens { ]; } + /** + * Get the tokens defined by the legacy hook. + * + * @return array + */ + protected function getHookTokens(): array { + if ($this->hookTokens === NULL) { + if (isset(Civi::$statics[__CLASS__]['hook_tokens'])) { + $this->hookTokens = Civi::$statics[__CLASS__]['hook_tokens']; + } + else { + $this->hookTokens = []; + \CRM_Utils_Hook::tokens($this->hookTokens); + Civi::$statics[__CLASS__]['hook_tokens'] = $this->hookTokens; + } + } + return $this->hookTokens; + } + } diff --git a/CRM/Core/EntityTokens.php b/CRM/Core/EntityTokens.php index f995bc3650..41aa6a8ecc 100644 --- a/CRM/Core/EntityTokens.php +++ b/CRM/Core/EntityTokens.php @@ -547,7 +547,7 @@ class CRM_Core_EntityTokens extends AbstractTokenSubscriber { if (isset($this->getTokenMappingsForRelatedEntities()[$fieldName])) { return $this->getTokenMetadata()[$this->getTokenMappingsForRelatedEntities()[$fieldName]]; } - return $this->getTokenMetadata()[$this->getDeprecatedTokens()[$fieldName]]; + return $this->getTokenMetadata()[$this->getDeprecatedTokens()[$fieldName]] ?? []; } /** -- 2.25.1