| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 | 
							- <?php
 
- /*
 
-  * This file is part of the Symfony CMF package.
 
-  *
 
-  * (c) 2011-2015 Symfony CMF
 
-  *
 
-  * For the full copyright and license information, please view the LICENSE
 
-  * file that was distributed with this source code.
 
-  */
 
- namespace Symfony\Cmf\Component\Routing;
 
- use Symfony\Component\Routing\RouterInterface;
 
- use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
 
- use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
 
- use Symfony\Component\Routing\RequestContext;
 
- use Symfony\Component\Routing\RequestContextAwareInterface;
 
- use Symfony\Component\Routing\Exception\ResourceNotFoundException;
 
- use Symfony\Component\Routing\Exception\RouteNotFoundException;
 
- use Symfony\Component\Routing\Exception\MethodNotAllowedException;
 
- use Symfony\Component\Routing\RouteCollection;
 
- use Symfony\Component\HttpFoundation\Request;
 
- use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
 
- use Psr\Log\LoggerInterface;
 
- /**
 
-  * The ChainRouter allows to combine several routers to try in a defined order.
 
-  *
 
-  * @author Henrik Bjornskov <henrik@bjrnskov.dk>
 
-  * @author Magnus Nordlander <magnus@e-butik.se>
 
-  */
 
- class ChainRouter implements ChainRouterInterface, WarmableInterface
 
