| 1 | <?php |
| 2 | /* |
| 3 | +--------------------------------------------------------------------+ |
| 4 | | Copyright CiviCRM LLC. All rights reserved. | |
| 5 | | | |
| 6 | | This work is published under the GNU AGPLv3 license with some | |
| 7 | | permitted exceptions and without any warranty. For full license | |
| 8 | | and copyright information, see https://civicrm.org/licensing | |
| 9 | +--------------------------------------------------------------------+ |
| 10 | */ |
| 11 | |
| 12 | use Civi\Token\TokenProcessor; |
| 13 | |
| 14 | /** |
| 15 | * `Token-Smarty` is a hybrid template format, combining Civi token notation with |
| 16 | * Smarty notation, as in `{if {contact.id} > 10}...{/if}`. |
| 17 | * |
| 18 | * NOTE: It is arguable about whether the existence of this format is a good thing, |
| 19 | * but it does exist, and this helper makes it a little easier to work with. |
| 20 | */ |
| 21 | class CRM_Core_TokenSmarty { |
| 22 | |
| 23 | /** |
| 24 | * Render some template(s), evaluating token expressions and Smarty expressions. |
| 25 | * |
| 26 | * This helper simplifies usage of hybrid notation. As a simplification, it may not be optimal for processing |
| 27 | * large batches (e.g. CiviMail or scheduled-reminders), but it's a little more convenient for 1-by-1 use-cases. |
| 28 | * |
| 29 | * @param array $messages |
| 30 | * Message templates. Any mix of the following templates ('text', 'html', 'subject', 'msg_text', 'msg_html', 'msg_subject'). |
| 31 | * Ex: ['subject' => 'Hello {contact.display_name}', 'text' => 'What up?']. |
| 32 | * Note: The content-type may be inferred by default. A key like 'html' or 'msg_html' indicates HTML formatting; any other key indicates text formatting. |
| 33 | * @param array $tokenContext |
| 34 | * Ex: ['contactId' => 123, 'activityId' => 456] |
| 35 | * @param array|null $smartyAssigns |
| 36 | * List of data to export via Smarty. |
| 37 | * Data is only exported temporarily (long enough to execute this render() method). |
| 38 | * @return array |
| 39 | * Rendered messages. These match the various inputted $messages. |
| 40 | * Ex: ['msg_subject' => 'Hello Bob Roberts', 'msg_text' => 'What up?'] |
| 41 | * @internal |
| 42 | */ |
| 43 | public static function render(array $messages, array $tokenContext = [], array $smartyAssigns = []): array { |
| 44 | $result = []; |
| 45 | $tokenContextDefaults = [ |
| 46 | 'controller' => __CLASS__, |
| 47 | 'smarty' => TRUE, |
| 48 | ]; |
| 49 | $tokenProcessor = new TokenProcessor(\Civi::dispatcher(), array_merge($tokenContextDefaults, $tokenContext)); |
| 50 | $tokenProcessor->addRow([]); |
| 51 | $useSmarty = !empty($tokenProcessor->context['smarty']); |
| 52 | |
| 53 | // Load templates |
| 54 | foreach ($messages as $messageId => $messageTpl) { |
| 55 | $format = preg_match('/html/', $messageId) ? 'text/html' : 'text/plain'; |
| 56 | $tokenProcessor->addMessage($messageId, $messageTpl, $format); |
| 57 | } |
| 58 | |
| 59 | // Evaluate/render templates |
| 60 | try { |
| 61 | if ($useSmarty) { |
| 62 | CRM_Core_Smarty::singleton()->pushScope($smartyAssigns); |
| 63 | } |
| 64 | $tokenProcessor->evaluate(); |
| 65 | foreach ($messages as $messageId => $ign) { |
| 66 | foreach ($tokenProcessor->getRows() as $row) { |
| 67 | $result[$messageId] = $row->render($messageId); |
| 68 | } |
| 69 | } |
| 70 | } |
| 71 | finally { |
| 72 | if ($useSmarty) { |
| 73 | CRM_Core_Smarty::singleton()->popScope(); |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | return $result; |
| 78 | } |
| 79 | |
| 80 | } |