Commit a524a35d authored by Crell's avatar Crell Committed by effulgentsia
Browse files

Add basic route compilation mechanism.

parent 2c79c025
<?php
namespace Drupal\Core\Routing;
use Symfony\Component\Routing\CompiledRoute as SymfonyCompiledRoute;
use Symfony\Component\Routing\Route;
/**
* Description of CompiledRoute
*/
class CompiledRoute extends SymfonyCompiledRoute {
/**
* The fitness of this route.
*
* @var int
*/
protected $fit;
/**
* Constructor.
*
* @param Route $route
* A original Route instance.
* @param int $fit
* The fitness of the route.
* @param string $regex The regular expression to use to match this route
* @param array $tokens An array of tokens to use to generate URL for this route
* @param array $variables An array of variables
*/
public function __construct(Route $route, $fit) {
// We're ignoring the rest of this stuff; really this should be just using
// an interface, but the Symfony component doesn't have one. This is a bug
// in Symfony.
parent::__construct($route, '', '', array(), array());
$this->fit = $fit;
}
public function getFit() {
return $this->fit;
}
}
<?php
namespace Drupal\Core\Routing;
use Symfony\Component\Routing\RouteCompilerInterface;
use Symfony\Component\Routing\Route;
/**
* Description of RouteCompiler
*/
class RouteCompiler implements RouteCompilerInterface {
/**
* The maximum number of path elements for a route pattern;
*/
const MAX_PARTS = 9;
/**
* Compiles the current route instance.
*
* @param Route $route
* A Route instance
*
* @return CompiledRoute
* A CompiledRoute instance
*/
public function compile(Route $route) {
$fit = $this->getFit($route->getPattern());
return new CompiledRoute($route, $fit);
}
/**
* Determines the fitness of the provided path.
*
* @param string $path
* The path whose fitness we want.
*
* @return int
* The fitness of the path, as an integer.
*/
public function getFit($path) {
$parts = explode('/', trim($path, '/'), static::MAX_PARTS);
$number_parts = count($parts);
// We store the highest index of parts here to save some work in the fit
// calculation loop.
$slashes = $number_parts - 1;
$fit = 0;
foreach ($parts as $k => $part) {
if (strpos($part, '{') === FALSE) {
$fit |= 1 << ($slashes - $k);
}
}
return $fit;
}
}
......@@ -99,5 +99,109 @@ class UrlMatcherDumperTestCase extends WebTestBase {
}
}
/**
* Confirms that we can add routes to the dumper when it already has some.
*/
protected function prepareTables() {
$connection = Database::getConnection();
$tables['test_routes'] = array(
'description' => 'Maps paths to various callbacks (access, page and title)',
'fields' => array(
'name' => array(
'description' => 'Primary Key: Machine name of this route',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'pattern' => array(
'description' => 'The path pattern for this URI',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'pattern_outline' => array(
'description' => 'The pattern',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'access_callback' => array(
'description' => 'The callback which determines the access to this router path. Defaults to user_access.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'access_arguments' => array(
'description' => 'A serialized array of arguments for the access callback.',
'type' => 'blob',
'not null' => FALSE,
),
'fit' => array(
'description' => 'A numeric representation of how specific the path is.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'number_parts' => array(
'description' => 'Number of parts in this router path.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'size' => 'small',
),
'route' => array(
'description' => 'A serialized Route object',
'type' => 'text',
),
),
'indexes' => array(
'fit' => array('fit'),
'pattern_outline' => array('pattern_outline'),
),
'primary key' => array('name'),
);
$schema = $connection->schema();
$schema->dropTable('test_routes');
$schema->createTable('test_routes', $tables['test_routes']);
}
}
/**
* Basic tests for the Route.
*
* Note: This should be a UnitTestBase, but those are broken right now in
* Drupal HEAD. Convert it to a UnitTest when that gets fixed.
*/
class RouteTestCase extends WebTestBase {
public static function getInfo() {
return array(
'name' => 'Routes',
'description' => 'Confirm that route object is functioning properly.',
'group' => 'Routng',
);
}
function setUp() {
parent::setUp();
}
public function testCompilation() {
$route = new Route('test/{something}/more');
$route->setOption('compiler_class', 'Drupal\Core\Routing\RouteCompiler');
$compiled = $route->compile();
$this->assertEqual($route, $compiled->getRoute(), t('Compiled route has the correct route object.'));
$this->assertEqual($compiled->getFit(), 5 /* That's 101 binary*/, t('The fit was correct.'));
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment