vendor/pimcore/pimcore/bundles/CoreBundle/EventListener/Frontend/FrontendRoutingListener.php line 94

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 Enterprise License (PEL)
  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 PEL
  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\Site;
  21. use Pimcore\Routing\RedirectHandler;
  22. use Pimcore\Tool;
  23. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  24. use Symfony\Component\HttpFoundation\RedirectResponse;
  25. use Symfony\Component\HttpFoundation\Request;
  26. use Symfony\Component\HttpFoundation\Response;
  27. use Symfony\Component\HttpKernel\Event\GetResponseEvent;
  28. use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
  29. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  30. use Symfony\Component\HttpKernel\KernelEvents;
  31. /**
  32.  * Runs before dynamic routing kicks in and resolves site + handles redirects
  33.  *
  34.  * TODO as this also handles the admin domain, a name without "Frontend" would be more suitable
  35.  */
  36. class FrontendRoutingListener implements EventSubscriberInterface
  37. {
  38.     use PimcoreContextAwareTrait;
  39.     /**
  40.      * @var RequestHelper
  41.      */
  42.     protected $requestHelper;
  43.     /**
  44.      * @var RedirectHandler
  45.      */
  46.     protected $redirectHandler;
  47.     /**
  48.      * @var SiteResolver
  49.      */
  50.     protected $siteResolver;
  51.     /**
  52.      * @var Config
  53.      */
  54.     protected $config;
  55.     /**
  56.      * @param RequestHelper $requestHelper
  57.      * @param RedirectHandler $redirectHandler
  58.      * @param SiteResolver $siteResolver
  59.      */
  60.     public function __construct(
  61.         RequestHelper $requestHelper,
  62.         RedirectHandler $redirectHandler,
  63.         SiteResolver $siteResolver,
  64.         Config $config
  65.     ) {
  66.         $this->requestHelper $requestHelper;
  67.         $this->redirectHandler $redirectHandler;
  68.         $this->siteResolver $siteResolver;
  69.         $this->config $config;
  70.     }
  71.     /**
  72.      * {@inheritdoc}
  73.      */
  74.     public static function getSubscribedEvents()
  75.     {
  76.         return [
  77.             // run with high priority as we need to set the site early
  78.             KernelEvents::REQUEST => ['onKernelRequest'512],
  79.             // run with high priority before handling real errors
  80.             KernelEvents::EXCEPTION => ['onKernelException'64]
  81.         ];
  82.     }
  83.     public function onKernelRequest(GetResponseEvent $event)
  84.     {
  85.         if (!$event->isMasterRequest()) {
  86.             return;
  87.         }
  88.         $request $event->getRequest();
  89.         // handle main domain redirect in admin context
  90.         if ($this->matchesPimcoreContext($requestPimcoreContextResolver::CONTEXT_ADMIN)) {
  91.             $this->handleMainDomainRedirect($eventtrue);
  92.             return;
  93.         }
  94.         if (!$this->matchesPimcoreContext($requestPimcoreContextResolver::CONTEXT_DEFAULT)) {
  95.             return;
  96.         }
  97.         $path urldecode($request->getPathInfo());
  98.         // resolve current site from request
  99.         $this->resolveSite($request$path);
  100.         // check for override redirects
  101.         $response $this->redirectHandler->checkForRedirect($requesttrue);
  102.         if ($response) {
  103.             $event->setResponse($response);
  104.             return;
  105.         }
  106.         // check for app.php in URL and remove it for SEO puroposes
  107.         $this->handleFrontControllerRedirect($event$path);
  108.         if ($event->hasResponse()) {
  109.             return;
  110.         }
  111.         // redirect to the main domain if specified
  112.         $this->handleMainDomainRedirect($event);
  113.         if ($event->hasResponse()) {
  114.             return;
  115.         }
  116.     }
  117.     public function onKernelException(GetResponseForExceptionEvent $event)
  118.     {
  119.         // in case routing didn't find a matching route, check for redirects without override
  120.         $exception $event->getException();
  121.         if ($exception instanceof NotFoundHttpException) {
  122.             $response $this->redirectHandler->checkForRedirect($event->getRequest(), false);
  123.             if ($response) {
  124.                 $event->setResponse($response);
  125.             }
  126.         }
  127.     }
  128.     /**
  129.      * Initialize Site
  130.      *
  131.      * @param Request $request
  132.      * @param string $path
  133.      *
  134.      * @return string
  135.      */
  136.     protected function resolveSite(Request $request$path)
  137.     {
  138.         // check for a registered site
  139.         // do not initialize a site if it is a "special" admin request
  140.         if (!$this->requestHelper->isFrontendRequestByAdmin($request)) {
  141.             // host name without port incl. X-Forwarded-For handling for trusted proxies
  142.             $host $request->getHost();
  143.             if ($site Site::getByDomain($host)) {
  144.                 $path $site->getRootPath() . $path;
  145.                 Site::setCurrentSite($site);
  146.                 $this->siteResolver->setSite($request$site);
  147.                 $this->siteResolver->setSitePath($request$path);
  148.             }
  149.         }
  150.         return $path;
  151.     }
  152.     /**
  153.      * @param GetResponseEvent $event
  154.      * @param string $path
  155.      */
  156.     protected function handleFrontControllerRedirect(GetResponseEvent $event$path)
  157.     {
  158.         $request $event->getRequest();
  159.         // do not allow requests including /app.php/ => SEO
  160.         // this is after the first redirect check, to allow redirects in app.php?xxx
  161.         if (preg_match('@^/app\.php(.*)@'$path$matches) && $request->getMethod() === 'GET') {
  162.             $redirectUrl $matches[1];
  163.             $redirectUrl ltrim($redirectUrl'/');
  164.             $redirectUrl '/' $redirectUrl;
  165.             $event->setResponse(new RedirectResponse($redirectUrlResponse::HTTP_MOVED_PERMANENTLY));
  166.         }
  167.     }
  168.     /**
  169.      * Redirect to the main domain if specified
  170.      *
  171.      * @param GetResponseEvent $event
  172.      * @param bool $adminContext
  173.      */
  174.     protected function handleMainDomainRedirect(GetResponseEvent $eventbool $adminContext false)
  175.     {
  176.         $request $event->getRequest();
  177.         $hostRedirect null;
  178.         if ($adminContext) {
  179.             $hostRedirect $this->resolveConfigDomainRedirectHost($request);
  180.         } else {
  181.             if (Site::isSiteRequest()) {
  182.                 $site Site::getCurrentSite();
  183.                 if ($site->getRedirectToMainDomain() && $site->getMainDomain() != $request->getHost()) {
  184.                     $hostRedirect $site->getMainDomain();
  185.                 }
  186.             } else {
  187.                 if (!$this->requestHelper->isFrontendRequestByAdmin()) {
  188.                     $hostRedirect $this->resolveConfigDomainRedirectHost($request);
  189.                 }
  190.             }
  191.         }
  192.         if ($hostRedirect && !$request->query->has('pimcore_disable_host_redirect')) {
  193.             $qs '';
  194.             if (null !== $qs $request->getQueryString()) {
  195.                 $qs '?' $qs;
  196.             }
  197.             $url $request->getScheme() . '://' $hostRedirect $request->getBaseUrl() . $request->getPathInfo() . $qs;
  198.             // TODO use symfony logger service
  199.             // log all redirects to the redirect log
  200.             \Pimcore\Log\Simple::log('redirect'Tool::getAnonymizedClientIp() . " \t Host-Redirect Source: " $request->getRequestUri() . ' -> ' $url);
  201.             $event->setResponse(new RedirectResponse($urlResponse::HTTP_MOVED_PERMANENTLY));
  202.         }
  203.     }
  204.     private function resolveConfigDomainRedirectHost(Request $request)
  205.     {
  206.         $hostRedirect null;
  207.         $gc $this->config['general'];
  208.         if (isset($gc['redirect_to_maindomain']) && $gc['redirect_to_maindomain'] === true && isset($gc['domain']) && $gc['domain'] !== $request->getHost()) {
  209.             $hostRedirect $gc['domain'];
  210.         }
  211.         return $hostRedirect;
  212.     }
  213. }