Mailer: Use users locale for translation

This commit is contained in:
Igor Scheller 2019-10-06 21:03:20 +02:00
parent 24bfc29220
commit faf74150e9
5 changed files with 141 additions and 53 deletions

View File

@ -40,8 +40,10 @@ class TranslationServiceProvider extends ServiceProvider
'localeChangeCallback' => [$this, 'setLocale'], 'localeChangeCallback' => [$this, 'setLocale'],
] ]
); );
$this->app->instance(Translator::class, $translator); $this->app->singleton(Translator::class, function () use ($translator) {
$this->app->instance('translator', $translator); return $translator;
});
$this->app->alias(Translator::class, 'translator');
} }
/** /**

View File

@ -2,6 +2,8 @@
namespace Engelsystem\Mail; namespace Engelsystem\Mail;
use Engelsystem\Helpers\Translation\Translator;
use Engelsystem\Models\User\User;
use Engelsystem\Renderer\Renderer; use Engelsystem\Renderer\Renderer;
use Swift_Mailer as SwiftMailer; use Swift_Mailer as SwiftMailer;
@ -10,30 +12,75 @@ class EngelsystemMailer extends Mailer
/** @var Renderer|null */ /** @var Renderer|null */
protected $view; protected $view;
/** @var Translator|null */
protected $translation;
/** @var string */ /** @var string */
protected $subjectPrefix = null; protected $subjectPrefix = null;
/** /**
* @param SwiftMailer $mailer * @param SwiftMailer $mailer
* @param Renderer $view * @param Renderer $view
* @param Translator $translation
*/ */
public function __construct(SwiftMailer $mailer, Renderer $view = null) public function __construct(SwiftMailer $mailer, Renderer $view = null, Translator $translation = null)
{ {
parent::__construct($mailer); parent::__construct($mailer);
$this->translation = $translation;
$this->view = $view; $this->view = $view;
} }
/**
* @param string|string[]|User $to
* @param string $subject
* @param string $template
* @param array $data
* @param string|null $locale
* @return int
*/
public function sendViewTranslated(
$to,
string $subject,
string $template,
array $data = [],
?string $locale = null
): int {
if ($to instanceof User) {
$locale = $locale ?: $to->settings->language;
$to = $to->contact->email ? $to->contact->email : $to->email;
}
$activeLocale = null;
if (
$locale
&& $this->translation
&& isset($this->translation->getLocales()[$locale])
) {
$activeLocale = $this->translation->getLocale();
$this->translation->setLocale($locale);
}
$subject = $this->translation ? $this->translation->translate($subject) : $subject;
$sentMails = $this->sendView($to, $subject, $template, $data);
if ($activeLocale) {
$this->translation->setLocale($activeLocale);
}
return $sentMails;
}
/** /**
* Send a template * Send a template
* *
* @param string $to * @param string|string[] $to
* @param string $subject * @param string $subject
* @param string $template * @param string $template
* @param array $data * @param array $data
* @return int * @return int
*/ */
public function sendView($to, $subject, $template, $data = []): int public function sendView($to, string $subject, string $template, array $data = []): int
{ {
$body = $this->view->render($template, $data); $body = $this->view->render($template, $data);

View File

@ -21,7 +21,7 @@ class TranslationServiceProviderTest extends ServiceProviderTest
$locales = ['fo_OO' => 'Foo', 'fo_OO.BAR' => 'Foo (Bar)', 'te_ST.WTF-9' => 'WTF\'s Testing?']; $locales = ['fo_OO' => 'Foo', 'fo_OO.BAR' => 'Foo (Bar)', 'te_ST.WTF-9' => 'WTF\'s Testing?'];
$config = new Config(['locales' => $locales, 'default_locale' => $defaultLocale]); $config = new Config(['locales' => $locales, 'default_locale' => $defaultLocale]);
$app = $this->getApp(['make', 'instance', 'get']); $app = $this->getApp(['make', 'singleton', 'alias', 'get']);
/** @var Session|MockObject $session */ /** @var Session|MockObject $session */
$session = $this->createMock(Session::class); $session = $this->createMock(Session::class);
/** @var Translator|MockObject $translator */ /** @var Translator|MockObject $translator */
@ -60,12 +60,16 @@ class TranslationServiceProviderTest extends ServiceProviderTest
) )
->willReturn($translator); ->willReturn($translator);
$app->expects($this->exactly(2)) $app->expects($this->once())
->method('instance') ->method('singleton')
->withConsecutive( ->willReturnCallback(function (string $abstract, callable $callback) use ($translator) {
[Translator::class, $translator], $this->assertEquals(Translator::class, $abstract);
['translator', $translator] $this->assertEquals($translator, $callback());
); });
$app->expects($this->once())
->method('alias')
->with(Translator::class, 'translator');
$serviceProvider->register(); $serviceProvider->register();
} }

