pimcore/lib/Pimcore/Bundle/CoreBundle/EventListener/Frontend/FrontendRoutingListener.php line 132

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