Various documentation and whitespace fixes.
parent
7019a0c1ca
commit
0703718bcd
|
@ -1,10 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Drupal\Component\Utility\NestedArray;
|
use Symfony\Component\DependencyInjection\Container;
|
||||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
use Drupal\Component\Utility\NestedArray;
|
||||||
use Drupal\Core\Cache\CacheBackendInterface;
|
use Drupal\Core\Cache\CacheBackendInterface;
|
||||||
use Symfony\Component\DependencyInjection\Container;
|
|
||||||
use Drupal\Core\Database\Database;
|
use Drupal\Core\Database\Database;
|
||||||
use Drupal\Core\Template\Attribute;
|
use Drupal\Core\Template\Attribute;
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,9 @@ class RouteProcessorSubscriber implements EventSubscriberInterface {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a default controller for a route if one was not specified.
|
* Sets a default controller for a route if one was not specified.
|
||||||
|
*
|
||||||
|
* @param Symfony\Component\HttpKernel\Event\GetResponseEvent $event
|
||||||
|
* Event that is created to create a response for a request.
|
||||||
*/
|
*/
|
||||||
public function onRequestSetController(GetResponseEvent $event) {
|
public function onRequestSetController(GetResponseEvent $event) {
|
||||||
$request = $event->getRequest();
|
$request = $event->getRequest();
|
||||||
|
|
|
@ -41,6 +41,7 @@ class HtmlPageController implements ContainerAwareInterface {
|
||||||
* The request object.
|
* The request object.
|
||||||
* @param type $_content
|
* @param type $_content
|
||||||
* The body content callable that contains the body region of this page.
|
* The body content callable that contains the body region of this page.
|
||||||
|
*
|
||||||
* @return \Symfony\Component\HttpFoundation\Response
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
*/
|
*/
|
||||||
public function content(Request $request, $_content) {
|
public function content(Request $request, $_content) {
|
||||||
|
|
|
@ -27,6 +27,7 @@ class ChainMatcher implements RequestMatcherInterface, RequestContextAwareInterf
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of RequestMatcherInterface objects, sorted.
|
* Array of RequestMatcherInterface objects, sorted.
|
||||||
|
*
|
||||||
* @var type
|
* @var type
|
||||||
*/
|
*/
|
||||||
protected $sortedMatchers = array();
|
protected $sortedMatchers = array();
|
||||||
|
@ -111,8 +112,8 @@ class ChainMatcher implements RequestMatcherInterface, RequestContextAwareInterf
|
||||||
* @param MatcherInterface $matcher
|
* @param MatcherInterface $matcher
|
||||||
* The matcher to add.
|
* The matcher to add.
|
||||||
* @param int $priority
|
* @param int $priority
|
||||||
* The priority of the matcher. Higher number matchers will be checked
|
* (optional) The priority of the matcher. Higher number matchers will be checked
|
||||||
* first.
|
* first. Default to 0.
|
||||||
*/
|
*/
|
||||||
public function add(RequestMatcherInterface $matcher, $priority = 0) {
|
public function add(RequestMatcherInterface $matcher, $priority = 0) {
|
||||||
if (empty($this->matchers[$priority])) {
|
if (empty($this->matchers[$priority])) {
|
||||||
|
|
|
@ -36,17 +36,22 @@ class CompiledRoute {
|
||||||
* @var Symfony\Component\Routing\Route
|
* @var Symfony\Component\Routing\Route
|
||||||
*/
|
*/
|
||||||
protected $route;
|
protected $route;
|
||||||
|
|
||||||
protected $variables;
|
protected $variables;
|
||||||
protected $tokens;
|
protected $tokens;
|
||||||
protected $staticPrefix;
|
protected $staticPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The regular expression to match placeholders out of this path.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $regex;
|
protected $regex;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new CompiledRoute object.
|
* Constructs a new CompiledRoute object.
|
||||||
*
|
*
|
||||||
* @param Route $route
|
* @param Route $route
|
||||||
* A original Route instance.
|
* A original Route instance.
|
||||||
* @param int $fit
|
* @param int $fit
|
||||||
* The fitness of the route.
|
* The fitness of the route.
|
||||||
|
@ -66,7 +71,7 @@ class CompiledRoute {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the fit of this route
|
* Returns the fit of this route.
|
||||||
*
|
*
|
||||||
* See RouteCompiler for a definition of how the fit is calculated.
|
* See RouteCompiler for a definition of how the fit is calculated.
|
||||||
*
|
*
|
||||||
|
@ -117,7 +122,7 @@ class CompiledRoute {
|
||||||
* Returns the Route instance.
|
* Returns the Route instance.
|
||||||
*
|
*
|
||||||
* @return Route
|
* @return Route
|
||||||
* A Route instance
|
* A Route instance.
|
||||||
*/
|
*/
|
||||||
public function getRoute() {
|
public function getRoute() {
|
||||||
return $this->route;
|
return $this->route;
|
||||||
|
@ -126,7 +131,8 @@ class CompiledRoute {
|
||||||
/**
|
/**
|
||||||
* Returns the pattern.
|
* Returns the pattern.
|
||||||
*
|
*
|
||||||
* @return string The pattern
|
* @return string
|
||||||
|
* The pattern.
|
||||||
*/
|
*/
|
||||||
public function getPattern() {
|
public function getPattern() {
|
||||||
return $this->route->getPattern();
|
return $this->route->getPattern();
|
||||||
|
@ -135,7 +141,8 @@ class CompiledRoute {
|
||||||
/**
|
/**
|
||||||
* Returns the options.
|
* Returns the options.
|
||||||
*
|
*
|
||||||
* @return array The options
|
* @return array
|
||||||
|
* The options.
|
||||||
*/
|
*/
|
||||||
public function getOptions() {
|
public function getOptions() {
|
||||||
return $this->route->getOptions();
|
return $this->route->getOptions();
|
||||||
|
@ -144,7 +151,8 @@ class CompiledRoute {
|
||||||
/**
|
/**
|
||||||
* Returns the defaults.
|
* Returns the defaults.
|
||||||
*
|
*
|
||||||
* @return array The defaults
|
* @return array
|
||||||
|
* The defaults.
|
||||||
*/
|
*/
|
||||||
public function getDefaults() {
|
public function getDefaults() {
|
||||||
return $this->route->getDefaults();
|
return $this->route->getDefaults();
|
||||||
|
@ -153,11 +161,11 @@ class CompiledRoute {
|
||||||
/**
|
/**
|
||||||
* Returns the requirements.
|
* Returns the requirements.
|
||||||
*
|
*
|
||||||
* @return array The requirements
|
* @return array
|
||||||
|
* The requirements.
|
||||||
*/
|
*/
|
||||||
public function getRequirements() {
|
public function getRequirements() {
|
||||||
return $this->route->getRequirements();
|
return $this->route->getRequirements();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ interface FinalMatcherInterface {
|
||||||
* A Request object against which to match.
|
* A Request object against which to match.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
* An array of parameters
|
* An array of parameters.
|
||||||
*/
|
*/
|
||||||
public function matchRequest(Request $request);
|
public function matchRequest(Request $request);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,9 @@ class FirstEntryFinalMatcher implements FinalMatcherInterface {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements Drupal\Core\Routing\FinalMatcherInterface::matchRequest().
|
||||||
|
*/
|
||||||
public function matchRequest(Request $request) {
|
public function matchRequest(Request $request) {
|
||||||
// Return whatever the first route in the collection is.
|
// Return whatever the first route in the collection is.
|
||||||
foreach ($this->routes as $name => $route) {
|
foreach ($this->routes as $name => $route) {
|
||||||
|
@ -54,12 +56,12 @@ class FirstEntryFinalMatcher implements FinalMatcherInterface {
|
||||||
* Get merged default parameters.
|
* Get merged default parameters.
|
||||||
*
|
*
|
||||||
* @param array $params
|
* @param array $params
|
||||||
* The parameters
|
* The parameters.
|
||||||
* @param array $defaults
|
* @param array $defaults
|
||||||
* The defaults
|
* The defaults.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
* Merged default parameters
|
* Merged default parameters.
|
||||||
*/
|
*/
|
||||||
protected function mergeDefaults($params, $defaults) {
|
protected function mergeDefaults($params, $defaults) {
|
||||||
$parameters = $defaults;
|
$parameters = $defaults;
|
||||||
|
@ -73,4 +75,3 @@ class FirstEntryFinalMatcher implements FinalMatcherInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,15 @@ class MatcherDumper implements MatcherDumperInterface {
|
||||||
*/
|
*/
|
||||||
protected $tableName;
|
protected $tableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the MatcherDumper.
|
||||||
|
*
|
||||||
|
* @param Drupal\Core\Database\Connection $connection
|
||||||
|
* The database connection which will be used to store the route
|
||||||
|
* information.
|
||||||
|
* @param string $table
|
||||||
|
* (optional) The table to store the route info in. Defaults to 'router'.
|
||||||
|
*/
|
||||||
public function __construct(Connection $connection, $table = 'router') {
|
public function __construct(Connection $connection, $table = 'router') {
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
|
|
||||||
|
@ -63,21 +72,18 @@ class MatcherDumper implements MatcherDumperInterface {
|
||||||
* Dumps a set of routes to the router table in the database.
|
* Dumps a set of routes to the router table in the database.
|
||||||
*
|
*
|
||||||
* Available options:
|
* Available options:
|
||||||
|
* - route_set: The route grouping that is being dumped. All existing
|
||||||
|
* routes with this route set will be deleted on dump.
|
||||||
|
* - base_class: The base class name
|
||||||
*
|
*
|
||||||
* * route_set: The route grouping that is being dumped. All existing
|
* @param array $options
|
||||||
* routes with this route set will be deleted on dump.
|
* An array of options
|
||||||
* * base_class: The base class name
|
|
||||||
*
|
|
||||||
* @param $options array
|
|
||||||
* $options An array of options
|
|
||||||
*/
|
*/
|
||||||
public function dump(array $options = array()) {
|
public function dump(array $options = array()) {
|
||||||
$options += array(
|
$options += array(
|
||||||
'route_set' => '',
|
'route_set' => '',
|
||||||
);
|
);
|
||||||
|
|
||||||
//$compiled = $this->compileRoutes($this->routes, $route_set);
|
|
||||||
|
|
||||||
// Convert all of the routes into database records.
|
// Convert all of the routes into database records.
|
||||||
$insert = $this->connection->insert($this->tableName)->fields(array(
|
$insert = $this->connection->insert($this->tableName)->fields(array(
|
||||||
'name',
|
'name',
|
||||||
|
@ -104,7 +110,7 @@ class MatcherDumper implements MatcherDumperInterface {
|
||||||
// compiled route object. Remove this once
|
// compiled route object. Remove this once
|
||||||
// https://github.com/symfony/symfony/pull/4755 is merged and brought
|
// https://github.com/symfony/symfony/pull/4755 is merged and brought
|
||||||
// back downstream.
|
// back downstream.
|
||||||
'route' => serialize(clone($route)),
|
'route' => serialize(clone($route)),
|
||||||
);
|
);
|
||||||
$insert->values($values);
|
$insert->values($values);
|
||||||
}
|
}
|
||||||
|
@ -160,4 +166,3 @@ class MatcherDumper implements MatcherDumperInterface {
|
||||||
return $fit;
|
return $fit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,9 @@ use Symfony\Component\HttpFoundation\Request;
|
||||||
class NestedMatcher implements NestedMatcherInterface {
|
class NestedMatcher implements NestedMatcherInterface {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The final matcher
|
* The final matcher.
|
||||||
*
|
*
|
||||||
* @var RequestMatcherInterface
|
* @var Symfony\Component\Routing\Matcher\RequestMatcherInterface
|
||||||
*/
|
*/
|
||||||
protected $finalMatcher;
|
protected $finalMatcher;
|
||||||
|
|
||||||
|
@ -32,14 +32,14 @@ class NestedMatcher implements NestedMatcherInterface {
|
||||||
/**
|
/**
|
||||||
* The initial matcher to match against.
|
* The initial matcher to match against.
|
||||||
*
|
*
|
||||||
* @var InitialMatcherInterface
|
* @var Drupal\core\Routing\InitialMatcherInterface
|
||||||
*/
|
*/
|
||||||
protected $initialMatcher;
|
protected $initialMatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The request context.
|
* The request context.
|
||||||
*
|
*
|
||||||
* @var RequestContext
|
* @var Symfony\Component\Routing\RequestContext
|
||||||
*/
|
*/
|
||||||
protected $context;
|
protected $context;
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ class NestedMatcher implements NestedMatcherInterface {
|
||||||
* Partial matchers will be run in the order in which they are added.
|
* Partial matchers will be run in the order in which they are added.
|
||||||
*
|
*
|
||||||
* @param PartialMatcherInterface $matcher
|
* @param PartialMatcherInterface $matcher
|
||||||
* A partial
|
* A partial.
|
||||||
*
|
*
|
||||||
* @return NestedMatcherInterface
|
* @return NestedMatcherInterface
|
||||||
* The current matcher.
|
* The current matcher.
|
||||||
|
@ -101,9 +101,11 @@ class NestedMatcher implements NestedMatcherInterface {
|
||||||
* If the matcher can not find information, it must throw one of the exceptions documented
|
* If the matcher can not find information, it must throw one of the exceptions documented
|
||||||
* below.
|
* below.
|
||||||
*
|
*
|
||||||
* @param Request $request The request to match
|
* @param Request $request
|
||||||
|
* The request to match.
|
||||||
*
|
*
|
||||||
* @return array An array of parameters
|
* @return array
|
||||||
|
* An array of parameters.
|
||||||
*
|
*
|
||||||
* @throws ResourceNotFoundException If no matching resource could be found
|
* @throws ResourceNotFoundException If no matching resource could be found
|
||||||
* @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed
|
* @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed
|
||||||
|
@ -146,4 +148,3 @@ class NestedMatcher implements NestedMatcherInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ use Drupal\Core\Database\Connection;
|
||||||
* Initial matcher to match a route against a built database, by path.
|
* Initial matcher to match a route against a built database, by path.
|
||||||
*/
|
*/
|
||||||
class PathMatcher implements InitialMatcherInterface {
|
class PathMatcher implements InitialMatcherInterface {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The database connection from which to read route information.
|
* The database connection from which to read route information.
|
||||||
*
|
*
|
||||||
|
@ -86,6 +87,7 @@ class PathMatcher implements InitialMatcherInterface {
|
||||||
*
|
*
|
||||||
* @param array $parts
|
* @param array $parts
|
||||||
* The parts of the path for which we want candidates.
|
* The parts of the path for which we want candidates.
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
* An array of outlines that could match the specified path parts.
|
* An array of outlines that could match the specified path parts.
|
||||||
*/
|
*/
|
||||||
|
@ -130,4 +132,3 @@ class PathMatcher implements InitialMatcherInterface {
|
||||||
return $ancestors;
|
return $ancestors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,19 @@ class RouteBuilder {
|
||||||
|
|
||||||
protected $dumper;
|
protected $dumper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construcs the RouteBuilder using the passed MatcherDumperInterface
|
||||||
|
*
|
||||||
|
* @param Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface $dumper
|
||||||
|
* The matcher dumper used to store the route information.
|
||||||
|
*/
|
||||||
public function __construct(MatcherDumperInterface $dumper) {
|
public function __construct(MatcherDumperInterface $dumper) {
|
||||||
$this->dumper = $dumper;
|
$this->dumper = $dumper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rebuilds the route info and dumps to dumper.
|
||||||
|
*/
|
||||||
public function rebuild() {
|
public function rebuild() {
|
||||||
// We need to manually call each module so that we can know which module
|
// We need to manually call each module so that we can know which module
|
||||||
// a given item came from.
|
// a given item came from.
|
||||||
|
|
|
@ -22,18 +22,18 @@ class RouteCompiler implements RouteCompilerInterface {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility constant to use for regular expressions against the path.
|
* Utility constant to use for regular expressions against the path.
|
||||||
*/
|
*/
|
||||||
const REGEX_DELIMITER = '#';
|
const REGEX_DELIMITER = '#';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiles the current route instance.
|
* Compiles the current route instance.
|
||||||
*
|
*
|
||||||
* @param \Symfony\Component\Routing\Route $route
|
* @param \Symfony\Component\Routing\Route $route
|
||||||
* A Route instance
|
* A Route instance.
|
||||||
*
|
*
|
||||||
* @return CompiledRoute
|
* @return CompiledRoute
|
||||||
* A CompiledRoute instance
|
* A CompiledRoute instance.
|
||||||
*/
|
*/
|
||||||
public function compile(Route $route) {
|
public function compile(Route $route) {
|
||||||
|
|
||||||
$stripped_path = $this->getPathWithoutDefaults($route);
|
$stripped_path = $this->getPathWithoutDefaults($route);
|
||||||
|
@ -62,7 +62,9 @@ class RouteCompiler implements RouteCompilerInterface {
|
||||||
* The route object.
|
* The route object.
|
||||||
* @param string $pattern
|
* @param string $pattern
|
||||||
* The pattern for which we want a matching regex.
|
* The pattern for which we want a matching regex.
|
||||||
|
*
|
||||||
* @return type
|
* @return type
|
||||||
|
*
|
||||||
* @throws \LogicException
|
* @throws \LogicException
|
||||||
*/
|
*/
|
||||||
public function getRegex(Route $route, $pattern) {
|
public function getRegex(Route $route, $pattern) {
|
||||||
|
@ -107,11 +109,11 @@ class RouteCompiler implements RouteCompilerInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the first optional token
|
// find the first optional token
|
||||||
$firstOptional = INF;
|
$first_optional = INF;
|
||||||
for ($i = count($tokens) - 1; $i >= 0; $i--) {
|
for ($i = count($tokens) - 1; $i >= 0; $i--) {
|
||||||
$token = $tokens[$i];
|
$token = $tokens[$i];
|
||||||
if ('variable' === $token[0] && $route->hasDefault($token[3])) {
|
if ('variable' === $token[0] && $route->hasDefault($token[3])) {
|
||||||
$firstOptional = $i;
|
$first_optional = $i;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -120,50 +122,56 @@ class RouteCompiler implements RouteCompilerInterface {
|
||||||
// compute the matching regexp
|
// compute the matching regexp
|
||||||
$regexp = '';
|
$regexp = '';
|
||||||
for ($i = 0, $nbToken = count($tokens); $i < $nbToken; $i++) {
|
for ($i = 0, $nbToken = count($tokens); $i < $nbToken; $i++) {
|
||||||
$regexp .= $this->computeRegexp($tokens, $i, $firstOptional);
|
$regexp .= $this->computeRegexp($tokens, $i, $first_optional);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'s';
|
return self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'s';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the regexp used to match a specific token. It can be static text or a subpattern.
|
* Computes the regexp used to match a specific token. It can be static text or a subpattern.
|
||||||
*
|
*
|
||||||
* @param array $tokens The route tokens
|
* @param array $tokens
|
||||||
* @param integer $index The index of the current token
|
* The route tokens
|
||||||
* @param integer $firstOptional The index of the first optional token
|
* @param integer $index
|
||||||
*
|
* The index of the current token
|
||||||
* @return string The regexp pattern for a single token
|
* @param integer $first_optional
|
||||||
*/
|
* The index of the first optional token
|
||||||
private function computeRegexp(array $tokens, $index, $firstOptional) {
|
*
|
||||||
$token = $tokens[$index];
|
* @return string
|
||||||
if ('text' === $token[0]) {
|
* The regexp pattern for a single token
|
||||||
// Text tokens
|
*/
|
||||||
return preg_quote($token[1], self::REGEX_DELIMITER);
|
private function computeRegexp(array $tokens, $index, $first_optional) {
|
||||||
} else {
|
$token = $tokens[$index];
|
||||||
// Variable tokens
|
if ('text' === $token[0]) {
|
||||||
if (0 === $index && 0 === $firstOptional) {
|
// Text tokens
|
||||||
// When the only token is an optional variable token, the separator is required
|
return preg_quote($token[1], self::REGEX_DELIMITER);
|
||||||
return sprintf('%s(?<%s>%s)?', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]);
|
}
|
||||||
} else {
|
else {
|
||||||
$regexp = sprintf('%s(?<%s>%s)', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]);
|
// Variable tokens
|
||||||
if ($index >= $firstOptional) {
|
if (0 === $index && 0 === $first_optional) {
|
||||||
// Enclose each optional token in a subpattern to make it optional.
|
// When the only token is an optional variable token, the separator is
|
||||||
// "?:" means it is non-capturing, i.e. the portion of the subject string that
|
// required.
|
||||||
// matched the optional subpattern is not passed back.
|
return sprintf('%s(?<%s>%s)?', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]);
|
||||||
$regexp = "(?:$regexp";
|
|
||||||
$nbTokens = count($tokens);
|
|
||||||
if ($nbTokens - 1 == $index) {
|
|
||||||
// Close the optional subpatterns
|
|
||||||
$regexp .= str_repeat(")?", $nbTokens - $firstOptional - (0 === $firstOptional ? 1 : 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $regexp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
|
$regexp = sprintf('%s(?<%s>%s)', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]);
|
||||||
|
if ($index >= $first_optional) {
|
||||||
|
// Enclose each optional token in a subpattern to make it optional.
|
||||||
|
// "?:" means it is non-capturing, i.e. the portion of the subject
|
||||||
|
// string that matched the optional subpattern is not passed back.
|
||||||
|
$regexp = "(?:$regexp";
|
||||||
|
$nbTokens = count($tokens);
|
||||||
|
if ($nbTokens - 1 == $index) {
|
||||||
|
// Close the optional subpatterns.
|
||||||
|
$regexp .= str_repeat(")?", $nbTokens - $first_optional - (0 === $first_optional ? 1 : 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $regexp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the pattern outline.
|
* Returns the pattern outline.
|
||||||
|
@ -217,6 +225,7 @@ class RouteCompiler implements RouteCompilerInterface {
|
||||||
* problem.
|
* problem.
|
||||||
*
|
*
|
||||||
* @param \Symfony\Component\Routing\Route $route
|
* @param \Symfony\Component\Routing\Route $route
|
||||||
|
* The route to have the placeholders removed from.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
* The path string, stripped of placeholders that have default values.
|
* The path string, stripped of placeholders that have default values.
|
||||||
|
@ -236,4 +245,3 @@ class RouteCompiler implements RouteCompilerInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ use Exception;
|
||||||
* Basic tests for the ChainMatcher.
|
* Basic tests for the ChainMatcher.
|
||||||
*/
|
*/
|
||||||
class ChainMatcherTest extends UnitTestBase {
|
class ChainMatcherTest extends UnitTestBase {
|
||||||
|
|
||||||
public static function getInfo() {
|
public static function getInfo() {
|
||||||
return array(
|
return array(
|
||||||
'name' => 'Chain matcher tests',
|
'name' => 'Chain matcher tests',
|
||||||
|
|
|
@ -44,9 +44,6 @@ class FirstEntryFinalMatcherTest extends UnitTestBase {
|
||||||
|
|
||||||
$this->fixtures = new RoutingFixtures();
|
$this->fixtures = new RoutingFixtures();
|
||||||
}
|
}
|
||||||
public function setUp() {
|
|
||||||
parent::setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Confirms the final matcher returns correct attributes for static paths.
|
* Confirms the final matcher returns correct attributes for static paths.
|
||||||
|
@ -113,4 +110,3 @@ class FirstEntryFinalMatcherTest extends UnitTestBase {
|
||||||
$this->assertEqual($attributes['value'], 'poink', 'Optional placeholder value used default.');
|
$this->assertEqual($attributes['value'], 'poink', 'Optional placeholder value used default.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,9 +44,6 @@ class HttpMethodMatcherTest extends UnitTestBase {
|
||||||
|
|
||||||
$this->fixtures = new RoutingFixtures();
|
$this->fixtures = new RoutingFixtures();
|
||||||
}
|
}
|
||||||
public function setUp() {
|
|
||||||
parent::setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Confirms that the HttpMethod matcher matches properly.
|
* Confirms that the HttpMethod matcher matches properly.
|
||||||
|
@ -106,4 +103,3 @@ class HttpMethodMatcherTest extends UnitTestBase {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,9 @@ use Closure;
|
||||||
*/
|
*/
|
||||||
class MockMatcher implements RequestMatcherInterface {
|
class MockMatcher implements RequestMatcherInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The matcher being tested.
|
||||||
|
*/
|
||||||
protected $matcher;
|
protected $matcher;
|
||||||
|
|
||||||
public function __construct(Closure $matcher) {
|
public function __construct(Closure $matcher) {
|
||||||
|
@ -32,4 +35,3 @@ class MockMatcher implements RequestMatcherInterface {
|
||||||
return $matcher($request);
|
return $matcher($request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,14 +9,23 @@ use Symfony\Component\Routing\RouteCollection;
|
||||||
use Drupal\Core\Routing\InitialMatcherInterface;
|
use Drupal\Core\Routing\InitialMatcherInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description of MockPathMatcher
|
* Provides a mock path matcher.
|
||||||
*
|
|
||||||
* @author crell
|
|
||||||
*/
|
*/
|
||||||
class MockPathMatcher implements InitialMatcherInterface {
|
class MockPathMatcher implements InitialMatcherInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Routes to be matched.
|
||||||
|
*
|
||||||
|
* @var Symfony\Component\Routing\RouteCollection
|
||||||
|
*/
|
||||||
protected $routes;
|
protected $routes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the matcher given the route collection.
|
||||||
|
*
|
||||||
|
* @param Symfony\Component\Routing\RouteCollection $routes
|
||||||
|
* The routes being matched.
|
||||||
|
*/
|
||||||
public function __construct(RouteCollection $routes) {
|
public function __construct(RouteCollection $routes) {
|
||||||
$this->routes = $routes;
|
$this->routes = $routes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,9 +44,6 @@ class NestedMatcherTest extends UnitTestBase {
|
||||||
|
|
||||||
$this->fixtures = new RoutingFixtures();
|
$this->fixtures = new RoutingFixtures();
|
||||||
}
|
}
|
||||||
public function setUp() {
|
|
||||||
parent::setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Confirms we can nest multiple partial matchers.
|
* Confirms we can nest multiple partial matchers.
|
||||||
|
@ -66,4 +63,3 @@ class NestedMatcherTest extends UnitTestBase {
|
||||||
$this->assertEqual($attributes['_route'], 'route_a', 'The correct matching route was found.');
|
$this->assertEqual($attributes['_route'], 'route_a', 'The correct matching route was found.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ class PathMatcherTest extends UnitTestBase {
|
||||||
public function tearDown() {
|
public function tearDown() {
|
||||||
$this->fixtures->dropTables(Database::getConnection());
|
$this->fixtures->dropTables(Database::getConnection());
|
||||||
|
|
||||||
parent::tearDown();
|
parent::tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,8 +63,6 @@ class PathMatcherTest extends UnitTestBase {
|
||||||
|
|
||||||
$candidates = $matcher->getCandidateOutlines($parts);
|
$candidates = $matcher->getCandidateOutlines($parts);
|
||||||
|
|
||||||
//debug($candidates);
|
|
||||||
|
|
||||||
$candidates = array_flip($candidates);
|
$candidates = array_flip($candidates);
|
||||||
|
|
||||||
$this->assertTrue(count($candidates) == 4, 'Correct number of candidates found');
|
$this->assertTrue(count($candidates) == 4, 'Correct number of candidates found');
|
||||||
|
@ -275,7 +273,7 @@ class PathMatcherTest extends UnitTestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Confirm that an exception is thrown when no matching path is found.
|
* Confirms that an exception is thrown when no matching path is found.
|
||||||
*/
|
*/
|
||||||
function testOutlinePathNoMatch() {
|
function testOutlinePathNoMatch() {
|
||||||
$connection = Database::getConnection();
|
$connection = Database::getConnection();
|
||||||
|
|
|
@ -45,8 +45,8 @@ class RouteTest extends UnitTestBase {
|
||||||
* Confirms that a compiled route with default values has the correct outline.
|
* Confirms that a compiled route with default values has the correct outline.
|
||||||
*/
|
*/
|
||||||
public function testCompilationDefaultValue() {
|
public function testCompilationDefaultValue() {
|
||||||
// Because "here" has a default value, it should not factor into the
|
// Because "here" has a default value, it should not factor into the outline
|
||||||
// outline or the fitness.
|
// or the fitness.
|
||||||
$route = new Route('/test/{something}/more/{here}', array(
|
$route = new Route('/test/{something}/more/{here}', array(
|
||||||
'here' => 'there',
|
'here' => 'there',
|
||||||
));
|
));
|
||||||
|
|
|
@ -12,6 +12,12 @@ use Drupal\Core\Database\Connection;
|
||||||
*/
|
*/
|
||||||
class RoutingFixtures {
|
class RoutingFixtures {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the tables required for the sample data.
|
||||||
|
*
|
||||||
|
* @param Drupal\Core\Database\Connection $connection
|
||||||
|
* The connection to use to create the tables.
|
||||||
|
*/
|
||||||
public function createTables(Connection $connection) {
|
public function createTables(Connection $connection) {
|
||||||
$tables = $this->routingTableDefinition();
|
$tables = $this->routingTableDefinition();
|
||||||
$schema = $connection->schema();
|
$schema = $connection->schema();
|
||||||
|
@ -22,6 +28,12 @@ class RoutingFixtures {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop the tables used for the sample data.
|
||||||
|
*
|
||||||
|
* @param Drupal\Core\Database\Connection $connection
|
||||||
|
* The connection to use to drop the tables.
|
||||||
|
*/
|
||||||
public function dropTables(Connection $connection) {
|
public function dropTables(Connection $connection) {
|
||||||
$tables = $this->routingTableDefinition();
|
$tables = $this->routingTableDefinition();
|
||||||
$schema = $connection->schema();
|
$schema = $connection->schema();
|
||||||
|
@ -91,6 +103,12 @@ class RoutingFixtures {
|
||||||
return $collection;
|
return $collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the table definition for the routing fixtures.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
* Table definitions.
|
||||||
|
*/
|
||||||
public function routingTableDefinition() {
|
public function routingTableDefinition() {
|
||||||
|
|
||||||
$tables['test_routes'] = array(
|
$tables['test_routes'] = array(
|
||||||
|
|
Loading…
Reference in New Issue