- {
 
-     /**
 
-      * @var RequestContext
 
-      */
 
-     private $context;
 
-     /**
 
-      * Array of arrays of routers grouped by priority.
 
-      *
 
-      * @var array
 
-      */
 
-     private $routers = array();
 
-     /**
 
-      * @var RouterInterface[] Array of routers, sorted by priority
 
-      */
 
-     private $sortedRouters;
 
-     /**
 
-      * @var RouteCollection
 
-      */
 
-     private $routeCollection;
 
-     /**
 
-      * @var null|LoggerInterface
 
-      */
 
-     protected $logger;
 
-     /**
 
-      * @param LoggerInterface $logger
 
-      */
 
-     public function __construct(LoggerInterface $logger = null)
 
-     {
 
-         $this->logger = $logger;
 
-     }
 
-     /**
 
-      * @return RequestContext
 
-      */
 
-     public function getContext()
 
-     {
 
-         return $this->context;
 
-     }
 
-     /**
 
-      * {@inheritdoc}
 
-      */
 
-     public function add($router, $priority = 0)
 
-     {
 
-         if (!$router instanceof RouterInterface
 
-             && !($router instanceof RequestMatcherInterface && $router instanceof UrlGeneratorInterface)
 
-         ) {
 
-             throw new \InvalidArgumentException(sprintf('%s is not a valid router.', get_class($router)));
 
-         }
 
-         if (empty($this->routers[$priority])) {
 
-             $this->routers[$priority] = array();
 
-         }
 
-         $this->routers[$priority][] = $router;
 
-         $this->sortedRouters = array();
 
-     }
 
-     /**
 
-      * {@inheritdoc}
 
-      */
 
-     public function all()
 
-     {
 
-         if (empty($this->sortedRouters)) {
 
-             $this->sortedRouters = $this->sortRouters();
 
-             // setContext() is done here instead of in add() to avoid fatal errors when clearing and warming up caches
 
-             // See https://github.com/symfony-cmf/Routing/pull/18
 
-             $context = $this->getContext();
 
-             if (null !== $context) {
 
-                 foreach ($this->sortedRouters as $router) {
 
-                     if ($router instanceof RequestContextAwareInterface) {
 
-                         $router->setContext($context);
 
-                     }
 
-                 }
 
-             }
 
-         }
 
-         return $this->sortedRouters;
 
-     }
 
-     /**
 
-      * Sort routers by priority.
 
-      * The highest priority number is the highest priority (reverse sorting).
 
-      *
 
-      * @return RouterInterface[]
 
-      */
 
-     protected function sortRouters()
 
-     {
 
-         $sortedRouters = array();
 
-         krsort($this->routers);
 
-         foreach ($this->routers as $routers) {
 
-             $sortedRouters = array_merge($sortedRouters, $routers);
 
-         }
 
-         return $sortedRouters;
 
-     }
 
-     /**
 
-      * {@inheritdoc}
 
-      *
 
-      * Loops through all routes and tries to match the passed url.
 
-      *
 
-      * Note: You should use matchRequest if you can.
 
-      */
 
-     public function match($pathinfo)
 
-     {
 
-         return $this->doMatch($pathinfo);
 
-     }
 
-     /**
 
-      * {@inheritdoc}
 
-      *
 
-      * Loops through all routes and tries to match the passed request.
 
-      */
 
-     public function matchRequest(Request $request)
 
-     {
 
-         return $this->doMatch($request->getPathInfo(), $request);
 
-     }
 
-     /**
 
-      * Loops through all routers and tries to match the passed request or url.
 
-      *
 
-      * At least the  url must be provided, if a request is additionally provided
 
-      * the request takes precedence.
 
-      *
 
-      * @param string  $pathinfo
 
-      * @param Request $request
 
-      *
 
-      * @return array An array of parameters
 
-      *
 
-      * @throws ResourceNotFoundException If no router matched.
 
-      */
 
-     private function doMatch($pathinfo, Request $request = null)
 
-     {
 
-         $methodNotAllowed = null;
 
-         $requestForMatching = $request;
 
-         foreach ($this->all() as $router) {
 
-             try {
 
-                 // the request/url match logic is the same as in Symfony/Component/HttpKernel/EventListener/RouterListener.php
 
-                 // matching requests is more powerful than matching URLs only, so try that first
 
-                 if ($router instanceof RequestMatcherInterface) {
 
-                     if (empty($requestForMatching)) {
 
-                         $requestForMatching = $this->rebuildRequest($pathinfo);
 
-                     }
 
-                     return $router->matchRequest($requestForMatching);
 
-                 }
 
-                 // every router implements the match method
 
-                 return $router->match($pathinfo);
 
-             } catch (ResourceNotFoundException $e) {
 
-                 if ($this->logger) {
 
-                     $this->logger->debug('Router '.get_class($router).' was not able to match, message "'.$e->getMessage().'"');
 
-                 }
 
-                 // Needs special care
 
-             } catch (MethodNotAllowedException $e) {
 
-                 if ($this->logger) {
 
-                     $this->logger->debug('Router '.get_class($router).' throws MethodNotAllowedException with message "'.$e->getMessage().'"');
 
-                 }
 
-                 $methodNotAllowed = $e;
 
-             }
 
-         }
 
-         $info = $request
 
-             ? "this request\n$request"
 
-             : "url '$pathinfo'";
 
-         throw $methodNotAllowed ?: new ResourceNotFoundException("None of the routers in the chain matched $info");
 
-     }
 
-     /**
 
-      * {@inheritdoc}
 
-      *
 
-      * Loops through all registered routers and returns a router if one is found.
 
-      * It will always return the first route generated.
 
-      */
 
-     public function generate($name, $parameters = array(), $absolute = UrlGeneratorInterface::ABSOLUTE_PATH)
 
-     {
 
-         $debug = array();
 
-         foreach ($this->all() as $router) {
 
-             // if $router does not announce it is capable of handling
 
-             // non-string routes and $name is not a string, continue
 
-             if ($name && !is_string($name) && !$router instanceof VersatileGeneratorInterface) {
 
-                 continue;
 
-             }
 
-             // If $router is versatile and doesn't support this route name, continue
 
-             if ($router instanceof VersatileGeneratorInterface && !$router->supports($name)) {
 
-                 continue;
 
-             }
 
-             try {
 
-                 return $router->generate($name, $parameters, $absolute);
 
-             } catch (RouteNotFoundException $e) {
 
-                 $hint = $this->getErrorMessage($name, $router, $parameters);
 
-                 $debug[] = $hint;
 
-                 if ($this->logger) {
 
-                     $this->logger->debug('Router '.get_class($router)." was unable to generate route. Reason: '$hint': ".$e->getMessage());
 
-                 }
 
-             }
 
-         }
 
-         if ($debug) {
 
-             $debug = array_unique($debug);
 
-             $info = implode(', ', $debug);
 
-         } else {
 
-             $info = $this->getErrorMessage($name);
 
-         }
 
-         throw new RouteNotFoundException(sprintf('None of the chained routers were able to generate route: %s', $info));
 
-     }
 
-     /**
 
-      * Rebuild the request object from a URL with the help of the RequestContext.
 
-      *
 
-      * If the request context is not set, this simply returns the request object built from $uri.
 
-      *
 
-      * @param string $pathinfo
 
-      *
 
-      * @return Request
 
-      */
 
-     private function rebuildRequest($pathinfo)
 
-     {
 
-         if (!$this->context) {
 
-             return Request::create('http://localhost'.$pathinfo);
 
-         }
 
-         $uri = $pathinfo;
 
-         $server = array();
 
-         if ($this->context->getBaseUrl()) {
 
-             $uri = $this->context->getBaseUrl().$pathinfo;
 
-             $server['SCRIPT_FILENAME'] = $this->context->getBaseUrl();
 
-             $server['PHP_SELF'] = $this->context->getBaseUrl();
 
-         }
 
-         $host = $this->context->getHost() ?: 'localhost';
 
-         if ('https' === $this->context->getScheme() && 443 !== $this->context->getHttpsPort()) {
 
-             $host .= ':'.$this->context->getHttpsPort();
 
-         }
 
-         if ('http' === $this->context->getScheme() && 80 !== $this->context->getHttpPort()) {
 
-             $host .= ':'.$this->context->getHttpPort();
 
-         }
 
-         $uri = $this->context->getScheme().'://'.$host.$uri.'?'.$this->context->getQueryString();
 
-         return Request::create($uri, $this->context->getMethod(), $this->context->getParameters(), array(), array(), $server);
 
-     }
 
-     private function getErrorMessage($name, $router = null, $parameters = null)
 
-     {
 
-         if ($router instanceof VersatileGeneratorInterface) {
 
-             $displayName = $router->getRouteDebugMessage($name, $parameters);
 
-         } elseif (is_object($name)) {
 
-             $displayName = method_exists($name, '__toString')
 
-                 ? (string) $name
 
-                 : get_class($name)
 
-             ;
 
-         } else {
 
-             $displayName = (string) $name;
 
-         }
 
-         return "Route '$displayName' not found";
 
-     }
 
-     /**
 
-      * {@inheritdoc}
 
-      */
 
-     public function setContext(RequestContext $context)
 
-     {
 
-         foreach ($this->all() as $router) {
 
-             if ($router instanceof RequestContextAwareInterface) {
 
-                 $router->setContext($context);
 
-             }
 
-         }
 
-         $this->context = $context;
 
-     }
 
-     /**
 
-      * {@inheritdoc}
 
-      *
 
-      * check for each contained router if it can warmup
 
-      */
 
-     public function warmUp($cacheDir)
 
-     {
 
-         foreach ($this->all() as $router) {
 
-             if ($router instanceof WarmableInterface) {
 
-                 $router->warmUp($cacheDir);
 
-             }
 
-         }
 
-     }
 
-     /**
 
-      * {@inheritdoc}
 
-      */
 
-     public function getRouteCollection()
 
-     {
 
-         if (!$this->routeCollection instanceof RouteCollection) {
 
-             $this->routeCollection = new ChainRouteCollection();
 
-             foreach ($this->all() as $router) {
 
-                 $this->routeCollection->addCollection($router->getRouteCollection());
 
-             }
 
-         }
 
-         return $this->routeCollection;
 
-     }
 
-     /**
 
-      * Identify if any routers have been added into the chain yet.
 
-      *
 
-      * @return bool
 
-      */
 
-     public function hasRouters()
 
-     {
 
-         return !empty($this->routers);
 
-     }
 
- }
 
 
  |