Skip to content

Commit

Permalink
Working on RouterRoute::match(). Adding tests for RouterRoute::match(…
Browse files Browse the repository at this point in the history
…) and removing defaults from routes that don't need defaults.
  • Loading branch information
markstory committed Nov 29, 2009
1 parent 0834cb4 commit 9e9559b
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 28 deletions.
84 changes: 71 additions & 13 deletions cake/libs/router.php
Expand Up @@ -264,9 +264,6 @@ function getNamedExpressions() {
function connect($route, $default = array(), $params = array()) {
$self =& Router::getInstance();

if (!isset($default['action'])) {
$default['action'] = 'index';
}
foreach ($self->__prefixes as $prefix) {
if (isset($default[$prefix])) {
$default['prefix'] = $prefix;
Expand All @@ -277,6 +274,9 @@ function connect($route, $default = array(), $params = array()) {
$self->__prefixes[] = $default['prefix'];
$self->__prefixes = array_keys(array_flip($self->__prefixes));
}
if (!isset($default['action'])) {
$default['action'] = 'index';
}
$self->routes[] =& new RouterRoute($route, $default, $params);
return $self->routes;
}
Expand Down Expand Up @@ -528,14 +528,16 @@ function __connectDefaultRoutes() {

foreach ($this->__prefixes as $prefix) {
$params = array('prefix' => $prefix, $prefix => true);
$this->connect("/{$prefix}/:plugin/:controller", $params, $match);
$indexParams = $params + array('action' => 'index');
$this->connect("/{$prefix}/:plugin/:controller", $indexParams, $match);
$this->connect("/{$prefix}/:plugin/:controller/:action/*", $params, $match);
}
}

foreach ($this->__prefixes as $prefix) {
$params = array('prefix' => $prefix, $prefix => true);
$this->connect("/{$prefix}/:controller", $params);
$indexParams = $params + array('action' => 'index');
$this->connect("/{$prefix}/:controller", $indexParams);
$this->connect("/{$prefix}/:controller/:action/*", $params);
}
$this->connect('/:controller', array('action' => 'index'));
Expand Down Expand Up @@ -1220,7 +1222,7 @@ function compile() {
return $this->_compiledRoute;
}
$this->_writeRoute($this->template, $this->defaults, $this->params);
$this->defaults += array('plugin' => null, 'controller' => null, 'action' => null);
$this->defaults += array('plugin' => null, 'controller' => null);
return $this->_compiledRoute;
}
/**
Expand Down Expand Up @@ -1265,6 +1267,7 @@ function _writeRoute($route, $default, $params) {
}
if (preg_match('#\/\*$#', $route, $m)) {
$parsed = preg_replace('#/\\\\\*$#', '(?:/(?P<_args_>.*))?', $parsed);
$this->_greedy = true;
}
$parsed = str_replace($search, $replacements, $parsed);
$this->_compiledRoute = '#^' . $parsed . '[/]*$#';
Expand Down Expand Up @@ -1315,6 +1318,7 @@ function parse($url) {
}
$route['pass'] = $route['named'] = array();
$route += $this->defaults;

foreach ($route as $key => $value) {
if (is_integer($key)) {
$route['pass'][] = $value;
Expand Down Expand Up @@ -1353,6 +1357,57 @@ function match($url) {
if (!$this->compiled()) {
$this->compile();
}
/* $url += array('controller' => null, 'plugin' => null);
$defaults = $this->defaults;
if (isset($defaults['prefix'])) {
$prefix = $defaults['prefix'];
unset($defaults['prefix']);
}
$diff = Set::diff($url, $defaults);
$url += array('controller' => null, 'plugin' => null);
$keyNames = array_flip($this->keys);
if (array_keys(array_intersect_key($url, $keyNames)) != $this->keys) {
return false;
}
//if the default keys aren't the same its not a match.
if (array_intersect_key($url, $this->defaults) != $this->defaults) {
return false;
}
//if this route is not greedy, make sure there are no more params
if (!$this->_greedy) {
if (array_diff_key($url, array_merge($this->defaults, $keyNames)) !== array()) {
return false;
}
}
//check that required passed parameters are the same.
$i = 0;
while (isset($this->defaults[$i])) {
if (isset($url[$i]) && $this->defaults[$i] !== $url[$i]) {
return false;
}
$i++;
}
//remove any pass params, they have numeric indexes
$pass = array();
$i = 0;
while (isset($url[$i])) {
$pass[] = $url[$i];
unset($url[$i]);
$i++;
}
return $this->_writeUrl(array_merge($url, compact('pass', 'named', 'prefix')));
//*/

$url += array('controller' => null, 'plugin' => null);
$defaults = $this->defaults;

Expand Down Expand Up @@ -1415,7 +1470,7 @@ function match($url) {
}

if (empty($params)) {
return $this->__mapRoute(array_merge($url, compact('pass', 'named', 'prefix')));
return $this->_writeUrl(array_merge($url, compact('pass', 'named', 'prefix')));
} elseif (!empty($routeParams) && !empty($defaults)) {
if (!empty($required)) {
return false;
Expand All @@ -1431,7 +1486,7 @@ function match($url) {
}
} else {
if (empty($required) && $defaults['plugin'] === $url['plugin'] && $defaults['controller'] === $url['controller'] && $defaults['action'] === $url['action']) {
return $this->__mapRoute(array_merge($url, compact('pass', 'named', 'prefix')));
return $this->_writeUrl(array_merge($url, compact('pass', 'named', 'prefix')));
}
return false;
}
Expand All @@ -1444,14 +1499,17 @@ function match($url) {
}
}
}
return $this->__mapRoute(array_merge($filled, compact('pass', 'named', 'prefix')));
return $this->_writeUrl(array_merge($filled, compact('pass', 'named', 'prefix')));
//*/
}
/**
* Converts Route arrays into strings.
* Converts a matching route array into a url string.
*
* @return void
* @params array $params The params to convert to a string url.
* @return string Compiled route string.
* @access protected
**/
function __mapRoute($params) {
function _writeUrl($params) {
if (isset($params['plugin'], $params['controller']) && $params['plugin'] === $params['controller']) {
unset($params['controller']);
}
Expand All @@ -1468,7 +1526,7 @@ function __mapRoute($params) {
$instance =& Router::getInstance();
$separator = $instance->named['separator'];

if (isset($params['named'])) {
if (!empty($params['named'])) {
if (is_array($params['named'])) {
$named = array();
foreach ($params['named'] as $key => $value) {
Expand Down
91 changes: 76 additions & 15 deletions cake/tests/cases/libs/router.test.php
Expand Up @@ -401,7 +401,7 @@ function testUrlGenerationBasic() {
Router::reload();
Router::parse('/');

Router::connect('/:controller/:id', array('action' => 'view', 'id' => '1'));
Router::connect('/:controller/:id', array('action' => 'view'));
$result = Router::url(array('controller' => 'posts', 'action' => 'view', 'id' => '1'));
$expected = '/posts/1';
$this->assertEqual($result, $expected);
Expand All @@ -410,7 +410,7 @@ function testUrlGenerationBasic() {
$expected = '/posts/index/0';
$this->assertEqual($result, $expected);

Router::connect('/view/*', array('controller' => 'posts', 'action' => 'view'));
Router::connect('/view/*', array('controller' => 'posts', 'action' => 'view'));
Router::promote();
$result = Router::url(array('controller' => 'posts', 'action' => 'view', '1'));
$expected = '/view/1';
Expand Down Expand Up @@ -810,7 +810,7 @@ function testPluginUrlGeneration() {

Router::reload();

Router::connect('/:lang/:plugin/:controller/*', array(), array('action' => 'index'));
Router::connect('/:lang/:plugin/:controller/*', array('action' => 'index'));

Router::setRequestInfo(array(
array(
Expand Down Expand Up @@ -902,7 +902,7 @@ function testUrlParsing() {
$this->assertEqual($result, $expected);

Router::reload();
Router::connect('/:controller/:action/*', array(), array('controller' => 'some_controller'));
Router::connect('/:controller/:action/*');
Router::connect('/', array('plugin' => 'pages', 'controller' => 'pages', 'action' => 'display'));
$result = Router::parse('/');
$expected = array('pass' => array(), 'named' => array(), 'controller' => 'pages', 'action' => 'display', 'plugin' => 'pages');
Expand Down Expand Up @@ -1431,10 +1431,8 @@ function testNamedArgsUrlParsing() {
function testUrlGenerationWithLegacyPrefixes() {
Router::reload();
Router::connect('/protected/:controller/:action/*', array(
'controller' => 'users',
'action' => 'index',
'prefix' => 'protected',
'protected' => true
'prefix' => 'protected',
'protected' => true
));
Router::parse('/');

Expand All @@ -1443,6 +1441,10 @@ function testUrlGenerationWithLegacyPrefixes() {
array('plugin' => null, 'controller' => null, 'action' => null, 'base' => '', 'here' => '/images/index', 'webroot' => '/')
));

$result = Router::url(array('protected' => true));
$expected = '/protected/images/index';
$this->assertEqual($result, $expected);

$result = Router::url(array('controller' => 'images', 'action' => 'add'));
$expected = '/images/add';
$this->assertEqual($result, $expected);
Expand Down Expand Up @@ -1947,7 +1949,7 @@ function testRouterConnectDefaults() {
}
}


// SimpleTest::ignore('RouterTest');
/**
* Test case for RouterRoute
*
Expand Down Expand Up @@ -1981,10 +1983,10 @@ function endTest() {
* @return void
**/
function testConstruction() {
$route =& new RouterRoute('/:controller/:action/:id', array('controller' => 'posts', 'id' => null), array('id' => '[0-9]+'));
$route =& new RouterRoute('/:controller/:action/:id', array(), array('id' => '[0-9]+'));

$this->assertEqual($route->template, '/:controller/:action/:id');
$this->assertEqual($route->defaults, array('controller' => 'posts', 'id' => null));
$this->assertEqual($route->defaults, array());
$this->assertEqual($route->params, array('id' => '[0-9]+'));
$this->assertFalse($route->compiled());
}
Expand Down Expand Up @@ -2036,7 +2038,7 @@ function testRouteCompilingWithParamPatterns() {

$route = new RouterRoute(
'/:controller/:action/:id',
array('controller' => 'testing4', 'id' => null),
array(),
array('id' => $ID)
);
$result = $route->compile();
Expand Down Expand Up @@ -2108,7 +2110,8 @@ function testComplexRouteCompilingAndParsing() {

$route =& new RouterRoute(
'/posts/:month/:day/:year/*',
array('controller' => 'posts', 'action' => 'view'), array('year' => $Year, 'month' => $Month, 'day' => $Day)
array('controller' => 'posts', 'action' => 'view'),
array('year' => $Year, 'month' => $Month, 'day' => $Day)
);
$result = $route->compile();
$this->assertPattern($result, '/posts/08/01/2007/title-of-post');
Expand Down Expand Up @@ -2147,21 +2150,79 @@ function testComplexRouteCompilingAndParsing() {
*
* @return void
**/
function testMatching() {
function testMatchBasic() {
$route = new RouterRoute('/:controller/:action/:id');
$result = $route->match(array('controller' => 'posts', 'action' => 'view'));
$this->assertFalse($result);

$route =& new RouterRoute('/', array('controller' => 'pages', 'action' => 'display', 'home'));
$result = $route->match(array('controller' => 'pages', 'action' => 'display', 'home'));
$this->assertEqual($result, '/');

$result = $route->match(array('controller' => 'pages', 'action' => 'display', 'about'));
$this->assertFalse($result);


$route =& new RouterRoute('/pages/*', array('controller' => 'pages', 'action' => 'display'));
$result = $route->match(array('controller' => 'pages', 'action' => 'display', 'home'));
$this->assertEqual($result, '/pages/home');

$result = $route->match(array('controller' => 'pages', 'action' => 'display', 'about'));
$this->assertEqual($result, '/pages/about');


$route =& new RouterRoute('/blog/:action', array('controller' => 'posts'));
$result = $route->match(array('controller' => 'posts', 'action' => 'view'));
$this->assertEqual($result, '/blog/view');

$result = $route->match(array('controller' => 'posts', 'action' => 'view', 1));
$this->assertFalse($result);

$result = $route->match(array('controller' => 'posts', 'action' => 'view', 'id' => 2));
$this->assertFalse($result);


$route =& new RouterRoute('/:plugin/:id/*', array('controller' => 'posts', 'action' => 'view'));
$result = $route->match(array('plugin' => 'test', 'controller' => 'posts', 'action' => 'view', 'id' => '1'));
$this->assertEqual($result, '/test/1/');

$result = $route->match(array('plugin' => 'fo', 'controller' => 'posts', 'action' => 'view', 'id' => '1', '0'));
$this->assertEqual($result, '/fo/1/0');

$result = $route->match(array('plugin' => 'fo', 'controller' => 'nodes', 'action' => 'view', 'id' => 1));
$this->assertFalse($result);

$result = $route->match(array('plugin' => 'fo', 'controller' => 'posts', 'action' => 'edit', 'id' => 1));
$this->assertFalse($result);


$route =& new RouterRoute('/admin/subscriptions/:action/*', array(
'controller' => 'subscribe', 'admin' => true, 'prefix' => 'admin'
));

$url = array('plugin' => null, 'controller' => 'subscribe', 'admin' => true, 'action' => 'edit', 1);
$result = $route->match($url);
$expected = '/admin/subscriptions/edit/1/';
$expected = '/admin/subscriptions/edit/1';
$this->assertEqual($result, $expected);
}

/**
* test that match with patterns works.
*
* @return void
*/
function testMatchWithPatterns() {
$route =& new RouterRoute('/:controller/:action/:id', array(), array('id' => '[0-9]+'));
$result = $route->match(array('controller' => 'posts', 'action' => 'view', 'id' => 'foo'));
$this->assertFalse($result);

$result = $route->match(array('controller' => 'posts', 'action' => 'view', 'id' => '9'));
$this->assertEqual($result, '/posts/view/9');

$result = $route->match(array('controller' => 'posts', 'action' => 'view', 'id' => '922'));
$this->assertEqual($result, '/posts/view/922');
}

/**
* test persistParams ability to persist parameters from $params and remove params.
*
Expand Down

0 comments on commit 9e9559b

Please sign in to comment.