vendor/sulu/sulu/src/Sulu/Bundle/CustomUrlBundle/Request/CustomUrlRequestProcessor.php line 62

  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\CustomUrlBundle\Request;
  11. use Sulu\Component\Content\Document\WorkflowStage;
  12. use Sulu\Component\CustomUrl\Generator\GeneratorInterface;
  13. use Sulu\Component\CustomUrl\Manager\CustomUrlManagerInterface;
  14. use Sulu\Component\Localization\Localization;
  15. use Sulu\Component\Webspace\Analyzer\Attributes\RequestAttributes;
  16. use Sulu\Component\Webspace\Analyzer\Attributes\RequestProcessorInterface;
  17. use Sulu\Component\Webspace\Analyzer\RequestAnalyzer;
  18. use Sulu\Component\Webspace\Manager\WebspaceManagerInterface;
  19. use Sulu\Component\Webspace\PortalInformation;
  20. use Symfony\Component\HttpFoundation\Request;
  21. /**
  22.  * Set localization in case of custom-url route.
  23.  */
  24. class CustomUrlRequestProcessor implements RequestProcessorInterface
  25. {
  26.     public function __construct(
  27.         private CustomUrlManagerInterface $customUrlManager,
  28.         private GeneratorInterface $generator,
  29.         private WebspaceManagerInterface $webspaceManager,
  30.         private ?string $environment
  31.     ) {
  32.     }
  33.     public function process(Request $requestRequestAttributes $requestAttributes)
  34.     {
  35.         $pathInfo $request->getPathInfo();
  36.         $position \strrpos($pathInfo'.');
  37.         if ($position) {
  38.             $pathInfo \substr($pathInfo0$position);
  39.         }
  40.         $queryString $request->getQueryString();
  41.         if (!empty($queryString)) {
  42.             $queryString '?' $queryString;
  43.         }
  44.         $url $this->decodeUrl(\rtrim(\sprintf('%s%s%s'$request->getHost(), $pathInfo$queryString), '/'));
  45.         $portalInformations $this->webspaceManager->findPortalInformationsByUrl($url$this->environment);
  46.         if (=== \count($portalInformations)) {
  47.             return new RequestAttributes();
  48.         }
  49.         /** @var PortalInformation[] $portalInformations */
  50.         $portalInformations \array_filter(
  51.             $portalInformations,
  52.             function(PortalInformation $portalInformation) {
  53.                 return RequestAnalyzer::MATCH_TYPE_WILDCARD === $portalInformation->getType();
  54.             }
  55.         );
  56.         foreach ($portalInformations as $portalInformation) {
  57.             if (!$portalInformation->getWebspace()) {
  58.                 continue;
  59.             }
  60.             if (null !== $attributes $this->matchCustomUrl($url$portalInformation$request)) {
  61.                 return new RequestAttributes($attributes);
  62.             }
  63.         }
  64.         return new RequestAttributes();
  65.     }
  66.     public function validate(RequestAttributes $attributes)
  67.     {
  68.         return true;
  69.     }
  70.     /**
  71.      * Matches given url to portal-information.
  72.      */
  73.     private function matchCustomUrl(string $urlPortalInformation $portalInformationRequest $request): array
  74.     {
  75.         $webspace $portalInformation->getWebspace();
  76.         $routeDocument $this->customUrlManager->findRouteByUrl(
  77.             \rawurldecode($url),
  78.             $webspace->getKey()
  79.         );
  80.         if (!$routeDocument) {
  81.             return [];
  82.         } elseif ($routeDocument->isHistory()) {
  83.             // redirect happen => no portal is needed
  84.             return ['customUrlRoute' => $routeDocument];
  85.         }
  86.         $customUrlDocument $this->customUrlManager->findByUrl(
  87.             \rawurldecode($url),
  88.             $webspace->getKey(),
  89.             $routeDocument->getTargetDocument()->getTargetLocale()
  90.         );
  91.         if (null === $customUrlDocument
  92.             || false === $customUrlDocument->isPublished()
  93.             || null === $customUrlDocument->getTargetDocument()
  94.             || WorkflowStage::PUBLISHED !== $customUrlDocument->getTargetDocument()->getWorkflowStage()
  95.         ) {
  96.             // error happen because this custom-url is not published => no portal is needed
  97.             return ['customUrlRoute' => $routeDocument'customUrl' => $customUrlDocument];
  98.         }
  99.         $localization Localization::createFromString($customUrlDocument->getTargetLocale());
  100.         $portalInformations $this->webspaceManager->findPortalInformationsByWebspaceKeyAndLocale(
  101.             $portalInformation->getWebspace()->getKey(),
  102.             $localization->getLocale(),
  103.             $this->environment
  104.         );
  105.         if (=== \count($portalInformations)) {
  106.             return ['customUrlRoute' => $routeDocument'customUrl' => $customUrlDocument];
  107.         }
  108.         return [
  109.             'portalInformation' => $portalInformation,
  110.             'localization' => $localization,
  111.             'locale' => $localization->getLocale(),
  112.             'customUrlRoute' => $routeDocument,
  113.             'customUrl' => $customUrlDocument,
  114.             'urlExpression' => $this->generator->generate(
  115.                 $customUrlDocument->getBaseDomain(),
  116.                 $customUrlDocument->getDomainParts()
  117.             ),
  118.         ];
  119.     }
  120.     /**
  121.      * Server encodes the url and symfony does not encode it
  122.      * Symfony decodes this data here https://github.com/symfony/symfony/blob/3.3/src/Symfony/Component/Routing/Matcher/UrlMatcher.php#L91.
  123.      */
  124.     private function decodeUrl(string $pathInfo): string
  125.     {
  126.         return \rawurldecode($pathInfo);
  127.     }
  128. }