From 58b954cf1674b9b0079b2524a18f94018dfb3031 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Mon, 11 Oct 2021 19:56:11 +1300 Subject: [PATCH] Switch replaceGreetingTokens over --- CRM/Contact/Tokens.php | 29 +++++++++-- CRM/Utils/Token.php | 106 ++++++++++++++++------------------------- 2 files changed, 65 insertions(+), 70 deletions(-) diff --git a/CRM/Contact/Tokens.php b/CRM/Contact/Tokens.php index 7df4720e93..6fa88a0759 100644 --- a/CRM/Contact/Tokens.php +++ b/CRM/Contact/Tokens.php @@ -288,8 +288,8 @@ class CRM_Contact_Tokens extends CRM_Core_EntityTokens { * @throws \CRM_Core_Exception */ public function onEvaluate(TokenValueEvent $e) { - $messageTokens = $e->getTokenProcessor()->getMessageTokens()['contact'] ?? []; - if (empty($messageTokens)) { + $this->activeTokens = $e->getTokenProcessor()->getMessageTokens()['contact'] ?? []; + if (empty($this->activeTokens)) { return; } @@ -302,10 +302,10 @@ class CRM_Contact_Tokens extends CRM_Core_EntityTokens { $swapLocale = empty($row->context['locale']) ? NULL : \CRM_Utils_AutoClean::swapLocale($row->context['locale']); if (empty($row->context['contact'])) { - $row->context['contact'] = $this->getContact($row->context['contactId'], $messageTokens); + $row->context['contact'] = $this->getContact($row->context['contactId'], $this->activeTokens); } - foreach ($messageTokens as $token) { + foreach ($this->activeTokens as $token) { if ($token === 'checksum') { $cs = \CRM_Contact_BAO_Contact_Utils::generateChecksum($row->context['contactId'], NULL, @@ -351,6 +351,13 @@ class CRM_Contact_Tokens extends CRM_Core_EntityTokens { return $row->context[$entityName][$possibility]; } } + $contactID = $this->getFieldValue($row, 'id'); + if ($contactID) { + $row->context['contact'] = array_merge($this->getContact($contactID, $this->activeTokens), $row->context['contact']); + if (isset($row->context[$entityName][$field])) { + return $row->context[$entityName][$field]; + } + } return ''; } @@ -446,6 +453,11 @@ class CRM_Contact_Tokens extends CRM_Core_EntityTokens { ($joinEntity !== 'Website' ? [$alias . '.is_primary', '=', 1] : [])); } $contact = $contactApi->execute()->first(); + if (!$contact) { + // This is probably a test-only situation where tokens are retrieved for a + // fake contact id - check `testReplaceGreetingTokens` + return []; + } foreach ($this->getDeprecatedTokens() as $apiv3Name => $fieldName) { // it would be set already with the right value for a greeting token @@ -678,6 +690,15 @@ class CRM_Contact_Tokens extends CRM_Core_EntityTokens { 'data_type' => 'String', 'audience' => 'sysadmin', ], + // this gets forced out if we specify individual fields + 'household_name' => [ + 'title' => ts('Household name'), + 'name' => 'household_name', + 'type' => 'Field', + 'options' => NULL, + 'data_type' => 'String', + 'audience' => 'sysadmin', + ], ]; } diff --git a/CRM/Utils/Token.php b/CRM/Utils/Token.php index 421e7cefc1..2f7db99438 100644 --- a/CRM/Utils/Token.php +++ b/CRM/Utils/Token.php @@ -9,6 +9,8 @@ +--------------------------------------------------------------------+ */ +use Civi\Token\TokenProcessor; + /** * * @package CRM @@ -592,6 +594,8 @@ class CRM_Utils_Token { * @param bool $returnBlankToken * Return unevaluated token if value is null. * + * @deprecated + * * @param bool $escapeSmarty * * @return string @@ -634,6 +638,13 @@ class CRM_Utils_Token { } /** + * Do Not use. + * + * Only core usage is from a deprecated unused function and + * from deprecated BAO_Mailing code (to be replaced by flexmailer). + * + * @deprecated + * * @param $token * @param $contact * @param bool $html @@ -718,9 +729,13 @@ class CRM_Utils_Token { } /** + * Do not use - unused in core. + * * Replace all the hook tokens in $str with information from * $contact. * + * @deprecated + * * @param string $str * The string with tokens to be replaced. * @param array $contact @@ -790,6 +805,10 @@ class CRM_Utils_Token { } /** + * Do not use, unused in core. + * + * @deprecated + * * @param $token * @param $contact * @param $category @@ -1303,9 +1322,6 @@ class CRM_Utils_Token { * * @TODO Remove that inconsistency in usage. * - * ::replaceContactTokens() may need to be called after this method, to - * replace tokens supplied from this method. - * * @param string $tokenString * @param array $contactDetails * @param int $contactId @@ -1317,73 +1333,25 @@ class CRM_Utils_Token { if (!$contactDetails && !$contactId) { return; } - // check if there are any tokens $greetingTokens = self::getTokens($tokenString); - - if (!empty($greetingTokens)) { - // first use the existing contact object for token replacement - if (!empty($contactDetails)) { - $tokenString = CRM_Utils_Token::replaceContactTokens($tokenString, $contactDetails, TRUE, $greetingTokens, TRUE, $escapeSmarty); - } - - self::removeNullContactTokens($tokenString, $contactDetails, $greetingTokens); - // check if there are any unevaluated tokens - $greetingTokens = self::getTokens($tokenString); - - // $greetingTokens not empty, means there are few tokens which are not - // evaluated, like custom data etc - // so retrieve it from database - if (!empty($greetingTokens) && array_key_exists('contact', $greetingTokens)) { - $greetingsReturnProperties = array_flip(CRM_Utils_Array::value('contact', $greetingTokens)); - $greetingsReturnProperties = array_fill_keys(array_keys($greetingsReturnProperties), 1); - $contactParams = ['contact_id' => $contactId]; - - $greetingDetails = self::getTokenDetails($contactParams, - $greetingsReturnProperties, - FALSE, FALSE, NULL, - $greetingTokens, - $className - ); - - // again replace tokens - $tokenString = CRM_Utils_Token::replaceContactTokens($tokenString, - $greetingDetails, - TRUE, - $greetingTokens, - TRUE, - $escapeSmarty - ); - } - - // check if there are still any unevaluated tokens - $remainingTokens = self::getTokens($tokenString); - - // $greetingTokens not empty, there are customized or hook tokens to replace - if (!empty($remainingTokens)) { - // Fill the return properties array - $greetingTokens = $remainingTokens; - reset($greetingTokens); - $greetingsReturnProperties = []; - foreach ($greetingTokens as $value) { - $props = array_flip($value); - $props = array_fill_keys(array_keys($props), 1); - $greetingsReturnProperties = $greetingsReturnProperties + $props; - } - $contactParams = ['contact_id' => $contactId]; - $greetingDetails = self::getTokenDetails($contactParams, - $greetingsReturnProperties, - FALSE, FALSE, NULL, - $greetingTokens, - $className - ); - // Prepare variables for calling replaceHookTokens - $categories = array_keys($greetingTokens); - [$contact] = $greetingDetails; - // Replace tokens defined in Hooks. - $tokenString = CRM_Utils_Token::replaceHookTokens($tokenString, $contact[$contactId], $categories); + $context = $contactId ? ['contactId' => $contactId] : []; + if ($contactDetails) { + foreach ($contactDetails[0] as $contact) { + // Only 1 - the loop is because we may not know the id. + $context['contact'] = $contact; } } + $tokenProcessor = new TokenProcessor(\Civi::dispatcher(), [ + 'smarty' => FALSE, + 'class' => $className, + ]); + $tokenProcessor->addRow($context); + $tokenProcessor->addMessage('greeting', $tokenString, 'text/plain'); + $tokenProcessor->evaluate(); + foreach ($tokenProcessor->getRows() as $row) { + $tokenString = $row->render('greeting'); + } } /** @@ -1391,6 +1359,8 @@ class CRM_Utils_Token { * (non-custom) missing fields are null. By removing them, we can avoid * expensive calls to CRM_Contact_BAO_Query. * + * @deprecated unused in core + * * @param string $tokenString * @param array $contactDetails * @param array $greetingTokens @@ -1862,6 +1832,10 @@ class CRM_Utils_Token { } /** + * @deprecated + * + * Only used from deprecated functions not called by core. + * * @return array * [legacy_token => new_token] */ -- 2.25.1