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

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\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 $request, RequestAttributes $requestAttributes)
  34. {
  35. $pathInfo = $request->getPathInfo();
  36. $position = \strrpos($pathInfo, '.');
  37. if ($position) {
  38. $pathInfo = \substr($pathInfo, 0, $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 (0 === \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 $url, PortalInformation $portalInformation, Request $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 (0 === \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. }