vendor/sulu/sulu/src/Sulu/Bundle/WebsiteBundle/Routing/ContentRouteProvider.php line 76

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of Sulu.
  4.  *
  5.  * (c) Sulu GmbH
  6.  *
  7.  * This source file is subject to the MIT license that is bundled
  8.  * with this source code in the file LICENSE.
  9.  */
  10. namespace Sulu\Bundle\WebsiteBundle\Routing;
  11. use PHPCR\RepositoryException;
  12. use Sulu\Bundle\DocumentManagerBundle\Bridge\DocumentInspector;
  13. use Sulu\Bundle\PageBundle\Document\PageDocument;
  14. use Sulu\Component\Content\Compat\Structure\PageBridge;
  15. use Sulu\Component\Content\Compat\StructureManagerInterface;
  16. use Sulu\Component\Content\Document\RedirectType;
  17. use Sulu\Component\Content\Exception\ResourceLocatorMovedException;
  18. use Sulu\Component\Content\Exception\ResourceLocatorNotFoundException;
  19. use Sulu\Component\Content\Types\ResourceLocator\Strategy\ResourceLocatorStrategyPoolInterface;
  20. use Sulu\Component\DocumentManager\DocumentManagerInterface;
  21. use Sulu\Component\Webspace\Analyzer\Attributes\RequestAttributes;
  22. use Sulu\Component\Webspace\Analyzer\RequestAnalyzerInterface;
  23. use Sulu\Component\Webspace\Manager\WebspaceManagerInterface;
  24. use Symfony\Cmf\Component\Routing\RouteProviderInterface;
  25. use Symfony\Component\HttpFoundation\Request;
  26. use Symfony\Component\Routing\Route;
  27. use Symfony\Component\Routing\RouteCollection;
  28. /**
  29.  * The PortalRouteProvider should load the dynamic routes created by Sulu.
  30.  */
  31. class ContentRouteProvider implements RouteProviderInterface
  32. {
  33.     /**
  34.      * @var DocumentManagerInterface
  35.      */
  36.     private $documentManager;
  37.     /**
  38.      * @var DocumentInspector
  39.      */
  40.     private $documentInspector;
  41.     /**
  42.      * @var ResourceLocatorStrategyPoolInterface
  43.      */
  44.     private $resourceLocatorStrategyPool;
  45.     /**
  46.      * @var StructureManagerInterface
  47.      */
  48.     private $structureManager;
  49.     /**
  50.      * @var WebspaceManagerInterface
  51.      */
  52.     private $webspaceManager;
  53.     public function __construct(
  54.         DocumentManagerInterface $documentManager,
  55.         DocumentInspector $documentInspector,
  56.         ResourceLocatorStrategyPoolInterface $resourceLocatorStrategyPool,
  57.         StructureManagerInterface $structureManager,
  58.         WebspaceManagerInterface $webspaceManager
  59.     ) {
  60.         $this->documentManager $documentManager;
  61.         $this->documentInspector $documentInspector;
  62.         $this->resourceLocatorStrategyPool $resourceLocatorStrategyPool;
  63.         $this->structureManager $structureManager;
  64.         $this->webspaceManager $webspaceManager;
  65.     }
  66.     public function getRouteCollectionForRequest(Request $request)
  67.     {
  68.         $collection = new RouteCollection();
  69.         if ('' === $request->getRequestFormat()) {
  70.             return $collection;
  71.         }
  72.         /** @var RequestAttributes $attributes */
  73.         $attributes $request->attributes->get('_sulu');
  74.         if (!$attributes) {
  75.             return $collection;
  76.         }
  77.         $matchType $attributes->getAttribute('matchType');
  78.         // no portal information without localization supported
  79.         if (null === $attributes->getAttribute('localization')
  80.             && RequestAnalyzerInterface::MATCH_TYPE_PARTIAL !== $matchType
  81.             && RequestAnalyzerInterface::MATCH_TYPE_REDIRECT !== $matchType
  82.         ) {
  83.             return $collection;
  84.         }
  85.         $resourceLocator $this->decodePathInfo($attributes->getAttribute('resourceLocator'));
  86.         $prefix $attributes->getAttribute('resourceLocatorPrefix');
  87.         $pathInfo $this->decodePathInfo($request->getPathInfo());
  88.         $htmlRedirect $pathInfo !== $prefix $resourceLocator
  89.                         && in_array($request->getRequestFormat(), ['htm''html']);
  90.         if ($htmlRedirect
  91.             || RequestAnalyzerInterface::MATCH_TYPE_REDIRECT == $matchType
  92.             || RequestAnalyzerInterface::MATCH_TYPE_PARTIAL == $matchType
  93.         ) {
  94.             return $collection;
  95.         }
  96.         // just show the page
  97.         $portal $attributes->getAttribute('portal');
  98.         $locale $attributes->getAttribute('localization')->getLocale();
  99.         $resourceLocatorStrategy $this->resourceLocatorStrategyPool->getStrategyByWebspaceKey(
  100.             $portal->getWebspace()->getKey()
  101.         );
  102.         try {
  103.             // load content by url ignore ending trailing slash
  104.             /** @var PageDocument $document */
  105.             $document $this->documentManager->find(
  106.                 $resourceLocatorStrategy->loadByResourceLocator(
  107.                     rtrim($resourceLocator'/'),
  108.                     $portal->getWebspace()->getKey(),
  109.                     $locale
  110.                 ),
  111.                 $locale,
  112.                 [
  113.                     'load_ghost_content' => false,
  114.                 ]
  115.             );
  116.             if (!$document->getTitle()) {
  117.                 // If the title is empty the document does not exist in this locale
  118.                 // Necessary because of https://github.com/sulu/sulu/issues/2724, otherwise locale could be checked
  119.                 return $collection;
  120.             }
  121.             if (preg_match('/\/$/'$resourceLocator) && ('/' !== $resourceLocator || $prefix)) {
  122.                 // redirect page to page without slash at the end
  123.                 $url $prefix rtrim($resourceLocator'/');
  124.                 if ($request->getQueryString()) {
  125.                     $url .= '?' $request->getQueryString();
  126.                 }
  127.                 $collection->add('redirect_' uniqid(), $this->getRedirectRoute($request$url));
  128.             } elseif (RedirectType::INTERNAL === $document->getRedirectType()) {
  129.                 $redirectUrl $this->webspaceManager->findUrlByResourceLocator(
  130.                     $document->getRedirectTarget()->getResourceSegment(),
  131.                     null,
  132.                     $document->getLocale(),
  133.                     $document->getRedirectTarget()->getWebspaceName()
  134.                 );
  135.                 if ($request->getQueryString()) {
  136.                     $redirectUrl .= '?' $request->getQueryString();
  137.                 }
  138.                 $collection->add(
  139.                     $document->getStructureType() . '_' $document->getUuid(),
  140.                     $this->getRedirectRoute($request$redirectUrl)
  141.                 );
  142.             } elseif (RedirectType::EXTERNAL === $document->getRedirectType()) {
  143.                 $collection->add(
  144.                     $document->getStructureType() . '_' $document->getUuid(),
  145.                     $this->getRedirectRoute($request$document->getRedirectExternal())
  146.                 );
  147.             } elseif (!$this->checkResourceLocator($resourceLocator$prefix)) {
  148.                 return $collection;
  149.             } else {
  150.                 // convert the page to a StructureBridge because of BC
  151.                 $metadata $this->documentInspector->getStructureMetadata($document);
  152.                 if (!$metadata) {
  153.                     return $collection;
  154.                 }
  155.                 /** @var PageBridge $structure */
  156.                 $structure $this->structureManager->wrapStructure(
  157.                     $this->documentInspector->getMetadata($document)->getAlias(),
  158.                     $metadata
  159.                 );
  160.                 $structure->setDocument($document);
  161.                 // show the page
  162.                 $collection->add(
  163.                     $document->getStructureType() . '_' $document->getUuid(),
  164.                     $this->getStructureRoute($request$structure)
  165.                 );
  166.             }
  167.         } catch (ResourceLocatorNotFoundException $exc) {
  168.             // just do not add any routes to the collection
  169.         } catch (ResourceLocatorMovedException $exc) {
  170.             // old url resource was moved
  171.             $collection->add(
  172.                 $exc->getNewResourceLocatorUuid() . '_' uniqid(),
  173.                 $this->getRedirectRoute($request$prefix $exc->getNewResourceLocator())
  174.             );
  175.         } catch (RepositoryException $exc) {
  176.             // just do not add any routes to the collection
  177.         }
  178.         return $collection;
  179.     }
  180.     public function getRouteByName($name$parameters = [])
  181.     {
  182.         // TODO: Implement getRouteByName() method.
  183.     }
  184.     public function getRoutesByNames($names$parameters = [])
  185.     {
  186.         // TODO
  187.         return [];
  188.     }
  189.     /**
  190.      * Checks if the resource locator is valid.
  191.      * A resource locator with a slash only is not allowed, the only exception is when it is a single language
  192.      * website, where the browser automatically adds the slash.
  193.      *
  194.      * @param string $resourceLocator
  195.      * @param string $resourceLocatorPrefix
  196.      *
  197.      * @return bool
  198.      */
  199.     private function checkResourceLocator($resourceLocator$resourceLocatorPrefix)
  200.     {
  201.         return !('/' === $resourceLocator && $resourceLocatorPrefix);
  202.     }
  203.     /**
  204.      * @param string $url
  205.      *
  206.      * @return Route
  207.      */
  208.     protected function getRedirectRoute(Request $request$url)
  209.     {
  210.         // redirect to linked page
  211.         return new Route(
  212.             $this->decodePathInfo($request->getPathInfo()),
  213.             [
  214.                 '_controller' => 'sulu_website.redirect_controller:redirectAction',
  215.                 'url' => $url,
  216.             ]
  217.         );
  218.     }
  219.     /**
  220.      * @return Route
  221.      */
  222.     protected function getStructureRoute(Request $requestPageBridge $content)
  223.     {
  224.         return new Route(
  225.             $this->decodePathInfo($request->getPathInfo()),
  226.             [
  227.                 '_controller' => $content->getController(),
  228.                 'structure' => $content,
  229.                 'partial' => 'true' === $request->get('partial''false'),
  230.             ]
  231.         );
  232.     }
  233.     /**
  234.      * Server encodes the url and symfony does not encode it
  235.      * Symfony decodes this data here https://github.com/symfony/symfony/blob/3.3/src/Symfony/Component/Routing/Matcher/UrlMatcher.php#L91.
  236.      *
  237.      * @param string $pathInfo
  238.      *
  239.      * @return string
  240.      */
  241.     private function decodePathInfo($pathInfo)
  242.     {
  243.         if (null === $pathInfo || '' === $pathInfo) {
  244.             return '';
  245.         }
  246.         return '/' ltrim(rawurldecode($pathInfo), '/');
  247.     }
  248. }