Skip to content

Commit ecc961b

Browse files
committed
Allow to use "symfony/mailer" within Mailer
1 parent 43f5cc3 commit ecc961b

File tree

4 files changed

+123
-19
lines changed

4 files changed

+123
-19
lines changed

UPGRADE-4.x.md

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ UPGRADE 4.x
44
UPGRADE FROM 4.x to 4.x
55
=======================
66

7+
### Sonata\UserBundle\Mailer\Mailer
8+
9+
Passing an instance of `\Swift_Mailer` as argument 3 for `Sonata\UserBundle\Mailer\Mailer::__construct()`
10+
is deprecated. Pass an instance of `Symfony\Component\Mailer\MailerInterface` instead.
11+
712
### Dependencies
813

914
- "sonata-project/datagrid-bundle" is bumped from ^2.4 to ^3.0.

composer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@
2828
"sonata-project/datagrid-bundle": "^3.0.1",
2929
"sonata-project/doctrine-extensions": "^1.10.1",
3030
"sonata-project/form-extensions": "^0.1 || ^1.4",
31-
"swiftmailer/swiftmailer": "^4.3 || ^5.0 || ^6.0",
3231
"symfony/config": "^4.4",
3332
"symfony/console": "^4.4",
3433
"symfony/dependency-injection": "^4.4",
3534
"symfony/form": "^4.4",
3635
"symfony/framework-bundle": "^4.4",
3736
"symfony/http-foundation": "^4.4",
3837
"symfony/http-kernel": "^4.4",
38+
"symfony/mailer": "^4.4 || ^5.1",
39+
"symfony/mime": "^4.4.10 || ^5.1",
3940
"symfony/options-resolver": "^4.4 || ^5.1",
4041
"symfony/security-acl": "^3.0",
4142
"symfony/security-core": "^4.4",

src/Mailer/Mailer.php

+57-8
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
use FOS\UserBundle\Mailer\MailerInterface;
1717
use FOS\UserBundle\Model\UserInterface;
18+
use Symfony\Component\Mailer\MailerInterface as SymfonyMailerInterface;
19+
use Symfony\Component\Mime\Email;
1820
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
1921
use Twig\Environment;
2022

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

3335
/**
34-
* @var \Swift_Mailer
36+
* NEXT_MAJOR: Remove the support for `\Swift_Mailer` in this property.
37+
*
38+
* @var SymfonyMailerInterface|\Swift_Mailer
3539
*/
3640
private $mailer;
3741

@@ -45,8 +49,28 @@ final class Mailer implements MailerInterface
4549
*/
4650
private $emailTemplate;
4751

48-
public function __construct(UrlGeneratorInterface $urlGenerator, Environment $twig, \Swift_Mailer $mailer, array $fromEmail, string $emailTemplate)
52+
public function __construct(UrlGeneratorInterface $urlGenerator, Environment $twig, object $mailer, array $fromEmail, string $emailTemplate)
4953
{
54+
// NEXT_MAJOR: Remove the following 2 conditions and use `Symfony\Component\Mailer\MailerInterface` as argument declaration for `$mailer`.
55+
if (!$mailer instanceof SymfonyMailerInterface && !$mailer instanceof \Swift_Mailer) {
56+
throw new \TypeError(sprintf(
57+
'Argument 3 passed to "%s()" must be an instance of "%s" or "%s", instance of "%s" given.',
58+
__METHOD__,
59+
SymfonyMailerInterface::class,
60+
\Swift_Mailer::class,
61+
\get_class($mailer)
62+
));
63+
}
64+
65+
if (!$mailer instanceof SymfonyMailerInterface) {
66+
@trigger_error(sprintf(
67+
'Passing other type than "%s" as argument 3 for "%s()" is deprecated since sonata-project/user-bundle 4.x'
68+
.' and will be not supported in version 5.x.',
69+
SymfonyMailerInterface::class,
70+
__METHOD__
71+
), E_USER_DEPRECATED);
72+
}
73+
5074
$this->urlGenerator = $urlGenerator;
5175
$this->twig = $twig;
5276
$this->mailer = $mailer;
@@ -69,17 +93,42 @@ public function sendResettingEmailMessage(UserInterface $user): void
6993
$renderedLines = preg_split('/\R/', trim($rendered), 2, PREG_SPLIT_NO_EMPTY);
7094
$subject = array_shift($renderedLines);
7195
$body = implode('', $renderedLines);
72-
$message = (new \Swift_Message())
73-
->setSubject($subject)
74-
->setFrom($this->fromEmail)
75-
->setTo((string) $user->getEmail())
76-
->setBody($body);
7796

78-
$this->mailer->send($message);
97+
// NEXT_MAJOR: Remove this condition.
98+
if ($this->mailer instanceof \Swift_Mailer) {
99+
$this->sendResettingEmailMessageWithSwiftMailer($user, $subject, $body);
100+
101+
return;
102+
}
103+
104+
$fromName = current($this->fromEmail);
105+
$fromAddress = current(array_keys($this->fromEmail));
106+
107+
$this->mailer->send(
108+
(new Email())
109+
->from(sprintf('%s <%s>', $fromName, $fromAddress))
110+
->to((string) $user->getEmail())
111+
->subject($subject)
112+
->html($body)
113+
);
79114
}
80115

