2010-02-17 13:53:31 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
2011-01-15 13:29:43 +00:00
|
|
|
* This file is part of the Symfony package.
|
2010-02-17 13:53:31 +00:00
|
|
|
*
|
2011-03-06 11:40:06 +00:00
|
|
|
* (c) Fabien Potencier <fabien@symfony.com>
|
2010-02-17 13:53:31 +00:00
|
|
|
*
|
2011-01-15 13:29:43 +00:00
|
|
|
* For the full copyright and license information, please view the LICENSE
|
|
|
|
* file that was distributed with this source code.
|
2010-02-17 13:53:31 +00:00
|
|
|
*/
|
|
|
|
|
2011-01-15 13:29:43 +00:00
|
|
|
namespace Symfony\Component\Routing;
|
|
|
|
|
2010-02-17 13:53:31 +00:00
|
|
|
/**
|
|
|
|
* RouteCompiler compiles Route instances to CompiledRoute instances.
|
|
|
|
*
|
2011-03-06 11:40:06 +00:00
|
|
|
* @author Fabien Potencier <fabien@symfony.com>
|
2010-02-17 13:53:31 +00:00
|
|
|
*/
|
|
|
|
class RouteCompiler implements RouteCompilerInterface
|
|
|
|
{
|
2010-05-06 12:25:53 +01:00
|
|
|
/**
|
|
|
|
* Compiles the current route instance.
|
|
|
|
*
|
|
|
|
* @param Route $route A Route instance
|
|
|
|
*
|
2010-07-01 19:17:03 +01:00
|
|
|
* @return CompiledRoute A CompiledRoute instance
|
2010-05-06 12:25:53 +01:00
|
|
|
*/
|
|
|
|
public function compile(Route $route)
|
2010-02-17 13:53:31 +00:00
|
|
|
{
|
2011-04-25 11:03:41 +01:00
|
|
|
$pattern = $route->getPattern();
|
|
|
|
$len = strlen($pattern);
|
2010-05-06 12:25:53 +01:00
|
|
|
$tokens = array();
|
2011-04-25 11:03:41 +01:00
|
|
|
$variables = array();
|
|
|
|
$pos = 0;
|
|
|
|
preg_match_all('#.\{([\w\d_]+)\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
|
|
|
|
foreach ($matches as $match) {
|
|
|
|
if ($text = substr($pattern, $pos, $match[0][1] - $pos)) {
|
|
|
|
$tokens[] = array('text', $text);
|
2010-05-06 12:25:53 +01:00
|
|
|
}
|
2011-04-26 08:01:25 +01:00
|
|
|
$seps = array($pattern[$pos]);
|
2011-04-25 11:03:41 +01:00
|
|
|
$pos = $match[0][1] + strlen($match[0][0]);
|
|
|
|
$var = $match[1][0];
|
2010-02-17 13:53:31 +00:00
|
|
|
|
2011-04-25 11:03:41 +01:00
|
|
|
if ($req = $route->getRequirement($var)) {
|
|
|
|
$regexp = $req;
|
|
|
|
} else {
|
2011-04-26 08:01:25 +01:00
|
|
|
if ($pos !== $len) {
|
|
|
|
$seps[] = $pattern[$pos];
|
|
|
|
}
|
2011-05-03 13:48:08 +01:00
|
|
|
$regexp = sprintf('[^%s]+?', preg_quote(implode('', array_unique($seps)), '#'));
|
2011-04-25 11:03:41 +01:00
|
|
|
}
|
2010-02-17 13:53:31 +00:00
|
|
|
|
2011-04-25 11:03:41 +01:00
|
|
|
$tokens[] = array('variable', $match[0][0][0], $regexp, $var);
|
2012-02-14 10:41:45 +00:00
|
|
|
|
|
|
|
if (in_array($var, $variables)) {
|
|
|
|
throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $route->getPattern(), $var));
|
|
|
|
}
|
|
|
|
|
2011-04-25 11:03:41 +01:00
|
|
|
$variables[] = $var;
|
2010-05-06 12:25:53 +01:00
|
|
|
}
|
|
|
|
|
2011-04-25 11:03:41 +01:00
|
|
|
if ($pos < $len) {
|
|
|
|
$tokens[] = array('text', substr($pattern, $pos));
|
2010-05-06 12:25:53 +01:00
|
|
|
}
|
|
|
|
|
2011-04-25 11:03:41 +01:00
|
|
|
// find the first optional token
|
|
|
|
$firstOptional = INF;
|
|
|
|
for ($i = count($tokens) - 1; $i >= 0; $i--) {
|
|
|
|
if ('variable' === $tokens[$i][0] && $route->hasDefault($tokens[$i][3])) {
|
|
|
|
$firstOptional = $i;
|
2010-05-07 15:09:11 +01:00
|
|
|
} else {
|
2011-04-25 11:03:41 +01:00
|
|
|
break;
|
2010-05-06 12:25:53 +01:00
|
|
|
}
|
|
|
|
}
|
2010-02-17 13:53:31 +00:00
|
|
|
|
2011-04-25 11:03:41 +01:00
|
|
|
// compute the matching regexp
|
|
|
|
$regex = '';
|
|
|
|
$indent = 1;
|
2011-05-03 07:54:33 +01:00
|
|
|
if (1 === count($tokens) && 0 === $firstOptional) {
|
|
|
|
$token = $tokens[0];
|
|
|
|
++$indent;
|
|
|
|
$regex .= str_repeat(' ', $indent * 4).sprintf("%s(?:\n", preg_quote($token[1], '#'));
|
|
|
|
$regex .= str_repeat(' ', $indent * 4).sprintf("(?P<%s>%s)\n", $token[3], $token[2]);
|
|
|
|
} else {
|
|
|
|
foreach ($tokens as $i => $token) {
|
|
|
|
if ('text' === $token[0]) {
|
|
|
|
$regex .= str_repeat(' ', $indent * 4).preg_quote($token[1], '#')."\n";
|
|
|
|
} else {
|
|
|
|
if ($i >= $firstOptional) {
|
|
|
|
$regex .= str_repeat(' ', $indent * 4)."(?:\n";
|
|
|
|
++$indent;
|
|
|
|
}
|
|
|
|
$regex .= str_repeat(' ', $indent * 4).sprintf("%s(?P<%s>%s)\n", preg_quote($token[1], '#'), $token[3], $token[2]);
|
2011-04-25 11:03:41 +01:00
|
|
|
}
|
|
|
|
}
|
2010-05-06 12:25:53 +01:00
|
|
|
}
|
2011-04-25 11:03:41 +01:00
|
|
|
while (--$indent) {
|
|
|
|
$regex .= str_repeat(' ', $indent * 4).")?\n";
|
2010-05-06 12:25:53 +01:00
|
|
|
}
|
2010-02-17 13:53:31 +00:00
|
|
|
|
2011-04-25 11:03:41 +01:00
|
|
|
return new CompiledRoute(
|
|
|
|
$route,
|
|
|
|
'text' === $tokens[0][0] ? $tokens[0][1] : '',
|
2011-09-23 15:53:06 +01:00
|
|
|
sprintf("#^\n%s$#xs", $regex),
|
2011-04-25 11:03:41 +01:00
|
|
|
array_reverse($tokens),
|
|
|
|
$variables
|
|
|
|
);
|
2010-05-06 12:25:53 +01:00
|
|
|
}
|
2010-02-17 13:53:31 +00:00
|
|
|
}
|