Moving named argument handling into Router

git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@5535 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
nate 2007-08-16 16:31:50 +00:00
parent 49df24a5e3
commit 90567a286a
9 changed files with 194 additions and 111 deletions

View file

@ -273,21 +273,6 @@ class Controller extends Object {
* @var mixed
*/
var $passedArgs = array();
/**
* Set to true to enable named URL parameters (/controller/action/name:value).
* Or set an array of actions and default named args: array('action'=> array('name'=>'defaultValue'));
*
* @var mixed
*/
var $namedArgs = true;
/**
* The character that separates named arguments in URLs.
*
* Example URL: /posts/view/title:first+post/category:general
*
* @var string
*/
var $argSeparator = ':';
/**
* Constructor.
*

View file

@ -109,25 +109,13 @@ class Scaffold extends Object {
* @var string
*/
var $plugin = null;
/**
* Controller URL-generation data
*
* @var mixed
*/
var $namedArgs = null;
/**
* Controller URL-generation data
*
* @var string
*/
var $argSeparator = null;
/**
* List of variables to collect from the associated controller
*
* @var array
* @access protected
*/
var $__passedVars = array('action', 'base', 'webroot', 'layout', 'name', 'viewPath', 'ext', 'params', 'data', 'webservices', 'plugin', 'namedArgs', 'argSeparator', 'cacheAction');
var $__passedVars = array('action', 'base', 'webroot', 'layout', 'name', 'viewPath', 'ext', 'params', 'data', 'webservices', 'plugin', 'cacheAction');
/**
* Title HTML element for current scaffolded view
*

View file

@ -136,6 +136,20 @@ class Router extends Object {
* @access private
*/
var $__params = array();
/**
* List of named arguments allowed in routes
*
* @var array
* @access private
*/
var $__namedArgs = array();
/**
* Separator used to join/split/detect named arguments
*
* @var string
* @access private
*/
var $__argSeparator = ':';
/**
* Maintains the path stack for the current request
*
@ -143,7 +157,6 @@ class Router extends Object {
* @access private
*/
var $__paths = array();
/**
* Maintains the mapped elements for array based urls
*
@ -151,6 +164,13 @@ class Router extends Object {
* @access private
*/
var $__mapped = array();
/**
* Keeps Router state to determine if default routes have already been connected
*
* @var boolean
* @access private
*/
var $__defaultsMapped = false;
/**
* Initialize the Router object
*
@ -206,10 +226,9 @@ class Router extends Object {
*/
function connect($route, $default = array(), $params = array()) {
$_this =& Router::getInstance();
$admin = Configure::read('Routing.admin');
if (defined('CAKE_ADMIN') && $default == null && $route == CAKE_ADMIN) {
$_this->routes[] = $_this->__admin;
$_this->__admin = null;
if ($admin && $default == null && $route == $admin) {
}
$default = am(array('plugin' => null, 'controller' => null, 'action' => null), $default);
@ -225,6 +244,29 @@ class Router extends Object {
}
return $_this->routes;
}
/**
* Connects an array of named arguments (with optional scoping options)
*
* @param array $named List of named arguments
* @param array $options Named argument handling options
* @access public
* @static
*/
function connectNamed($named, $options = array()) {
$_this =& Router::getInstance();
if (isset($options['argSeparator'])) {
$_this->__argSeparator = $options['argSeparator'];
}
foreach ($named as $key => $val) {
if (is_numeric($key)) {
$_this->__namedArgs[$val] = true;
} else {
$_this->__namedArgs[$key] = $val;
}
}
}
/**
* Creates REST resource routes for the given controller(s)
*
@ -278,7 +320,7 @@ class Router extends Object {
if (preg_match('/^:(.+)$/', $element, $r)) {
if (isset($params[$r[1]])) {
if (array_key_exists($r[1], $default)) {
if (array_key_exists($r[1], $default) && $r[1] != 'plugin') {
$q = '?';
}
$parsed[] = '(?:\/(' . $params[$r[1]] . '))' . $q;
@ -440,9 +482,28 @@ class Router extends Object {
*/
function __connectDefaultRoutes() {
$_this =& Router::getInstance();
if ($_this->__defaultsMapped) {
return;
}
if ($admin = Configure::read('Routing.admin')) {
$params = array('prefix' => $admin, $admin => true);
}
$Inflector =& Inflector::getInstance();
$plugins = array_map(array(&$Inflector, 'underscore'), Configure::listObjects('plugin'));
if(!empty($plugins)) {
$match = array('plugin' => implode('|', $plugins));
$_this->connect('/:plugin/:controller/:action/*', array(), $match);
if ($admin) {
$_this->connect("/{$admin}/:plugin/:controller", $params, $match);
$_this->connect("/{$admin}/:plugin/:controller/:action/*", $params, $match);
}
}
if ($admin) {
$_this->connect("/{$admin}/:controller", $params);
$_this->connect("/{$admin}/:controller/:action/*", $params);
}
@ -465,19 +526,11 @@ class Router extends Object {
}
$_this->connect('/:controller/:action/*');
$Inflector =& Inflector::getInstance();
$plugins = array_map(array(&$Inflector, 'underscore'), Configure::listObjects('plugin'));
if(!empty($plugins)) {
$match = array('plugin' => implode('|', $plugins));
$_this->connect('/:plugin/:controller/:action/*', array('action' => 'index'), array('plugin' => implode('|', $plugins)));
$_this->promote();
if ($admin) {
$_this->connect("/{$admin}/:plugin/:controller/:action/*", am($params, array('action' => 'index')), $match);
$_this->promote();
}
if (empty($_this->__namedArgs)) {
$_this->connectNamed(array('page', 'fields', 'order', 'limit', 'recursive', 'sort', 'direction'));
}
$_this->__defaultsMapped = true;
}
/**
* Takes parameter and path information back from the Dispatcher
@ -569,8 +622,9 @@ class Router extends Object {
if (!isset($_this->routes[$which])) {
return false;
}
array_unshift($_this->routes, $_this->routes[$which]);
$route = $_this->routes[$which];
unset($_this->routes[$which]);
array_unshift($_this->routes, $route);
return true;
}
/**
@ -602,7 +656,7 @@ class Router extends Object {
$params = end($_this->__params);
}
}
$path = array('base' => null, 'argSeparator' => ':');
$path = array('base' => null);
if (!empty($_this->__paths)) {
if (isset($this) && !isset($this->params['requested'])) {
@ -627,8 +681,8 @@ class Router extends Object {
$frag = '#' . urlencode($url['#']);
unset($url['#']);
}
if (!isset($url['action'])) {
if (!isset($url['controller']) || $params['controller'] == $url['controller']) {
if (empty($url['action'])) {
if (empty($url['controller']) || $params['controller'] == $url['controller']) {
$url['action'] = $params['action'];
} else {
$url['action'] = 'index';
@ -639,11 +693,13 @@ class Router extends Object {
if (isset($url['ext'])) {
$extension = '.' . $url['ext'];
}
if (defined('CAKE_ADMIN') && !isset($url[CAKE_ADMIN]) && isset($params[CAKE_ADMIN])) {
$url[CAKE_ADMIN] = CAKE_ADMIN;
$url['action'] = str_replace(CAKE_ADMIN.'_', '', $url['action']);
} elseif (defined('CAKE_ADMIN') && isset($url[CAKE_ADMIN]) && $url[CAKE_ADMIN] == false) {
unset($url[CAKE_ADMIN]);
if ($admin = Configure::read('Routing.admin')) {
if (!isset($url[$admin]) && isset($params[$admin])) {
$url[$admin] = true;
$url['action'] = str_replace("{$admin}_", '', $url['action']);
} elseif ($admin && isset($url[$admin]) && $url[$admin] == false) {
unset($url[$admin]);
}
}
$match = false;
@ -659,9 +715,6 @@ class Router extends Object {
$named = $args = array();
$skip = am(array_keys($_this->__mapped), array('bare', 'action', 'controller', 'plugin', 'ext', '?', '#'));
if (defined('CAKE_ADMIN')) {
$skip[] = CAKE_ADMIN;
}
$_this->__mapped = array();
$keys = array_values(array_diff(array_keys($url), $skip));
$count = count($keys);
@ -672,9 +725,9 @@ class Router extends Object {
} elseif (is_numeric($keys[$i]) || $keys[$i] == 'id') {
$args[] = $url[$keys[$i]];
} elseif (!empty($path['namedArgs']) && in_array($keys[$i], array_keys($path['namedArgs'])) && !empty($url[$keys[$i]])) {
$named[] = $keys[$i] . $path['argSeparator'] . $url[$keys[$i]];
$named[] = $keys[$i] . $_this->__argSeparator . $url[$keys[$i]];
} elseif (!empty($url[$keys[$i]]) || is_numeric($url[$keys[$i]])) {
$named[] = $keys[$i] . $path['argSeparator'] . $url[$keys[$i]];
$named[] = $keys[$i] . $_this->__argSeparator . $url[$keys[$i]];
}
}
@ -747,10 +800,10 @@ class Router extends Object {
$_this =& Router::getInstance();
unset($route[3]['prefix']);
$pass = array();
$defaults = $route[3];
$params = Set::diff($url, $defaults);
$routeParams = $route[2];
$pass = array();
foreach ($params as $key => $value) {
if (is_int($key)) {
@ -758,8 +811,9 @@ class Router extends Object {
unset($params[$key]);
}
}
list($named, $params) = $_this->getNamedElements($params);
if (!strpos($route[0], '*') && !empty($pass)) {
if (!strpos($route[0], '*') && (!empty($pass) || !empty($named))) {
return false;
}
if (!empty($params)) {
@ -770,17 +824,17 @@ class Router extends Object {
krsort($url);
if (empty($params)) {
return array(Router::__mapRoute($route, am($url, compact('pass'))), array());
return array(Router::__mapRoute($route, am($url, compact('pass', 'named'))), array());
} elseif (!empty($routeParams) && !empty($route[3])) {
if (!empty($required)) {
return false;
}
foreach ($defaults as $key => $val) {
if ($url[$key] != $val && !in_array($key, $routeParams)) {
foreach ($params as $key => $val) {
if ((!isset($url[$key]) || $url[$key] != $val) || (!isset($defaults[$key]) || $defaults[$key] != $val) && !in_array($key, $routeParams)) {
return false;
}
}
$filled = array_intersect_key($url, array_combine($routeParams, array_keys($routeParams)));
if (array_keys($filled) != $routeParams) {
@ -788,7 +842,7 @@ class Router extends Object {
}
} else {
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 array(Router::__mapRoute($route, am($url, compact('pass', 'named'))), $url);
}
return false;
}
@ -800,7 +854,7 @@ class Router extends Object {
}
}
}
return array(Router::__mapRoute($route, am($url, compact('pass'))), $url);
return array(Router::__mapRoute($route, am($url, compact('pass', 'named'))), $url);
}
/**
* Merges URL parameters into a route string
@ -826,6 +880,20 @@ class Router extends Object {
}
}
if (isset($params['named'])) {
if (is_array($params['named'])) {
$count = count($params['named']);
$keys = array_keys($params['named']);
$named = array();
for ($i = 0; $i < $count; $i++) {
$named[] = $keys[$i] . $_this->__argSeparator . $params['named'][$keys[$i]];
}
$params['named'] = join('/', $named);
}
$params['pass'] = str_replace('//', '/', $params['pass'] . '/' . $params['named']);
}
if (strpos($route[0], '*')) {
$out = str_replace('*', $params['pass'], $route[0]);
} else {
@ -841,8 +909,53 @@ class Router extends Object {
$out = str_replace(':' . $key, $string, $out);
$_this->__mapped[$key] = $string;
}
if (substr($out, -1) == '/') {
$out = substr($out, 0, strlen($out) - 1);
}
return $out;
}
/**
* Takes an array of URL parameters and separates the ones that can be used as named arguments
*
* @param array $params Associative array of URL parameters.
* @param string $controller Name of controller being routed. Used in scoping.
* @param string $action Name of action being routed. Used in scoping.
* @return array
* @access public
* @static
*/
function getNamedElements($params, $controller = null, $action = null) {
$_this =& Router::getInstance();
$named = array();
foreach ($params as $key => $val) {
if (isset($_this->__namedArgs[$key])) {
$match = true;
if (is_array($_this->__namedArgs[$key])) {
$opts = $_this->__namedArgs[$key];
if (isset($opts['controller']) && !in_array($controller, (array)$opts['controller'])) {
$match = false;
}
if (isset($opts['action']) && !in_array($action, (array)$opts['action'])) {
$match = false;
}
if (isset($opts['match']) && !preg_match('/' . $opts['match'] . '/', $val)) {
$match = false;
}
} elseif (!$_this->__namedArgs[$key]) {
$match = false;
}
if ($match) {
$named[$key] = $val;
unset($params[$key]);
}
}
}
return array($named, $params);
}
/**
* Generates a well-formed querystring from $q
*
@ -976,8 +1089,12 @@ class Router extends Object {
* @param string $separator
* @static
*/
function getArgs($params, $named = true, $separator = ':') {
function getArgs($params, $named = true) {
$_this =& Router::getInstance();
$passedArgs = $namedArgs = array();
$separator = $_this->__argSeparator;
$namedArgs = true;
if (is_array($named)) {
if (array_key_exists($params['action'], $named)) {
$named = $named[$params['action']];

View file

@ -46,8 +46,6 @@ class JsHelper extends Overloadable2 {
var $data = null;
var $themeWeb = null;
var $plugin = null;
var $namedArgs = null;
var $argSeparator = null;
var $helpers = array();

View file

@ -251,25 +251,13 @@ class View extends Object {
* @var mixed
*/
var $passedArgs = array();
/**
* Controller URL-generation data
*
* @var mixed
*/
var $namedArgs = array();
/**
* Controller URL-generation data
*
* @var string
*/
var $argSeparator = null;
/**
* List of variables to collect from the associated controller
*
* @var array
* @access protected
*/
var $__passedVars = array('viewVars', 'action', 'autoLayout', 'autoRender', 'ext', 'base', 'webroot', 'helpers', 'here', 'layout', 'modelNames', 'name', 'pageTitle', 'layoutPath', 'viewPath', 'params', 'data', 'webservices', 'plugin', 'passedArgs', 'namedArgs', 'argSeparator', 'cacheAction');
var $__passedVars = array('viewVars', 'action', 'autoLayout', 'autoRender', 'ext', 'base', 'webroot', 'helpers', 'here', 'layout', 'modelNames', 'name', 'pageTitle', 'layoutPath', 'viewPath', 'params', 'data', 'webservices', 'plugin', 'passedArgs', 'cacheAction');
/**
* List of generated DOM UUIDs
*
@ -457,8 +445,9 @@ class View extends Object {
function renderLayout($content_for_layout) {
$layout_fn = $this->_getLayoutFileName();
if (Configure::read() > 2 && $this->controller != null) {
$debug = View::_render(LIBS . 'view' . DS . 'templates' . DS . 'elements' . DS . 'dump.ctp', array('controller' => $this->controller), false);
if (Configure::read() > 2 && isset($this->viewVars['cakeDebug'])) {
$debug = View::_render(LIBS . 'view' . DS . 'templates' . DS . 'elements' . DS . 'dump.ctp', array('controller' => $this->viewVars['cakeDebug']), false);
unset($this->viewVars['cakeDebug']);
} else {
$debug = '';
}

View file

@ -427,13 +427,13 @@ class DispatcherTest extends UnitTestCase {
$url = 'pages/home/param:value/param2:value2';
restore_error_handler();
@$controller = $dispatcher->dispatch($url, array('return'=> 1));
@$controller = $dispatcher->dispatch($url, array('return' => 1));
set_error_handler('simpleTestErrorHandler');
$expected = 'Pages';
$this->assertEqual($expected, $controller->name);
$expected = array('param'=>'value', 'param2' => 'value2');
$expected = array('param' => 'value', 'param2' => 'value2');
$this->assertIdentical($expected, $controller->namedArgs);
}
@ -478,7 +478,7 @@ class DispatcherTest extends UnitTestCase {
$url = 'my_plugin/some_pages/home/param:value/param2:value2';
restore_error_handler();
@$controller = $dispatcher->dispatch($url, array('return'=> 1));
@$controller = $dispatcher->dispatch($url, array('return' => 1));
set_error_handler('simpleTestErrorHandler');
@ -550,21 +550,23 @@ class DispatcherTest extends UnitTestCase {
Router::reload();
$dispatcher =& new TestDispatcher();
$dispatcher->base = false;
$url = 'my_plugin/add/param:value/param2:value2';
restore_error_handler();
@$controller = $dispatcher->dispatch($url, array('return'=> 1));
@$controller = $dispatcher->dispatch($url, array('return' => 1));
set_error_handler('simpleTestErrorHandler');
$expected = 'my_plugin';
$this->assertIdentical($expected, $controller->plugin);
$this->assertIdentical($controller->plugin, $expected);
$expected = 'MyPlugin';
$this->assertIdentical($expected, $controller->name);
$this->assertIdentical($controller->name, $expected);
$expected = 'add';
$this->assertIdentical($expected, $controller->action);
$this->assertIdentical($controller->action, $expected);
$expected = array('param:value', 'param2:value2');
$this->assertEqual($controller->params['pass'], $expected);
}
function testAutomaticPluginControllerMissingActionDispatch() {

View file

@ -2497,7 +2497,6 @@ function testRecursiveFindAllWithLimit() {
$this->assertEqual($this->model->invalidFields(), array('published' => 'This field cannot be left blank'));
$this->model->create();
$this->model->testing = true;
$this->model->set(array('title' => 'Hello', 'published' => 1, 'body' => ''));
$this->assertEqual($this->model->invalidFields(), array('body' => 'This field cannot be left blank'));
}*/

View file

@ -106,23 +106,23 @@ class RouterTest extends UnitTestCase {
$_SERVER['REQUEST_METHOD'] = 'GET';
$result = $this->router->parse('/posts');
$this->assertEqual($result, array ('pass' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'index', '[method]' => 'GET'));
$this->assertEqual($result, array('pass' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'index', '[method]' => 'GET'));
$_SERVER['REQUEST_METHOD'] = 'GET';
$result = $this->router->parse('/posts/13');
$this->assertEqual($result, array ('pass' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'view', 'id' => '13', '[method]' => 'GET'));
$this->assertEqual($result, array('pass' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'view', 'id' => '13', '[method]' => 'GET'));
$_SERVER['REQUEST_METHOD'] = 'POST';
$result = $this->router->parse('/posts');
$this->assertEqual($result, array ('pass' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'add', '[method]' => 'POST'));
$this->assertEqual($result, array('pass' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'add', '[method]' => 'POST'));
$_SERVER['REQUEST_METHOD'] = 'PUT';
$result = $this->router->parse('/posts/13');
$this->assertEqual($result, array ('pass' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'edit', 'id' => '13', '[method]' => 'PUT'));
$this->assertEqual($result, array('pass' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'edit', 'id' => '13', '[method]' => 'PUT'));
$_SERVER['REQUEST_METHOD'] = 'DELETE';
$result = $this->router->parse('/posts/13');
$this->assertEqual($result, array ('pass' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'delete', 'id' => '13', '[method]' => 'DELETE'));
$this->assertEqual($result, array('pass' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'delete', 'id' => '13', '[method]' => 'DELETE'));
}
function testUrlGeneration() {
@ -183,19 +183,21 @@ class RouterTest extends UnitTestCase {
$expected = '/view/1';
$this->assertEqual($result, $expected);
Configure::write('Routing.admin', 'admin');
$this->router->reload();
$this->router->connect('/admin/subscriptions/:action/*', array('controller' => 'subscribe', 'admin' => 'admin'));
$this->router->connect('/admin/subscriptions/:action/*', array('controller' => 'subscribe', 'admin' => true));
Router::setRequestInfo(array(
array(
'pass' => array(), 'action' => 'admin_index', 'plugin' => null, 'controller' => 'subscribe',
'admin' => 'admin', 'url' => array('url' => 'admin/subscriptions/index/page:2'), 'bare' => 0, 'webservices' => ''
'admin' => true, 'url' => array('url' => 'admin/subscriptions/index/page:2'), 'bare' => 0, 'webservices' => ''
),
array(
'base' => '/magazine', 'here' => '/magazine/admin/subscriptions/index/page:2',
'webroot' => '/magazine/', 'passedArgs' => array('page' => 2), 'argSeparator' => ':', 'namedArgs' => array('page' => 2),
'webroot' => '/magazine/', 'passedArgs' => array('page' => 2), 'namedArgs' => array('page' => 2),
'webservices' => null
)
));
$this->router->parse('/');
$result = $this->router->url(array('page' => 3));
$expected = '/magazine/admin/subscriptions/index/page:3';
@ -209,11 +211,12 @@ class RouterTest extends UnitTestCase {
),
array(
'base' => '/', 'here' => '/',
'webroot' => '/', 'passedArgs' => array('page' => 2), 'argSeparator' => ':', 'namedArgs' => array('page' => 2),
'webroot' => '/', 'passedArgs' => array('page' => 2), 'namedArgs' => array('page' => 2),
'webservices' => null
)
));
$this->router->connect('short_controller_name/:action/*', array('controller' => 'real_controller_name'));
$this->router->parse('/');
$result = $this->router->url(array('controller' => 'real_controller_name', 'page' => '1'));
$expected = '/short_controller_name/index/page:1';
@ -358,7 +361,7 @@ class RouterTest extends UnitTestCase {
$expected = array('year' => '2007', 'month' => '08', 'day' => '01', 'controller' => 'posts', 'action' => 'view', 'plugin' =>'', 'pass' => array('0' => 'title-of-post-here'));
$this->assertEqual($result, $expected);
$this->router->routes = array();
$this->router->reload();
$result = $this->router->parse('/pages/display/home');
$expected = array('plugin' => null, 'pass' => array('home'), 'controller' => 'pages', 'action' => 'display');
$this->assertEqual($result, $expected);
@ -380,10 +383,14 @@ class RouterTest extends UnitTestCase {
$this->router->reload();
$this->router->parse('/');
$this->router->testing = true;
$out = $this->router->url(array('admin' => true, 'controller' => 'posts', 'action' => 'index', '0', '?' => 'var=test&var2=test2'));
$result = $this->router->url(array('admin' => true, 'controller' => 'posts', 'action' => 'index', '0', '?' => 'var=test&var2=test2'));
$expected = '/admin/posts/index/0?var=test&var2=test2';
$this->assertEqual($out, $expected);
$this->assertEqual($result, $expected);
$this->router->reload();
$result = $this->router->parse('admin/users/view/');
$expected = array('pass' => array(), 'controller' => 'users', 'action' => 'view', 'plugin' => null, 'prefix' => 'admin', 'admin' => true);
$this->assertEqual($result, $expected);
}
function testExtensionParsingSetting() {
@ -490,7 +497,6 @@ class RouterTest extends UnitTestCase {
function testParsingWithPrefixes() {
$this->router->reload();
$this->router->testing = true;
$adminParams = array('prefix' => 'admin', 'admin' => true);
$this->router->connect('/admin/:controller', $adminParams);
$this->router->connect('/admin/:controller/:action', $adminParams);
@ -515,7 +521,6 @@ class RouterTest extends UnitTestCase {
$result = $this->router->prefixes();
$expected = array('admin');
$this->assertEqual($result, $expected);
unset($this->router->testing);
}
}

View file

@ -84,8 +84,8 @@ class PaginatorTest extends UnitTestCase {
function testSortLinks() {
Router::reload();
Router::setRequestInfo(array(
array ('plugin' => null, 'controller' => 'accounts', 'action' => 'index', 'pass' => array(), 'form' => array(), 'url' => array('url' => 'accounts/', 'mod_rewrite' => 'true'), 'bare' => 0, 'webservices' => null),
array ('plugin' => null, 'controller' => null, 'action' => null, 'base' => '/officespace', 'here' => '/officespace/accounts/', 'webroot' => '/officespace/', 'passedArgs' => array(), 'argSeparator' => ':', 'namedArgs' => array(), 'webservices' => null)
array ('plugin' => null, 'controller' => 'accounts', 'action' => 'index', 'pass' => array(), 'form' => array(), 'url' => array('url' => 'accounts/', 'mod_rewrite' => 'true'), 'bare' => 0),
array ('plugin' => null, 'controller' => null, 'action' => null, 'base' => '/officespace', 'here' => '/officespace/accounts/', 'webroot' => '/officespace/', 'passedArgs' => array())
));
$this->Paginator->options(array('url' => array('param')));
$result = $this->Paginator->sort('title');