Skip to content

Commit

Permalink
Allow to use "symfony/mailer" within Mailer
Browse files Browse the repository at this point in the history
  • Loading branch information
phansys committed Nov 23, 2020
1 parent 43f5cc3 commit ecc961b
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 19 deletions.
5 changes: 5 additions & 0 deletions UPGRADE-4.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ UPGRADE 4.x
UPGRADE FROM 4.x to 4.x
=======================

### Sonata\UserBundle\Mailer\Mailer

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

### Dependencies

- "sonata-project/datagrid-bundle" is bumped from ^2.4 to ^3.0.
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@
"sonata-project/datagrid-bundle": "^3.0.1",
"sonata-project/doctrine-extensions": "^1.10.1",
"sonata-project/form-extensions": "^0.1 || ^1.4",
"swiftmailer/swiftmailer": "^4.3 || ^5.0 || ^6.0",
"symfony/config": "^4.4",
"symfony/console": "^4.4",
"symfony/dependency-injection": "^4.4",
"symfony/form": "^4.4",
"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 || ^5.1",
"symfony/security-acl": "^3.0",
"symfony/security-core": "^4.4",
Expand Down
65 changes: 57 additions & 8 deletions src/Mailer/Mailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

use FOS\UserBundle\Mailer\MailerInterface;
use FOS\UserBundle\Model\UserInterface;
use Symfony\Component\Mailer\MailerInterface as SymfonyMailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Twig\Environment;

Expand All @@ -31,7 +33,9 @@ final class Mailer implements MailerInterface
private $twig;

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

Expand All @@ -45,8 +49,28 @@ final class Mailer implements MailerInterface
*/
private $emailTemplate;

public function __construct(UrlGeneratorInterface $urlGenerator, Environment $twig, \Swift_Mailer $mailer, array $fromEmail, string $emailTemplate)
public function __construct(UrlGeneratorInterface $urlGenerator, Environment $twig, object $mailer, array $fromEmail, string $emailTemplate)
{
// 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 3 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 3 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->urlGenerator = $urlGenerator;
$this->twig = $twig;
$this->mailer = $mailer;
Expand All @@ -69,17 +93,42 @@ public function sendResettingEmailMessage(UserInterface $user): void
$renderedLines = preg_split('/\R/', trim($rendered), 2, PREG_SPLIT_NO_EMPTY);
$subject = array_shift($renderedLines);
$body = implode('', $renderedLines);
$message = (new \Swift_Message())
->setSubject($subject)
->setFrom($this->fromEmail)
->setTo((string) $user->getEmail())
->setBody($body);

$this->mailer->send($message);
// NEXT_MAJOR: Remove this condition.
if ($this->mailer instanceof \Swift_Mailer) {
$this->sendResettingEmailMessageWithSwiftMailer($user, $subject, $body);

return;
}

$fromName = current($this->fromEmail);
$fromAddress = current(array_keys($this->fromEmail));

$this->mailer->send(
(new Email())
->from(sprintf('%s <%s>', $fromName, $fromAddress))
->to((string) $user->getEmail())
->subject($subject)
->html($body)
);
}

public function sendConfirmationEmailMessage(UserInterface $user): void
{
throw new \LogicException('This method is not implemented.');
}

/**
* NEXT_MAJOR: Remove this method.
*/
private function sendResettingEmailMessageWithSwiftMailer(UserInterface $user, string $subject, string $body): void
{
$this->mailer->send(
(new \Swift_Message())
->setSubject($subject)
->setFrom($this->fromEmail)
->setTo((string) $user->getEmail())
->setBody($body)
);
}
}
69 changes: 59 additions & 10 deletions tests/Mailer/MailerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Sonata\UserBundle\Mailer\Mailer;
use Symfony\Component\Mailer\MailerInterface as SymfonyMailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Routing\RouterInterface;
use Twig\Environment;

Expand All @@ -33,7 +35,7 @@ class MailerTest extends TestCase
private $templating;

/**
* @var \Swift_Mailer|MockObject
* @var SymfonyMailerInterface|MockObject
*/
private $mailer;

Expand All @@ -51,8 +53,10 @@ protected function setUp(): void
{
$this->router = $this->createMock(RouterInterface::class);
$this->templating = $this->createMock(Environment::class);
$this->mailer = $this->createMock(\Swift_Mailer::class);
$this->emailFrom = ['noreply@sonata-project.org'];
$this->mailer = $this->createMock(SymfonyMailerInterface::class);
$this->emailFrom = [
'noreply@sonata-project.org' => 'Sonata Project',
];
$this->template = 'foo';
}

Expand All @@ -71,7 +75,7 @@ public function testSendConfirmationEmailMessage(): void
*/
public function testSendResettingEmailMessage(string $template, string $subject, string $body): void
{
$user = $this->createMock(UserInterface::class);
$user = $this->createStub(UserInterface::class);
$user
->method('getConfirmationToken')
->willReturn('user-token');
Expand All @@ -89,18 +93,63 @@ public function testSendResettingEmailMessage(string $template, string $subject,
->with('foo', ['user' => $user, 'confirmationUrl' => '/foo'])
->willReturn($template);

$fromName = current($this->emailFrom);
$fromAddress = current(array_keys($this->emailFrom));

$email = (new Email())
->from(sprintf('%s <%s>', $fromName, $fromAddress))
->to((string) $user->getEmail())
->subject($subject)
->html($body);

$this->mailer->expects($this->once())
->method('send')
->willReturnCallback(function (\Swift_Message $message) use ($subject, $body): void {
$this->assertSame($subject, $message->getSubject());
$this->assertSame($body, $message->getBody());
$this->assertArrayHasKey($this->emailFrom[0], $message->getFrom());
$this->assertArrayHasKey('user@sonata-project.org', $message->getTo());
});
->with($this->equalTo($email));

$this->getMailer()->sendResettingEmailMessage($user);
}

/**
* NEXT_MAJOR: Remove this method.
*
* @group legacy
*
* @dataProvider emailTemplateData
*/
public function testSendResettingEmailMessageWithSwiftMailer(string $template, string $subject, string $body): void
{
$user = $this->createStub(UserInterface::class);
$user
->method('getConfirmationToken')
->willReturn('user-token');
$user
->method('getEmail')
->willReturn('user@sonata-project.org');

$this->router->expects($this->once())
->method('generate')
->with('sonata_user_admin_resetting_reset', ['token' => 'user-token'])
->willReturn('/foo');

$this->templating->expects($this->once())
->method('render')
->with('foo', ['user' => $user, 'confirmationUrl' => '/foo'])
->willReturn($template);

$swiftMailer = $this->createMock(\Swift_Mailer::class);

$swiftMailer->expects($this->once())
->method('send')
->with($this->callback(function (\Swift_Message $message) use ($subject, $body, $user): bool {
return $subject === $message->getSubject()
&& $body === $message->getBody()
&& $this->emailFrom === $message->getFrom()
&& \array_key_exists((string) $user->getEmail(), $message->getTo());
}));

(new Mailer($this->router, $this->templating, $swiftMailer, $this->emailFrom, $this->template))->sendResettingEmailMessage($user);
}

public function emailTemplateData(): array
{
return [
Expand Down

0 comments on commit ecc961b

Please sign in to comment.