Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

Commit

Permalink
Allow to use "symfony/mailer" within Mailer (#711)
Browse files Browse the repository at this point in the history
* Allow to use "symfony/mailer" within `Mailer`

* Add tests

* Improve tests
  • Loading branch information
wbloszyk authored Feb 12, 2021
1 parent d6598b6 commit c3b7332
Show file tree
Hide file tree
Showing 4 changed files with 259 additions and 13 deletions.
8 changes: 8 additions & 0 deletions UPGRADE-3.x.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
UPGRADE 3.x
===========

UPGRADE FROM 3.x to 3.x
=======================

### Sonata\NewsBundle\Mailer\Mailer

Passing an instance of `\Swift_Mailer` as argument 1 for `Sonata\NewsBundle\Mailer\Mailer::__construct()`
is deprecated. Pass an instance of `Symfony\Component\Mailer\MailerInterface` instead.

UPGRADE FROM 3.13 to 3.14
=========================

Expand Down
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@
"symfony/framework-bundle": "^4.4",
"symfony/http-foundation": "^4.4",
"symfony/http-kernel": "^4.4",
"symfony/mailer": "^4.4 || ^5.1",
"symfony/mime": "^4.4.10 || ^5.1",
"symfony/options-resolver": "^4.4",
"symfony/routing": "^4.4",
"symfony/security-core": "^4.4",
"symfony/swiftmailer-bundle": "^3.4",
"symfony/templating": "^4.4 || ^5.1",
"symfony/translation-contracts": "^1.1 || ^2.0",
"twig/string-extra": "^3.0",
Expand Down Expand Up @@ -74,7 +75,8 @@
"sonata-project/notification-bundle": "^3.4",
"sonata-project/seo-bundle": "^2.5",
"symfony/browser-kit": "^4.3",
"symfony/phpunit-bridge": "^5.1.8"
"symfony/phpunit-bridge": "^5.1.8",
"symfony/swiftmailer-bundle": "^3.4"
},
"suggest": {
"nelmio/api-doc-bundle": "If you want to use the API.",
Expand Down
59 changes: 48 additions & 11 deletions src/Mailer/Mailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
use Sonata\NewsBundle\Model\BlogInterface;
use Sonata\NewsBundle\Model\CommentInterface;
use Sonata\NewsBundle\Util\HashGeneratorInterface;
use Symfony\Component\Mailer\MailerInterface as SymfonyMailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Templating\EngineInterface;

Expand All @@ -42,7 +44,9 @@ class Mailer implements MailerInterface
protected $hashGenerator;

/**
* @var \Swift_Mailer
* NEXT_MAJOR: Remove the support for `\Swift_Mailer` in this property.
*
* @var SymfonyMailerInterface|\Swift_Mailer
*/
protected $mailer;

Expand All @@ -51,11 +55,28 @@ class Mailer implements MailerInterface
*/
protected $blog;

/**
* @param \Swift_Mailer $mailer
*/
public function __construct($mailer, BlogInterface $blog, HashGeneratorInterface $generator, RouterInterface $router, EngineInterface $templating, array $emails)
public function __construct(object $mailer, BlogInterface $blog, HashGeneratorInterface $generator, RouterInterface $router, EngineInterface $templating, array $emails)
{
// NEXT_MAJOR: Remove the following 2 conditions and use `Symfony\Component\Mailer\MailerInterface` as argument declaration for `$mailer`.
if (!$mailer instanceof SymfonyMailerInterface && !$mailer instanceof \Swift_Mailer) {
throw new \TypeError(sprintf(
'Argument 1 passed to "%s()" must be an instance of "%s" or "%s", instance of "%s" given.',
__METHOD__,
SymfonyMailerInterface::class,
\Swift_Mailer::class,
\get_class($mailer)
));
}

if (!$mailer instanceof SymfonyMailerInterface) {
@trigger_error(sprintf(
'Passing other type than "%s" as argument 1 for "%s()" is deprecated since sonata-project/user-bundle 4.x'
.' and will be not supported in version 5.x.',
SymfonyMailerInterface::class,
__METHOD__
), \E_USER_DEPRECATED);
}

$this->blog = $blog;
$this->mailer = $mailer;
$this->hashGenerator = $generator;
Expand Down Expand Up @@ -90,12 +111,28 @@ protected function sendEmailMessage($renderedTemplate, $fromEmail, $toEmail)
// Render the email, use the first line as the subject, and the rest as the body
[$subject, $body] = explode("\n", trim($renderedTemplate), 2);

$message = $this->mailer->createMessage()
->setSubject($subject)
->setFrom($fromEmail)
->setTo($toEmail)
->setBody($body);
// NEXT_MAJOR: Remove this condition.
if ($this->mailer instanceof \Swift_Mailer) {
$message = $this->mailer->createMessage()
->setSubject($subject)
->setFrom($fromEmail)
->setTo($toEmail)
->setBody($body);

$this->mailer->send($message);

return;
}

$email = (new Email())
->from($fromEmail)
->subject($subject)
->html($body);

foreach ($this->emails['notification']['emails'] as $address) {
$email->addTo($address);
}

$this->mailer->send($message);
$this->mailer->send($email);
}
}
199 changes: 199 additions & 0 deletions tests/Mailer/MailerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\NewsBundle\Tests\Mailer;

