/lib/Routing/Element/Router.php

https://github.com/pimcore/pimcore · PHP · 210 lines · 124 code · 26 blank · 60 comment · 21 complexity · 416f342bea85fcab6f950710d3ef16f0 MD5 · raw file

  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 Commercial License (PCL)
  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 PCL
  13. */
  14. namespace Pimcore\Routing\Element;
  15. use Pimcore\Http\RequestHelper;
  16. use Pimcore\Model\Asset;
  17. use Pimcore\Model\DataObject\Concrete;
  18. use Pimcore\Model\Document;
  19. use Pimcore\Model\Element\ElementInterface;
  20. use Symfony\Cmf\Component\Routing\VersatileGeneratorInterface;
  21. use Symfony\Component\HttpFoundation\Request;
  22. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  23. use Symfony\Component\Routing\Exception\RouteNotFoundException;
  24. use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
  25. use Symfony\Component\Routing\RequestContext;
  26. use Symfony\Component\Routing\RouteCollection;
  27. use Symfony\Component\Routing\RouterInterface;
  28. /**
  29. * A custom router implementation handling pimcore elements.
  30. */
  31. class Router implements RouterInterface, RequestMatcherInterface, VersatileGeneratorInterface
  32. {
  33. /**
  34. * @var RequestContext
  35. */
  36. protected $context;
  37. /**
  38. * @var RequestHelper
  39. */
  40. protected $requestHelper;
  41. /**
  42. * @param RequestContext $context
  43. * @param RequestHelper $requestHelper
  44. */
  45. public function __construct(RequestContext $context, RequestHelper $requestHelper)
  46. {
  47. $this->context = $context;
  48. $this->requestHelper = $requestHelper;
  49. }
  50. /**
  51. * {@inheritdoc}
  52. */
  53. public function setContext(RequestContext $context)
  54. {
  55. $this->context = $context;
  56. }
  57. /**
  58. * {@inheritdoc}
  59. *
  60. * @return RequestContext
  61. */
  62. public function getContext()// : RequestContext
  63. {
  64. return $this->context;
  65. }
  66. /**
  67. * {@inheritdoc}
  68. *
  69. * @return bool
  70. */
  71. public function supports($name)// : bool
  72. {
  73. return $name === 'pimcore_element';
  74. }
  75. /**
  76. * {@inheritdoc}
  77. */
  78. public function getRouteDebugMessage($name, array $parameters = [])// : string
  79. {
  80. $element = $parameters['element'] ?? null;
  81. if ($element instanceof ElementInterface) {
  82. return sprintf('Element (Type: %s, ID: %d)', $element->getType(), $element->getId());
  83. }
  84. return 'No element';
  85. }
  86. /**
  87. * {@inheritdoc}
  88. */
  89. public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH)// : string
  90. {
  91. $element = $parameters['element'] ?? null;
  92. unset($parameters['element']);
  93. if ($element instanceof Document || $element instanceof Asset) {
  94. $schemeAuthority = '';
  95. $host = $this->context->getHost();
  96. $scheme = $this->context->getScheme();
  97. $path = $element->getFullPath();
  98. $needsHostname = self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType;
  99. if (strpos($path, '://') !== false) {
  100. $host = parse_url($path, PHP_URL_HOST);
  101. $scheme = parse_url($path, PHP_URL_SCHEME);
  102. $path = parse_url($path, PHP_URL_PATH);
  103. $needsHostname = true;
  104. }
  105. if ($needsHostname) {
  106. if ('' !== $host || ('' !== $scheme && 'http' !== $scheme && 'https' !== $scheme)) {
  107. $port = '';
  108. if ('http' === $scheme && 80 !== $this->context->getHttpPort()) {
  109. $port = ':'.$this->context->getHttpPort();
  110. } elseif ('https' === $scheme && 443 !== $this->context->getHttpsPort()) {
  111. $port = ':'.$this->context->getHttpsPort();
  112. }
  113. $schemeAuthority = self::NETWORK_PATH === $referenceType || '' === $scheme ? '//' : "$scheme://";
  114. $schemeAuthority .= $host.$port;
  115. }
  116. }
  117. $qs = http_build_query($parameters);
  118. if ($qs) {
  119. $qs = '?' . $qs;
  120. }
  121. return $schemeAuthority . $this->context->getBaseUrl() . $path . $qs;
  122. }
  123. if ($element instanceof Concrete) {
  124. $linkGenerator = $element->getClass()->getLinkGenerator();
  125. if ($linkGenerator) {
  126. return $linkGenerator->generate($element, [
  127. 'route' => $this->getCurrentRoute(),
  128. 'parameters' => $parameters,
  129. 'context' => $this,
  130. 'referenceType' => $referenceType,
  131. ]);
  132. }
  133. }
  134. if ($element instanceof ElementInterface) {
  135. throw new RouteNotFoundException(
  136. sprintf(
  137. 'Could not generate URL for element (Type: %s, ID: %d)',
  138. $element->getType(),
  139. $element->getId()
  140. )
  141. );
  142. }
  143. throw new RouteNotFoundException('Could not generate URL for non elements');
  144. }
  145. /**
  146. * Tries to get the current route name from current or master request
  147. *
  148. * @return string|null
  149. */
  150. protected function getCurrentRoute()
  151. {
  152. $route = null;
  153. if ($this->requestHelper->hasCurrentRequest()) {
  154. $route = $this->requestHelper->getCurrentRequest()->attributes->get('_route');
  155. }
  156. if (!$route && $this->requestHelper->hasMainRequest()) {
  157. $route = $this->requestHelper->getMainRequest()->attributes->get('_route');
  158. }
  159. return $route;
  160. }
  161. /**
  162. * {@inheritdoc}
  163. */
  164. public function matchRequest(Request $request)
  165. {
  166. throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $request->getPathInfo()));
  167. }
  168. /**
  169. * {@inheritdoc}
  170. */
  171. public function match($pathinfo)
  172. {
  173. throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo));
  174. }
  175. /**
  176. * {@inheritdoc}
  177. *
  178. * @return RouteCollection
  179. */
  180. public function getRouteCollection()// : RouteCollection
  181. {
  182. return new RouteCollection();
  183. }
  184. }