Convert Smarty & domain token processing to use token processor
authoreileen <emcnaughton@wikimedia.org>
Sat, 6 Feb 2021 03:36:45 +0000 (16:36 +1300)
committereileen <emcnaughton@wikimedia.org>
Mon, 15 Feb 2021 03:39:40 +0000 (16:39 +1300)
This is a subset of the changes in
https://github.com/civicrm/civicrm-core/pull/19550 that we should be able to resolve
& merge while addressing that takes longer. It still gets us the
benefit of adopting a preferred pattern

Note that some test changes exist around handling of subject -
the code now converts a new line to a space consistently. In addition
tests that rely on leakage have been altered as smarty does not leak with
this approach

CRM/Core/BAO/MessageTemplate.php
tests/phpunit/CRM/Core/BAO/MessageTemplateTest.php
tests/phpunit/CRM/Event/Form/Registration/ConfirmTest.php
tests/phpunit/api/v3/ContributionTest.php

index 2b217a834bccca0f9c5743d69648b068279efd0b..e64e2639a9254fd4725b447aad42161d8b97cb54 100644 (file)
@@ -9,6 +9,8 @@
  +--------------------------------------------------------------------+
  */
 
+use Civi\Token\TokenProcessor;
+
 /**
  *
  * @package CRM
@@ -425,7 +427,7 @@ class CRM_Core_BAO_MessageTemplate extends CRM_Core_DAO_MessageTemplate {
       $mailContent['subject'] = $params['subject'];
     }
 
-    $mailContent = self::renderMessageTemplate($mailContent, $params['disableSmarty'], $params['contactId'] ?? NULL, $params['tplParams']);
+    $mailContent = self::renderMessageTemplate($mailContent, (bool) $params['disableSmarty'], $params['contactId'] ?? NULL, $params['tplParams']);
 
     // send the template, honouring the target user’s preferences (if any)
     $sent = FALSE;
@@ -692,35 +694,33 @@ class CRM_Core_BAO_MessageTemplate extends CRM_Core_DAO_MessageTemplate {
    *
    * @param array $mailContent
    * @param bool $disableSmarty
-   * @param int $contactID
+   * @param int|NULL $contactID
    * @param array $smartyAssigns
    *
    * @return array
-   * @throws \CRM_Core_Exception
    */
