vendor/boldr/cms-bundle/src/EventSubscriber/LocaleSubscriber.php line 144

Open in your IDE?
  1. <?php
  2. namespace Boldr\Cms\CmsBundle\EventSubscriber;
  3. use Boldr\Cms\CmsBundle\Locale\LocaleDeterminerInterface;
  4. use Boldr\Cms\CmsBundle\Controller\PermalinkController;
  5. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  6. use Symfony\Component\HttpKernel\KernelEvents;
  7. use Symfony\Component\HttpKernel\Event\{ RequestEventResponseEvent };
  8. use Symfony\Component\HttpFoundation\{ RequestRedirectResponseHeaderUtils };
  9. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  10. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  11. class LocaleSubscriber implements EventSubscriberInterface
  12. {
  13.     /**
  14.      * @var string[]
  15.      */
  16.     private array $enabledLocales;
  17.     /**
  18.      * @var iterable<LocaleDeterminerInterface>
  19.      */
  20.     private iterable $localeDeterminers;
  21.     /**
  22.      * @var array<string,string|array>
  23.      */
  24.     private array $localeBaseUrls;
  25.     private UrlGeneratorInterface $urlGenerator;
  26.     private PermalinkController $permalinkController;
  27.     private bool $prefixPermalinksWithLocale;
  28.     private bool $useHeaderLocale;
  29.     /**
  30.      * @param string[] $enabledLocales
  31.      * @param iterable<LocaleDeterminerInterface> $localeDeterminers
  32.      */
  33.     public function __construct(
  34.         array $enabledLocales,
  35.         iterable $localeDeterminers,
  36.         array $localeBaseUrls,
  37.         UrlGeneratorInterface $urlGenerator,
  38.         PermalinkController $permalinkController,
  39.         bool $prefixPermalinksWithLocale,
  40.         bool $useHeaderLocale
  41.     )
  42.     {
  43.         $this->enabledLocales $enabledLocales;
  44.         $this->localeDeterminers $localeDeterminers;
  45.         $this->localeBaseUrls $localeBaseUrls;
  46.         $this->urlGenerator $urlGenerator;
  47.         $this->permalinkController $permalinkController;
  48.         $this->prefixPermalinksWithLocale $prefixPermalinksWithLocale;
  49.         $this->useHeaderLocale $useHeaderLocale;
  50.     }
  51.     public static function getSubscribedEvents()
  52.     {
  53.         return [
  54.             KernelEvents::REQUEST => [['onKernelRequest'25]],
  55.             KernelEvents::RESPONSE => [['onKernelResponse']]
  56.         ];
  57.     }
  58.     public function onKernelResponse(ResponseEvent $event)
  59.     {
  60.         $request $event->getRequest();
  61.         $urls = [];
  62.         /** @var array<string,string> */
  63.         if ($request->attributes->has('_permalinkable'))
  64.         {
  65.             foreach ($this->enabledLocales as $locale)
  66.             {
  67.                 $urls[$locale] = $this->permalinkController->generate($request->attributes->get('_permalinkable'), $locale);
  68.             }
  69.         }
  70.         elseif ($request->attributes->has('_route'))
  71.         {
  72.             foreach ($this->enabledLocales as $locale)
  73.             {
  74.                 $urls[$locale] = $this->urlGenerator->generate(
  75.                     $request->attributes->get('_route'),
  76.                     array_merge(
  77.                         $request->attributes->get('_route_params') ?: [],
  78.                         $request->query->all(),
  79.                         ['_locale' => $locale]
  80.                     )
  81.                 );
  82.             }
  83.         }
  84.         $response $event->getResponse();
  85.         $linkHeader $response->headers->get('Link');
  86.         $baseUrl $request->getSchemeAndHttpHost() . $request->getBaseUrl();
  87.         foreach ($urls as $locale => $url)
  88.         {
  89.             if (!$url)
  90.             {
  91.                 continue;
  92.             }
  93.             if ($linkHeader)
  94.             {
  95.                 $linkHeader .= ', ';
  96.             }
  97.             $localeBaseUrl $this->localeBaseUrls[$locale] ?? $baseUrl;
  98.             if (is_array($localeBaseUrl))
  99.             {
  100.                 $localeBaseUrl $localeBaseUrl[0];
  101.             }
  102.             $linkHeader .= '<'$localeBaseUrl $url .'>; rel="alternate"; hreflang="'$locale .'"';
  103.         }
  104.         $response->headers->set('Link'$linkHeader);
  105.     }
  106.     private function getAcceptHeaderLocale(Request $request): ?string
  107.     {
  108.         $acceptLanguageHeader $request->headers->get("accept-language");
  109.         if (empty($acceptLanguageHeader))
  110.         {
  111.             return null;
  112.         }
  113.         $arr HeaderUtils::split($acceptLanguageHeader',;');
  114.         if (empty($arr[0][0]))
  115.         {
  116.             return null;
  117.         }
  118.         // Symfony expects underscore instead of dash in locale
  119.         $locale str_replace('-''_'$arr[0][0]);
  120.         return $locale;
  121.     }
  122.     public function onKernelRequest(RequestEvent $event)
  123.     {
  124.         $request $event->getRequest();
  125.         $pathInfo $request->getPathInfo();
  126.         $requestLocale $request->attributes->get('_locale');
  127.         if ($requestLocale === null)
  128.         {
  129.             if ($request->attributes->get('_route') === 'cms_permalink' && $this->prefixPermalinksWithLocale)
  130.             {
  131.                 $parts explode('/'$request->attributes->get('permalink'), 2);
  132.                 if (in_array($parts[0], $this->enabledLocales))
  133.                 {
  134.                     $requestLocale $parts[0];
  135.                 }
  136.             }
  137.         }
  138.         // check baseurl
  139.         $localeSetByBaseUrl false;
  140.         $baseUrl $request->getSchemeAndHttpHost().$request->getBaseUrl();
  141.         foreach ($this->localeBaseUrls as $locale => $localeBaseUrl)
  142.         {
  143.             if (is_array($localeBaseUrl) ? in_array($baseUrl$localeBaseUrl) : $localeBaseUrl === $baseUrl)
  144.             {
  145.                 $request->setLocale($locale);
  146.                 $localeSetByBaseUrl true;
  147.             }
  148.         }
  149.         if (str_starts_with($pathInfo'/boldr-admin/') || str_starts_with($pathInfo'/boldr-admin-api/') || str_starts_with($pathInfo'/boldr-api/'))
  150.         {
  151.             return;
  152.         }
  153.         if (!$localeSetByBaseUrl && $this->useHeaderLocale)
  154.         {
  155.             // Use LocaleDeterminers to determine locale for this request
  156.             // Can be based on headers, sessions, request parameters, cookies, etc.
  157.             $locale $this->getAcceptHeaderLocale($request);
  158.             // Check if the locale is enabled, or if the primary part of the locale is enabled
  159.             if (!in_array($locale$this->enabledLocales))
  160.             {
  161.                 $split explode('_'$locale);
  162.                 $locale $split[0];
  163.                 if (!in_array($locale$this->enabledLocales))
  164.                 {
  165.                     $locale $this->enabledLocales[0];
  166.                 }
  167.             }
  168.             if ($locale !== null)
  169.             {
  170.                 $request->setLocale($locale);
  171.             }
  172.         }
  173.         // Redirect to correct base URL if locale changed
  174.         if ($request->getMethod() === 'GET' && $localeSetByBaseUrl && $requestLocale !== null && $request->getLocale() !== $requestLocale)
  175.         {
  176.             // check baseurl
  177.             if (isset($this->localeBaseUrls[$requestLocale]))
  178.             {
  179.                 $localeBaseUrl $this->localeBaseUrls[$requestLocale];
  180.                 $baseUrl $request->getSchemeAndHttpHost().$request->getBaseUrl();
  181.                 if (is_array($localeBaseUrl) ? in_array($baseUrl$localeBaseUrl) : ($baseUrl !== $localeBaseUrl))
  182.                 {
  183.                     if (null !== $queryString $request->getQueryString())
  184.                     {
  185.                         $queryString '?'.$queryString;
  186.                     }
  187.                     $newUrl = (is_array($localeBaseUrl) ? $localeBaseUrl[0] : $localeBaseUrl) . $request->getPathInfo() . $queryString;
  188.                     $event->setResponse(new RedirectResponse($newUrl));
  189.                     return;
  190.                 }
  191.             }
  192.         }
  193.         // Otherwise just use kernel default locale
  194.     }
  195. }