vendor/contao/core-bundle/src/Routing/UrlGenerator.php line 73

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * This file is part of Contao.
  5.  *
  6.  * (c) Leo Feyer
  7.  *
  8.  * @license LGPL-3.0-or-later
  9.  */
  10. namespace Contao\CoreBundle\Routing;
  11. use Contao\Config;
  12. use Contao\CoreBundle\Framework\ContaoFramework;
  13. use Contao\CoreBundle\Util\LocaleUtil;
  14. use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
  15. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  16. use Symfony\Component\Routing\RequestContext;
  17. class UrlGenerator implements UrlGeneratorInterface
  18. {
  19.     private UrlGeneratorInterface $router;
  20.     private ContaoFramework $framework;
  21.     private bool $prependLocale;
  22.     /**
  23.      * @internal
  24.      */
  25.     public function __construct(UrlGeneratorInterface $routerContaoFramework $frameworkbool $prependLocale)
  26.     {
  27.         trigger_deprecation('contao/core-bundle''4.10''Using the "Contao\CoreBundle\Routing\UrlGenerator" class has been deprecated and will no longer work in Contao 5.0. Use the Symfony router instead.');
  28.         $this->router $router;
  29.         $this->framework $framework;
  30.         $this->prependLocale $prependLocale;
  31.     }
  32.     public function setContext(RequestContext $context): void
  33.     {
  34.         $this->router->setContext($context);
  35.     }
  36.     public function getContext(): RequestContext
  37.     {
  38.         return $this->router->getContext();
  39.     }
  40.     public function generate(string $name, array $parameters = [], int $referenceType self::ABSOLUTE_PATH): ?string
  41.     {
  42.         $this->framework->initialize();
  43.         if (!\is_array($parameters)) {
  44.             $parameters = [];
  45.         }
  46.         $context $this->getContext();
  47.         // Store the original request context
  48.         $host $context->getHost();
  49.         $scheme $context->getScheme();
  50.         $httpPort $context->getHttpPort();
  51.         $httpsPort $context->getHttpsPort();
  52.         $this->prepareLocale($parameters);
  53.         $this->prepareAlias($name$parameters);
  54.         $this->prepareDomain($context$parameters$referenceType);
  55.         unset($parameters['auto_item']);
  56.         $url $this->router->generate(
  57.             'index' === $name 'contao_index' 'contao_frontend',
  58.             $parameters,
  59.             $referenceType
  60.         );
  61.         // Reset the request context
  62.         $context->setHost($host);
  63.         $context->setScheme($scheme);
  64.         $context->setHttpPort($httpPort);
  65.         $context->setHttpsPort($httpsPort);
  66.         return $url;
  67.     }
  68.     /**
  69.      * Removes the locale parameter if it is disabled.
  70.      */
  71.     private function prepareLocale(array &$parameters): void
  72.     {
  73.         if (!\array_key_exists('_locale'$parameters)) {
  74.             return;
  75.         }
  76.         if ($this->prependLocale) {
  77.             $parameters['_locale'] = LocaleUtil::formatAsLanguageTag($parameters['_locale']);
  78.         } else {
  79.             unset($parameters['_locale']);
  80.         }
  81.     }
  82.     /**
  83.      * Adds the parameters to the alias.
  84.      */
  85.     private function prepareAlias(string $alias, array &$parameters): void
  86.     {
  87.         if ('index' === $alias) {
  88.             return;
  89.         }
  90.         $hasAutoItem false;
  91.         $autoItems $this->getAutoItems($parameters);
  92.         $config $this->framework->getAdapter(Config::class);
  93.         $parameters['alias'] = preg_replace_callback(
  94.             '/{([^}]+)}/',
  95.             static function (array $matches) use ($alias, &$parameters$autoItems, &$hasAutoItem$config): string {
  96.                 $param $matches[1];
  97.                 if (!isset($parameters[$param])) {
  98.                     throw new MissingMandatoryParametersException(sprintf('Parameters "%s" is missing to generate a URL for "%s"'$param$alias));
  99.                 }
  100.                 $value $parameters[$param];
  101.                 unset($parameters[$param]);
  102.                 if ($hasAutoItem || !$config->get('useAutoItem') || !\in_array($param$autoItemstrue)) {
  103.                     return $param.'/'.$value;
  104.                 }
  105.                 $hasAutoItem true;
  106.                 return $value;
  107.             },
  108.             $alias
  109.         );
  110.     }
  111.     /**
  112.      * Forces the router to add the host if necessary.
  113.      */
  114.     private function prepareDomain(RequestContext $context, array &$parametersint &$referenceType): void
  115.     {
  116.         if (isset($parameters['_ssl'])) {
  117.             $context->setScheme(true === $parameters['_ssl'] ? 'https' 'http');
  118.         }
  119.         if (isset($parameters['_domain']) && '' !== $parameters['_domain']) {
  120.             $this->addHostToContext($context$parameters$referenceType);
  121.         }
  122.         unset($parameters['_domain'], $parameters['_ssl']);
  123.     }
  124.     /**
  125.      * Sets the context from the domain.
  126.      */
  127.     private function addHostToContext(RequestContext $context, array $parametersint &$referenceType): void
  128.     {
  129.         /**
  130.          * @var string   $host
  131.          * @var int|null $port
  132.          */
  133.         [$host$port] = $this->getHostAndPort($parameters['_domain']);
  134.         if ($context->getHost() === $host) {
  135.             return;
  136.         }
  137.         $context->setHost($host);
  138.         $referenceType UrlGeneratorInterface::ABSOLUTE_URL;
  139.         if (!$port) {
  140.             return;
  141.         }
  142.         if (isset($parameters['_ssl']) && true === $parameters['_ssl']) {
  143.             $context->setHttpsPort($port);
  144.         } else {
  145.             $context->setHttpPort($port);
  146.         }
  147.     }
  148.     /**
  149.      * Extracts host and port from the domain.
  150.      *
  151.      * @return array<string|int|null>
  152.      */
  153.     private function getHostAndPort(string $domain): array
  154.     {
  155.         if (false !== strpos($domain':')) {
  156.             [$host$port] = explode(':'$domain2);
  157.             return [$host, (int) $port];
  158.         }
  159.         return [$domainnull];
  160.     }
  161.     /**
  162.      * Returns the auto_item key from the parameters or the global array.
  163.      *
  164.      * @return array<string>
  165.      */
  166.     private function getAutoItems(array $parameters): array
  167.     {
  168.         if (isset($parameters['auto_item'])) {
  169.             return [$parameters['auto_item']];
  170.         }
  171.         if (isset($GLOBALS['TL_AUTO_ITEM']) && \is_array($GLOBALS['TL_AUTO_ITEM'])) {
  172.             return $GLOBALS['TL_AUTO_ITEM'];
  173.         }
  174.         return [];
  175.     }
  176. }