This removes the last function fromCRM/Contribute/Form/Task/PDFLetterCommon.php
The function was calling a protected function on the parent which had to be unravelled.
I used the method we used in
https://github.com/civicrm/civicrm-core/blob/
5e67eb7ff3f1f202d5112d15ad5c6a5f23f35795/CRM/SMS/Form/Upload.php#L341
to replace the code with the part that we have tested as being done in via render - ie replacing
hook, contact, domain tokens & smarty parsing.
However, there are quite a few tests on this code & one checked that we don't over-call
the token hook. I added some caching for the results of this hook so we can start to
eliminate these but I also allowed the calls to increment by 1 because it is not 1 per row
I made the results of this hook optional to replaceHookTokens & in general I think that
is the only place it needs to be called - perhaps once it used to pass more parameters &
the results were dynamic but now they really aren't
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, CRM_Contribute_Form_Task_PDFLetterCommon::resolveTokens($html_message, $contact, $contribution, $messageToken, $grouped, $separator, $groupedContributions));
+ $html = str_replace($separator, $realSeparator, $this->resolveTokens($html_message, $contact, $contribution, $messageToken, $grouped, $separator, $groupedContributions));
}
return $html;
return TRUE;
}
+ /**
+ *
+ * @param string $html_message
+ * @param array $contact
+ * @param array $contribution
+ * @param array $messageToken
+ * @param bool $grouped
+ * Does this letter represent more than one contribution.
+ * @param string $separator
+ * What is the preferred letter separator.
+ * @param array $contributions
+ *
+ * @return string
+ */
+ protected function resolveTokens(string $html_message, $contact, $contribution, $messageToken, $grouped, $separator, $contributions): string {
+ if ($grouped) {
+ $tokenHtml = CRM_Utils_Token::replaceMultipleContributionTokens($separator, $html_message, $contributions, $messageToken);
+ }
+ else {
+ // no change to normal behaviour to avoid risk of breakage
+ $tokenHtml = CRM_Utils_Token::replaceContributionTokens($html_message, $contribution, TRUE, $messageToken);
+ }
+ $useSmarty = (defined('CIVICRM_MAIL_SMARTY') && CIVICRM_MAIL_SMARTY);
+ return CRM_Core_BAO_MessageTemplate::renderMessageTemplate(['text' => '', 'html' => $tokenHtml, 'subject' => ''], !$useSmarty, $contact['contact_id'], ['contact' => $contact])['html'];
+ }
+
}
+++ /dev/null
-<?php
-
-/**
- * This class provides the common functionality for creating PDF letter for
- * one or a group of contact ids.
- */
-class CRM_Contribute_Form_Task_PDFLetterCommon extends CRM_Contact_Form_Task_PDFLetterCommon {
-
- /**
- *
- * @param string $html_message
- * @param array $contact
- * @param array $contribution
- * @param array $messageToken
- * @param bool $grouped
- * Does this letter represent more than one contribution.
- * @param string $separator
- * What is the preferred letter separator.
- * @param array $contributions
- *
- * @return string
- * @throws \CRM_Core_Exception
- */
- public static function resolveTokens(string $html_message, $contact, $contribution, $messageToken, $grouped, $separator, $contributions): string {
- $categories = CRM_Contact_Form_Task_PDFLetterCommon::getTokenCategories();
- $domain = CRM_Core_BAO_Domain::getDomain();
- $tokenHtml = CRM_Utils_Token::replaceDomainTokens($html_message, $domain, TRUE, $messageToken);
- $tokenHtml = CRM_Utils_Token::replaceContactTokens($tokenHtml, $contact, TRUE, $messageToken);
- if ($grouped) {
- $tokenHtml = CRM_Utils_Token::replaceMultipleContributionTokens($separator, $tokenHtml, $contributions, $messageToken);
- }
- else {
- // no change to normal behaviour to avoid risk of breakage
- $tokenHtml = CRM_Utils_Token::replaceContributionTokens($tokenHtml, $contribution, TRUE, $messageToken);
- }
- $tokenHtml = CRM_Utils_Token::replaceHookTokens($tokenHtml, $contact, $categories, TRUE);
- if (defined('CIVICRM_MAIL_SMARTY') && CIVICRM_MAIL_SMARTY) {
- $smarty = CRM_Core_Smarty::singleton();
- // also add the tokens to the template
- $smarty->assign_by_ref('contact', $contact);
- $tokenHtml = $smarty->fetch("string:$tokenHtml");
- }
- return $tokenHtml;
- }
-
-}
public static function &replaceHookTokens(
$str,
&$contact,
- &$categories,
+ $categories = NULL,
$html = FALSE,
$escapeSmarty = FALSE
) {
+ if (!$categories) {
+ $categories = self::getTokenCategories();
+ }
foreach ($categories as $key) {
$str = preg_replace_callback(
self::tokenRegex($key),
return $str;
}
+ /**
+ * Get the categories required for rendering tokens.
+ *
+ * @return array
+ */
+ public static function getTokenCategories(): array {
+ if (!isset(\Civi::$statics[__CLASS__]['token_categories'])) {
+ $tokens = [];
+ \CRM_Utils_Hook::tokens($tokens);
+ \Civi::$statics[__CLASS__]['token_categories'] = array_keys($tokens);
+ }
+ return \Civi::$statics[__CLASS__]['token_categories'];
+ }
+
/**
* Parse html through Smarty resolving any smarty functions.
* @param string $tokenHtml
* @throws TokenException
*/
public function onEvaluate(TokenValueEvent $e) {
- // For reasons unknown, replaceHookTokens requires a pre-computed list of
- // hook *categories* (aka entities aka namespaces). We'll cache
- // this in the TokenProcessor's context.
-
- $hookTokens = [];
- \CRM_Utils_Hook::tokens($hookTokens);
- $categories = array_keys($hookTokens);
- $e->getTokenProcessor()->context['hookTokenCategories'] = $categories;
+ // For reasons unknown, replaceHookTokens used to require a pre-computed list of
+ // hook *categories* (aka entities aka namespaces). We cache
+ // this in the TokenProcessor's context but can likely remove it now.
+
+ $e->getTokenProcessor()->context['hookTokenCategories'] = \CRM_Utils_Token::getTokenCategories();
$messageTokens = $e->getTokenProcessor()->getMessageTokens();
$returnProperties = array_fill_keys($messageTokens['contact'] ?? [], 1);
<td></td>
</tr>
<!--
- -->
+ -->
<tr>
<td><strong>Total</strong></td>
<td><strong>$ 100.00</strong></td>
<th>Source</th>
</tr>
<!--
- -->
+ -->
<tr>
<td>25 December 2016</td>
<td>$ 10.00</td>
$this->assertEquals($html[2], $activities['values'][1]['details']);
// Checking it is not called multiple times.
// once for each contact create + once for the activities.
- $this->assertEquals(3, $this->hookTokensCalled);
+ // & once for the token processor, for now.
+ // By calling the cached function we can get this down to 1
+ $this->assertEquals(4, $this->hookTokensCalled);
$this->mut->checkAllMailLog($html);
}