Skip to content

Commit

Permalink
[Mailer] Support for localise email
Browse files Browse the repository at this point in the history
  • Loading branch information
mpoiriert committed Dec 18, 2023
1 parent 7144f88 commit b93fc86
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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',
[
Expand Down
40 changes: 40 additions & 0 deletions packages/mailer/BodyRenderer/LocalizeBodyRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Draw\Component\Mailer\BodyRenderer;

use Draw\Component\Mailer\Email\LocalizeEmailInterface;
use Symfony\Component\Mime\BodyRendererInterface;
use Symfony\Component\Mime\Message;
use Symfony\Contracts\Translation\LocaleAwareInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

class LocalizeBodyRenderer implements BodyRendererInterface
{
private ?LocaleAwareInterface $translator = null;

public function __construct(
private BodyRendererInterface $bodyRenderer,
TranslatorInterface $translator
) {
if ($translator instanceof LocaleAwareInterface) {
$this->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);
}
}
}
}
8 changes: 8 additions & 0 deletions packages/mailer/Email/LocalizeEmailInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Draw\Component\Mailer\Email;

interface LocalizeEmailInterface
{
public function getLocale(): ?string;
}
37 changes: 30 additions & 7 deletions packages/mailer/EmailComposer.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,52 @@
namespace Draw\Component\Mailer;

use Draw\Component\Core\Reflection\ReflectionAccessor;
use Draw\Component\Mailer\Email\LocalizeEmailInterface;
use Draw\Component\Mailer\EmailWriter\EmailWriterInterface;
use Psr\Container\ContainerInterface;
use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Mime\Message;
use Symfony\Component\Mime\RawMessage;
use Symfony\Contracts\Translation\LocaleAwareInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

class EmailComposer
{
private array $writers = [];

private array $sortedWriters = [];

public function __construct(private ContainerInterface $serviceLocator)
{
private ?LocaleAwareInterface $translator = null;

public function __construct(
private ContainerInterface $serviceLocator,
TranslatorInterface $translator
) {
if ($translator instanceof LocaleAwareInterface) {
$this->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);
}
}
}
Expand Down
38 changes: 37 additions & 1 deletion packages/mailer/Tests/EmailComposerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
);
}

Expand Down Expand Up @@ -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('[email protected]'), [new Address('[email protected]')])
);
}
}

0 comments on commit b93fc86

Please sign in to comment.