use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Sonata\NewsBundle\Mailer\Mailer;
use Sonata\NewsBundle\Model\BlogInterface;
use Sonata\NewsBundle\Model\CommentInterface;
use Sonata\NewsBundle\Model\PostInterface;
use Sonata\NewsBundle\Util\HashGeneratorInterface;
use Symfony\Component\Mailer\MailerInterface as SymfonyMailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Templating\EngineInterface;

final class MailerTest extends TestCase
{
/**
* @var RouterInterface|MockObject
*/
private $router;

/**
* @var BlogInterface|MockObject
*/
private $blog;

/**
* @var HashGeneratorInterface|MockObject
*/
private $generator;

/**
* @var EngineInterface|MockObject
*/
private $templating;

/**
* NEXT_MAJOR: Remove the support for `\Swift_Mailer` in this property.
*
* @var SymfonyMailerInterface|\Swift_Mailer
*/
private $mailer;

/**
* @var array
*/
private $emails;

protected function setUp(): void
{
$this->mailer = $this->createMock(SymfonyMailerInterface::class);
$this->blog = $this->createStub(BlogInterface::class);
$this->generator = $this->createMock(HashGeneratorInterface::class);
$this->router = $this->createStub(RouterInterface::class);
$this->templating = $this->createMock(EngineInterface::class);
$this->emails = [
'notification' => [
'template' => 'email_test.html.twig',
'from' => '[email protected]',
'emails' => ['[email protected]', '[email protected]'],
],
];
}

/**
* NEXT_MAJOR: Remove this method.
*
* @group legacy
*
* @dataProvider emailTemplateData
*/
public function testSendCommentNotificationWithSwiftMailer(string $template, string $subject, string $body): void
{
$post = $this->createMock(PostInterface::class);

$comment = $this->createStub(CommentInterface::class);
$comment
->expects($this->once())
->method('getPost')
->willReturn($post);

$this->generator
//->expects($this->once())
->method('generate')
->with($comment)
->willReturn('some_result');

$this->emails['notification']['template'] = $template;

$this->templating
->expects($this->once())
->method('render')
->with($this->emails['notification']['template'], [
'comment' => $comment,
'post' => $post,
'hash' => 'some_result',
'blog' => $this->blog,
])
->willReturn($template);

$message = (new \Swift_Message())
->setSubject($subject)
->setFrom($this->emails['notification']['from'])
->setTo($this->emails['notification']['emails'])
->setBody($body);

$this->mailer = $this->createStub(\Swift_Mailer::class);
$this->mailer
->expects($this->once())
->method('createMessage')
->willReturn($message);

$this->mailer
->expects($this->once())
->method('send')
->with($message);

$mailer = $this->getMailer();

$mailer->sendCommentNotification($comment);
}

/**
* @dataProvider emailTemplateData
*/
public function testSendCommentNotification(string $template, string $subject, string $body): void
{
$post = $this->createMock(PostInterface::class);

$comment = $this->createStub(CommentInterface::class);
$comment
->expects($this->once())
->method('getPost')
->willReturn($post);

$this->generator
//->expects($this->once())
->method('generate')
->with($comment)
->willReturn('some_result');

$this->emails['notification']['template'] = $template;

$this->templating
->expects($this->once())
->method('render')
->with($this->emails['notification']['template'], [
'comment' => $comment,
'post' => $post,
'hash' => 'some_result',
'blog' => $this->blog,
])
->willReturn($template);

$email = (new Email())
->from($this->emails['notification']['from'])
->subject($subject)
->html($body);

foreach ($this->emails['notification']['emails'] as $address) {
$email->addTo($address);
}

$this->mailer
->expects($this->once())
->method('send')
->with($email);

$mailer = $this->getMailer();

$mailer->sendCommentNotification($comment);
}

public function emailTemplateData(): iterable
{
return [
'LF' => ["Subject\nFirst line\nSecond line", 'Subject', "First line\nSecond line"],
'LFLF' => ["Subject\n\nFirst line\n\nSecond line", 'Subject', "\nFirst line\n\nSecond line"],
];
}

private function getMailer(): Mailer
{
return new Mailer($this->mailer, $this->blog, $this->generator, $this->router, $this->templating, $this->emails);
}
}

0 comments on commit c3b7332

Please sign in to comment.