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

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony CMF package.
  4.  *
  5.  * (c) 2011-2017 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\Route;
  26. use Symfony\Component\Routing\RouteCollection;
  27. use Symfony\Component\Routing\RouterInterface;
  28. /**
  29.  * A flexible router accepting matcher and generator through injection and
  30.  * using the RouteEnhancer concept to generate additional data on the routes.
  31.  *
  32.  * @author Larry Garfield
  33.  * @author David Buchmann
  34.  */
  35. class DynamicRouter implements RouterInterfaceRequestMatcherInterfaceChainedRouterInterface
  36. {
  37.     use RouteEnhancerTrait;
  38.     /**
  39.      * @var RequestMatcherInterface|UrlMatcherInterface
  40.      */
  41.     protected $matcher;
  42.     /**
  43.      * @var UrlGeneratorInterface
  44.      */
  45.     protected $generator;
  46.     /**
  47.      * @var EventDispatcherInterface
  48.      */
  49.     protected $eventDispatcher;
  50.     /**
  51.      * The regexp pattern that needs to be matched before a dynamic lookup is
  52.      * made.
  53.      *
  54.      * @var string
  55.      */
  56.     protected $uriFilterRegexp;
  57.     /**
  58.      * @var RouteProviderInterface
  59.      */
  60.     private $provider;
  61.     /**
  62.      * @var RequestContext
  63.      */
  64.     protected $context;
  65.     /**
  66.      * @var RouteCollection
  67.      */
  68.     private $routeCollection;
  69.     /**
  70.      * @param RequestContext                              $context
  71.      * @param RequestMatcherInterface|UrlMatcherInterface $matcher
  72.      * @param UrlGeneratorInterface                       $generator
  73.      * @param string                                      $uriFilterRegexp
  74.      * @param EventDispatcherInterface|null               $eventDispatcher
  75.      * @param RouteProviderInterface                      $provider
  76.      *
  77.      * @throws \InvalidArgumentException If the matcher is not a request or url matcher
  78.      */
  79.     public function __construct(RequestContext $context,
  80.                                 $matcher,
  81.                                 UrlGeneratorInterface $generator,
  82.                                 $uriFilterRegexp '',
  83.                                 EventDispatcherInterface $eventDispatcher null,
  84.                                 RouteProviderInterface $provider null
  85.     ) {
  86.         $this->context $context;
  87.         if (!$matcher instanceof RequestMatcherInterface && !$matcher instanceof UrlMatcherInterface) {
  88.             throw new \InvalidArgumentException(
  89.                 sprintf('Matcher must implement either %s or %s'RequestMatcherInterface::class, UrlMatcherInterface::class)
  90.             );
  91.         }
  92.         $this->matcher $matcher;
  93.         $this->generator $generator;
  94.         $this->eventDispatcher $eventDispatcher;
  95.         $this->uriFilterRegexp $uriFilterRegexp;
  96.         $this->provider $provider;
  97.         $this->generator->setContext($context);
  98.     }
  99.     /**
  100.      * {@inheritdoc}
  101.      */
  102.     public function getRouteCollection()
  103.     {
  104.         if (!$this->routeCollection instanceof RouteCollection) {
  105.             $this->routeCollection $this->provider
  106.                 ? new LazyRouteCollection($this->provider) : new RouteCollection();
  107.         }
  108.         return $this->routeCollection;
  109.     }
  110.     /**
  111.      * @return RequestMatcherInterface|UrlMatcherInterface
  112.      */
  113.     public function getMatcher()
  114.     {
  115.         /* we may not set the context in DynamicRouter::setContext as this
  116.          * would lead to symfony cache warmup problems.
  117.          * a request matcher does not need the request context separately as it
  118.          * can get it from the request.
  119.          */
  120.         if ($this->matcher instanceof RequestContextAwareInterface) {
  121.             $this->matcher->setContext($this->getContext());
  122.         }
  123.         return $this->matcher;
  124.     }
  125.     /**
  126.      * @return UrlGeneratorInterface
  127.      */
  128.     public function getGenerator()
  129.     {
  130.         $this->generator->setContext($this->getContext());
  131.         return $this->generator;
  132.     }
  133.     /**
  134.      * Generates a URL from the given parameters.
  135.      *
  136.      * If the generator is not able to generate the url, it must throw the
  137.      * RouteNotFoundException as documented below.
  138.      *
  139.      * @param string|Route $name          The name of the route or the Route instance
  140.      * @param mixed        $parameters    An array of parameters
  141.      * @param bool|string  $referenceType The type of reference to be generated (one of the constants in UrlGeneratorInterface)
  142.      *
  143.      * @return string The generated URL
  144.      *
  145.      * @throws RouteNotFoundException if route doesn't exist
  146.      *
  147.      * @api
  148.      */
  149.     public function generate($name$parameters = [], $referenceType UrlGeneratorInterface::ABSOLUTE_PATH)
  150.     {
  151.         if ($this->eventDispatcher) {
  152.             $event = new RouterGenerateEvent($name$parameters$referenceType);
  153.             $this->eventDispatcher->dispatch(Events::PRE_DYNAMIC_GENERATE$event);
  154.             $name $event->getRoute();
  155.             $parameters $event->getParameters();
  156.             $referenceType $event->getReferenceType();
  157.         }
  158.         return $this->getGenerator()->generate($name$parameters$referenceType);
  159.     }
  160.     /**
  161.      * Delegate to our generator.
  162.      *
  163.      * {@inheritdoc}
  164.      */
  165.     public function supports($name)
  166.     {
  167.         if ($this->generator instanceof VersatileGeneratorInterface) {
  168.             return $this->generator->supports($name);
  169.         }
  170.         return is_string($name);
  171.     }
  172.     /**
  173.      * Tries to match a URL path with a set of routes.
  174.      *
  175.      * If the matcher can not find information, it must throw one of the
  176.      * exceptions documented below.
  177.      *
  178.      * @param string $pathinfo The path info to be parsed (raw format, i.e. not
  179.      *                         urldecoded)
  180.      *
  181.      * @return array An array of parameters
  182.      *
  183.      * @throws ResourceNotFoundException If the resource could not be found
  184.      * @throws MethodNotAllowedException If the resource was found but the
  185.      *                                   request method is not allowed
  186.      *
  187.      * @deprecated Use matchRequest exclusively to avoid problems. This method will be removed in version 2.0
  188.      *
  189.      * @api
  190.      */
  191.     public function match($pathinfo)
  192.     {
  193.         @trigger_error(__METHOD__.'() is deprecated since version 1.3 and will be removed in 2.0. Use matchRequest() instead.'E_USER_DEPRECATED);
  194.         $request Request::create($pathinfo);
  195.         if ($this->eventDispatcher) {
  196.             $event = new RouterMatchEvent();
  197.             $this->eventDispatcher->dispatch(Events::PRE_DYNAMIC_MATCH$event);
  198.         }
  199.         if (!empty($this->uriFilterRegexp) && !preg_match($this->uriFilterRegexp$pathinfo)) {
  200.             throw new ResourceNotFoundException("$pathinfo does not match the '{$this->uriFilterRegexp}' pattern");
  201.         }
  202.         $matcher $this->getMatcher();
  203.         if (!$matcher instanceof UrlMatcherInterface) {
  204.             throw new \InvalidArgumentException('Wrong matcher type, you need to call matchRequest');
  205.         }
  206.         $defaults $matcher->match($pathinfo);
  207.         return $this->applyRouteEnhancers($defaults$request);
  208.     }
  209.     /**
  210.      * Tries to match a request with a set of routes and returns the array of
  211.      * information for that route.
  212.      *
  213.      * If the matcher can not find information, it must throw one of the
  214.      * exceptions documented below.
  215.      *
  216.      * @param Request $request The request to match
  217.      *
  218.      * @return array An array of parameters
  219.      *
  220.      * @throws ResourceNotFoundException If no matching resource could be found
  221.      * @throws MethodNotAllowedException If a matching resource was found but
  222.      *                                   the request method is not allowed
  223.      */
  224.     public function matchRequest(Request $request)
  225.     {
  226.         if ($this->eventDispatcher) {
  227.             $event = new RouterMatchEvent($request);
  228.             $this->eventDispatcher->dispatch(Events::PRE_DYNAMIC_MATCH_REQUEST$event);
  229.         }
  230.         if ($this->uriFilterRegexp
  231.             && !preg_match($this->uriFilterRegexp$request->getPathInfo())
  232.         ) {
  233.             throw new ResourceNotFoundException("{$request->getPathInfo()} does not match the '{$this->uriFilterRegexp}' pattern");
  234.         }
  235.         $matcher $this->getMatcher();
  236.         if ($matcher instanceof UrlMatcherInterface) {
  237.             $defaults $matcher->match($request->getPathInfo());
  238.         } else {
  239.             $defaults $matcher->matchRequest($request);
  240.         }
  241.         return $this->applyRouteEnhancers($defaults$request);
  242.     }
  243.     /**
  244.      * Sets the request context.
  245.      *
  246.      * @param RequestContext $context The context
  247.      *
  248.      * @api
  249.      */
  250.     public function setContext(RequestContext $context)
  251.     {
  252.         $this->context $context;
  253.     }
  254.     /**
  255.      * Gets the request context.
  256.      *
  257.      * @return RequestContext The context
  258.      *
  259.      * @api
  260.      */
  261.     public function getContext()
  262.     {
  263.         return $this->context;
  264.     }
  265.     /**
  266.      * {@inheritdoc}
  267.      *
  268.      * Forwards to the generator.
  269.      */
  270.     public function getRouteDebugMessage($name, array $parameters = [])
  271.     {
  272.         if ($this->generator instanceof VersatileGeneratorInterface) {
  273.             return $this->generator->getRouteDebugMessage($name$parameters);
  274.         }
  275.         return "Route '$name' not found";
  276.     }
  277. }