From 72f2e1bf3c391d197196b7ab926f2be5a46483ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Bj=C3=B8rnskov?= Date: Mon, 24 Mar 2014 11:47:53 +0100 Subject: [PATCH] Port chain matcher from Brick --- src/Flint/Provider/RoutingServiceProvider.php | 11 +- src/Flint/Routing/ChainMatcher.php | 100 ++++++++++++++++++ .../Provider/RoutingServiceProviderTest.php | 15 +-- 3 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 src/Flint/Routing/ChainMatcher.php diff --git a/src/Flint/Provider/RoutingServiceProvider.php b/src/Flint/Provider/RoutingServiceProvider.php index 7e832d0..b792ff6 100644 --- a/src/Flint/Provider/RoutingServiceProvider.php +++ b/src/Flint/Provider/RoutingServiceProvider.php @@ -4,6 +4,7 @@ use Silex\Application; use Flint\Routing\Loader\NullLoader; +use Flint\Routing\ChainMatcher; use Symfony\Component\Routing\Router; use Symfony\Component\Routing\Loader\XmlFileLoader; use Symfony\Component\Routing\Loader\PhpFileLoader; @@ -70,11 +71,13 @@ public function register(Application $app) return new Router($app['routing.loader'], $app['routing.resource'], $options, $app['request_context'], $app['logger']); }); - $app['routes'] = function (Application $app) { - return $app['router']->getRouteCollection(); - }; + $app['url_matcher'] = $app->share($app->extend('url_matcher', function ($matcher, $app) { + $matcher = new ChainMatcher(array($app['router'], $matcher)); + $matcher->setContext($app['request_context']); + + return $matcher; + })); - $app['url_matcher'] = $app->raw('router'); $app['url_generator'] = $app->raw('router'); } diff --git a/src/Flint/Routing/ChainMatcher.php b/src/Flint/Routing/ChainMatcher.php new file mode 100644 index 0000000..5d158c9 --- /dev/null +++ b/src/Flint/Routing/ChainMatcher.php @@ -0,0 +1,100 @@ +add($matcher); + } + } + + public function add(UrlMatcherInterface $matcher, $priority = 0) + { + $this->matchers[$priority][] = $matcher; + } + + public function setContext(RequestContext $context) + { + $this->context = $context; + } + + public function getContext() + { + return $this->context; + } + + public function matchRequest(Request $request) + { + return $this->doMatch($request->getPathInfo(), $request); + } + + public function match($pathinfo) + { + return $this->doMatch($pathinfo); + } + + protected function doMatch($pathinfo, Request $request = null) + { + $notAllowed = null; + + foreach ($this->sort() as $matcher) { + $matcher->setContext($this->context); + + try { + if ($request && $matcher instanceof RequestMatcherInterface) { + return $matcher->matchRequest($request); + } + + return $matcher->match($pathinfo); + } catch (ResourceNotFoundException $e) { + // Special case + } catch (MethodNotAllowedException $e) { + $notAllowed = $e; + } + } + + if ($notAllowed) { + throw $notAllowed; + } + + $info = $request ? 'this request\n' . $request : 'url "' . $pathinfo . '"'; + + throw new ResourceNotFoundException('None of the routers in the chain matched ' . $info); + } + + protected function sort() + { + $matchers = array(); + + krsort($this->matchers); + + foreach ($this->matchers as $collection) { + $matchers = array_merge($matchers, $collection); + } + + return $matchers; + } +} diff --git a/tests/Flint/Tests/Provider/RoutingServiceProviderTest.php b/tests/Flint/Tests/Provider/RoutingServiceProviderTest.php index abfe6c5..2de185e 100644 --- a/tests/Flint/Tests/Provider/RoutingServiceProviderTest.php +++ b/tests/Flint/Tests/Provider/RoutingServiceProviderTest.php @@ -17,8 +17,9 @@ public function testUrlMatcherAndGeneratorIsAliasOfRouter() { $this->provider->register($this->app); - $this->assertInstanceOf('Symfony\Component\Routing\Router', $this->app['url_matcher']); + $this->assertInstanceOf('Flint\Routing\ChainMatcher', $this->app['url_matcher']); $this->assertInstanceOf('Symfony\Component\Routing\Router', $this->app['url_generator']); + $this->assertInstanceOf('Symfony\Component\Routing\Router', $this->app['router']); } public function testRedirectableUrlMatcherIsUsed() @@ -28,16 +29,4 @@ public function testRedirectableUrlMatcherIsUsed() $this->assertEquals('Silex\\RedirectableUrlMatcher', $this->app['router']->getOption('matcher_class')); $this->assertEquals('Silex\\RedirectableUrlMatcher', $this->app['router']->getOption('matcher_base_class')); } - - public function testRouteCollectionIsGottenFromRouter() - { - $router = $this->getMockBuilder('Symfony\Component\Routing\Router')->disableOriginalConstructor()->getMock(); - $router->expects($this->once())->method('getRouteCollection'); - - $this->provider->register($this->app); - - $this->app['router'] = $router; - - $this->app['routes']; - } }