* @return string
* The processed string
*/
- public static function &token_replace($type, $var, $value, &$str, $escapeSmarty = FALSE) {
+ public static function token_replace($type, $var, $value, &$str, $escapeSmarty = FALSE) {
$token = preg_quote('{' . "$type.$var") . '(\|([^\}]+?))?' . preg_quote('}');
if (!$value) {
$value = '$3';
* regular expression sutiable for using in preg_replace
*/
private static function tokenRegex($token_type) {
- return '/(?<!\{|\\\\)\{' . $token_type . '\.([\w]+(\-[\w\s]+)?)\}(?!\})/';
+ return '/(?<!\{|\\\\)\{' . $token_type . '\.([\w]+:?\w*(\-[\w\s]+)?)\}(?!\})/';
}
/**
* @return string
* The processed string
*/
- public static function &replaceDomainTokens(
+ public static function replaceDomainTokens(
$str,
- &$domain,
+ $domain,
$html = FALSE,
$knownTokens = NULL,
$escapeSmarty = FALSE
$str = preg_replace_callback(
self::tokenRegex($key),
- function ($matches) use (&$domain, $html, $escapeSmarty) {
+ function ($matches) use ($domain, $html, $escapeSmarty) {
return CRM_Utils_Token::getDomainTokenReplacement($matches[1], $domain, $html, $escapeSmarty);
},
$str
}
/**
- * @param $token
+ * @param string $token
* @param CRM_Core_BAO_Domain $domain
* @param bool $html
* @param bool $escapeSmarty
*
- * @return mixed|null|string
+ * @return null|string
*/
- public static function getDomainTokenReplacement($token, &$domain, $html = FALSE, $escapeSmarty = FALSE) {
+ public static function getDomainTokenReplacement($token, $domain, $html = FALSE, $escapeSmarty = FALSE): ?string {
// check if the token we were passed is valid
// we have to do this because this function is
// called only when we find a token in the string
if (!in_array($token, self::$_tokens['domain'])) {
$value = "{domain.$token}";
}
- elseif ($token == 'address') {
- static $addressCache = [];
+ elseif ($token === 'address') {
+ $cacheKey = __CLASS__ . 'address_token_cache' . CRM_Core_Config::domainID();
+ $addressCache = Civi::cache()->has($cacheKey) ? Civi::cache()->get($cacheKey) : [];
- $cache_key = $html ? 'address-html' : 'address-text';
- if (array_key_exists($cache_key, $addressCache)) {
- return $addressCache[$cache_key];
+ $fieldKey = $html ? 'address-html' : 'address-text';
+ if (array_key_exists($fieldKey, $addressCache)) {
+ return $addressCache[$fieldKey];
}
$value = NULL;
if (!empty($loc[$token])) {
if ($html) {
- $value = $loc[$token][1]['display'];
- $value = str_replace("\n", '<br />', $value);
+ $value = str_replace("\n", '<br />', $loc[$token][1]['display']);
}
else {
$value = $loc[$token][1]['display_text'];
}
- $addressCache[$cache_key] = $value;
+ Civi::cache()->set($cacheKey, $addressCache);
}
}
- elseif ($token == 'name' || $token == 'id' || $token == 'description') {
+ elseif ($token === 'name' || $token === 'id' || $token === 'description') {
$value = $domain->$token;
}
- elseif ($token == 'phone' || $token == 'email') {
+ elseif ($token === 'phone' || $token === 'email') {
// Construct the phone and email tokens
$value = NULL;
/**
* Replace all the org-level tokens in $str
*
- * @fixme: This function appears to be broken, as it depends on
+ * @fixme: This function appears to be broken, as it depended on
* nonexistant method: CRM_Core_BAO_CustomValue::getContactValues()
- * Marking as deprecated until this is fixed
+ * Marking as deprecated until this is clarified.
+ *
* @deprecated
+ * - the above hard-breakage was there from 2015 to 2021 and
+ * no error was ever reported on it -does that mean
+ * 1) the code is never hit because the only function that
+ * calls this function is never called or
+ * 2) it was called but never required to resolve any tokens
+ * or more specifically custom field tokens
+ *
+ * The handling for custom fields with the removed token has
+ * now been removed.
*
* @param string $str
* The string with tokens to be replaced.
* @return string
* The processed string
*/
- public static function &replaceOrgTokens($str, &$org, $html = FALSE, $escapeSmarty = FALSE) {
+ public static function replaceOrgTokens($str, &$org, $html = FALSE, $escapeSmarty = FALSE) {
self::$_tokens['org']
= array_merge(
array_keys(CRM_Contact_BAO_Contact::importableFields('Organization')),
['address', 'display_name', 'checksum', 'contact_id']
);
- $cv = NULL;
foreach (self::$_tokens['org'] as $token) {
// print "Getting token value for $token<br/><br/>";
- if ($token == '') {
+ if ($token === '') {
continue;
}
$value = NULL;
- if ($cfID = CRM_Core_BAO_CustomField::getKeyID($token)) {
- // only generate cv if we need it
- if ($cv === NULL) {
- $cv = CRM_Core_BAO_CustomValue::getContactValues($org['contact_id']);
- }
- foreach ($cv as $cvFieldID => $value) {
- if ($cvFieldID == $cfID) {
- $value = CRM_Core_BAO_CustomField::displayValue($value, $cfID);
- break;
- }
- }
- }
- elseif ($token == 'checksum') {
+ if ($token === 'checksum') {
$cs = CRM_Contact_BAO_Contact_Utils::generateChecksum($org['contact_id']);
$value = "cs={$cs}";
}
- elseif ($token == 'address') {
+ elseif ($token === 'address') {
// Build the location values array
$loc = [];
* @return string
* The processed string
*/
- public static function &replaceContactTokens(
+ public static function replaceContactTokens(
$str,
&$contact,
$html = FALSE,
$value = "cs={$cs}";
}
else {
- $value = CRM_Utils_Array::retrieveValueRecursive($contact, $token);
+ $value = (array) CRM_Utils_Array::retrieveValueRecursive($contact, $token);
- // FIXME: for some pseudoconstants we get array ( 0 => id, 1 => label )
- if (is_array($value)) {
- $value = $value[1];
- }
- // Convert pseudoconstants using metadata
- elseif ($value && is_numeric($value)) {
- $allFields = CRM_Contact_BAO_Contact::exportableFields('All');
- if (!empty($allFields[$token]['pseudoconstant'])) {
- $value = CRM_Core_PseudoConstant::getLabel('CRM_Contact_BAO_Contact', $token, $value);
- }
- }
- elseif ($value && CRM_Utils_String::endsWith($token, '_date')) {
- $value = CRM_Utils_Date::customFormat($value);
+ foreach ($value as $index => $item) {
+ $value[$index] = self::convertPseudoConstantsUsingMetadata($value[$index], $token);
}
+ $value = implode(', ', $value);
}
if (!$html) {
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
public static function getTokens($string) {
$matches = [];
$tokens = [];
- preg_match_all('/(?<!\{|\\\\)\{(\w+\.\w+)\}(?!\})/',
+ preg_match_all('/(?<!\{|\\\\)\{(\w+\.\w+:?\w*)\}(?!\})/',
$string,
$matches,
PREG_PATTERN_ORDER
* @param bool $skipDeceased Don't return deceased contact info.
* Don't return deceased contact info.
* @param array $extraParams
- * Extra params.
+ * Extra params - DEPRECATED
* @param array $tokens
* The list of tokens we've extracted from the content.
* @param string|null $className
}
if ($extraParams) {
+ CRM_Core_Error::deprecatedWarning('Passing $extraParams to getTokenDetails() is not supported and will be removed in a future version');
$params = array_merge($params, $extraParams);
}
if (!empty($contactDetails[$contactID]['preferred_communication_method'])
) {
$communicationPreferences = [];
- foreach ($contactDetails[$contactID]['preferred_communication_method'] as $val) {
+ foreach ((array) $contactDetails[$contactID]['preferred_communication_method'] as $val) {
if ($val) {
$communicationPreferences[$val] = CRM_Core_PseudoConstant::getLabel('CRM_Contact_DAO_Contact', 'preferred_communication_method', $val);
}
protected static function _buildContributionTokens() {
$key = 'contribution';
- if (self::$_tokens[$key] == NULL) {
- self::$_tokens[$key] = array_keys(array_merge(CRM_Contribute_BAO_Contribution::exportableFields('All'),
- ['campaign', 'financial_type'],
- self::getCustomFieldTokens('Contribution')
- ));
+
+ if (!isset(Civi::$statics[__CLASS__][__FUNCTION__][$key])) {
+ $processor = new CRM_Contribute_Tokens();
+ $tokens = array_merge(CRM_Contribute_BAO_Contribution::exportableFields('All'),
+ ['campaign' => [], 'financial_type' => [], 'payment_instrument' => []],
+ self::getCustomFieldTokens('Contribution'),
+ $processor->getPseudoTokens()
+ );
+ foreach ($tokens as $token) {
+ if (!empty($token['name'])) {
+ $tokens[$token['name']] = [];
+ }
+ }
+ Civi::$statics[__CLASS__][__FUNCTION__][$key] = array_keys($tokens);
}
+ self::$_tokens[$key] = Civi::$statics[__CLASS__][__FUNCTION__][$key];
}
/**
//early return
return $str;
}
- self::_buildContributionTokens();
// here we intersect with the list of pre-configured valid tokens
// so that we remove anything we do not recognize
return $output;
}
+ /**
+ * @param $value
+ * @param $token
+ *
+ * @return bool|int|mixed|string|null
+ */
+ protected static function convertPseudoConstantsUsingMetadata($value, $token) {
+ // Convert pseudoconstants using metadata
+ if ($value && is_numeric($value)) {
+ $allFields = CRM_Contact_BAO_Contact::exportableFields('All');
+ if (!empty($allFields[$token]['pseudoconstant'])) {
+ $value = CRM_Core_PseudoConstant::getLabel('CRM_Contact_BAO_Contact', $token, $value);
+ }
+ }
+ elseif ($value && CRM_Utils_String::endsWith($token, '_date')) {
+ $value = CRM_Utils_Date::customFormat($value);
+ }
+ return $value;
+ }
+
+ /**
+ * Get token deprecation information.
+ *
+ * @return array
+ */
+ public static function getTokenDeprecations(): array {
+ return [
+ 'WorkFlowMessageTemplates' => [
+ 'contribution_invoice_receipt' => [
+ '$display_name' => 'contact.display_name',
+ ],
+ ],
+ ];
+ }
+
}