-  public static function renderMessageTemplate(array $mailContent, $disableSmarty, $contactID, $smartyAssigns): array {
-    $tokens = self::getTokensToResolve($mailContent);
-
-    // When using Smarty we need to pass the $escapeSmarty parameter.
-    $escapeSmarty = !$disableSmarty;
-
-    $mailContent = self::resolveDomainTokens($mailContent, $tokens, $escapeSmarty);
-
+  public static function renderMessageTemplate(array $mailContent, bool $disableSmarty, $contactID, array $smartyAssigns): array {
     if ($contactID) {
-      $mailContent = self::resolveContactTokens($contactID, $tokens, $mailContent, $escapeSmarty);
+      // @todo resolve contact ID below - see https://github.com/civicrm/civicrm-core/pull/19550
+      // for things to resolve first.
+      $tokens = self::getTokensToResolve($mailContent);
+      $mailContent = self::resolveContactTokens($contactID, $tokens, $mailContent, !$disableSmarty);
     }
-
-    // Normally Smarty is run, but it can be disabled using the disableSmarty
-    // parameter, which may be useful for non-core uses of MessageTemplate.send
-    // In particular it helps with the mosaicomsgtpl extension.
-    if (!$disableSmarty) {
-      $mailContent = self::parseThroughSmarty($mailContent, $smartyAssigns);
-    }
-    else {
-      // Since we're not relying on Smarty for this function, we DIY.
-      // strip whitespace from ends and turn into a single line
-      $mailContent['subject'] = trim(preg_replace('/[\r\n]+/', ' ', $mailContent['subject']));
+    CRM_Core_Smarty::singleton()->pushScope($smartyAssigns);
+    $tokenProcessor = new TokenProcessor(\Civi::dispatcher(), ['smarty' => !$disableSmarty]);
+    $tokenProcessor->addMessage('html', $mailContent['html'], 'text/html');
+    $tokenProcessor->addMessage('text', $mailContent['text'], 'text/plain');
+    $tokenProcessor->addMessage('subject', $mailContent['subject'], 'text/plain');
+    $tokenProcessor->addRow([]);
+    $tokenProcessor->evaluate();
+    foreach ($tokenProcessor->getRows() as $row) {
+      $mailContent['html'] = $row->render('html');
+      $mailContent['text'] = $row->render('text');
+      $mailContent['subject'] = $row->render('subject');
     }
+    CRM_Core_Smarty::singleton()->popScope();
+
+    $mailContent['subject'] = trim(preg_replace('/[\r\n]+/', ' ', $mailContent['subject']));
     return $mailContent;
   }
 
index 4ab571b5c58b1738533e3a5b17c4fb13e7aa4a3c..5ca3f5ed2db6ca1c5e2bef46abd85ad53a2c2122 100644 (file)
@@ -92,7 +92,7 @@ class CRM_Core_BAO_MessageTemplateTest extends CiviUnitTestCase {
 Up the road
 London, 90210
  ~ crown@example.com ~ 1 ~ rather nice', $messageContent['text']);
-    $this->assertEquals('Default Domain Name ~  ~ Buckingham palaceUp the roadLondon, 90210~ crown@example.com ~ 1 ~ rather nice', $messageContent['subject']);
+    $this->assertEquals('Default Domain Name ~  ~ Buckingham palace Up the road London, 90210  ~ crown@example.com ~ 1 ~ rather nice', $messageContent['subject']);
   }
 
   /**
@@ -246,7 +246,7 @@ contact_id:' . $tokenData['contact_id'] . '
 ';
     $this->assertEquals($expected, $messageContent['html']);
     $this->assertEquals($expected, $messageContent['text']);
-    $this->assertEquals(str_replace("\n", '', $expected), $messageContent['subject']);
+    $this->assertEquals(rtrim(str_replace("\n", ' ', $expected)), $messageContent['subject']);
   }
 
   /**
index 7278eacafc1de7e516d0c5f47fc63d04f8efb12c..0411a6da6b2a3063b0a1063890ea78bdf81b5a51 100644 (file)
@@ -20,7 +20,7 @@ class CRM_Event_Form_Registration_ConfirmTest extends CiviUnitTestCase {
    *
    * @throws \Exception
    */
-  public function testSubmit() {
+  public function testSubmit(): void {
     $event = $this->eventCreate();
     $mut = new CiviMailUtils($this, TRUE);
     CRM_Event_Form_Registration_Confirm::testSubmit([
@@ -77,15 +77,11 @@ class CRM_Event_Form_Registration_ConfirmTest extends CiviUnitTestCase {
       ],
     ]);
 
-    $participant = $this->callAPISuccessGetSingle('Participant', []);
     $mut->checkMailLog([
       'Dear Logged In,  Thank you for your registration.  This is a confirmation that your registration has been received and your status has been updated to Registered.',
     ]);
     $mut->stop();
     $mut->clearMessages();
-    $tplVars = CRM_Core_Smarty::singleton()->get_template_vars();
-    $this->assertEquals($participant['id'], $tplVars['participantID']);
-
   }
 
   /**
@@ -486,8 +482,6 @@ class CRM_Event_Form_Registration_ConfirmTest extends CiviUnitTestCase {
     $mut->checkMailLog(['Comment: ' . $event['note'] . chr(0x0A)]);
     $mut->stop();
     $mut->clearMessages();
-    $tplVars = CRM_Core_Smarty::singleton()->get_template_vars();
-    $this->assertEquals($participant['id'], $tplVars['participantID']);
     //return ['contact_id' => $contact_id, 'participant_id' => $participant['id']];
     return [$contact_id, $participant['id']];
   }
@@ -557,13 +551,17 @@ class CRM_Event_Form_Registration_ConfirmTest extends CiviUnitTestCase {
    * /dev/event#10
    * Test submission with a note in the profile, ensuring the confirmation
    * email reflects the submitted value
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
+   * @throws \Exception
    */
-  public function testNoteSubmission() {
+  public function testNoteSubmission(): void {
     //create an event with an attached profile containing a note
     $event = $this->creatEventWithProfile(NULL);
-    $event['custom_pre_id'] = $this->ids["UFGroup"]["our profile"];
+    $event['custom_pre_id'] = $this->ids['UFGroup']['our profile'];
     $event['note'] = 'This is note 1';
-    list($contact_id, $participant_id) = $this->submitWithNote($event, NULL);
+    [$contact_id, $participant_id] = $this->submitWithNote($event, NULL);
     civicrm_api3('Participant', 'delete', ['id' => $participant_id]);
 
     //now that the contact has one note, register this contact again with a different note
@@ -571,7 +569,7 @@ class CRM_Event_Form_Registration_ConfirmTest extends CiviUnitTestCase {
     $event = $this->creatEventWithProfile($event);
     $event['custom_pre_id'] = $this->ids["UFGroup"]["our profile"];
     $event['note'] = 'This is note 2';
-    list($contact_id, $participant_id) = $this->submitWithNote($event, $contact_id);
+    [$contact_id, $participant_id] = $this->submitWithNote($event, $contact_id);
     civicrm_api3('Participant', 'delete', ['id' => $participant_id]);
 
     //finally, submit a blank note and confirm that the note shown in the email is blank
index 3696a1c2a4bf5c28a8355e557df604151138e2a0..c3f95ad348edee379bd30be54d7317d2f47593be 100644 (file)
@@ -3666,9 +3666,8 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
    * Test sending a mail via the API.
    *
    * @throws \CRM_Core_Exception
-   * @throws \CiviCRM_API3_Exception
    */
-  public function testSendMail() {
+  public function testSendMail(): void {
     $mut = new CiviMailUtils($this, TRUE);
     $orderParams = $this->_params;
     $orderParams['contribution_status_id'] = 'Pending';
@@ -3698,7 +3697,6 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
     $mut->stop();
     $tplVars = CRM_Core_Smarty::singleton()->get_template_vars();
     $this->assertEquals('bob', $tplVars['billingName']);
-    $this->assertEquals("bob\nblah\n", $tplVars['address']);
   }
 
   /**