81116
public function sendConfirmationEmailMessage(UserInterface $user): void
82117
{
83118
throw new \LogicException('This method is not implemented.');
84119
}
120+
121+
/**
122+
* NEXT_MAJOR: Remove this method.
123+
*/
124+
private function sendResettingEmailMessageWithSwiftMailer(UserInterface $user, string $subject, string $body): void
125+
{
126+
$this->mailer->send(
127+
(new \Swift_Message())
128+
->setSubject($subject)
129+
->setFrom($this->fromEmail)
130+
->setTo((string) $user->getEmail())
131+
->setBody($body)
132+
);
133+
}
85134
}

tests/Mailer/MailerTest.php

+59-10
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
use PHPUnit\Framework\MockObject\MockObject;
1818
use PHPUnit\Framework\TestCase;
1919
use Sonata\UserBundle\Mailer\Mailer;
20+
use Symfony\Component\Mailer\MailerInterface as SymfonyMailerInterface;
21+
use Symfony\Component\Mime\Email;
2022
use Symfony\Component\Routing\RouterInterface;
2123
use Twig\Environment;
2224

@@ -33,7 +35,7 @@ class MailerTest extends TestCase
3335
private $templating;
3436

3537
/**
36-
* @var \Swift_Mailer|MockObject
38+
* @var SymfonyMailerInterface|MockObject
3739
*/
3840
private $mailer;
3941

@@ -51,8 +53,10 @@ protected function setUp(): void
5153
{
5254
$this->router = $this->createMock(RouterInterface::class);
5355
$this->templating = $this->createMock(Environment::class);
54-
$this->mailer = $this->createMock(\Swift_Mailer::class);
55-
$this->emailFrom = ['noreply@sonata-project.org'];
56+
$this->mailer = $this->createMock(SymfonyMailerInterface::class);
57+
$this->emailFrom = [
58+
'noreply@sonata-project.org' => 'Sonata Project',
59+
];
5660
$this->template = 'foo';
5761
}
5862

@@ -71,7 +75,7 @@ public function testSendConfirmationEmailMessage(): void
7175
*/
7276
public function testSendResettingEmailMessage(string $template, string $subject, string $body): void
7377
{
74-
$user = $this->createMock(UserInterface::class);
78+
$user = $this->createStub(UserInterface::class);
7579
$user
7680
->method('getConfirmationToken')
7781
->willReturn('user-token');
@@ -89,18 +93,63 @@ public function testSendResettingEmailMessage(string $template, string $subject,
8993
->with('foo', ['user' => $user, 'confirmationUrl' => '/foo'])
9094
->willReturn($template);
9195

96+
$fromName = current($this->emailFrom);
97+
$fromAddress = current(array_keys($this->emailFrom));
98+
99+
$email = (new Email())
100+
->from(sprintf('%s <%s>', $fromName, $fromAddress))
101+
->to((string) $user->getEmail())
102+
->subject($subject)
103+
->html($body);
104+
92105
$this->mailer->expects($this->once())
93106
->method('send')
94-
->willReturnCallback(function (\Swift_Message $message) use ($subject, $body): void {
95-
$this->assertSame($subject, $message->getSubject());
96-
$this->assertSame($body, $message->getBody());
97-
$this->assertArrayHasKey($this->emailFrom[0], $message->getFrom());
98-
$this->assertArrayHasKey('user@sonata-project.org', $message->getTo());
99-
});
107+
->with($this->equalTo($email));
100108

101109
$this->getMailer()->sendResettingEmailMessage($user);
102110
}
103111

112+
/**
113+
* NEXT_MAJOR: Remove this method.
114+
*
115+
* @group legacy
116+
*
117+
* @dataProvider emailTemplateData
118+
*/
119+
public function testSendResettingEmailMessageWithSwiftMailer(string $template, string $subject, string $body): void
120+
{
121+
$user = $this->createStub(UserInterface::class);
122+
$user
123+
->method('getConfirmationToken')
124+
->willReturn('user-token');
125+
$user
126+
->method('getEmail')
127+
->willReturn('user@sonata-project.org');
128+
129+
$this->router->expects($this->once())
130+
->method('generate')
131+
->with('sonata_user_admin_resetting_reset', ['token' => 'user-token'])
132+
->willReturn('/foo');
133+
134+
$this->templating->expects($this->once())
135+
->method('render')
136+
->with('foo', ['user' => $user, 'confirmationUrl' => '/foo'])
137+
->willReturn($template);
138+
139+
$swiftMailer = $this->createMock(\Swift_Mailer::class);
140+
141+
$swiftMailer->expects($this->once())
142+
->method('send')
143+
->with($this->callback(function (\Swift_Message $message) use ($subject, $body, $user): bool {
144+
return $subject === $message->getSubject()
145+
&& $body === $message->getBody()
146+
&& $this->emailFrom === $message->getFrom()
147+
&& \array_key_exists((string) $user->getEmail(), $message->getTo());
148+
}));
149+
150+
(new Mailer($this->router, $this->templating, $swiftMailer, $this->emailFrom, $this->template))->sendResettingEmailMessage($user);
151+
}
152+
104153
public function emailTemplateData(): array
105154
{
106155
return [

0 commit comments

Comments
 (0)