From 522446e0c2847cb0eef456003a1e9c37a1955196 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 31 Jul 2010 13:03:45 -0400 Subject: [PATCH] Fixing issues where route elements could not have '-' in the parameter name because of limitations in pcre named capturing subpatterns. Tests added. Fixes #974 --- cake/libs/router.php | 27 +++++++++++++++------------ cake/tests/cases/libs/router.test.php | 23 ++++++++++++++++++++++- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/cake/libs/router.php b/cake/libs/router.php index 7db844236..9886f7275 100644 --- a/cake/libs/router.php +++ b/cake/libs/router.php @@ -1352,9 +1352,9 @@ class CakeRoute { $names = $routeParams = array(); $parsed = preg_quote($this->template, '#'); - preg_match_all('#:([A-Za-z0-9_-]+[A-Z0-9a-z])#', $route, $namedElements); + preg_match_all('#:([A-Za-z0-9_-]+[A-Z0-9a-z])#', $this->template, $namedElements); foreach ($namedElements[1] as $i => $name) { - $search = '\\' . $namedElements[0][$i]; + $search = '\\' . str_replace('-', '\\-', $namedElements[0][$i]); if (isset($this->options[$name])) { $option = null; if ($name !== 'plugin' && array_key_exists($name, $this->defaults)) { @@ -1362,12 +1362,12 @@ class CakeRoute { } $slashParam = '/\\' . $namedElements[0][$i]; if (strpos($parsed, $slashParam) !== false) { - $routeParams[$slashParam] = '(?:/(?P<' . $name . '>' . $this->options[$name] . ')' . $option . ')' . $option; + $routeParams[$slashParam] = '(?:/(' . $this->options[$name] . ')' . $option . ')' . $option; } else { - $routeParams[$search] = '(?:(?P<' . $name . '>' . $this->options[$name] . ')' . $option . ')' . $option; + $routeParams[$search] = '(?:(' . $this->options[$name] . ')' . $option . ')' . $option; } } else { - $routeParams[$search] = '(?:(?P<' . $name . '>[^/]+))'; + $routeParams[$search] = '(?:([^/]+))'; } $names[] = $name; } @@ -1394,7 +1394,7 @@ class CakeRoute { if (!$this->compiled()) { $this->compile(); } - if (!preg_match($this->_compiledRoute, $url, $route)) { + if (!preg_match($this->_compiledRoute, $url, $parsed)) { return false; } else { foreach ($this->defaults as $key => $val) { @@ -1418,15 +1418,18 @@ class CakeRoute { } } } - array_shift($route); - $count = count($this->keys); - for ($i = 0; $i <= $count; $i++) { - unset($route[$i]); + array_shift($parsed); + $route = array(); + foreach ($this->keys as $i => $key) { + if (isset($parsed[$i])) { + $route[$key] = $parsed[$i]; + } } $route['pass'] = $route['named'] = array(); $route += $this->defaults; - - //move numerically indexed elements from the defaults into pass. + if (isset($parsed['_args_'])) { + $route['_args_'] = $parsed['_args_']; + } foreach ($route as $key => $value) { if (is_integer($key)) { $route['pass'][] = $value; diff --git a/cake/tests/cases/libs/router.test.php b/cake/tests/cases/libs/router.test.php index 00c57b069..ff995499d 100644 --- a/cake/tests/cases/libs/router.test.php +++ b/cake/tests/cases/libs/router.test.php @@ -2179,6 +2179,27 @@ class CakeRouteTestCase extends CakeTestCase { $this->assertPattern($result, '/test_plugin/posts/edit/5/name:value/nick:name'); } +/** + * test route names with - in them. + * + * @return void + */ + function testHyphenNames() { + $route =& new CakeRoute('/articles/:date-from/:date-to', array( + 'controller' => 'articles', 'action' => 'index' + )); + $expected = array( + 'controller' => 'articles', + 'action' => 'index', + 'date-from' => '2009-07-31', + 'date-to' => '2010-07-31', + 'named' => array(), + 'pass' => array() + ); + $result = $route->parse('/articles/2009-07-31/2010-07-31'); + $this->assertEqual($result, $expected); + } + /** * test that route parameters that overlap don't cause errors. * @@ -2390,7 +2411,6 @@ class CakeRouteTestCase extends CakeTestCase { $result = $route->match(array('plugin' => 'fo', 'controller' => 'posts', 'action' => 'edit', 'id' => 1)); $this->assertFalse($result); - $route =& new CakeRoute('/admin/subscriptions/:action/*', array( 'controller' => 'subscribe', 'admin' => true, 'prefix' => 'admin' )); @@ -2409,6 +2429,7 @@ class CakeRouteTestCase extends CakeTestCase { 'date-from' => '2009-07-31', 'date-to' => '2010-07-31' ); + $result = $route->match($url); $expected = '/articles/2009-07-31/2010-07-31'; $this->assertEqual($result, $expected);