From b93fc86bb29dbeb332385d1d8a3facfb2e8319b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Poirier=20Th=C3=A9or=C3=AAt?= Date: Mon, 18 Dec 2023 12:21:24 -0500 Subject: [PATCH] [Mailer] Support for localise email --- .../Integration/MailerIntegration.php | 10 +++++ .../Integration/MailerIntegrationTest.php | 7 ++++ .../BodyRenderer/LocalizeBodyRenderer.php | 40 +++++++++++++++++++ .../mailer/Email/LocalizeEmailInterface.php | 8 ++++ packages/mailer/EmailComposer.php | 37 +++++++++++++---- packages/mailer/Tests/EmailComposerTest.php | 38 +++++++++++++++++- 6 files changed, 132 insertions(+), 8 deletions(-) create mode 100644 packages/mailer/BodyRenderer/LocalizeBodyRenderer.php create mode 100644 packages/mailer/Email/LocalizeEmailInterface.php diff --git a/packages/framework-extra-bundle/DependencyInjection/Integration/MailerIntegration.php b/packages/framework-extra-bundle/DependencyInjection/Integration/MailerIntegration.php index 711e6de9..5ef3d9a9 100644 --- a/packages/framework-extra-bundle/DependencyInjection/Integration/MailerIntegration.php +++ b/packages/framework-extra-bundle/DependencyInjection/Integration/MailerIntegration.php @@ -2,6 +2,7 @@ namespace Draw\Bundle\FrameworkExtraBundle\DependencyInjection\Integration; +use Draw\Component\Mailer\BodyRenderer\LocalizeBodyRenderer; use Draw\Component\Mailer\EmailComposer; use Draw\Component\Mailer\EmailWriter\DefaultFromEmailWriter; use Draw\Component\Mailer\EmailWriter\EmailWriterInterface; @@ -12,6 +13,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\Mime\Address; class MailerIntegration implements IntegrationInterface, PrependIntegrationInterface @@ -33,6 +35,14 @@ public function load(array $config, PhpFileLoader $loader, ContainerBuilder $con ), ); + $container + ->getDefinition(LocalizeBodyRenderer::class) + ->setDecoratedService( + 'twig.mime_body_renderer', + 'draw.mailer.body_renderer.localize_body_renderer.inner' + ) + ->setArgument('$bodyRenderer', new Reference('draw.mailer.body_renderer.localize_body_renderer.inner')); + $container ->registerForAutoconfiguration(EmailWriterInterface::class) ->addTag(EmailWriterInterface::class); diff --git a/packages/framework-extra-bundle/Tests/DependencyInjection/Integration/MailerIntegrationTest.php b/packages/framework-extra-bundle/Tests/DependencyInjection/Integration/MailerIntegrationTest.php index bdcb6e73..5c590d07 100644 --- a/packages/framework-extra-bundle/Tests/DependencyInjection/Integration/MailerIntegrationTest.php +++ b/packages/framework-extra-bundle/Tests/DependencyInjection/Integration/MailerIntegrationTest.php @@ -4,6 +4,7 @@ use Draw\Bundle\FrameworkExtraBundle\DependencyInjection\Integration\IntegrationInterface; use Draw\Bundle\FrameworkExtraBundle\DependencyInjection\Integration\MailerIntegration; +use Draw\Component\Mailer\BodyRenderer\LocalizeBodyRenderer; use Draw\Component\Mailer\Command\SendTestEmailCommand; use Draw\Component\Mailer\EmailComposer; use Draw\Component\Mailer\EmailWriter\AddTemplateHeaderEmailWriter; @@ -116,6 +117,12 @@ public static function provideTestLoad(): iterable EmailComposer::class, ] ), + new ServiceConfiguration( + 'draw.mailer.body_renderer.localize_body_renderer', + [ + LocalizeBodyRenderer::class, + ] + ), new ServiceConfiguration( 'draw.mailer.email_writer.add_template_header_email_writer', [ diff --git a/packages/mailer/BodyRenderer/LocalizeBodyRenderer.php b/packages/mailer/BodyRenderer/LocalizeBodyRenderer.php new file mode 100644 index 00000000..78f6d025 --- /dev/null +++ b/packages/mailer/BodyRenderer/LocalizeBodyRenderer.php @@ -0,0 +1,40 @@ +translator = $translator; + } + } + + public function render(Message $message): void + { + $currentLocale = null; + if ($this->translator && $message instanceof LocalizeEmailInterface && $message->getLocale()) { + $currentLocale = $this->translator->getLocale(); + $this->translator->setLocale($message->getLocale()); + } + + try { + $this->bodyRenderer->render($message); + } finally { + if ($currentLocale) { + $this->translator?->setLocale($currentLocale); + } + } + } +} diff --git a/packages/mailer/Email/LocalizeEmailInterface.php b/packages/mailer/Email/LocalizeEmailInterface.php new file mode 100644 index 00000000..031acdff --- /dev/null +++ b/packages/mailer/Email/LocalizeEmailInterface.php @@ -0,0 +1,8 @@ +translator = $translator; + } } public function compose(Message $message, Envelope $envelope): void { - foreach ($this->getTypes($message) as $type) { - foreach ($this->getWriters($type) as $writerConfiguration) { - [$writer, $writerMethod] = $writerConfiguration; - $writer = $writer instanceof EmailWriterInterface ? $writer : $this->serviceLocator->get($writer); - \call_user_func([$writer, $writerMethod], $message, $envelope); + $currentLocale = null; + + if ($this->translator && $message instanceof LocalizeEmailInterface && $message->getLocale()) { + $currentLocale = $this->translator->getLocale(); + $this->translator->setLocale($message->getLocale()); + } + + try { + foreach ($this->getTypes($message) as $type) { + foreach ($this->getWriters($type) as $writerConfiguration) { + [$writer, $writerMethod] = $writerConfiguration; + $writer = $writer instanceof EmailWriterInterface ? $writer : $this->serviceLocator->get($writer); + \call_user_func([$writer, $writerMethod], $message, $envelope); + } + } + } finally { + if ($currentLocale) { + $this->translator?->setLocale($currentLocale); } } } diff --git a/packages/mailer/Tests/EmailComposerTest.php b/packages/mailer/Tests/EmailComposerTest.php index d5ddca03..93af4bd5 100644 --- a/packages/mailer/Tests/EmailComposerTest.php +++ b/packages/mailer/Tests/EmailComposerTest.php @@ -2,6 +2,7 @@ namespace Draw\Component\Mailer\Tests; +use Draw\Component\Mailer\Email\LocalizeEmailInterface; use Draw\Component\Mailer\EmailComposer; use Draw\Component\Mailer\EmailWriter\EmailWriterInterface; use Draw\Component\Tester\MockTrait; @@ -14,19 +15,24 @@ use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Email; use Symfony\Component\Mime\Message; +use Symfony\Component\Translation\Translator; #[CoversClass(EmailComposer::class)] class EmailComposerTest extends TestCase { use MockTrait; + private EmailComposer $object; private ContainerInterface&MockObject $serviceLocator; + private Translator&MockObject $translator; + protected function setUp(): void { $this->object = new EmailComposer( - $this->serviceLocator = $this->createMock(ContainerInterface::class) + $this->serviceLocator = $this->createMock(ContainerInterface::class), + $this->translator = $this->createMock(Translator::class) ); } @@ -156,4 +162,34 @@ public function compose2(Message $email): void static::assertSame(1, $emailWriter->compose1CallCounter); static::assertSame(1, $emailWriter->compose2CallCounter); } + + public function testComposeLocalizeEmail(): void + { + $message = new class() extends Email implements LocalizeEmailInterface { + public function getLocale(): ?string + { + return 'fr'; + } + }; + + $this->translator + ->expects(static::once()) + ->method('getLocale') + ->willReturn('en'); + + $this->translator + ->expects(static::exactly(2)) + ->method('setLocale') + ->with( + ...static::withConsecutive( + ['fr'], + ['en'] + ) + ); + + $this->object->compose( + $message, + new Envelope(new Address('test@example.com'), [new Address('test@example.com')]) + ); + } }