Merge pull request #22560 from eileenmcnaughton/fin_type
[civicrm-core.git] / Civi / Token / TokenCompatSubscriber.php
1 <?php
2 namespace Civi\Token;
3
4 use Civi\Token\Event\TokenRenderEvent;
5 use Civi\Token\Event\TokenValueEvent;
6 use Money\Money;
7 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
8
9 /**
10 * Class TokenCompatSubscriber
11 * @package Civi\Token
12 *
13 * This class handles the smarty processing of tokens.
14 */
15 class TokenCompatSubscriber implements EventSubscriberInterface {
16
17 /**
18 * @inheritDoc
19 */
20 public static function getSubscribedEvents(): array {
21 return [
22 'civi.token.eval' => [
23 ['setupSmartyAliases', 1000],
24 ],
25 'civi.token.render' => 'onRender',
26 ];
27 }
28
29 /**
30 * Interpret the variable `$context['smartyTokenAlias']` (e.g. `mySmartyField' => `tkn_entity.tkn_field`).
31 *
32 * We need to ensure that any tokens like `{tkn_entity.tkn_field}` are hydrated, so
33 * we pretend that they are in use.
34 *
35 * @param \Civi\Token\Event\TokenValueEvent $e
36 */
37 public function setupSmartyAliases(TokenValueEvent $e) {
38 $aliasedTokens = [];
39 foreach ($e->getRows() as $row) {
40 $aliasedTokens = array_unique(array_merge($aliasedTokens,
41 array_values($row->context['smartyTokenAlias'] ?? [])));
42 }
43
44 $fakeMessage = implode('', array_map(function ($f) {
45 return '{' . $f . '}';
46 }, $aliasedTokens));
47
48 $proc = $e->getTokenProcessor();
49 $proc->addMessage('TokenCompatSubscriber.aliases', $fakeMessage, 'text/plain');
50 }
51
52 /**
53 * Apply the various CRM_Utils_Token helpers.
54 *
55 * @param \Civi\Token\Event\TokenRenderEvent $e
56 */
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.
61 return '';
62 });
63
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);
69
70 if ($useSmarty) {
71 $smartyVars = [];
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());
76 }
77 }
78 \CRM_Core_Smarty::singleton()->pushScope($smartyVars);
79 try {
80 $e->string = \CRM_Utils_String::parseOneOffStringThroughSmarty($e->string);
81 }
82 finally {
83 \CRM_Core_Smarty::singleton()->popScope();
84 }
85 }
86 }
87
88 }