From 31f2ebacef0f58d15cf6479ee1374201a154fe5c Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Tue, 28 Sep 2021 20:17:57 +1300 Subject: [PATCH] Remove call to the dreaded replaceMultipleContributionTokens --- CRM/Contribute/BAO/Contribution.php | 4 ++ CRM/Contribute/Form/Task/PDFLetter.php | 59 +++++++++++++++---- CRM/Utils/Token.php | 11 ++++ .../Form/Task/PDFLetterCommonTest.php | 12 ++-- 4 files changed, 68 insertions(+), 18 deletions(-) diff --git a/CRM/Contribute/BAO/Contribution.php b/CRM/Contribute/BAO/Contribution.php index 4b400a8b69..f0f84f988d 100644 --- a/CRM/Contribute/BAO/Contribution.php +++ b/CRM/Contribute/BAO/Contribution.php @@ -4858,6 +4858,8 @@ LIMIT 1;"; } /** + * Do not use - unused in core. + * * Function to replace contribution tokens. * * @param array $contributionIds @@ -4874,6 +4876,8 @@ LIMIT 1;"; * * @param bool $escapeSmarty * + * @deprecated + * * @return array * @throws \CiviCRM_API3_Exception */ diff --git a/CRM/Contribute/Form/Task/PDFLetter.php b/CRM/Contribute/Form/Task/PDFLetter.php index 1d2f9b845d..ce5839b712 100644 --- a/CRM/Contribute/Form/Task/PDFLetter.php +++ b/CRM/Contribute/Form/Task/PDFLetter.php @@ -9,6 +9,8 @@ +--------------------------------------------------------------------+ */ +use Civi\Token\TokenProcessor; + /** * * @package CRM @@ -133,7 +135,17 @@ class CRM_Contribute_Form_Task_PDFLetter extends CRM_Contribute_Form_Task { */ public function postProcess() { $formValues = $this->controller->exportValues($this->getName()); - [$formValues, $html_message, $messageToken, $returnProperties] = $this->processMessageTemplate($formValues); + [$formValues, $html_message] = $this->processMessageTemplate($formValues); + + $messageToken = CRM_Utils_Token::getTokens($html_message); + + $returnProperties = []; + if (isset($messageToken['contact'])) { + foreach ($messageToken['contact'] as $key => $value) { + $returnProperties[$value] = 1; + } + } + $isPDF = FALSE; $emailParams = []; if (!empty($formValues['email_options'])) { @@ -427,7 +439,7 @@ class CRM_Contribute_Form_Task_PDFLetter extends CRM_Contribute_Form_Task { CRM_Core_Session::setStatus(ts('You have selected the table cell separator, but one or more token fields are not placed inside a table cell. This would result in invalid HTML, so comma separators have been used instead.')); } $validated = TRUE; - $html = str_replace($separator, $realSeparator, $this->resolveTokens($html_message, $contact, $contribution, $messageToken, $grouped, $separator, $groupedContributions)); + $html = str_replace($separator, $realSeparator, $this->resolveTokens($html_message, $contact, $contribution['id'], $grouped, $separator, $groupedContributions)); } return $html; @@ -535,8 +547,7 @@ class CRM_Contribute_Form_Task_PDFLetter extends CRM_Contribute_Form_Task { * * @param string $html_message * @param array $contact - * @param array $contribution - * @param array $messageToken + * @param int $contributionID * @param bool $grouped * Does this letter represent more than one contribution. * @param string $separator @@ -545,20 +556,44 @@ class CRM_Contribute_Form_Task_PDFLetter extends CRM_Contribute_Form_Task { * * @return string */ - protected function resolveTokens(string $html_message, $contact, $contribution, $messageToken, $grouped, $separator, $contributions): string { + protected function resolveTokens(string $html_message, $contact, $contributionID, $grouped, $separator, $contributions): string { $tokenContext = [ 'smarty' => (defined('CIVICRM_MAIL_SMARTY') && CIVICRM_MAIL_SMARTY), 'contactId' => $contact['contact_id'], + 'schema' => ['contributionId'], ]; if ($grouped) { - $html_message = CRM_Utils_Token::replaceMultipleContributionTokens($separator, $html_message, $contributions, $messageToken); - } - else { - $tokenContext['schema'] = ['contributionId']; - $tokenContext['contributionId'] = $contribution['id']; + // First replace the contribution tokens. These are pretty ... special. + // if the text looks like `{contribution.currency} {contribution.total_amount}' + // and there are 2 rows with a currency separator of + // you wind up with a string like + // 'USDUSD> $50$89 + // see https://docs.civicrm.org/user/en/latest/contributions/manual-receipts-and-thank-yous/#grouped-contribution-thank-you-letters + $tokenProcessor = new TokenProcessor(\Civi::dispatcher(), $tokenContext); + $contributionTokens = CRM_Utils_Token::getTokens($html_message)['contribution'] ?? []; + foreach ($contributionTokens as $token) { + $tokenProcessor->addMessage($token, '{contribution.' . $token . '}', 'text/html'); + } + + foreach ($contributions as $contribution) { + $tokenProcessor->addRow([ + 'contributionId' => $contribution['id'], + 'contribution' => $contribution, + ]); + } + $tokenProcessor->evaluate(); + $resolvedTokens = []; + foreach ($contributionTokens as $token) { + foreach ($tokenProcessor->getRows() as $row) { + $resolvedTokens[$token][$row->context['contributionId']] = $row->render($token); + } + // We've resolved the value for each row - resorting to swapping them out + // with the old function. + $html_message = CRM_Utils_Token::token_replace('contribution', $token, implode($separator, $resolvedTokens[$token]), $html_message); + } } - $smarty = ['contact' => $contact]; - return CRM_Core_TokenSmarty::render(['html' => $html_message], $tokenContext, $smarty)['html']; + $tokenContext['contributionId'] = $contributionID; + return CRM_Core_TokenSmarty::render(['html' => $html_message], $tokenContext)['html']; } } diff --git a/CRM/Utils/Token.php b/CRM/Utils/Token.php index 992578e2f5..71a199c193 100644 --- a/CRM/Utils/Token.php +++ b/CRM/Utils/Token.php @@ -1636,6 +1636,8 @@ class CRM_Utils_Token { } /** + * Do not use - unused in core. + * * Replace Contribution tokens in html. * * @param string $str @@ -1644,6 +1646,8 @@ class CRM_Utils_Token { * @param string $knownTokens * @param bool|string $escapeSmarty * + * @deprecated + * * @return mixed */ public static function replaceContributionTokens($str, &$contribution, $html = FALSE, $knownTokens = NULL, $escapeSmarty = FALSE) { @@ -1685,9 +1689,12 @@ class CRM_Utils_Token { * @param array $contributions * @param array $knownTokens * + * @deprecated + * * @return string */ public static function replaceMultipleContributionTokens(string $separator, string $str, array $contributions, array $knownTokens): string { + CRM_Core_Error::deprecatedFunctionWarning('no alternative'); foreach ($knownTokens['contribution'] ?? [] as $token) { $resolvedTokens = []; foreach ($contributions as $contribution) { @@ -1778,11 +1785,15 @@ class CRM_Utils_Token { } /** + * Do not use - unused in core. + * * @param $token * @param $contribution * @param bool $html * @param bool $escapeSmarty * + * @deprecated + * * @return mixed|string * @throws \CRM_Core_Exception */ diff --git a/tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php b/tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php index 6cbc71de8e..54250b806d 100644 --- a/tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php +++ b/tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php @@ -48,7 +48,6 @@ class CRM_Contribute_Form_Task_PDFLetterCommonTest extends CiviUnitTestCase { * @throws \CRM_Core_Exception */ public function tearDown(): void { - CRM_Utils_Token::$_tokens['contribution'] = NULL; $this->quickCleanUpFinancialEntities(); $this->quickCleanup(['civicrm_uf_match', 'civicrm_campaign'], TRUE); CRM_Utils_Hook::singleton()->reset(); @@ -78,6 +77,7 @@ class CRM_Contribute_Form_Task_PDFLetterCommonTest extends CiviUnitTestCase { 'receive_date' => '2021-02-01 2:21', 'currency' => 'USD', ])['id']; + /* @var CRM_Contribute_Form_Task_PDFLetter $form */ $form = $this->getFormObject('CRM_Contribute_Form_Task_PDFLetter', [ 'campaign_id' => '', 'subject' => '', @@ -139,7 +139,7 @@ class CRM_Contribute_Form_Task_PDFLetterCommonTest extends CiviUnitTestCase { 'total_amount' => 6, 'campaign_id' => $this->campaignCreate(['title' => $campaignTitle], FALSE), 'financial_type_id' => 'Donation', - $customFieldKey => 'Text_' . substr(sha1(rand()), 0, 7), + $customFieldKey => 'Text_', ]; $contributionIDs = $returnProperties = []; $result = $this->callAPISuccess('Contribution', 'create', $params); @@ -301,15 +301,15 @@ total_amount : € 9,999.99 fee_amount : € 1,111.11 net_amount : € 7,777.78 non_deductible_amount : € 2,222.22 -receive_date : July 20th, 2018 12:00 AM +receive_date : July 20th, 2018 payment_instrument_id:label : Check trxn_id : 1234 invoice_id : 568 currency : EUR -cancel_date : December 30th, 2019 12:00 AM +cancel_date : December 30th, 2019 cancel_reason : Contribution Cancel Reason -receipt_date : October 30th, 2019 12:00 AM -thankyou_date : November 30th, 2019 12:00 AM +receipt_date : October 30th, 2019 +thankyou_date : November 30th, 2019 source : Contribution Source amount_level : Amount Level contribution_status_id : 2 -- 2.25.1