Complete exact-path matching.

8.0.x
Larry Garfield 2012-06-30 15:44:30 -05:00 committed by effulgentsia
parent f55ab1aff6
commit d372d6de99
2 changed files with 43 additions and 20 deletions

View File

@ -29,7 +29,6 @@ class PathMatcher implements InitialMatcherInterface {
public function __construct(Connection $connection, $table = 'router') { public function __construct(Connection $connection, $table = 'router') {
$this->connection = $connection; $this->connection = $connection;
$this->tableName = $table; $this->tableName = $table;
} }
@ -46,26 +45,18 @@ class PathMatcher implements InitialMatcherInterface {
$path = $request->getPathInfo(); $path = $request->getPathInfo();
$parts = array_slide(explode('/', $path), 0, MatcherDumper::MAX_PARTS); $parts = array_slice(array_filter(explode('/', $path)), 0, MatcherDumper::MAX_PARTS);
$number_parts = count($parts);
$ancestors = $this->getCandidateOutlines($parts); $ancestors = $this->getCandidateOutlines($parts);
// @todo We want to allow matching more than one result because there could $routes = $this->connection->query("SELECT name, route FROM {{$this->tableName}} WHERE pattern_outline IN (:patterns) ORDER BY fit", array(
// be more than one result with the same path. But how do we do that and ':patterns' => $ancestors,
// limit by fit? ))
$routes = $this->connection
->select($this->tableName, 'r')
->fields('r', array('name', 'route'))
->condition('pattern_outline', $ancestors, 'IN')
->condition('number_parts', $number_parts)
->execute()
->fetchAllKeyed(); ->fetchAllKeyed();
$collection = new RouteCollection(); $collection = new RouteCollection();
foreach ($routes as $name => $route) { foreach ($routes as $name => $route) {
$collection->add($name, $route); $collection->add($name, unserialize($route));
} }
return $collection; return $collection;
@ -93,7 +84,7 @@ class PathMatcher implements InitialMatcherInterface {
$masks = range($end, $start); $masks = range($end, $start);
foreach ($masks as $i) { foreach ($masks as $i) {
$current = ''; $current = '/';
for ($j = $length; $j >= 0; $j--) { for ($j = $length; $j >= 0; $j--) {
// Check the bit on the $j offset. // Check the bit on the $j offset.
if ($i & (1 << $j)) { if ($i & (1 << $j)) {

View File

@ -14,6 +14,7 @@ use Symfony\Component\Routing\RouteCollection;
use Drupal\simpletest\UnitTestBase; use Drupal\simpletest\UnitTestBase;
use Drupal\Core\Routing\PathMatcher; use Drupal\Core\Routing\PathMatcher;
use Drupal\Core\Database\Database; use Drupal\Core\Database\Database;
use Drupal\Core\Routing\MatcherDumper;
/** /**
* Basic tests for the UrlMatcherDumper. * Basic tests for the UrlMatcherDumper.
@ -64,10 +65,41 @@ class PathMatcherTest extends UnitTestBase {
$candidates = array_flip($candidates); $candidates = array_flip($candidates);
$this->assertTrue(count($candidates) == 4, t('Correct number of candidates found')); $this->assertTrue(count($candidates) == 4, t('Correct number of candidates found'));
$this->assertTrue(array_key_exists('node/5/edit', $candidates), t('First candidate found.')); $this->assertTrue(array_key_exists('/node/5/edit', $candidates), t('First candidate found.'));
$this->assertTrue(array_key_exists('node/5/%', $candidates), t('Second candidate found.')); $this->assertTrue(array_key_exists('/node/5/%', $candidates), t('Second candidate found.'));
$this->assertTrue(array_key_exists('node/%/edit', $candidates), t('Third candidate found.')); $this->assertTrue(array_key_exists('/node/%/edit', $candidates), t('Third candidate found.'));
$this->assertTrue(array_key_exists('node/%/%', $candidates), t('Fourth candidate found.')); $this->assertTrue(array_key_exists('/node/%/%', $candidates), t('Fourth candidate found.'));
}
/**
* Confirms that we can find routes with the exact incoming path.
*/
function testExactPathMatch() {
$connection = Database::getConnection();
$matcher = new PathMatcher($connection, 'test_routes');
$this->fixtures->createTables($connection);
$dumper = new MatcherDumper($connection, 'test_routes');
$dumper->addRoutes($this->fixtures->sampleRouteCollection());
$dumper->dump();
$path = '/path/one';
$request = Request::create($path, 'GET');
$routes = $matcher->matchRequestPartial($request);
foreach ($routes as $route) {
$this->assertEqual($route->getPattern(), $path, t('Found path has correct pattern'));
}
}
/**
* Confirms that we can find routes whose pattern would match the request.
*/
function testOutlinePathMatch() {
} }