<?php
declare(strict_types=1);
namespace App\EventSubscriber;
use Doctrine\ORM\EntityManagerInterface;
use phpDocumentor\Reflection\Types\This;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class LocaleSubscriber implements EventSubscriberInterface
{
private $defaultLocale;
/**
* @var UrlMatcherInterface
*/
private $urlMatcher;
/** @var string[] */
private $allowedLanguages = ['en', 'es', 'it', 'fr'];
/**
* LocaleSubscriber constructor.
* @param UrlMatcherInterface $urlMatcher
* @param string $defaultLocale
*/
public function __construct(UrlMatcherInterface $urlMatcher, $defaultLocale = 'en')
{
$this->defaultLocale = $defaultLocale;
$this->urlMatcher = $urlMatcher;
}
/**
* @param RequestEvent $event
*/
public function onKernelRequest(RequestEvent $event)
{
$request = $event->getRequest();
if ($request->attributes->get('_route') == '_wdt') {
return;
}
if ($request->getPathInfo() && strpos($request->getPathInfo(), '_wdt') !== false) {
return;
}
if ($request->attributes->get('_route') && strpos($request->attributes->get('_route'), '_profiler') !== false) {
return;
}
$newUrl = strtolower($request->getPathInfo());
if (preg_match_all("/js\/routing/", $newUrl) || preg_match_all("/[a-z]{2}\/notifications\/widget/", $newUrl)
|| preg_match_all("#/_fragment#", $newUrl)) {
return;
}
$session = $request->getSession();
$cookieForLanguage = $request->cookies->get('preferred_language');
if ($request->attributes->get('path') === '/invalid-route') {
$lang = $this->defaultLocale;
if ($cookieForLanguage) {
$lang = $cookieForLanguage;
$this->setSessionLocale($session, $cookieForLanguage);
}
$event->setResponse(new RedirectResponse($newUrl . $lang));
} else {
$urlLang = $this->extractLanguage($newUrl);
$sessionLocale = $session->get('_locale', $this->defaultLocale);
$attrLocale = $request->attributes->get('_locale');
$localToSet = $this->defaultLocale;
// In case a not valid language has been set in the url, default one will be set
// and request will be redirect to same url with default language
if (!$this->isValidLanguage($urlLang)) {
$newUrlNoLocale = $this->replaceLocale($this->defaultLocale, $newUrl);
$event->setResponse(new RedirectResponse($newUrlNoLocale));
} elseif ($attrLocale && $this->isValidLanguage($attrLocale)) {
$localToSet = $attrLocale;
} elseif ($sessionLocale !== $urlLang) {
$localToSet = $urlLang;
}
$this->setSessionLocale($session, $localToSet);
}
}
/**
* @return array
*/
public static function getSubscribedEvents()
{
return [
// must be registered before (i.e. with a higher priority than) the default Locale listener
KernelEvents::REQUEST => [['onKernelRequest', 20]],
];
}
/**
* @param string $newUrl
* @return mixed
*/
private function extractLanguage(string $newUrl)
{
$languageInUrl = explode("/", substr($newUrl, 1));
return $languageInUrl[0];
}
/**
* @param string $language
* @param string $url
* @return string
*/
private function replaceLocale(string $language, string $url)
{
$indexAfterLocale = strpos(substr($url, 1), "/") + 1;
return "/".$language.substr($url, $indexAfterLocale);
}
private function isValidLanguage(string $localeInNewUrl): bool
{
return in_array($localeInNewUrl, $this->allowedLanguages);
}
/**
* @param SessionInterface $session
* @param string $localToSet
*/
private function setSessionLocale(SessionInterface $session, string $localToSet): void
{
$session->set('_locale', $localToSet);
}
}