From a4965e0c7127093c6b5cbf13d41661e3dbf2e081 Mon Sep 17 00:00:00 2001 From: eileen Date: Mon, 18 Jan 2021 14:37:13 +1300 Subject: [PATCH 1/2] dev/core#2303 Extract function to load the messageContent for a template This is a fairly straightforward extraction, seeking to break down the very-busy sendtemplate function into the sub-functions within it. Essentially we load the template content, we swap out the tokens and we send it. Note that I have added a parameter to the output sent to alterMailContent of 'workflow_name' which is more accurate - I will update the docs --- CRM/Core/BAO/MessageTemplate.php | 124 +++++++++++++--------- tests/phpunit/api/v3/ContributionTest.php | 10 +- 2 files changed, 80 insertions(+), 54 deletions(-) diff --git a/CRM/Core/BAO/MessageTemplate.php b/CRM/Core/BAO/MessageTemplate.php index 922fbbd26a13..72395333019b 100644 --- a/CRM/Core/BAO/MessageTemplate.php +++ b/CRM/Core/BAO/MessageTemplate.php @@ -261,7 +261,7 @@ public static function sendReminder($contactId, $email, $messageTemplateID, $fro $returnProperties[$value] = 1; } } - list($details) = CRM_Utils_Token::getTokenDetails([$contactId], + [$details] = CRM_Utils_Token::getTokenDetails([$contactId], $returnProperties, NULL, NULL, FALSE, $tokens, @@ -413,56 +413,11 @@ public static function sendTemplate($params) { } CRM_Utils_Hook::alterMailParams($params, 'messageTemplate'); - - if (!$params['valueName'] && !$params['messageTemplateID']) { - throw new CRM_Core_Exception(ts("Message template's option value or ID missing.")); - } - - $apiCall = MessageTemplate::get(FALSE) - ->addSelect('msg_subject', 'msg_text', 'msg_html', 'pdf_format_id', 'id') - ->addWhere('is_default', '=', 1); - - if ($params['messageTemplateID']) { - $apiCall->addWhere('id', '=', (int) $params['messageTemplateID']); - } - else { - $apiCall->addWhere('workflow_name', '=', $params['valueName']); - } - $messageTemplate = $apiCall->execute()->first(); - - if (empty($messageTemplate['id'])) { - if ($params['messageTemplateID']) { - throw new CRM_Core_Exception(ts('No such message template: id=%1.', [1 => $params['messageTemplateID']])); - } - throw new CRM_Core_Exception(ts('No message template with workflow name %2.', [2 => $params['valueName']])); - } - - $mailContent = [ - 'subject' => $messageTemplate['msg_subject'], - 'text' => $messageTemplate['msg_text'], - 'html' => $messageTemplate['msg_html'], - 'format' => $messageTemplate['pdf_format_id'], - // Group name is a deprecated parameter. At some point it will not be passed out. - // https://github.com/civicrm/civicrm-core/pull/17180 - 'groupName' => $params['groupName'] ?? NULL, - 'valueName' => $params['valueName'], - 'messageTemplateID' => $params['messageTemplateID'], - ]; - - CRM_Utils_Hook::alterMailContent($mailContent); - - // add the test banner (if requested) - if ($params['isTest']) { - $query = "SELECT msg_subject subject, msg_text text, msg_html html - FROM civicrm_msg_template mt - WHERE workflow_name = 'test_preview' AND mt.is_default = 1"; - $testDao = CRM_Core_DAO::executeQuery($query); - $testDao->fetch(); - - $mailContent['subject'] = $testDao->subject . $mailContent['subject']; - $mailContent['text'] = $testDao->text . $mailContent['text']; - $mailContent['html'] = preg_replace('/html}", $mailContent['html']); + if (!is_int($params['messageTemplateID']) && !is_null($params['messageTemplateID'])) { + CRM_Core_Error::deprecatedWarning('message template id should be an integer'); + $params['messageTemplateID'] = (int) $params['messageTemplateID']; } + $mailContent = self::loadTemplate((string) $params['valueName'], $params['isTest'], $params['messageTemplateID'] ?? NULL, $params['groupName'] ?? ''); // Overwrite subject from form field if (!empty($params['subject'])) { @@ -506,7 +461,7 @@ public static function sendTemplate($params) { // effectively comment out this next (performance-expensive) line // but unfortunately testing is a bit think on the ground to that needs to // be added. - list($contact) = CRM_Utils_Token::getTokenDetails($contactParams, + [$contact] = CRM_Utils_Token::getTokenDetails($contactParams, $returnProperties, FALSE, FALSE, NULL, CRM_Utils_Token::flattenTokens($tokens), @@ -640,4 +595,71 @@ protected static function getWorkflowNameIdMap() { ])->fetchMap('name', 'id'); } + /** + * Load the specified template. + * + * @param string $workflowName + * @param bool $isTest + * @param int|null $messageTemplateID + * @param string $groupName + * + * @return array + * @throws \API_Exception + * @throws \CRM_Core_Exception + */ + protected static function loadTemplate(string $workflowName, bool $isTest, int $messageTemplateID = NULL, $groupName = NULL): array { + if (!$workflowName && !$messageTemplateID) { + throw new CRM_Core_Exception(ts("Message template's option value or ID missing.")); + } + + $apiCall = MessageTemplate::get(FALSE) + ->addSelect('msg_subject', 'msg_text', 'msg_html', 'pdf_format_id', 'id') + ->addWhere('is_default', '=', 1); + + if ($messageTemplateID) { + $apiCall->addWhere('id', '=', (int) $messageTemplateID); + } + else { + $apiCall->addWhere('workflow_name', '=', $workflowName); + } + $messageTemplate = $apiCall->execute()->first(); + if (empty($messageTemplate['id'])) { + if ($messageTemplateID) { + throw new CRM_Core_Exception(ts('No such message template: id=%1.', [1 => $messageTemplateID])); + } + throw new CRM_Core_Exception(ts('No message template with workflow name %2.', [2 => $workflowName])); + } + + $mailContent = [ + 'subject' => $messageTemplate['msg_subject'], + 'text' => $messageTemplate['msg_text'], + 'html' => $messageTemplate['msg_html'], + 'format' => $messageTemplate['pdf_format_id'], + 'workflow_name' => $workflowName, + // Note messageTemplateID is the id but when present we also know it was specifically requested. + 'messageTemplateID' => $messageTemplateID, + // Group name & valueName are deprecated parameters. At some point it will not be passed out. + // https://github.com/civicrm/civicrm-core/pull/17180 + 'groupName' => $groupName, + 'valueName' => $workflowName, + ]; + + CRM_Utils_Hook::alterMailContent($mailContent); + + // add the test banner (if requested) + if ($isTest) { + $testText = MessageTemplate::get(FALSE) + ->setSelect(['msg_subject', 'msg_text', 'msg_html']) + ->addWhere('workflow_name', '=', 'test_preview') + ->addWhere('is_default', '=', TRUE) + ->execute()->first(); + + $mailContent['subject'] = $testText['msg_subject'] . $mailContent['subject']; + $mailContent['text'] = $testText['msg_text'] . $mailContent['text']; + $mailContent['html'] = preg_replace('/_params['is_test'] = 1; $originalContribution = $this->setUpRepeatTransaction(['is_test' => 1], 'single'); $this->callAPISuccess('contribution', 'repeattransaction', [ 'original_contribution_id' => $originalContribution['id'], 'contribution_status_id' => 'Completed', - 'trxn_id' => uniqid(), + 'trxn_id' => '1234', ]); $this->callAPISuccessGetCount('Contribution', ['contribution_test' => 1], 2); } /** * Test repeat contribution passed in status. + * + * @throws \CRM_Core_Exception */ - public function testRepeatTransactionPassedInStatus() { + public function testRepeatTransactionPassedInStatus(): void { $originalContribution = $this->setUpRepeatTransaction($recurParams = [], 'single'); $this->callAPISuccess('contribution', 'repeattransaction', [ From 87c4c149513b9dee5c12ae6c29262124bae9d031 Mon Sep 17 00:00:00 2001 From: eileen Date: Tue, 19 Jan 2021 09:18:37 +1300 Subject: [PATCH 2/2] Add in-code notes about the workflow_name --- CRM/Core/BAO/MessageTemplate.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CRM/Core/BAO/MessageTemplate.php b/CRM/Core/BAO/MessageTemplate.php index 72395333019b..1904d750cafa 100644 --- a/CRM/Core/BAO/MessageTemplate.php +++ b/CRM/Core/BAO/MessageTemplate.php @@ -635,6 +635,11 @@ protected static function loadTemplate(string $workflowName, bool $isTest, int $ 'text' => $messageTemplate['msg_text'], 'html' => $messageTemplate['msg_html'], 'format' => $messageTemplate['pdf_format_id'], + // Workflow name is the field in the message templates table that denotes the + // workflow the template is used for. This is intended to eventually + // replace the non-standard option value/group implementation - see + // https://github.com/civicrm/civicrm-core/pull/17227 and the longer + // discussion on https://github.com/civicrm/civicrm-core/pull/17180 'workflow_name' => $workflowName, // Note messageTemplateID is the id but when present we also know it was specifically requested. 'messageTemplateID' => $messageTemplateID,