<?php
namespace AWCmsBundle\EventListener;
use AWCmsBundle\Service\SiteByHostNameProvider;
use AWCmsBundle\Service\SiteProvider;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\HttpKernel\Event\KernelEvent;
use AWCmsBundle\Entity\Site;
use AWCmsBundle\Manager\SiteManager;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
/**
* Class HostListener
*
* @package AWCmsBundle\EventListener
*/
class HostListener
{
private $siteManager;
private $router;
private $siteByHostNameProvider;
/**
* @param SiteManager $siteManager
* @param RouterInterface $router
*/
public function __construct(SiteManager $siteManager, RouterInterface $router, SiteByHostNameProvider $siteByHostNameProvider)
{
$this->siteManager = $siteManager;
$this->router = $router;
$this->siteByHostNameProvider = $siteByHostNameProvider;
}
/**
*
* Executed when loading the page
*
* @author Zilong Qiu
*
* @param GetResponseEvent $event
*
* @throws \Symfony\Component\Config\Definition\Exception\Exception
* @throws \DomainException
*/
public function onKernelRequest(GetResponseEvent $event)
{
$isAdmin = preg_match('|^/[a-z]{0,2}/admin/|', $event->getRequest()->getRequestUri());
$sessionSiteId = $event->getRequest()->getSession()->get('site');
if(!$isAdmin){
$siteHost = $this->siteByHostNameProvider->get($event);
if ($siteHost instanceof Site) {
$this->siteManager->setSite($siteHost);
}
}
if ($sessionSiteId and empty($siteHost)){
if(!$this->siteManager->getSite() or $this->siteManager->getSite()->getId() != $sessionSiteId){
$site = $this->siteManager->getSiteById($sessionSiteId);
$this->siteManager->setSite($site);
}
}
if(!$event->isMasterRequest()){
return;
}
if ($this->siteManager->getSite() and !$isAdmin) {
$site = $this->siteManager->getSite();
if (!$site->getDefaultLanguage()) {
throw new \DomainException('Your site has no default language');
}
// If url have local, (/it/articles) but locale doesn't exist in current site, we redirect to default site locale homepage
preg_match('#^/([a-z]{2})/#i', $event->getRequest()->getRequestUri(), $matches);
$localeUrl = (!empty($matches[1])) ? strtolower($matches[1]) : null;
$locales = $site->getEnabledLanguagesCodes();
if($localeUrl and !in_array($localeUrl, $locales)){
$event->setResponse(new RedirectResponse(
$this->router->generate('show_home_page', ['_locale' => $site->getDefaultLanguage()->getCode()]),
Response::HTTP_TEMPORARY_REDIRECT
));
return;
}
}
// If user on / -> redirecting to best site locale based on user's locale
if($event->getRequest()->getRequestUri() === '/' and $this->siteManager->getSite()){
$languagesCodes = $this->getOrderedLanguages();
$preferredLanguage = $event->getRequest()->getPreferredLanguage($languagesCodes);
if(!$preferredLanguage){
$preferredLanguage = $this->siteManager->getSite()->getDefaultLanguage()->getCode();
}
$event->setResponse(new RedirectResponse(
$this->router->generate('show_home_page', ['_locale' => $preferredLanguage]),
Response::HTTP_TEMPORARY_REDIRECT
));
}
}
/**
* @return array
*/
public function getOrderedLanguages(): array
{
$defaultLanguageCode = $this->siteManager->getSite()->getDefaultLanguage()->getCode();
$languagesCodes = array_values($this->siteManager->getSite()->getLanguagesCodes());
$key = array_search($defaultLanguageCode, $languagesCodes);
if ($key > 0) {
unset($languagesCodes[$key]);
array_unshift($languagesCodes, $defaultLanguageCode);
}
return $languagesCodes;
}
}