Skip to content

Commit

Permalink
Merge pull request #21 from henrikbjorn/master
Browse files Browse the repository at this point in the history
Port chain matcher from Brick
  • Loading branch information
henrikbjorn committed Mar 24, 2014
2 parents 135e3a5 + 72f2e1b commit 6c6eb5b
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 17 deletions.
11 changes: 7 additions & 4 deletions src/Flint/Provider/RoutingServiceProvider.php
Expand Up @@ -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;
Expand Down Expand Up @@ -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');
}

Expand Down
100 changes: 100 additions & 0 deletions src/Flint/Routing/ChainMatcher.php
@@ -0,0 +1,100 @@
<?php

namespace Flint\Routing;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;

/**
* ChainMatcher.
*
* This wraps multiple UrlMatcherInterface's in order to not overwrite Silex
* internals.
*
* Created with inspiration from my own work of symfony-cmf ChainRouter and the
* ChainMatcher found in Drupal.
*
*/
class ChainMatcher implements UrlMatcherInterface, RequestMatcherInterface
{
protected $matchers = array();
protected $context;

public function __construct($matchers = array())
{
foreach ($matchers as $matcher) {
$this->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;
}
}
15 changes: 2 additions & 13 deletions tests/Flint/Tests/Provider/RoutingServiceProviderTest.php
Expand Up @@ -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()
Expand All @@ -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'];
}
}

0 comments on commit 6c6eb5b

Please sign in to comment.