Fixing and refactoring reverse routing, and adding URL generation fixes (Ticket #3034)

git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@5523 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
nate 2007-08-15 14:18:39 +00:00
parent c3dc8cb827
commit ad75ecea81
3 changed files with 85 additions and 51 deletions

View file

@ -204,7 +204,7 @@ class Router extends Object {
$_this->routes[] = $_this->__admin;
$_this->__admin = null;
}
$default = am(array('plugin' => null, 'controller' => null), $default);
$default = am(array('plugin' => null, 'controller' => null, 'action' => null), $default);
if (!empty($default) && empty($default['action'])) {
$default['action'] = 'index';
@ -262,10 +262,6 @@ class Router extends Object {
$names = array();
$elements = Set::filter(array_map('trim', explode('/', $route)));
if (!count($elements)) {
return false;
}
foreach ($elements as $element) {
$q = null;
@ -422,11 +418,6 @@ class Router extends Object {
*/
function __connectDefaultRoutes() {
$_this =& Router::getInstance();
$default_route = array(
'/:controller/:action/*',
'/^(?:\/(?:([a-zA-Z0-9_\\-\\.\\;\\:]+)(?:\\/([a-zA-Z0-9_\\-\\.\\;\\:]+)(?:[\\/\\?](.*))?)?))[\\/]*$/',
array('controller', 'action'), array()
);
if (defined('CAKE_ADMIN') && $_this->__admin != null) {
$_this->routes[] = $_this->__admin;
@ -444,20 +435,15 @@ class Router extends Object {
$_this->connect('/xml/:controller/:action/*', array('webservices' => 'Xml'));
$_this->connect('/xmlrpc/:controller/:action/*', array('webservices' => 'XmlRpc'));
}
$_this->routes[] = $default_route;
//$_this->connect('/:controller/:action/*');
//pr($this->routes[count($_this->routes) - 1]);
//pr($default_route);
//die();
$_this->connect('/:controller/:action/*');
$Inflector =& Inflector::getInstance();
$plugins = array_map(array(&$Inflector, 'underscore'), Configure::listObjects('plugin'));
if(!empty($plugins)) {
array_unshift($_this->routes, array(
"/:plugin/:controller/:action/*",
'/^(?:\/(?:(' . implode('|', $plugins) . ')(?:\\/([a-zA-Z0-9_\\-\\.\\;\\:]+)(?:\\/([a-zA-Z0-9_\\-\\.\\;\\:]+)(?:[\\/\\?](.*))?)?)?))[\/]*$/',
array('plugin', 'controller', 'action'), array()
));
$_this->connect('/:plugin/:controller/:action/*', array('action' => 'index'), array('plugin' => implode('|', $plugins)));
array_unshift($_this->routes, $_this->routes[count($_this->routes) - 1]);
unset($_this->routes[count($_this->routes) - 1]);
}
}
/**
@ -564,13 +550,11 @@ class Router extends Object {
$params = end($_this->__params);
}
}
$path = array('base' => null);
$path = array('base' => null, 'argSeparator' => ':');
if (!empty($_this->__paths)) {
if (isset($this) && !isset($this->params['requested'])) {
$path = $_this->__paths[0];
} elseif (isset($this) && isset($this->params['requested'])) {
$path = end($_this->__paths);
} else {
$path = end($_this->__paths);
}
@ -709,14 +693,14 @@ class Router extends Object {
*/
function mapRouteElements($route, $url) {
$_this =& Router::getInstance();
$defaults = am(array('plugin' => null, 'controller' => null, 'action' => 'index'), $route[3]);
$defaults = $route[3];
$params = Set::diff($url, $defaults);
$routeParams = $route[2];
$pass = array();
foreach ($params as $key => $value) {
if (is_numeric($key)) {
$pass[$key] = $value;
if (is_int($key)) {
$pass[] = $value;
unset($params[$key]);
}
}
@ -727,6 +711,9 @@ class Router extends Object {
if (defined('CAKE_ADMIN') && isset($params[CAKE_ADMIN])) {
return false;
}
if (!empty($params)) {
$required = array_diff(array_keys($defaults), array_keys($url));
}
krsort($defaults);
krsort($url);
@ -734,31 +721,36 @@ class Router extends Object {
if (empty($params)) {
return array(Router::__mapRoute($route, am($url, compact('pass'))), array());
} elseif (!empty($routeParams) && !empty($route[3])) {
$required = array_diff(array_keys($defaults), array_keys($url));
if (!empty($required)) {
return false;
}
$filled = array_intersect_key($url, array_combine($routeParams, array_keys($routeParams)));
$keysFilled = array_keys($filled);
sort($routeParams);
sort($keysFilled);
if ($keysFilled != $routeParams) {
return false;
if (isset($_this->testing)) {
pr($defaults);
pr($url);
pr($params);
pr($required);
}
if (Set::diff($keysFilled, $routeParams) != array()) {
foreach ($defaults as $key => $val) {
if ($url[$key] != $val && !in_array($key, $routeParams)) {
return false;
}
}
$filled = array_intersect_key($url, array_combine($routeParams, array_keys($routeParams)));
if (array_keys($filled) != $routeParams) {
return false;
}
} else {
$required = array_diff(array_keys($defaults), array_keys($url));
if (empty($required) && $defaults['plugin'] == $url['plugin'] && $defaults['controller'] == $url['controller'] && $defaults['action'] == $url['action']) {
return array(Router::__mapRoute($route, am($url, compact('pass'))), $url);
}
return false;
}
if (isset($route[3]['controller']) && !empty($route[3]['controller']) && $url['controller'] != $route[3]['controller']) {
if (!empty($route[3]['controller']) && $url['controller'] != $route[3]['controller']) {
return false;
}
@ -769,6 +761,7 @@ class Router extends Object {
}
}
}
return array(Router::__mapRoute($route, am($url, compact('pass'))), $url);
}
/**

View file

@ -39,6 +39,11 @@ if (!defined('CAKE_ADMIN')) {
*/
class RouterTest extends UnitTestCase {
function RouterTest() {
parent::UnitTestCase();
$this->startTime = getMicrotime();
}
function setUp() {
$this->router =& Router::getInstance();
//$this->router->reload();
@ -57,7 +62,7 @@ class RouterTest extends UnitTestCase {
$this->assertEqual($this->router->routes[0][1], '/^[\/]*$/');
$this->assertEqual($this->router->routes[0][2], array());
$this->router->routes = array();
$this->router->reload();
$this->router->connect('/', array('controller' => 'testing'));
$this->assertTrue(is_array($this->router->routes[0][3]) && !empty($this->router->routes[0][3]));
$this->assertEqual($this->router->routes[0][3]['controller'], 'testing');
@ -126,10 +131,11 @@ class RouterTest extends UnitTestCase {
}
function testUrlGeneration() {
$this->router->reload();
extract($this->router->getNamedExpressions());
$this->router->connect('/', array('controller'=>'pages', 'action'=>'display', 'home'));
$out = $this->router->url(array('controller'=>'pages', 'action'=>'display', 'home'));
$this->router->connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
$out = $this->router->url(array('controller' => 'pages', 'action' => 'display', 'home'));
$this->assertEqual($out, '/');
$this->router->connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
@ -219,7 +225,6 @@ class RouterTest extends UnitTestCase {
$this->assertEqual($result, $expected);
$this->router->reload();
$this->router->testing = true;
$this->router->connect(
':language/galleries',
@ -228,9 +233,9 @@ class RouterTest extends UnitTestCase {
);
$this->router->connect(
'/:language/:'. CAKE_ADMIN .'/:controller/:action/*',
array(CAKE_ADMIN => CAKE_ADMIN),
array('language' => '[a-z]{3}', CAKE_ADMIN => CAKE_ADMIN)
'/:language/:admin/:controller/:action/*',
array('admin' => 'admin'),
array('language' => '[a-z]{3}', 'admin' => 'admin')
);
$this->router->connect('/:language/:controller/:action/*',
@ -238,14 +243,38 @@ class RouterTest extends UnitTestCase {
array('language' => '[a-z]{3}')
);
$result = $this->router->url(array(CAKE_ADMIN => false, 'language' => 'dan', 'action' => 'index', 'controller' => 'galleries'));
$expected = '/dan/galleries'; // Passes
$result = $this->router->url(array('admin' => false, 'language' => 'dan', 'action' => 'index', 'controller' => 'galleries'));
$expected = '/dan/galleries';
$this->assertEqual($result, $expected);
$result = $this->router->url(array(CAKE_ADMIN => false, 'language' => 'eng', 'action' => 'index', 'controller' => 'galleries'));
$expected = '/eng/galleries'; // Fails, actual result: /eng/galleries/index/
$result = $this->router->url(array('admin' => false, 'language' => 'eng', 'action' => 'index', 'controller' => 'galleries'));
$expected = '/eng/galleries';
$this->assertEqual($result, $expected);
$this->router->reload();
$this->router->connect('/:language/pages',
array(
'controller' => 'pages',
'action' => 'index'
),
array('language' => '[a-z]{3}')
);
$this->router->connect('/:language/:controller/:action/*',
array(),
array('language' => '[a-z]{3}')
);
$result = $this->router->url(array('language' => 'eng', 'action' => 'index', 'controller' => 'pages'));
$expected = '/eng/pages'; // Passes as expected
$this->assertEqual($result, $expected);
$result = $this->router->url(array('language' => 'eng', 'controller' => 'pages'));
$this->assertEqual($result, $expected);
$result = $this->router->url(array('language' => 'eng', 'controller' => 'pages', 'action' => 'add'));
$expected = '/eng/pages/add/';
$this->assertEqual($result, $expected);
unset($this->router->testing);
}
function testUrlGenerationWithExtensions() {
@ -318,7 +347,7 @@ class RouterTest extends UnitTestCase {
$this->router->routes = array();
$result = $this->router->parse('/pages/display/home');
$expected = array('pass' => array ('home'), 'controller' => 'pages', 'action' => 'display');
$expected = array('plugin' => null, 'pass' => array('home'), 'controller' => 'pages', 'action' => 'display');
$this->assertEqual($result, $expected);
$result = $this->router->parse('pages/display/home/');
@ -352,7 +381,7 @@ class RouterTest extends UnitTestCase {
$this->assertEqual($result, $expected);
$result = $this->router->parse('/posts/view/1.rss');
$expected = array('controller' => 'posts', 'action' => 'view', 'pass' => array('1'), 'url' => array('ext' => 'rss'));
$expected = array('plugin' => null, 'controller' => 'posts', 'action' => 'view', 'pass' => array('1'), 'url' => array('ext' => 'rss'));
$this->assertEqual($result, $expected);
$result = $this->router->parse('/posts/view/1.rss?query=test');
@ -435,6 +464,10 @@ class RouterTest extends UnitTestCase {
$expected = array('pass'=>array('contact'), 'plugin'=> null, 'controller'=>'pages', 'action'=>'display');
$this->assertEqual($result, $expected);
}
function testEnd() {
pr(round(getMicrotime() - $this->startTime, 5));
}
}
?>

View file

@ -768,6 +768,14 @@ class FormHelperTest extends CakeTestCase {
$result = $this->Form->create('Contact', array('id' => 'TestId'));
$this->assertPattern('/id="TestId"/', $result);
$result = $this->Form->create('User', array('url' => array('action' => 'login')));
$this->assertPattern('/id="UserAddForm"/', $result);
$this->assertPattern('/action="\/users\/login[\/]"/', $result);
$result = $this->Form->create('User', array('action' => 'login'));
$this->assertPattern('/id="UserLoginForm"/', $result);
$this->assertPattern('/action="\/users\/login[\/]"/', $result);
}
function testFormMagicInput() {