vendor/pimcore/pimcore/bundles/CoreBundle/EventListener/Frontend/DocumentFallbackListener.php line 117

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\Controller\PublicServicesController;
  16. use Pimcore\Bundle\CoreBundle\EventListener\Traits\PimcoreContextAwareTrait;
  17. use Pimcore\Http\Request\Resolver\DocumentResolver;
  18. use Pimcore\Http\Request\Resolver\PimcoreContextResolver;
  19. use Pimcore\Http\Request\Resolver\SiteResolver;
  20. use Pimcore\Model\Document;
  21. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  22. use Symfony\Component\HttpFoundation\RequestStack;
  23. use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
  24. use Symfony\Component\HttpKernel\Event\GetResponseEvent;
  25. use Symfony\Component\HttpKernel\KernelEvents;
  26. use Symfony\Component\OptionsResolver\OptionsResolver;
  27. /**
  28.  * If no document was found on the active request (not set by router or by initiator of a sub-request), try to find and
  29.  * set a fallback document:
  30.  *
  31.  *  - if request is a sub-request, try to read document from master request
  32.  *  - if all fails, try to find the nearest document by path
  33.  */
  34. class DocumentFallbackListener implements EventSubscriberInterface
  35. {
  36.     use PimcoreContextAwareTrait;
  37.     /**
  38.      * @var RequestStack
  39.      */
  40.     protected $requestStack;
  41.     /**
  42.      * @var DocumentResolver
  43.      */
  44.     protected $documentResolver;
  45.     /**
  46.      * @var SiteResolver
  47.      */
  48.     protected $siteResolver;
  49.     /**
  50.      * @var Document\Service
  51.      */
  52.     protected $documentService;
  53.     /**
  54.      * @var array
  55.      */
  56.     protected $options;
  57.     /**
  58.      * @var Document
  59.      */
  60.     private $fallbackDocument;
  61.     public function __construct(
  62.         RequestStack $requestStack,
  63.         DocumentResolver $documentResolver,
  64.         SiteResolver $siteResolver,
  65.         Document\Service $documentService,
  66.         array $options = []
  67.     ) {
  68.         $this->requestStack $requestStack;
  69.         $this->documentResolver $documentResolver;
  70.         $this->siteResolver $siteResolver;
  71.         $this->documentService $documentService;
  72.         $optionsResolver = new OptionsResolver();
  73.         $this->configureOptions($optionsResolver);
  74.         $this->options $optionsResolver->resolve($options);
  75.     }
  76.     protected function configureOptions(OptionsResolver $optionsResolver)
  77.     {
  78.         $optionsResolver->setDefaults([
  79.             'nearestDocumentTypes' => ['page''snippet''hardlink''link''folder']
  80.         ]);
  81.         $optionsResolver->setAllowedTypes('nearestDocumentTypes''array');
  82.     }
  83.     /**
  84.      * {@inheritdoc}
  85.      */
  86.     public static function getSubscribedEvents()
  87.     {
  88.         return [
  89.             // priority must be before
  90.             // -> Symfony\Component\HttpKernel\EventListener\LocaleListener::onKernelRequest()
  91.             // -> Pimcore\Bundle\CoreBundle\EventListener\Frontend\EditmodeListener::onKernelRequest()
  92.             KernelEvents::REQUEST => ['onKernelRequest'20],
  93.             KernelEvents::CONTROLLER => ['onKernelController'20],
  94.         ];
  95.     }
  96.     /**
  97.      * Finds the nearest document for the current request if the routing/document router didn't find one (e.g. static routes)
  98.      *
  99.      * @param GetResponseEvent $event
  100.      */
  101.     public function onKernelRequest(GetResponseEvent $event)
  102.     {
  103.         $request $event->getRequest();
  104.         if (!$this->matchesPimcoreContext($requestPimcoreContextResolver::CONTEXT_DEFAULT)) {
  105.             return;
  106.         }
  107.         if ($this->documentResolver->getDocument($request)) {
  108.             return;
  109.         }
  110.         if ($event->isMasterRequest()) {
  111.             // no document found yet - try to find the nearest document by request path
  112.             // this is only done on the master request as a sub-request's pathInfo is _fragment when
  113.             // rendered via actions helper
  114.             $path null;
  115.             if ($this->siteResolver->isSiteRequest($request)) {
  116.                 $path $this->siteResolver->getSitePath($request);
  117.             } else {
  118.                 $path urldecode($request->getPathInfo());
  119.             }
  120.             $document $this->documentService->getNearestDocumentByPath($pathfalse$this->options['nearestDocumentTypes']);
  121.             if ($document) {
  122.                 $this->fallbackDocument $document;
  123.                 if ($document->getProperty('language')) {
  124.                     $request->setLocale($document->getProperty('language'));
  125.                 }
  126.             }
  127.         } else {
  128.             // if we're in a sub request and no explicit document is set - try to load document from
  129.             // parent and/or master request and set it on our sub-request
  130.             $parentRequest $this->requestStack->getParentRequest();
  131.             $masterRequest $this->requestStack->getMasterRequest();
  132.             $eligibleRequests = [];
  133.             if (null !== $parentRequest) {
  134.                 $eligibleRequests[] = $parentRequest;
  135.             }
  136.             if ($masterRequest !== $parentRequest) {
  137.                 $eligibleRequests[] = $masterRequest;
  138.             }
  139.             foreach ($eligibleRequests as $eligibleRequest) {
  140.                 if ($document $this->documentResolver->getDocument($eligibleRequest)) {
  141.                     $this->documentResolver->setDocument($request$document);
  142.                     return;
  143.                 }
  144.             }
  145.         }
  146.     }
  147.     public function onKernelController(FilterControllerEvent $event)
  148.     {
  149.         $controller $event->getController();
  150.         if (is_array($controller) && isset($controller[0]) && $controller[0] instanceof PublicServicesController) {
  151.             // ignore PublicServicesController because this could lead to conflicts of Asset and Document paths, see #2704
  152.             return;
  153.         }
  154.         if ($this->fallbackDocument && $event->isMasterRequest()) {
  155.             $this->documentResolver->setDocument($event->getRequest(), $this->fallbackDocument);
  156.         }
  157.     }
  158. }