vendor/symfony/twig-bridge/Extension/RoutingExtension.php line 45

  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Bridge\Twig\Extension;
  11. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  12. use Twig\Extension\AbstractExtension;
  13. use Twig\Node\Expression\ArrayExpression;
  14. use Twig\Node\Expression\ConstantExpression;
  15. use Twig\Node\Node;
  16. use Twig\TwigFunction;
  17. /**
  18.  * Provides integration of the Routing component with Twig.
  19.  *
  20.  * @author Fabien Potencier <fabien@symfony.com>
  21.  */
  22. final class RoutingExtension extends AbstractExtension
  23. {
  24.     private UrlGeneratorInterface $generator;
  25.     public function __construct(UrlGeneratorInterface $generator)
  26.     {
  27.         $this->generator $generator;
  28.     }
  29.     public function getFunctions(): array
  30.     {
  31.         return [
  32.             new TwigFunction('url'$this->getUrl(...), ['is_safe_callback' => $this->isUrlGenerationSafe(...)]),
  33.             new TwigFunction('path'$this->getPath(...), ['is_safe_callback' => $this->isUrlGenerationSafe(...)]),
  34.         ];
  35.     }
  36.     public function getPath(string $name, array $parameters = [], bool $relative false): string
  37.     {
  38.         return $this->generator->generate($name$parameters$relative UrlGeneratorInterface::RELATIVE_PATH UrlGeneratorInterface::ABSOLUTE_PATH);
  39.     }
  40.     public function getUrl(string $name, array $parameters = [], bool $schemeRelative false): string
  41.     {
  42.         return $this->generator->generate($name$parameters$schemeRelative UrlGeneratorInterface::NETWORK_PATH UrlGeneratorInterface::ABSOLUTE_URL);
  43.     }
  44.     /**
  45.      * Determines at compile time whether the generated URL will be safe and thus
  46.      * saving the unneeded automatic escaping for performance reasons.
  47.      *
  48.      * The URL generation process percent encodes non-alphanumeric characters. So there is no risk
  49.      * that malicious/invalid characters are part of the URL. The only character within a URL that
  50.      * must be escaped in html is the ampersand ("&") which separates query params. So we cannot mark
  51.      * the URL generation as always safe, but only when we are sure there won't be multiple query
  52.      * params. This is the case when there are none or only one constant parameter given.
  53.      * E.g. we know beforehand this will be safe:
  54.      * - path('route')
  55.      * - path('route', {'param': 'value'})
  56.      * But the following may not:
  57.      * - path('route', var)
  58.      * - path('route', {'param': ['val1', 'val2'] }) // a sub-array
  59.      * - path('route', {'param1': 'value1', 'param2': 'value2'})
  60.      * If param1 and param2 reference placeholder in the route, it would still be safe. But we don't know.
  61.      *
  62.      * @param Node $argsNode The arguments of the path/url function
  63.      *
  64.      * @return array An array with the contexts the URL is safe
  65.      */
  66.     public function isUrlGenerationSafe(Node $argsNode): array
  67.     {
  68.         // support named arguments
  69.         $paramsNode $argsNode->hasNode('parameters') ? $argsNode->getNode('parameters') : (
  70.             $argsNode->hasNode(1) ? $argsNode->getNode(1) : null
  71.         );
  72.         if (null === $paramsNode || $paramsNode instanceof ArrayExpression && \count($paramsNode) <= &&
  73.             (!$paramsNode->hasNode(1) || $paramsNode->getNode(1) instanceof ConstantExpression)
  74.         ) {
  75.             return ['html'];
  76.         }
  77.         return [];
  78.     }
  79. }