diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php index bf5503bf4af7..4b5350455017 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php @@ -135,24 +135,6 @@ protected function outputRoute(OutputInterface $output, $routes, $name) $output->writeln(sprintf('Options %s', $options)); $output->write('Regex '); $output->writeln(preg_replace('/^ /', '', preg_replace('/^/m', ' ', $route->getRegex())), OutputInterface::OUTPUT_RAW); - - $tokens = ''; - foreach ($route->getTokens() as $token) { - if (!$tokens) { - $tokens = $this->displayToken($token); - } else { - $tokens .= "\n".str_repeat(' ', 13).$this->displayToken($token); - } - } - $output->writeln(sprintf('Tokens %s', $tokens)); - } - - protected function displayToken($token) - { - $type = array_shift($token); - array_shift($token); - - return sprintf('%-10s %s', $type, $this->formatValue($token)); } protected function formatValue($value) diff --git a/src/Symfony/Component/Routing/Generator/UrlGenerator.php b/src/Symfony/Component/Routing/Generator/UrlGenerator.php index 3b3548e26e93..3e445a8245c4 100644 --- a/src/Symfony/Component/Routing/Generator/UrlGenerator.php +++ b/src/Symfony/Component/Routing/Generator/UrlGenerator.php @@ -89,6 +89,8 @@ public function generate($name, array $parameters = array(), $absolute = false) */ protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $absolute) { + $variables = array_flip($variables); + $originParameters = $parameters; $parameters = array_replace($this->context->getParameters(), $parameters); $tparams = array_replace($defaults, $parameters); @@ -104,8 +106,8 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa if ('variable' === $token[0]) { if (false === $optional || !isset($defaults[$token[3]]) || (isset($parameters[$token[3]]) && $parameters[$token[3]] != $defaults[$token[3]])) { // check requirement - if (isset($requirements[$token[3]]) && !preg_match('#^'.$requirements[$token[3]].'$#', $tparams[$token[3]])) { - throw new \InvalidArgumentException(sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given).', $token[3], $name, $requirements[$token[3]], $tparams[$token[3]])); + if (!preg_match('#^'.$token[2].'$#', $tparams[$token[3]])) { + throw new \InvalidArgumentException(sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given).', $token[3], $name, $token[2], $tparams[$token[3]])); } if ($tparams[$token[3]] || !$optional) { @@ -116,14 +118,8 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa $optional = false; } } elseif ('text' === $token[0]) { - $url = $token[1].$token[2].$url; + $url = $token[1].$url; $optional = false; - } else { - // handle custom tokens - if ($segment = call_user_func_array(array($this, 'generateFor'.ucfirst(array_shift($token))), array_merge(array($optional, $tparams), $token))) { - $url = $segment.$url; - $optional = false; - } } } diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php index 5752d297d8f8..131ba0b37404 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php @@ -47,13 +47,13 @@ public function dump(array $options = array()) $compiledRoute = $route->compile(); // prepare the apache regex - $regex = preg_replace('/\?P<.+?>/', '', substr($compiledRoute->getRegex(), 1, -2)); + $regex = preg_replace('/\?P<.+?>/', '', substr(str_replace(array("\n", ' '), '', $compiledRoute->getRegex()), 1, -2)); $regex = '^'.preg_quote($options['base_uri']).substr($regex, 1); $hasTrailingSlash = '/$' == substr($regex, -2) && '^/$' != $regex; $variables = array('E=_ROUTING__route:'.$name); - foreach (array_keys($compiledRoute->getVariables()) as $i => $variable) { + foreach ($compiledRoute->getVariables() as $i => $variable) { $variables[] = 'E=_ROUTING_'.$variable.':%'.($i + 1); } foreach ($route->getDefaults() as $key => $value) { diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index 339715be649a..b4243e4229ce 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -60,7 +60,7 @@ private function addMatcher($supportsRedirections) $conditions = array(); $hasTrailingSlash = false; $matches = false; - if (!count($compiledRoute->getVariables()) && false !== preg_match('#^(.)\^(?P.*?)\$\1#', $compiledRoute->getRegex(), $m)) { + if (!count($compiledRoute->getVariables()) && false !== preg_match('#^(.)\^(?P.*?)\$\1#', str_replace(array("\n", ' '), '', $compiledRoute->getRegex()), $m)) { if ($supportsRedirections && substr($m['url'], -1) === '/') { $conditions[] = sprintf("rtrim(\$pathinfo, '/') === '%s'", rtrim(str_replace('\\', '', $m['url']), '/')); $hasTrailingSlash = true; @@ -72,7 +72,7 @@ private function addMatcher($supportsRedirections) $conditions[] = sprintf("0 === strpos(\$pathinfo, '%s')", $compiledRoute->getStaticPrefix()); } - $regex = $compiledRoute->getRegex(); + $regex = str_replace(array("\n", ' '), '', $compiledRoute->getRegex()); if ($supportsRedirections && $pos = strpos($regex, '/$')) { $regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2); $hasTrailingSlash = true; diff --git a/src/Symfony/Component/Routing/Route.php b/src/Symfony/Component/Routing/Route.php index 7525f728b634..36170c49bc12 100644 --- a/src/Symfony/Component/Routing/Route.php +++ b/src/Symfony/Component/Routing/Route.php @@ -31,9 +31,7 @@ class Route * * Available options: * - * * segment_separators: An array of allowed characters for segment separators (/ by default) - * * text_regex: A regex that match a valid text name (.+? by default) - * * compiler_class: A class name able to compile this route instance (RouteCompiler by default) + * * compiler_class: A class name able to compile this route instance (RouteCompiler by default) * * @param string $pattern The pattern to match * @param array $defaults An array of default parameter values @@ -101,8 +99,6 @@ public function getOptions() public function setOptions(array $options) { $this->options = array_merge(array( - 'segment_separators' => array('/', '.'), - 'text_regex' => '.+?', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', ), $options); diff --git a/src/Symfony/Component/Routing/RouteCompiler.php b/src/Symfony/Component/Routing/RouteCompiler.php index 7c1bd5da5e72..7e0aa8e52cc2 100644 --- a/src/Symfony/Component/Routing/RouteCompiler.php +++ b/src/Symfony/Component/Routing/RouteCompiler.php @@ -18,15 +18,6 @@ */ class RouteCompiler implements RouteCompilerInterface { - protected $options; - protected $route; - protected $variables; - protected $firstOptional; - protected $segments; - protected $tokens; - protected $staticPrefix; - protected $regex; - /** * Compiles the current route instance. * @@ -36,200 +27,67 @@ class RouteCompiler implements RouteCompilerInterface */ public function compile(Route $route) { - $this->route = $route; - $this->firstOptional = 0; - $this->segments = array(); - $this->variables = array(); - $this->tokens = array(); - $this->staticPrefix = ''; - $this->regex = ''; - $this->options = $this->getOptions(); - - $this->preCompile(); - - $this->tokenize(); - - foreach ($this->tokens as $token) { - call_user_func_array(array($this, 'compileFor'.ucfirst(array_shift($token))), $token); - } - - $this->postCompile(); - - $separator = ''; - if (count($this->tokens)) { - $lastToken = $this->tokens[count($this->tokens) - 1]; - $separator = 'separator' == $lastToken[0] ? $lastToken[2] : ''; - } - - $this->regex = "#^".implode("", $this->segments)."".preg_quote($separator, '#')."$#x"; - - // optimize tokens for generation + $pattern = $route->getPattern(); + $len = strlen($pattern); $tokens = array(); - foreach ($this->tokens as $i => $token) { - if ($i + 1 === count($this->tokens) && 'separator' === $token[0]) { - // trailing / - $tokens[] = array('text', $token[2], '', null); - } elseif ('separator' !== $token[0]) { - $tokens[] = $token; + $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); } - } - - $tokens = array_reverse($tokens); - - return new CompiledRoute($this->route, $this->staticPrefix, $this->regex, $tokens, $this->variables); - } + $pos = $match[0][1] + strlen($match[0][0]); + $var = $match[1][0]; - /** - * Pre-compiles a route. - */ - protected function preCompile() - { - } + if ($req = $route->getRequirement($var)) { + $regexp = $req; + } else { + $regexp = $pos !== $len ? sprintf('[^%s]*?', $pattern[$pos]) : '.*?'; + } - /** - * Post-compiles a route. - */ - protected function postCompile() - { - // all segments after the last static segment are optional - // be careful, the n-1 is optional only if n is empty - for ($i = $this->firstOptional, $max = count($this->segments); $i < $max; $i++) { - $this->segments[$i] = (0 == $i ? '/?' : '').str_repeat(' ', $i - $this->firstOptional).'(?:'.$this->segments[$i]; - $this->segments[] = str_repeat(' ', $max - $i - 1).')?'; + $tokens[] = array('variable', $match[0][0][0], $regexp, $var); + $variables[] = $var; } - $this->staticPrefix = ''; - foreach ($this->tokens as $token) { - switch ($token[0]) { - case 'separator': - break; - case 'text': - // text is static - $this->staticPrefix .= $token[1].$token[2]; - break; - default: - // everything else indicates variable parts. break switch and for loop - break 2; - } + if ($pos < $len) { + $tokens[] = array('text', substr($pattern, $pos)); } - } - - /** - * Tokenizes the route. - * - * @throws \InvalidArgumentException When route can't be parsed - */ - private function tokenize() - { - $this->tokens = array(); - $buffer = $this->route->getPattern(); - $afterASeparator = false; - $currentSeparator = ''; - - // a route is an array of (separator + variable) or (separator + text) segments - while (strlen($buffer)) { - if (false !== $this->tokenizeBufferBefore($buffer, $tokens, $afterASeparator, $currentSeparator)) { - // a custom token - $this->customToken = true; - } else if ($afterASeparator && preg_match('#^\{([\w\d_]+)\}#', $buffer, $match)) { - // a variable - $this->tokens[] = array('variable', $currentSeparator, $match[0], $match[1]); - - $currentSeparator = ''; - $buffer = substr($buffer, strlen($match[0])); - $afterASeparator = false; - } else if ($afterASeparator && preg_match('#^('.$this->options['text_regex'].')(?:'.$this->options['segment_separators_regex'].'|$)#', $buffer, $match)) { - // a text - $this->tokens[] = array('text', $currentSeparator, $match[1], null); - - $currentSeparator = ''; - $buffer = substr($buffer, strlen($match[1])); - $afterASeparator = false; - } else if (!$afterASeparator && preg_match('#^'.$this->options['segment_separators_regex'].'#', $buffer, $match)) { - // a separator - $this->tokens[] = array('separator', $currentSeparator, $match[0], null); - $currentSeparator = $match[0]; - $buffer = substr($buffer, strlen($match[0])); - $afterASeparator = true; - } else if (false !== $this->tokenizeBufferAfter($buffer, $tokens, $afterASeparator, $currentSeparator)) { - // a custom token - $this->customToken = true; + // 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; } else { - // parsing problem - throw new \InvalidArgumentException(sprintf('Unable to parse "%s" route near "%s".', $this->route->getPattern(), $buffer)); + break; } } - } - - /** - * Tokenizes the buffer before default logic is applied. - * - * This method must return false if the buffer has not been parsed. - * - * @param string $buffer The current route buffer - * @param array $tokens An array of current tokens - * @param Boolean $afterASeparator Whether the buffer is just after a separator - * @param string $currentSeparator The last matched separator - * - * @return Boolean true if a token has been generated, false otherwise - */ - protected function tokenizeBufferBefore(&$buffer, &$tokens, &$afterASeparator, &$currentSeparator) - { - return false; - } - - /** - * Tokenizes the buffer after default logic is applied. - * - * This method must return false if the buffer has not been parsed. - * - * @param string $buffer The current route buffer - * @param array $tokens An array of current tokens - * @param Boolean $afterASeparator Whether the buffer is just after a separator - * @param string $currentSeparator The last matched separator - * - * @return Boolean true if a token has been generated, false otherwise - */ - protected function tokenizeBufferAfter(&$buffer, &$tokens, &$afterASeparator, &$currentSeparator) - { - return false; - } - protected function compileForText($separator, $text) - { - $this->firstOptional = count($this->segments) + 1; - - $this->segments[] = preg_quote($separator, '#').preg_quote($text, '#'); - } - - protected function compileForVariable($separator, $name, $variable) - { - if (null === $requirement = $this->route->getRequirement($variable)) { - $requirement = $this->options['variable_content_regex']; + // compute the matching regexp + $regex = ''; + $indent = 1; + 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]); + } } - - $this->segments[] = preg_quote($separator, '#').'(?P<'.$variable.'>'.$requirement.')'; - $this->variables[$variable] = $name; - - if (!$this->route->hasDefault($variable)) { - $this->firstOptional = count($this->segments); + while (--$indent) { + $regex .= str_repeat(' ', $indent * 4).")?\n"; } - } - - protected function compileForSeparator($separator, $regexSeparator) - { - } - - private function getOptions() - { - $options = $this->route->getOptions(); - - // compute some regexes - $quoter = function ($a) { return preg_quote($a, '#'); }; - $options['segment_separators_regex'] = '(?:'.implode('|', array_map($quoter, $options['segment_separators'])).')'; - $options['variable_content_regex'] = '[^'.implode('', array_map($quoter, $options['segment_separators'])).']+?'; - return $options; + return new CompiledRoute( + $route, + 'text' === $tokens[0][0] ? $tokens[0][1] : '', + sprintf("#^\n%s$#x", $regex), + array_reverse($tokens), + $variables + ); } } diff --git a/tests/Symfony/Tests/Component/Routing/CompiledRouteTest.php b/tests/Symfony/Tests/Component/Routing/CompiledRouteTest.php index 295381671c41..0e5bdffd3eb1 100644 --- a/tests/Symfony/Tests/Component/Routing/CompiledRouteTest.php +++ b/tests/Symfony/Tests/Component/Routing/CompiledRouteTest.php @@ -37,8 +37,6 @@ public function testgetPatterngetDefaultsgetOptionsgetRequirements() $this->assertEquals(array('foo' => 'bar'), $compiled->getDefaults(), '->getDefaults() returns the route defaults'); $this->assertEquals(array('foo' => '\d+'), $compiled->getRequirements(), '->getRequirements() returns the route requirements'); $this->assertEquals(array_merge(array( - 'segment_separators' => array('/', '.'), - 'text_regex' => '.+?', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', ), array('foo' => 'bar')), $compiled->getOptions(), '->getOptions() returns the route options'); } diff --git a/tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher1.apache b/tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher1.apache index e4e468c75d6d..84c7d5c9c122 100644 --- a/tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher1.apache +++ b/tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher1.apache @@ -7,10 +7,10 @@ RewriteCond %{REQUEST_URI} ^/foo/(baz|symfony)$ RewriteRule .* app.php [QSA,L,E=_ROUTING__route:foo,E=_ROUTING_bar:%1,E=_ROUTING_def:test] # bar -RewriteCond %{REQUEST_URI} ^/bar/([^/\.]+?)$ +RewriteCond %{REQUEST_URI} ^/bar/(.*?)$ RewriteCond %{REQUEST_METHOD} !^(get|head)$ [NC] RewriteRule .* - [S=1,E=_ROUTING__allow_get:1,E=_ROUTING__allow_head:1] -RewriteCond %{REQUEST_URI} ^/bar/([^/\.]+?)$ +RewriteCond %{REQUEST_URI} ^/bar/(.*?)$ RewriteRule .* app.php [QSA,L,E=_ROUTING__route:bar,E=_ROUTING_foo:%1] # baz @@ -28,18 +28,18 @@ RewriteCond %{REQUEST_URI} ^/test/baz3/$ RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz3] # baz4 -RewriteCond %{REQUEST_URI} ^/test/([^/\.]+?)$ +RewriteCond %{REQUEST_URI} ^/test/([^/]*?)$ RewriteRule .* $0/ [QSA,L,R=301] -RewriteCond %{REQUEST_URI} ^/test/([^/\.]+?)/$ +RewriteCond %{REQUEST_URI} ^/test/([^/]*?)/$ RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz4,E=_ROUTING_foo:%1] # baz5 -RewriteCond %{REQUEST_URI} ^/test/([^/\.]+?)/$ +RewriteCond %{REQUEST_URI} ^/test/([^/]*?)/$ RewriteCond %{REQUEST_METHOD} !^(post)$ [NC] RewriteRule .* - [S=2,E=_ROUTING__allow_post:1] -RewriteCond %{REQUEST_URI} ^/test/([^/\.]+?)$ +RewriteCond %{REQUEST_URI} ^/test/([^/]*?)$ RewriteRule .* $0/ [QSA,L,R=301] -RewriteCond %{REQUEST_URI} ^/test/([^/\.]+?)/$ +RewriteCond %{REQUEST_URI} ^/test/([^/]*?)/$ RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz5,E=_ROUTING_foo:%1] # 405 Method Not Allowed diff --git a/tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher1.php b/tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher1.php index 325021512561..1da750bd05e0 100644 --- a/tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher1.php +++ b/tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher1.php @@ -30,7 +30,7 @@ public function match($pathinfo) } // bar - if (0 === strpos($pathinfo, '/bar') && preg_match('#^/bar/(?P[^/\.]+?)$#x', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/bar') && preg_match('#^/bar/(?P.*?)$#x', $pathinfo, $matches)) { if (!in_array($this->context->getMethod(), array('get', 'head'))) { $allow = array_merge($allow, array('get', 'head')); goto not_bar; @@ -56,13 +56,13 @@ public function match($pathinfo) } // baz4 - if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P[^/\.]+?)/$#x', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P[^/]*?)/$#x', $pathinfo, $matches)) { $matches['_route'] = 'baz4'; return $matches; } // baz5 - if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P[^/\.]+?)/$#x', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P[^/]*?)/$#x', $pathinfo, $matches)) { if ($this->context->getMethod() != 'post') { $allow[] = 'post'; goto not_baz5; @@ -73,7 +73,7 @@ public function match($pathinfo) not_baz5: // baz.baz6 - if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P[^/\.]+?)/$#x', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P[^/]*?)/$#x', $pathinfo, $matches)) { if ($this->context->getMethod() != 'put') { $allow[] = 'put'; goto not_bazbaz6; diff --git a/tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher2.php b/tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher2.php index db003bb89dcc..e046a1ad10c8 100644 --- a/tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher2.php +++ b/tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher2.php @@ -30,7 +30,7 @@ public function match($pathinfo) } // bar - if (0 === strpos($pathinfo, '/bar') && preg_match('#^/bar/(?P[^/\.]+?)$#x', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/bar') && preg_match('#^/bar/(?P.*?)$#x', $pathinfo, $matches)) { if (!in_array($this->context->getMethod(), array('get', 'head'))) { $allow = array_merge($allow, array('get', 'head')); goto not_bar; @@ -59,7 +59,7 @@ public function match($pathinfo) } // baz4 - if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P[^/\.]+?)/?$#x', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P[^/]*?)/?$#x', $pathinfo, $matches)) { if (substr($pathinfo, -1) !== '/') { return $this->redirect($pathinfo.'/', 'baz4'); } @@ -68,7 +68,7 @@ public function match($pathinfo) } // baz5 - if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P[^/\.]+?)/?$#x', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P[^/]*?)/?$#x', $pathinfo, $matches)) { if ($this->context->getMethod() != 'post') { $allow[] = 'post'; goto not_baz5; @@ -82,7 +82,7 @@ public function match($pathinfo) not_baz5: // baz.baz6 - if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P[^/\.]+?)/?$#x', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P[^/]*?)/?$#x', $pathinfo, $matches)) { if ($this->context->getMethod() != 'put') { $allow[] = 'put'; goto not_bazbaz6; diff --git a/tests/Symfony/Tests/Component/Routing/RouteCompiler.php b/tests/Symfony/Tests/Component/Routing/RouteCompiler.php deleted file mode 100644 index dc1dce449328..000000000000 --- a/tests/Symfony/Tests/Component/Routing/RouteCompiler.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Tests\Component\Routing; - -use Symfony\Component\Routing\RouteCompiler as BaseRouteCompiler; -use Symfony\Component\Routing\Route; - -class RouteCompiler extends BaseRouteCompiler -{ - protected function tokenizeBufferBefore(&$buffer, &$tokens, &$afterASeparator, &$currentSeparator) - { - if ($afterASeparator && preg_match('#^=([\w\d_]+)#', $buffer, $match)) { - // a labelled variable - $this->tokens[] = array('label', $currentSeparator, $match[0], $match[1]); - - $currentSeparator = ''; - $buffer = substr($buffer, strlen($match[0])); - $afterASeparator = false; - } else { - return false; - } - } - - protected function compileForLabel($separator, $name, $variable) - { - if (null === $requirement = $this->route->getRequirement($variable)) { - $requirement = $this->options['variable_content_regex']; - } - - $this->segments[] = preg_quote($separator, '#').$variable.$separator.'(?P<'.$variable.'>'.$requirement.')'; - $this->variables[$variable] = $name; - - if (!$this->route->getDefault($variable)) { - $this->firstOptional = count($this->segments); - } - } - - protected function generateForLabel($optional, $tparams, $separator, $name, $variable) - { - if (!empty($tparams[$variable]) && (!$optional || !isset($this->defaults[$variable]) || $tparams[$variable] != $this->defaults[$variable])) { - return $variable.'/'.urlencode($tparams[$variable]); - } - } -} diff --git a/tests/Symfony/Tests/Component/Routing/RouteCompilerTest.php b/tests/Symfony/Tests/Component/Routing/RouteCompilerTest.php index ae167f22f138..c708e3da038e 100644 --- a/tests/Symfony/Tests/Component/Routing/RouteCompilerTest.php +++ b/tests/Symfony/Tests/Component/Routing/RouteCompilerTest.php @@ -13,8 +13,6 @@ use Symfony\Component\Routing\Route; -require __DIR__.'/RouteCompiler.php'; - class RouteCompilerTest extends \PHPUnit_Framework_TestCase { /** @@ -27,7 +25,7 @@ public function testCompile($name, $arguments, $prefix, $regex, $variables, $tok $compiled = $route->compile(); $this->assertEquals($prefix, $compiled->getStaticPrefix(), $name.' (static prefix)'); - $this->assertEquals($regex, $compiled->getRegex(), $name.' (regex)'); + $this->assertEquals($regex, str_replace(array("\n", ' '), '', $compiled->getRegex()), $name.' (regex)'); $this->assertEquals($variables, $compiled->getVariables(), $name.' (variables)'); $this->assertEquals($tokens, $compiled->getTokens(), $name.' (tokens)'); } @@ -39,57 +37,50 @@ public function provideCompileData() 'Static route', array('/foo'), '/foo', '#^/foo$#x', array(), array( - array('text', '/', 'foo', null), + array('text', '/foo'), )), array( 'Route with a variable', array('/foo/{bar}'), - '/foo', '#^/foo/(?P[^/\.]+?)$#x', array('bar' => '{bar}'), array( - array('variable', '/', '{bar}', 'bar'), - array('text', '/', 'foo', null), + '/foo', '#^/foo/(?P.*?)$#x', array('bar'), array( + array('variable', '/', '.*?', 'bar'), + array('text', '/foo'), )), array( 'Route with a variable that has a default value', array('/foo/{bar}', array('bar' => 'bar')), - '/foo', '#^/foo(?:/(?P[^/\.]+?))?$#x', array('bar' => '{bar}'), array( - array('variable', '/', '{bar}', 'bar'), - array('text', '/', 'foo', null), + '/foo', '#^/foo(?:/(?P.*?))?$#x', array('bar'), array( + array('variable', '/', '.*?', 'bar'), + array('text', '/foo'), )), array( 'Route with several variables', array('/foo/{bar}/{foobar}'), - '/foo', '#^/foo/(?P[^/\.]+?)/(?P[^/\.]+?)$#x', array('bar' => '{bar}', 'foobar' => '{foobar}'), array( - array('variable', '/', '{foobar}', 'foobar'), - array('variable', '/', '{bar}', 'bar'), - array('text', '/', 'foo', null), + '/foo', '#^/foo/(?P[^/]*?)/(?P.*?)$#x', array('bar', 'foobar'), array( + array('variable', '/', '.*?', 'foobar'), + array('variable', '/', '[^/]*?', 'bar'), + array('text', '/foo'), )), array( 'Route with several variables that have default values', array('/foo/{bar}/{foobar}', array('bar' => 'bar', 'foobar' => '')), - '/foo', '#^/foo(?:/(?P[^/\.]+?) (?:/(?P[^/\.]+?) )?)?$#x', array('bar' => '{bar}', 'foobar' => '{foobar}'), array( - array('variable', '/', '{foobar}', 'foobar'), - array('variable', '/', '{bar}', 'bar'), - array('text', '/', 'foo', null), + '/foo', '#^/foo(?:/(?P[^/]*?)(?:/(?P.*?))?)?$#x', array('bar', 'foobar'), array( + array('variable', '/', '.*?', 'foobar'), + array('variable', '/', '[^/]*?', 'bar'), + array('text', '/foo'), )), array( 'Route with several variables but some of them have no default values', array('/foo/{bar}/{foobar}', array('bar' => 'bar')), - '/foo', '#^/foo/(?P[^/\.]+?)/(?P[^/\.]+?)$#x', array('bar' => '{bar}', 'foobar' => '{foobar}'), array( - array('variable', '/', '{foobar}', 'foobar'), - array('variable', '/', '{bar}', 'bar'), - array('text', '/', 'foo', null), - )), - - array( - 'Route with a custom token', - array('/=foo', array(), array(), array('compiler_class' => 'Symfony\\Tests\\Component\\Routing\\RouteCompiler')), - '', '#^/foo/(?P[^/\.]+?)$#x', array('foo' => '=foo'), array( - array('label', '/', '=foo', 'foo'), + '/foo', '#^/foo/(?P[^/]*?)/(?P.*?)$#x', array('bar', 'foobar'), array( + array('variable', '/', '.*?', 'foobar'), + array('variable', '/', '[^/]*?', 'bar'), + array('text', '/foo'), )), ); } diff --git a/tests/Symfony/Tests/Component/Routing/RouteTest.php b/tests/Symfony/Tests/Component/Routing/RouteTest.php index c06c3254ce4b..b0703de90f62 100644 --- a/tests/Symfony/Tests/Component/Routing/RouteTest.php +++ b/tests/Symfony/Tests/Component/Routing/RouteTest.php @@ -41,8 +41,6 @@ public function testOptions() $route = new Route('/{foo}'); $route->setOptions(array('foo' => 'bar')); $this->assertEquals(array_merge(array( - 'segment_separators' => array('/', '.'), - 'text_regex' => '.+?', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', ), array('foo' => 'bar')), $route->getOptions(), '->setOptions() sets the options'); $this->assertEquals($route, $route->setOptions(array()), '->setOptions() implements a fluent interface');