From 34ba95a9ef728cf52c520945b2a349857b8e64e4 Mon Sep 17 00:00:00 2001 From: core23 Date: Sun, 7 Jul 2024 19:53:04 +0200 Subject: [PATCH] Fix setting locale --- src/EventListener/LocaleEventListener.php | 20 +- .../EventListener/LocaleEventListenerTest.php | 178 ++++++++++++++++++ 2 files changed, 186 insertions(+), 12 deletions(-) create mode 100644 tests/EventListener/LocaleEventListenerTest.php diff --git a/src/EventListener/LocaleEventListener.php b/src/EventListener/LocaleEventListener.php index 0ee9c003..cd7e4700 100644 --- a/src/EventListener/LocaleEventListener.php +++ b/src/EventListener/LocaleEventListener.php @@ -56,8 +56,8 @@ public function onImplicitLogin(UserEvent $event): void return; } - $this->setLocale($event->getRequest(), $user); - $this->setTimezone($event->getRequest(), $user); + $this->setLocale($event->getRequest(), $user->getLocale()); + $this->setTimezone($event->getRequest(), $user->getTimezone()); } public function onSecurityInteractiveLogin(InteractiveLoginEvent $event): void @@ -68,8 +68,8 @@ public function onSecurityInteractiveLogin(InteractiveLoginEvent $event): void return; } - $this->setLocale($event->getRequest(), $user); - $this->setTimezone($event->getRequest(), $user); + $this->setLocale($event->getRequest(), $user->getLocale()); + $this->setTimezone($event->getRequest(), $user->getTimezone()); } public function onKernelRequest(RequestEvent $event): void @@ -92,7 +92,7 @@ public function onTimezoneChanged(UserEvent $event): void $user = $event->getUser(); if ($user instanceof LocaleAwareUser && null !== $event->getRequest()) { - $this->setTimezone($event->getRequest(), $user); + $this->setTimezone($event->getRequest(), $user->getTimezone()); } } @@ -101,11 +101,11 @@ public function onLocaleChanged(UserEvent $event): void $user = $event->getUser(); if ($user instanceof LocaleAwareUser && null !== $event->getRequest()) { - $this->setLocale($event->getRequest(), $user); + $this->setLocale($event->getRequest(), $user->getLocale()); } } - private function setLocale(Request $request, LocaleAwareUser $user): void + private function setLocale(Request $request, ?string $locale): void { if (!$request->hasSession()) { return; @@ -113,8 +113,6 @@ private function setLocale(Request $request, LocaleAwareUser $user): void $session = $request->getSession(); - $locale = $user->getLocale(); - if ('' === $locale || null === $locale) { $session->remove(self::ATTR_LOCALE); @@ -126,7 +124,7 @@ private function setLocale(Request $request, LocaleAwareUser $user): void $session->set(self::ATTR_LOCALE, $locale); } - private function setTimezone(Request $request, LocaleAwareUser $user): void + private function setTimezone(Request $request, ?string $timezone): void { if (!$request->hasSession()) { return; @@ -134,8 +132,6 @@ private function setTimezone(Request $request, LocaleAwareUser $user): void $session = $request->getSession(); - $timezone = $user->getTimezone(); - if ('' === $timezone || null === $timezone) { $session->remove(self::ATTR_TIMEZONE); diff --git a/tests/EventListener/LocaleEventListenerTest.php b/tests/EventListener/LocaleEventListenerTest.php new file mode 100644 index 00000000..16a40d57 --- /dev/null +++ b/tests/EventListener/LocaleEventListenerTest.php @@ -0,0 +1,178 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Nucleos\UserBundle\Tests\EventListener; + +use Nucleos\UserBundle\Event\UserEvent; +use Nucleos\UserBundle\EventListener\LocaleEventListener; +use Nucleos\UserBundle\NucleosUserEvents; +use Nucleos\UserBundle\Tests\App\Entity\TestUser; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\Test\TestBrowserToken; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; +use Symfony\Component\Security\Http\SecurityEvents; +use Symfony\Contracts\Translation\LocaleAwareInterface as LocaleAwareTranslator; + +final class LocaleEventListenerTest extends TestCase +{ + /** + * @var LocaleAwareTranslator&MockObject + */ + private LocaleAwareTranslator $translator; + + private LocaleEventListener $listener; + + protected function setUp(): void + { + $this->translator = $this->createMock(LocaleAwareTranslator::class); + $this->listener = new LocaleEventListener($this->translator); + } + + #[Test] + public function getSubscribedEvents(): void + { + self::assertSame([ + NucleosUserEvents::SECURITY_IMPLICIT_LOGIN => 'onImplicitLogin', + SecurityEvents::INTERACTIVE_LOGIN => 'onSecurityInteractiveLogin', + KernelEvents::REQUEST => [['onKernelRequest', 20]], + NucleosUserEvents::USER_LOCALE_CHANGED => 'onLocaleChanged', + NucleosUserEvents::USER_TIMEZONE_CHANGED => 'onTimezoneChanged', + ], LocaleEventListener::getSubscribedEvents()); + } + + #[Test] + public function onImplicitLogin(): void + { + $session = new Session(new MockArraySessionStorage()); + + $request = new Request(); + $request->setSession($session); + + $user = new TestUser(); + $user->setLocale('fr'); + $user->setTimezone('Europe/Paris'); + + $event = new UserEvent($user, $request); + + $this->translator->expects(self::once()) + ->method('setLocale') + ->with('fr') + ; + + $this->listener->onImplicitLogin($event); + + self::assertSame('fr', $request->getLocale()); + self::assertSame('fr', $session->get('_locale')); + self::assertSame('Europe/Paris', $session->get('_timezone')); + } + + #[Test] + public function onSecurityInteractiveLogin(): void + { + $session = new Session(new MockArraySessionStorage()); + + $request = new Request(); + $request->setSession($session); + + $user = new TestUser(); + $user->setLocale('fr'); + $user->setTimezone('Europe/Paris'); + + $event = new InteractiveLoginEvent($request, new TestBrowserToken(user: $user)); + + $this->translator->expects(self::once()) + ->method('setLocale') + ->with('fr') + ; + + $this->listener->onSecurityInteractiveLogin($event); + + self::assertSame('fr', $request->getLocale()); + self::assertSame('fr', $session->get('_locale')); + self::assertSame('Europe/Paris', $session->get('_timezone')); + } + + #[Test] + public function onKernelRequest(): void + { + $session = new Session(new MockArraySessionStorage()); + $session->set('_locale', 'fr'); + $session->set('_timezone', 'Europe/Paris'); + + $request = new Request(); + $request->setSession($session); + $request->cookies->set($session->getName(), $session->getId()); + + $event = new RequestEvent($this->createMock(KernelInterface::class), $request, HttpKernelInterface::MAIN_REQUEST); + + $this->translator->expects(self::once()) + ->method('setLocale') + ->with('fr') + ; + + $this->listener->onKernelRequest($event); + + self::assertSame('fr', $request->getLocale()); + self::assertSame('fr', $session->get('_locale')); + self::assertSame('Europe/Paris', $session->get('_timezone')); + } + + #[Test] + public function onTimezoneChanged(): void + { + $session = new Session(new MockArraySessionStorage()); + + $request = new Request(); + $request->setSession($session); + + $user = new TestUser(); + $user->setTimezone('Europe/Paris'); + + $event = new UserEvent($user, $request); + + $this->listener->onTimezoneChanged($event); + + self::assertSame('Europe/Paris', $session->get('_timezone')); + } + + #[Test] + public function onLocaleChanged(): void + { + $session = new Session(new MockArraySessionStorage()); + + $request = new Request(); + $request->setSession($session); + + $user = new TestUser(); + $user->setLocale('de'); + + $event = new UserEvent($user, $request); + + $this->translator->expects(self::once()) + ->method('setLocale') + ->with('de') + ; + + $this->listener->onLocaleChanged($event); + + self::assertSame('de', $request->getLocale()); + self::assertSame('de', $session->get('_locale')); + } +}