vendor/symfony-cmf/routing/src/DynamicRouter.php line 186

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony CMF package.
  4.  *
  5.  * (c) Symfony CMF
  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\Cmf\Component\Routing;
  11. use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerTrait;
  12. use Symfony\Cmf\Component\Routing\Event\Events;
  13. use Symfony\Cmf\Component\Routing\Event\RouterGenerateEvent;
  14. use Symfony\Cmf\Component\Routing\Event\RouterMatchEvent;
  15. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\Routing\Exception\MethodNotAllowedException;
  18. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  19. use Symfony\Component\Routing\Exception\RouteNotFoundException;
  20. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  21. use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
  22. use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
  23. use Symfony\Component\Routing\RequestContext;
  24. use Symfony\Component\Routing\RequestContextAwareInterface;
  25. use Symfony\Component\Routing\RouteCollection;
  26. /**
  27.  * A flexible router accepting matcher and generator through injection and
  28.  * using the RouteEnhancer concept to generate additional data on the routes.
  29.  *
  30.  * @author Larry Garfield
  31.  * @author David Buchmann
  32.  */
  33. class DynamicRouter implements RequestMatcherInterfaceChainedRouterInterface
  34. {
  35.     use RouteEnhancerTrait;
  36.     private RequestMatcherInterface|UrlMatcherInterface $matcher;
  37.     private UrlGeneratorInterface $generator;
  38.     private ?EventDispatcherInterface $eventDispatcher;
  39.     /**
  40.      * The regexp pattern that needs to be matched before a dynamic lookup is
  41.      * made.
  42.      */
  43.     private string $uriFilterRegexp;
  44.     private ?RouteProviderInterface $provider;
  45.     private RequestContext $context;
  46.     private ?RouteCollection $routeCollection null;
  47.     public function __construct(
  48.         RequestContext $context,
  49.         UrlMatcherInterface|RequestMatcherInterface $matcher,
  50.         UrlGeneratorInterface $generator,
  51.         string $uriFilterRegexp '',
  52.         ?EventDispatcherInterface $eventDispatcher null,
  53.         ?RouteProviderInterface $provider null
  54.     ) {
  55.         $this->context $context;
  56.         $this->matcher $matcher;
  57.         $this->generator $generator;
  58.         $this->eventDispatcher $eventDispatcher;
  59.         $this->uriFilterRegexp $uriFilterRegexp;
  60.         $this->provider $provider;
  61.         $this->generator->setContext($context);
  62.     }
  63.     /**
  64.      * {@inheritdoc}
  65.      */
  66.     public function getRouteCollection(): ?RouteCollection
  67.     {
  68.         if (!$this->routeCollection instanceof RouteCollection) {
  69.             $this->routeCollection $this->provider
  70.                 ? new LazyRouteCollection($this->provider) : new RouteCollection();
  71.         }
  72.         return $this->routeCollection;
  73.     }
  74.     public function getMatcher(): UrlMatcherInterface|RequestMatcherInterface
  75.     {
  76.         /* we may not set the context in DynamicRouter::setContext as this
  77.          * would lead to symfony cache warmup problems.
  78.          * a request matcher does not need the request context separately as it
  79.          * can get it from the request.
  80.          */
  81.         if ($this->matcher instanceof RequestContextAwareInterface) {
  82.             $this->matcher->setContext($this->getContext());
  83.         }
  84.         return $this->matcher;
  85.     }
  86.     public function getGenerator(): UrlGeneratorInterface
  87.     {
  88.         $this->generator->setContext($this->getContext());
  89.         return $this->generator;
  90.     }
  91.     /**
  92.      * Generates a URL from the given parameters.
  93.      *
  94.      * If the generator is not able to generate the url, it must throw the
  95.      * RouteNotFoundException as documented below.
  96.      *
  97.      * The CMF routing system used to allow to pass route objects as $name to generate the route.
  98.      * To generate the route from a string, pass the RouteObjectInterface::OBJECT_BASED_ROUTE_NAME
  99.      * as route name and the object in the parameters with key RouteObjectInterface::ROUTE_OBJECT.
  100.      *
  101.      * @throws RouteNotFoundException if route doesn't exist
  102.      */
  103.     public function generate(string $name, array $parameters = [], int $referenceType UrlGeneratorInterface::ABSOLUTE_PATH): string
  104.     {
  105.         if ($this->eventDispatcher) {
  106.             $event = new RouterGenerateEvent($name$parameters$referenceType);
  107.             $this->eventDispatcher->dispatch($eventEvents::PRE_DYNAMIC_GENERATE);
  108.             $name $event->getRoute();
  109.             $parameters $event->getParameters();
  110.             $referenceType $event->getReferenceType();
  111.         }
  112.         return $this->getGenerator()->generate($name$parameters$referenceType);
  113.     }
  114.     /**
  115.      * Tries to match a URL path with a set of routes.
  116.      *
  117.      * If the matcher can not find information, it must throw one of the
  118.      * exceptions documented below.
  119.      *
  120.      * @param string $pathinfo The path info to be parsed (raw format, i.e. not
  121.      *                         urldecoded)
  122.      *
  123.      * @return array An array of parameters
  124.      *
  125.      * @throws ResourceNotFoundException If the resource could not be found
  126.      * @throws MethodNotAllowedException If the resource was found but the
  127.      *                                   request method is not allowed
  128.      *
  129.      * @api
  130.      */
  131.     public function match(string $pathinfo): array
  132.     {
  133.         $request Request::create($pathinfo);
  134.         if ($this->eventDispatcher) {
  135.             $event = new RouterMatchEvent();
  136.             $this->eventDispatcher->dispatch($eventEvents::PRE_DYNAMIC_MATCH);
  137.         }
  138.         if (!empty($this->uriFilterRegexp) && !preg_match($this->uriFilterRegexp$pathinfo)) {
  139.             throw new ResourceNotFoundException("$pathinfo does not match the '{$this->uriFilterRegexp}' pattern");
  140.         }
  141.         $matcher $this->getMatcher();
  142.         if (!$matcher instanceof UrlMatcherInterface) {
  143.             throw new \InvalidArgumentException('Wrong matcher type, you need to call matchRequest');
  144.         }
  145.         $defaults $matcher->match($pathinfo);
  146.         return $this->applyRouteEnhancers($defaults$request);
  147.     }
  148.     /**
  149.      * Tries to match a request with a set of routes and returns the array of
  150.      * information for that route.
  151.      *
  152.      * If the matcher can not find information, it must throw one of the
  153.      * exceptions documented below.
  154.      *
  155.      * @param Request $request The request to match
  156.      *
  157.      * @return array An array of parameters
  158.      *
  159.      * @throws ResourceNotFoundException If no matching resource could be found
  160.      * @throws MethodNotAllowedException If a matching resource was found but
  161.      *                                   the request method is not allowed
  162.      */
  163.     public function matchRequest(Request $request): array
  164.     {
  165.         if ($this->eventDispatcher) {
  166.             $event = new RouterMatchEvent($request);
  167.             $this->eventDispatcher->dispatch($eventEvents::PRE_DYNAMIC_MATCH_REQUEST);
  168.         }
  169.         if ($this->uriFilterRegexp
  170.             && !preg_match($this->uriFilterRegexp$request->getPathInfo())
  171.         ) {
  172.             throw new ResourceNotFoundException("{$request->getPathInfo()} does not match the '{$this->uriFilterRegexp}' pattern");
  173.         }
  174.         $matcher $this->getMatcher();
  175.         if ($matcher instanceof UrlMatcherInterface) {
  176.             $defaults $matcher->match($request->getPathInfo());
  177.         } else {
  178.             $defaults $matcher->matchRequest($request);
  179.         }
  180.         return $this->applyRouteEnhancers($defaults$request);
  181.     }
  182.     public function setContext(RequestContext $context): void
  183.     {
  184.         $this->context $context;
  185.     }
  186.     public function getContext(): RequestContext
  187.     {
  188.         return $this->context;
  189.     }
  190.     /**
  191.      * {@inheritdoc}
  192.      *
  193.      * Forwards to the generator.
  194.      */
  195.     public function getRouteDebugMessage(string $name, array $parameters = []): string
  196.     {
  197.         if ($this->generator instanceof VersatileGeneratorInterface) {
  198.             return $this->generator->getRouteDebugMessage($name$parameters);
  199.         }
  200.         return "Route '$name' not found";
  201.     }
  202. }