diff --git a/modules/system/ServiceProvider.php b/modules/system/ServiceProvider.php index 1bc573b359..d8e21c4eec 100644 --- a/modules/system/ServiceProvider.php +++ b/modules/system/ServiceProvider.php @@ -357,9 +357,7 @@ protected function registerMailer() * Override standard Mailer content with template */ Event::listen('mailer.beforeAddContent', function ($mailer, $message, $view, $data, $raw, $plain) { - $method = $raw === null ? 'addContentToMailer' : 'addRawContentToMailer'; - $plainOnly = $view === null; // When "plain-text only" email is sent, $view is null, this sets the flag appropriately - return !MailManager::instance()->$method($message, $raw ?: $view ?: $plain, $data, $plainOnly); + return !MailManager::instance()->addContent($message, $view, $plain, $raw, $data); }); } diff --git a/modules/system/classes/MailManager.php b/modules/system/classes/MailManager.php index b11fee91cb..08e8a10c41 100644 --- a/modules/system/classes/MailManager.php +++ b/modules/system/classes/MailManager.php @@ -52,14 +52,15 @@ class MailManager * Same as `addContentToMailer` except with raw content. * * @return bool + * + * @deprecated Use addContent() instead */ public function addRawContentToMailer($message, $content, $data) { - $template = new MailTemplate; - - $template->fillFromContent($content); + $text = new MailTemplate; + $text->fillFromContent($content); - $this->addContentToMailerInternal($message, $template, $data); + $this->addContentToMailerInternal($message, null, $text, $data); return true; } @@ -73,6 +74,8 @@ public function addRawContentToMailer($message, $content, $data) * @param array $data * @param bool $plainOnly Add only plain text content to the message * @return bool + * + * @deprecated Use addContent() instead */ public function addContentToMailer($message, $code, $data, $plainOnly = false) { @@ -92,21 +95,75 @@ public function addContentToMailer($message, $code, $data, $plainOnly = false) return false; } - $this->addContentToMailerInternal($message, $template, $data, $plainOnly); + $html = $text = $template; + + if ($plainOnly) { + $html = null; + } + $this->addContentToMailerInternal($message, $html, $text, $data); return true; } /** - * Internal method used to share logic between `addRawContentToMailer` and `addContentToMailer` + * Restore proper behavior in-line with Laravel Mailer + * Replaces both `addContentToMailer` and `addRawContentToMailer` * * @param \Illuminate\Mail\Message $message - * @param string $template + * @param string|null $view + * @param string|null $plain + * @param string|null $raw + * @param array $data + * @return bool + */ + public function addContent($message, $view = null, $plain = null, $raw = null, $data = []) + { + $html = $text = null; + + // We only handle mail template names as a string, let the caller handle the content if we receive anything else + + if (is_string($view)) { + if (isset($this->templateCache[$view])) { + $html = $this->templateCache[$view]; + } else { + $this->templateCache[$view] = $html = MailTemplate::findOrMakeTemplate($view); + } + } + + if (is_string($plain)) { + if (isset($this->templateCache[$plain])) { + $text = $this->templateCache[$plain]; + } else { + $this->templateCache[$plain] = $text = MailTemplate::findOrMakeTemplate($plain); + } + } + + // raw content will overwrite plain view content, as done in laravel + if (is_string($raw)) { + $text = new MailTemplate; + $text->fillFromContent($raw); + } + + // bailout if we have no content + if (is_null($html) && is_null($text)) { + return false; + } + + $this->addContentToMailerInternal($message, $html, $text, $data); + + return true; + } + + /** + * Internal method used to share logic between `addContent`, `addRawContentToMailer` and `addContentToMailer` + * + * @param \Illuminate\Mail\Message $message + * @param MailTemplate|null $html + * @param MailTemplate|null $text * @param array $data - * @param bool $plainOnly Add only plain text content to the message * @return void */ - protected function addContentToMailerInternal($message, $template, $data, $plainOnly = false) + protected function addContentToMailerInternal($message, $html = null, $text = null, array $data = []) { /* * Inject global view variables @@ -122,28 +179,39 @@ protected function addContentToMailerInternal($message, $template, $data, $plain $symfonyMessage = $message->getSymfonyMessage(); if (empty($symfonyMessage->getSubject())) { - $message->subject($this->renderTwig($template->subject, $data)); + if ($html) { + $message->subject($this->renderTwig($html->subject, $data)); + } else if ($text) { + $message->subject($this->renderTwig($text->subject, $data)); + } } $data += [ 'subject' => $symfonyMessage->getSubject() ]; - if (!$plainOnly) { - /* - * HTML contents - */ - $html = $this->renderTemplate($template, $data); - - $message->html($html); + /* + * HTML content + */ + if ($html) { + $message->setBody($this->renderTemplate($html, $data), 'text/html'); + if (!$text && $html->content_text) { + $text = $html; + } } /* - * Text contents + * Text content */ - $text = $this->renderTextTemplate($template, $data); + if ($text) { + $method = $html ? 'addPart' : 'setBody'; + $message->{$method}($this->renderTextTemplate($text, $data), 'text/plain'); + } - $message->text($text); + /* + * End twig transaction + */ + $this->stopTwig(); } // diff --git a/tests/unit/system/classes/MailManagerTest.php b/tests/unit/system/classes/MailManagerTest.php new file mode 100644 index 0000000000..364cb47402 --- /dev/null +++ b/tests/unit/system/classes/MailManagerTest.php @@ -0,0 +1,112 @@ +message = new Message(new Email()); + + foreach (['html', 'plain'] as $view) { + $t = new MailTemplate(); + $t->is_custom = true; + $t->code = "$view-view"; + $t->subject = "$view view [{{ mode }}]"; + $t->content_html = "my $view view content"; + $t->description = "my $view view description"; + $t->save(); + } + } + + // + // Tests + // + + public function testAddContent_Html() + { + $plain = $raw = null; + $html = new TextPart('html-view', $subtype="html"); + $data = ['mode' => 'test']; + + $result = MailManager::instance()->addContent($this->message, $html, $plain, $raw, $data); + $symfonyMessage = $this->message->getSymfonyMessage(); + + $this->assertEquals($html, $symfonyMessage->getHtmlBody()); + $this->assertEquals('html view [test]', $symfonyMessage->getSubject()); + } + + public function testAddContent_Plain() + { + $html = $raw = null; + $plain = new TextPart('plain-view'); + $data = ['mode' => 'test']; + + $result = MailManager::instance()->addContent($this->message, $html, $plain, $raw, $data); + $symfonyMessage = $this->message->getSymfonyMessage(); + + $this->assertTrue($result); + $this->assertEquals($plain, $symfonyMessage->getTextBody()); + $this->assertEquals('plain view [test]', $symfonyMessage->getSubject()); + } + + public function testAddContent_Raw() + { + $html = $plain = null; + $raw = new TextPart('my raw content'); + $data = ['mode' => 'test']; + + $result = MailManager::instance()->addContent($this->message, $html, $plain, $raw, $data); + $symfonyMessage = $this->message->getSymfonyMessage(); + + $this->assertTrue($result); + $this->assertEquals('No subject', $symfonyMessage->getSubject()); + $this->assertEquals($raw, $symfonyMessage->getBody()); + } + + public function testAddContent_Html_Plain() + { + $raw = null; + $html = new TextPart('html-view', $subtype="html"); + $plain = new TextPart('plain-view'); + $data = ['mode' => 'test']; + + $result = MailManager::instance()->addContent($this->message, $html, $plain, $raw, $data); + $symfonyMessage = $this->message->getSymfonyMessage(); + $parts = $symfonyMessage->getAttachments(); + + $this->assertTrue($result); + $this->assertEquals('html view [test]', $symfonyMessage->getSubject()); + $this->assertEquals($html, $symfonyMessage->getHtmlBody()); + + $this->assertEquals(1, count($parts)); + $this->assertEquals($plain, $symfonyMessage->getTextBody()); + } + + public function testAddContent_Html_Plain_Raw() + { + $html = new TextPart('html-view', $subtype="html"); + $plain = new TextPart('plain-view'); + $raw = new TextPart('my raw content'); + $data = ['mode' => 'test']; + + $result = MailManager::instance()->addContent($this->message, $html, $plain, $raw, $data); + $symfonyMessage = $this->message->getSymfonyMessage(); + $parts = $symfonyMessage->getAttachments(); + + $this->assertTrue($result); + $this->assertEquals('html view [test]', $symfonyMessage->getSubject()); + $this->assertEquals($html, $symfonyMessage->getHtmlBody()); + + $this->assertEquals(1, count($parts)); + $this->assertEquals($plain, $symfonyMessage->getTextBody()); + $this->assertEquals($raw, $symfonyMessage->getBody()); + } +}