4 use Civi\Token\Event\TokenRenderEvent
;
5 use Civi\Token\Event\TokenValueEvent
;
7 use Symfony\Component\EventDispatcher\EventSubscriberInterface
;
10 * Class TokenCompatSubscriber
13 * This class handles the smarty processing of tokens.
15 class TokenCompatSubscriber
implements EventSubscriberInterface
{
20 public static function getSubscribedEvents(): array {
22 'civi.token.eval' => [
23 ['setupSmartyAliases', 1000],
25 'civi.token.render' => 'onRender',
30 * Interpret the variable `$context['smartyTokenAlias']` (e.g. `mySmartyField' => `tkn_entity.tkn_field`).
32 * We need to ensure that any tokens like `{tkn_entity.tkn_field}` are hydrated, so
33 * we pretend that they are in use.
35 * @param \Civi\Token\Event\TokenValueEvent $e
37 public function setupSmartyAliases(TokenValueEvent
$e) {
39 foreach ($e->getRows() as $row) {
40 $aliasedTokens = array_unique(array_merge($aliasedTokens,
41 array_values($row->context
['smartyTokenAlias'] ??
[])));
44 $fakeMessage = implode('', array_map(function ($f) {
45 return '{' . $f . '}';
48 $proc = $e->getTokenProcessor();
49 $proc->addMessage('TokenCompatSubscriber.aliases', $fakeMessage, 'text/plain');
53 * Apply the various CRM_Utils_Token helpers.
55 * @param \Civi\Token\Event\TokenRenderEvent $e
57 public function onRender(TokenRenderEvent
$e): void
{
58 $useSmarty = !empty($e->context
['smarty']);
59 $e->string = $e->getTokenProcessor()->visitTokens($e->string, function() {
60 // For historical consistency, we filter out unrecognized tokens.
64 // This removes the pattern used in greetings of having bits of text that
65 // depend on the tokens around them - ie '{first_name}{ }{last_name}
66 // has an extra construct '{ }' which will resolve as a space if the
67 // tokens on either side are resolved to 'something'
68 $e->string = preg_replace('/\\\\|\{(\s*)?\}/', ' ', $e->string);
72 foreach ($e->context
['smartyTokenAlias'] ??
[] as $smartyName => $tokenName) {
73 $smartyVars[$smartyName] = \CRM_Utils_Array
::pathGet($e->row
->tokens
, explode('.', $tokenName), $e->context
['locale'] ??
NULL);
74 if ($smartyVars[$smartyName] instanceof \Brick\Money\Money
) {
75 $smartyVars[$smartyName] = \Civi
::format()->money($smartyVars[$smartyName]->getAmount(), $smartyVars[$smartyName]->getCurrency());
78 \CRM_Core_Smarty
::singleton()->pushScope($smartyVars);
80 $e->string = \CRM_Utils_String
::parseOneOffStringThroughSmarty($e->string);
83 \CRM_Core_Smarty
::singleton()->popScope();