vendor/pimcore/pimcore/bundles/CoreBundle/EventListener/Frontend/RoutingListener.php line 118

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Commercial License (PCL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PCL
  13.  */
  14. namespace Pimcore\Bundle\CoreBundle\EventListener\Frontend;
  15. use Pimcore\Bundle\CoreBundle\EventListener\Traits\PimcoreContextAwareTrait;
  16. use Pimcore\Config;
  17. use Pimcore\Http\Request\Resolver\PimcoreContextResolver;
  18. use Pimcore\Http\Request\Resolver\SiteResolver;
  19. use Pimcore\Http\RequestHelper;
  20. use Pimcore\Model\DataObject\ClassDefinition\PreviewGeneratorInterface;
  21. use Pimcore\Model\Site;
  22. use Pimcore\Routing\RedirectHandler;
  23. use Pimcore\Tool;
  24. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  25. use Symfony\Component\HttpFoundation\RedirectResponse;
  26. use Symfony\Component\HttpFoundation\Request;
  27. use Symfony\Component\HttpFoundation\Response;
  28. use Symfony\Component\HttpKernel\Event\ExceptionEvent;
  29. use Symfony\Component\HttpKernel\Event\RequestEvent;
  30. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  31. use Symfony\Component\HttpKernel\KernelEvents;
  32. /**
  33.  * Runs before dynamic routing kicks in and resolves site + handles redirects
  34.  *
  35.  * @internal
  36.  */
  37. class RoutingListener implements EventSubscriberInterface
  38. {
  39.     use PimcoreContextAwareTrait;
  40.     /**
  41.      * @param RequestHelper $requestHelper
  42.      * @param RedirectHandler $redirectHandler
  43.      * @param SiteResolver $siteResolver
  44.      * @param Config $config
  45.      */
  46.     public function __construct(
  47.         protected RequestHelper $requestHelper,
  48.         protected RedirectHandler $redirectHandler,
  49.         protected SiteResolver $siteResolver,
  50.         protected Config $config
  51.     ) {
  52.     }
  53.     /**
  54.      * {@inheritdoc}
  55.      */
  56.     public static function getSubscribedEvents(): array
  57.     {
  58.         return [
  59.             // run with high priority as we need to set the site early
  60.             KernelEvents::REQUEST => ['onKernelRequest'512],
  61.             // run with high priority before handling real errors
  62.             KernelEvents::EXCEPTION => ['onKernelException'64],
  63.         ];
  64.     }
  65.     public function onKernelRequest(RequestEvent $event)
  66.     {
  67.         if (!$event->isMainRequest()) {
  68.             return;
  69.         }
  70.         $request $event->getRequest();
  71.         // handle main domain redirect in admin context
  72.         if ($this->matchesPimcoreContext($requestPimcoreContextResolver::CONTEXT_ADMIN)) {
  73.             $this->handleMainDomainRedirect($eventtrue);
  74.             return;
  75.         }
  76.         if (!$this->matchesPimcoreContext($requestPimcoreContextResolver::CONTEXT_DEFAULT)) {
  77.             return;
  78.         }
  79.         $path urldecode($request->getPathInfo());
  80.         // resolve current site from request
  81.         $this->resolveSite($request$path);
  82.         // check for override redirects
  83.         $response $this->redirectHandler->checkForRedirect($requesttrue);
  84.         if ($response) {
  85.             $event->setResponse($response);
  86.             return;
  87.         }
  88.         // check for app.php in URL and remove it for SEO puroposes
  89.         $this->handleFrontControllerRedirect($event$path);
  90.         if ($event->hasResponse()) {
  91.             return;
  92.         }
  93.         // redirect to the main domain if specified
  94.         $this->handleMainDomainRedirect($event);
  95.         if ($event->hasResponse()) {
  96.             return;
  97.         }
  98.     }
  99.     public function onKernelException(ExceptionEvent $event)
  100.     {
  101.         // in case routing didn't find a matching route, check for redirects without override
  102.         $exception $event->getThrowable();
  103.         if ($exception instanceof NotFoundHttpException) {
  104.             $response $this->redirectHandler->checkForRedirect($event->getRequest(), false);
  105.             if ($response) {
  106.                 $event->setResponse($response);
  107.             }
  108.         }
  109.     }
  110.     /**
  111.      * Initialize Site
  112.      *
  113.      * @param Request $request
  114.      * @param string $path
  115.      *
  116.      * @return string
  117.      */
  118.     protected function resolveSite(Request $request$path)
  119.     {
  120.         $site null;
  121.         // check for a registered site
  122.         // do not initialize a site if it is a "special" admin request
  123.         if (!$this->requestHelper->isFrontendRequestByAdmin($request)) {
  124.             // host name without port incl. X-Forwarded-For handling for trusted proxies
  125.             $host $request->getHost();
  126.             $site Site::getByDomain($host);
  127.         } elseif ($this->requestHelper->isObjectPreviewRequestByAdmin($request)) {
  128.             // When rendering an object's preview tab, resolve the site via a parameter
  129.             $siteId $request->query->getInt(PreviewGeneratorInterface::PARAMETER_SITE);
  130.             $site Site::getById($siteId);
  131.         }
  132.         if ($site) {
  133.             $path $site->getRootPath() . $path;
  134.             Site::setCurrentSite($site);
  135.             $this->siteResolver->setSite($request$site);
  136.             $this->siteResolver->setSitePath($request$path);
  137.         }
  138.         return $path;
  139.     }
  140.     /**
  141.      * @param RequestEvent $event
  142.      * @param string $path
  143.      */
  144.     protected function handleFrontControllerRedirect(RequestEvent $event$path)
  145.     {
  146.         $request $event->getRequest();
  147.         // do not allow requests including /app.php/ => SEO
  148.         // this is after the first redirect check, to allow redirects in app.php?xxx
  149.         if (preg_match('@^/app\.php(.*)@'$path$matches) && $request->getMethod() === 'GET') {
  150.             $redirectUrl $matches[1];
  151.             $redirectUrl ltrim($redirectUrl'/');
  152.             $redirectUrl '/' $redirectUrl;
  153.             $event->setResponse(new RedirectResponse($redirectUrlResponse::HTTP_MOVED_PERMANENTLY));
  154.         }
  155.     }
  156.     /**
  157.      * Redirect to the main domain if specified
  158.      *
  159.      * @param RequestEvent $event
  160.      * @param bool $adminContext
  161.      */
  162.     protected function handleMainDomainRedirect(RequestEvent $eventbool $adminContext false)
  163.     {
  164.         $request $event->getRequest();
  165.         $hostRedirect null;
  166.         if ($adminContext) {
  167.             $hostRedirect $this->resolveConfigDomainRedirectHost($request);
  168.         } else {
  169.             if (Site::isSiteRequest()) {
  170.                 $site Site::getCurrentSite();
  171.                 if ($site->getRedirectToMainDomain() && $site->getMainDomain() != $request->getHost()) {
  172.                     $hostRedirect $site->getMainDomain();
  173.                 }
  174.             } else {
  175.                 if (!$this->requestHelper->isFrontendRequestByAdmin()) {
  176.                     $hostRedirect $this->resolveConfigDomainRedirectHost($request);
  177.                 }
  178.             }
  179.         }
  180.         if ($hostRedirect && !$request->query->has('pimcore_disable_host_redirect')) {
  181.             $qs '';
  182.             if (null !== $qs $request->getQueryString()) {
  183.                 $qs '?' $qs;
  184.             }
  185.             $url $request->getScheme() . '://' $hostRedirect $request->getBaseUrl() . $request->getPathInfo() . $qs;
  186.             // TODO use symfony logger service
  187.             // log all redirects to the redirect log
  188.             \Pimcore\Log\Simple::log('redirect'Tool::getAnonymizedClientIp() . " \t Host-Redirect Source: " $request->getRequestUri() . ' -> ' $url);
  189.             $event->setResponse(new RedirectResponse($urlResponse::HTTP_MOVED_PERMANENTLY));
  190.         }
  191.     }
  192.     private function resolveConfigDomainRedirectHost(Request $request)
  193.     {
  194.         $hostRedirect null;
  195.         $gc $this->config['general'];
  196.         if (isset($gc['redirect_to_maindomain']) && $gc['redirect_to_maindomain'] === true && isset($gc['domain']) && $gc['domain'] !== $request->getHost()) {
  197.             $hostRedirect $gc['domain'];
  198.         }
  199.         return $hostRedirect;
  200.     }
  201. }