View File

@ -2,15 +2,22 @@
namespace Engelsystem\Test\Unit\Mail; namespace Engelsystem\Test\Unit\Mail;
use Engelsystem\Helpers\Translation\Translator;
use Engelsystem\Mail\EngelsystemMailer; use Engelsystem\Mail\EngelsystemMailer;
use Engelsystem\Models\User\Contact;
use Engelsystem\Models\User\Settings;
use Engelsystem\Models\User\User;
use Engelsystem\Renderer\Renderer; use Engelsystem\Renderer\Renderer;
use Engelsystem\Test\Unit\HasDatabase;
use Engelsystem\Test\Unit\TestCase;
use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Swift_Mailer as SwiftMailer; use Swift_Mailer as SwiftMailer;
use Swift_Message as SwiftMessage; use Swift_Message as SwiftMessage;
class EngelsystemMailerTest extends TestCase class EngelsystemMailerTest extends TestCase
{ {
use HasDatabase;
/** /**
* @covers \Engelsystem\Mail\EngelsystemMailer::__construct * @covers \Engelsystem\Mail\EngelsystemMailer::__construct
* @covers \Engelsystem\Mail\EngelsystemMailer::sendView * @covers \Engelsystem\Mail\EngelsystemMailer::sendView
@ -24,21 +31,69 @@ class EngelsystemMailerTest extends TestCase
/** @var EngelsystemMailer|MockObject $mailer */ /** @var EngelsystemMailer|MockObject $mailer */
$mailer = $this->getMockBuilder(EngelsystemMailer::class) $mailer = $this->getMockBuilder(EngelsystemMailer::class)
->setConstructorArgs(['mailer' => $swiftMailer, 'view' => $view]) ->setConstructorArgs(['mailer' => $swiftMailer, 'view' => $view])
->setMethods(['send']) ->onlyMethods(['send'])
->getMock(); ->getMock();
$mailer->expects($this->once()) $this->setExpects($mailer, 'send', ['foo@bar.baz', 'Lorem dolor', 'Rendered Stuff!'], 1);
->method('send') $this->setExpects($view, 'render', ['test/template.tpl', ['dev' => true]], 'Rendered Stuff!');
->with('foo@bar.baz', 'Lorem dolor', 'Rendered Stuff!')
->willReturn(1);
$view->expects($this->once())
->method('render')
->with('test/template.tpl', ['dev' => true])
->willReturn('Rendered Stuff!');
$return = $mailer->sendView('foo@bar.baz', 'Lorem dolor', 'test/template.tpl', ['dev' => true]); $return = $mailer->sendView('foo@bar.baz', 'Lorem dolor', 'test/template.tpl', ['dev' => true]);
$this->equalTo(1, $return); $this->equalTo(1, $return);
} }
/**
* @covers \Engelsystem\Mail\EngelsystemMailer::sendViewTranslated
*/
public function testSendViewTranslated()
{
$this->initDatabase();
$settings = new Settings([
'language' => 'de_DE',
'theme' => '',
]);
$contact = new Contact(['email' => null]);
$user = new User([
'id' => 42,
'name' => 'username',
'email' => 'foo@bar.baz',
'password' => '',
'api_key' => '',
]);
$user->save();
$settings->user()->associate($user)->save();
$contact->user()->associate($user)->save();
/** @var Renderer|MockObject $view */
$view = $this->createMock(Renderer::class);
/** @var SwiftMailer|MockObject $swiftMailer */
$swiftMailer = $this->createMock(SwiftMailer::class);
/** @var Translator|MockObject $translator */
$translator = $this->createMock(Translator::class);
/** @var EngelsystemMailer|MockObject $mailer */
$mailer = $this->getMockBuilder(EngelsystemMailer::class)
->setConstructorArgs(['mailer' => $swiftMailer, 'view' => $view, 'translation' => $translator])
->onlyMethods(['sendView'])
->getMock();
$this->setExpects($mailer, 'sendView', ['foo@bar.baz', 'Lorem dolor', 'test/template.tpl', ['dev' => true]], 1);
$this->setExpects($translator, 'getLocales', null, ['de_DE' => 'de_DE', 'en_US' => 'en_US']);
$this->setExpects($translator, 'getLocale', null, 'en_US');
$this->setExpects($translator, 'translate', ['translatable.text'], 'Lorem dolor');
$translator->expects($this->exactly(2))
->method('setLocale')
->withConsecutive(['de_DE'], ['en_US']);
$return = $mailer->sendViewTranslated(
$user,
'translatable.text',
'test/template.tpl',
['dev' => true],
'de_DE'
);
$this->equalTo(1, $return);
}
/** /**
* @covers \Engelsystem\Mail\EngelsystemMailer::getSubjectPrefix * @covers \Engelsystem\Mail\EngelsystemMailer::getSubjectPrefix
* @covers \Engelsystem\Mail\EngelsystemMailer::send * @covers \Engelsystem\Mail\EngelsystemMailer::send
@ -50,32 +105,12 @@ class EngelsystemMailerTest extends TestCase
$message = $this->createMock(SwiftMessage::class); $message = $this->createMock(SwiftMessage::class);
/** @var SwiftMailer|MockObject $swiftMailer */ /** @var SwiftMailer|MockObject $swiftMailer */
$swiftMailer = $this->createMock(SwiftMailer::class); $swiftMailer = $this->createMock(SwiftMailer::class);
$swiftMailer->expects($this->once()) $this->setExpects($swiftMailer, 'createMessage', null, $message);
->method('createMessage') $this->setExpects($swiftMailer, 'send', null, 1);
->willReturn($message); $this->setExpects($message, 'setTo', [['to@xam.pel']], $message);
$swiftMailer->expects($this->once()) $this->setExpects($message, 'setFrom', ['foo@bar.baz', 'Lorem Ipsum'], $message);
->method('send') $this->setExpects($message, 'setSubject', ['[Mail test] Foo Bar'], $message);
->willReturn(1); $this->setExpects($message, 'setBody', ['Lorem Ipsum!'], $message);
$message->expects($this->once())
->method('setTo')
->with(['to@xam.pel'])
->willReturn($message);
$message->expects($this->once())
->method('setFrom')
->with('foo@bar.baz', 'Lorem Ipsum')
->willReturn($message);
$message->expects($this->once())
->method('setSubject')
->with('[Mail test] Foo Bar')
->willReturn($message);
$message->expects($this->once())
->method('setBody')
->with('Lorem Ipsum!')
->willReturn($message);
$mailer = new EngelsystemMailer($swiftMailer); $mailer = new EngelsystemMailer($swiftMailer);
$mailer->setFromAddress('foo@bar.baz'); $mailer->setFromAddress('foo@bar.baz');

View File

@ -2,8 +2,8 @@
namespace Engelsystem\Test\Unit; namespace Engelsystem\Test\Unit;
use PHPUnit\Framework\MockObject\Matcher\InvokedRecorder;
use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
use PHPUnit\Framework\TestCase as PHPUnitTestCase; use PHPUnit\Framework\TestCase as PHPUnitTestCase;
abstract class TestCase extends PHPUnitTestCase abstract class TestCase extends PHPUnitTestCase
@ -13,7 +13,7 @@ abstract class TestCase extends PHPUnitTestCase
* @param string $method * @param string $method
* @param array $arguments * @param array $arguments
* @param mixed $return * @param mixed $return
* @param InvokedRecorder $times * @param InvocationOrder $times
*/ */
protected function setExpects($object, $method, $arguments = null, $return = null, $times = null) protected function setExpects($object, $method, $arguments = null, $return = null, $times = null)
{ {