From 2a55af8e4b2d450e919a3a0aef9c3cb33071477c Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Fri, 20 May 2022 14:53:12 +1200 Subject: [PATCH] dev/core#3177 Switch sms to use flexmailer token rendering --- CRM/Mailing/BAO/MailingJob.php | 19 +-- CRM/Mailing/BAO/SMSJob.php | 108 ++++++++++++++++++ CRM/Mailing/Page/View.php | 2 +- CRM/SMS/Provider.php | 32 ------ ext/flexmailer/src/API/MailingPreview.php | 2 +- .../src/Listener/DefaultComposer.php | 2 +- tests/phpunit/CRM/SMS/PreviewTest.php | 8 +- 7 files changed, 117 insertions(+), 56 deletions(-) create mode 100644 CRM/Mailing/BAO/SMSJob.php diff --git a/CRM/Mailing/BAO/MailingJob.php b/CRM/Mailing/BAO/MailingJob.php index 8ce0203223..6457ba2c67 100644 --- a/CRM/Mailing/BAO/MailingJob.php +++ b/CRM/Mailing/BAO/MailingJob.php @@ -67,7 +67,7 @@ class CRM_Mailing_BAO_MailingJob extends CRM_Mailing_DAO_MailingJob { * @return bool|null */ public static function runJobs($testParams = NULL, $mode = NULL) { - $job = new CRM_Mailing_BAO_MailingJob(); + $job = $mode === 'sms' ? new CRM_Mailing_BAO_SMSJob() : new CRM_Mailing_BAO_MailingJob(); $jobTable = CRM_Mailing_DAO_MailingJob::getTableName(); $mailingTable = CRM_Mailing_DAO_Mailing::getTableName(); @@ -580,15 +580,6 @@ VALUES (%1, %2, %3, %4, %5, %6, %7) $mail_sync_interval = Civi::settings()->get('civimail_sync_interval'); $retryGroup = FALSE; - // CRM-15702: Sending bulk sms to contacts without e-mail address fails. - // Solution is to skip checking for on hold - //do include a statement to check wether e-mail address is on hold - $skipOnHold = TRUE; - if ($mailing->sms_provider_id) { - //do not include a statement to check wether e-mail address is on hold - $skipOnHold = FALSE; - } - foreach ($fields as $key => $field) { $params[] = $field['contact_id']; } @@ -596,7 +587,7 @@ VALUES (%1, %2, %3, %4, %5, %6, %7) [$details] = CRM_Utils_Token::getTokenDetails( $params, $returnProperties, - $skipOnHold, TRUE, NULL, + TRUE, TRUE, NULL, $mailing->getFlattenedTokens(), get_class($this), $this->id @@ -633,12 +624,6 @@ VALUES (%1, %2, %3, %4, %5, %6, %7) $body = $message->get(); $headers = $message->headers(); - if ($mailing->sms_provider_id) { - $provider = CRM_SMS_Provider::singleton(['mailing_id' => $mailing->id]); - $body = $provider->getMessage($message, $field['contact_id'], $details[$contactID]); - $headers = $provider->getRecipientDetails($field, $details[$contactID]); - } - // make $recipient actually be the *encoded* header, so as not to baffle Mail_RFC822, CRM-5743 $recipient = $headers['To']; $result = NULL; diff --git a/CRM/Mailing/BAO/SMSJob.php b/CRM/Mailing/BAO/SMSJob.php new file mode 100644 index 0000000000..d558d49e35 --- /dev/null +++ b/CRM/Mailing/BAO/SMSJob.php @@ -0,0 +1,108 @@ +get('civimail_sync_interval'); + $retryGroup = FALSE; + + foreach ($fields as $field) { + $contact = civicrm_api3('Contact', 'getsingle', ['id' => $field['contact_id']]); + + $preview = civicrm_api3('Mailing', 'preview', [ + 'id' => $mailing->id, + 'contact_id' => $field['contact_id'], + ])['values']; + $mailParams = [ + 'text' => $preview['body_text'], + 'toName' => $contact['display_name'], + 'job_id' => $this->id, + ]; + CRM_Utils_Hook::alterMailParams($mailParams, 'civimail'); + $body = $mailParams['text']; + $headers = ['To' => $field['phone']]; + + try { + $result = $mailer->send($headers['To'], $headers, $body, $this->id); + + // Register the delivery event. + $deliveredParams[] = $field['id']; + $targetParams[] = $field['contact_id']; + + $count++; + // dev/core#1768 Mail sync interval is now configurable. + if ($count % $mail_sync_interval == 0) { + $this->writeToDB( + $deliveredParams, + $targetParams, + $mailing, + $job_date + ); + $count = 0; + + // hack to stop mailing job at run time, CRM-4246. + // to avoid making too many DB calls for this rare case + // lets do it when we snapshot + $status = CRM_Core_DAO::getFieldValue( + 'CRM_Mailing_DAO_MailingJob', + $this->id, + 'status', + 'id', + TRUE + ); + + if ($status !== 'Running') { + return FALSE; + } + } + } + catch (CRM_Core_Exception $e) { + // Handle SMS errors: CRM-15426 + $job_id = (int) $this->id; + $mailing_id = (int) $mailing->id; + CRM_Core_Error::debug_log_message("Failed to send SMS message. Vars: mailing_id: ${mailing_id}, job_id: ${job_id}. Error message follows."); + CRM_Core_Error::debug_log_message($e->getMessage()); + } + + unset($result); + + // If we have enabled the Throttle option, this is the time to enforce it. + $mailThrottleTime = Civi::settings()->get('mailThrottleTime'); + if (!empty($mailThrottleTime)) { + usleep((int ) $mailThrottleTime); + } + } + + $result = $this->writeToDB( + $deliveredParams, + $targetParams, + $mailing, + $job_date + ); + + if ($retryGroup) { + return FALSE; + } + + return $result; + } + +} diff --git a/CRM/Mailing/Page/View.php b/CRM/Mailing/Page/View.php index 2981807442..4b63e2b4a2 100644 --- a/CRM/Mailing/Page/View.php +++ b/CRM/Mailing/Page/View.php @@ -150,7 +150,7 @@ class CRM_Mailing_Page_View extends CRM_Core_Page { $mailing = $result['values'] ?? NULL; $title = NULL; - if (isset($mailing['body_html']) && empty($_GET['text'])) { + if (!empty($mailing['body_html']) && empty($_GET['text'])) { $header = 'text/html; charset=utf-8'; $content = $mailing['body_html']; if (strpos($content, '') === FALSE && strpos($content, '') === FALSE) { diff --git a/CRM/SMS/Provider.php b/CRM/SMS/Provider.php index c1f740b5b2..9cb40538cd 100644 --- a/CRM/SMS/Provider.php +++ b/CRM/SMS/Provider.php @@ -83,38 +83,6 @@ abstract class CRM_SMS_Provider { */ abstract public function send($recipients, $header, $message, $dncID = NULL); - /** - * Return message text. - * - * Child class could override this function to have better control over the message being sent. - * - * @param Mail_mime $message - * @param int $contactID - * @param array $contactDetails - * - * @return string - */ - public function getMessage($message, $contactID, $contactDetails) { - $html = $message->getHTMLBody(); - $text = $message->getTXTBody(); - - return $html ? $html : $text; - } - - /** - * Get recipient details. - * - * @param array $fields - * @param array $additionalDetails - * - * @return mixed - */ - public function getRecipientDetails($fields, $additionalDetails) { - // we could do more altering here - $fields['To'] = $fields['phone']; - return $fields; - } - /** * @param int $apiMsgID * @param $message diff --git a/ext/flexmailer/src/API/MailingPreview.php b/ext/flexmailer/src/API/MailingPreview.php index e585eda77a..4d3810c4ff 100644 --- a/ext/flexmailer/src/API/MailingPreview.php +++ b/ext/flexmailer/src/API/MailingPreview.php @@ -33,7 +33,7 @@ class MailingPreview { $mailing->copyValues($params); } - if (!Abdicator::isFlexmailPreferred($mailing)) { + if (!Abdicator::isFlexmailPreferred($mailing) && empty($mailing->sms_provider_id)) { require_once 'api/v3/Mailing.php'; return civicrm_api3_mailing_preview($params); } diff --git a/ext/flexmailer/src/Listener/DefaultComposer.php b/ext/flexmailer/src/Listener/DefaultComposer.php index d9c61df4a2..93559b8a1a 100644 --- a/ext/flexmailer/src/Listener/DefaultComposer.php +++ b/ext/flexmailer/src/Listener/DefaultComposer.php @@ -57,7 +57,7 @@ class DefaultComposer extends BaseListener { $this->createTokenProcessorContext($e)); $tpls = $this->createMessageTemplates($e); - $tp->addMessage('subject', $tpls['subject'], 'text/plain'); + $tp->addMessage('subject', $tpls['subject'] ?? '', 'text/plain'); $tp->addMessage('body_text', isset($tpls['text']) ? $tpls['text'] : '', 'text/plain'); $tp->addMessage('body_html', isset($tpls['html']) ? $tpls['html'] : '', diff --git a/tests/phpunit/CRM/SMS/PreviewTest.php b/tests/phpunit/CRM/SMS/PreviewTest.php index fa81cecad3..c3dd21950f 100644 --- a/tests/phpunit/CRM/SMS/PreviewTest.php +++ b/tests/phpunit/CRM/SMS/PreviewTest.php @@ -27,7 +27,7 @@ class CRM_SMS_PreviewTest extends CiviUnitTestCase { /** * Test SMS preview. */ - public function testSMSPreview() { + public function testSMSPreview(): void { $result = $this->callAPISuccess('SmsProvider', 'create', [ 'title' => 'test SMS provider', 'username' => 'test', @@ -41,10 +41,10 @@ class CRM_SMS_PreviewTest extends CiviUnitTestCase { $provider_id = $result['id']; $result = $this->callAPISuccess('Mailing', 'create', [ 'name' => "Test1", - 'from_name' => "+12223334444", - 'from_email' => "test@test.com", + 'from_name' => '+12223334444', + 'from_email' => 'test@test.com', 'replyto_email' => "test@test.com", - 'body_text' => "Testing body", + 'body_text' => 'Testing body', 'sms_provider_id' => $provider_id, 'header_id' => NULL, 'footer_id' => NULL, -- 2.25.1