Fixing reverse route matching in Router::url() and updating Router tests

git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@4556 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
nate 2007-02-26 02:11:30 +00:00
parent 563f960ae0
commit 9b904515f3
2 changed files with 330 additions and 162 deletions

View file

@ -31,7 +31,7 @@
*
*/
if (!class_exists('Object')) {
uses ('object');
uses('object');
}
/**
@ -40,9 +40,8 @@ if (!class_exists('Object')) {
* @package cake
* @subpackage cake.cake.libs
*/
uses('overloadable');
class Router extends Object {
class Router extends Overloadable {
/**
* Array of routes
*
@ -85,25 +84,22 @@ class Router extends Overloadable {
* @var array
*/
var $__currentRoute = array();
/**
* Maintains the parameter stack for the current request
*
* @var array
*/
var $__params = array();
/**
* Maintains the path stack for the current request
*
* @var array
*/
var $__paths = array();
/**
* Initialize the Router object
*
*/
* Initialize the Router object
*
*/
function __construct() {
if (defined('CAKE_ADMIN')) {
$admin = CAKE_ADMIN;
@ -139,7 +135,7 @@ class Router extends Overloadable {
return $_this->__named;
}
/**
* TODO: Better description. Returns this object's routes array. Returns false if there are no routes available.
* Returns this object's routes array. Returns false if there are no routes available.
*
* @param string $route An empty string, or a route string "/"
* @param array $default NULL or an array describing the default route
@ -148,9 +144,8 @@ class Router extends Overloadable {
* @return array Array of routes
*/
function connect($route, $default = array(), $params = array()) {
$_this =& Router::getInstance();
$parsed = $names = array();
$parsed = array();
if (defined('CAKE_ADMIN') && $default == null) {
if ($route == CAKE_ADMIN) {
@ -162,27 +157,33 @@ class Router extends Overloadable {
if (empty($default['plugin'])) {
$default['plugin'] = null;
}
if (empty($default['controller'])) {
$default['controller'] = null;
}
if (!empty($default) && empty($default['action'])) {
$default['action'] = 'index';
}
$r = null;
if (($route == '') || ($route == '/')) {
$regexp = '/^[\/]*$/';
$_this->routes[] = array($route, $regexp, array(), $default, array());
if ($route = $_this->writeRoute($route, $default, $params)) {
$_this->routes[] = $route;
}
return $_this->routes;
}
/**
* Builds a route regular expression
*
* @access public
* @param string $route An empty string, or a route string "/"
* @param array $default NULL or an array describing the default route
* @param array $params An array matching the named elements in the route to regular expressions which that element should match.
* @return string
* @see routes
*/
function writeRoute($route, $default, $params) {
if (empty($route) || ($route == '/')) {
return array($route, '/^[\/]*$/', array(), $default, array());
} else {
$elements = array();
foreach(explode('/', $route) as $element) {
if (trim($element)) {
$elements[] = $element;
}
}
$names = array();
$elements = $this->__filter(array_map('trim', explode('/', $route)));
if (!count($elements)) {
return false;
@ -207,12 +208,8 @@ class Router extends Overloadable {
$parsed[] = '/' . $element;
}
}
$regexp = '#^' . join('', $parsed) . '[\/]*$#';
$_this->routes[] = array($route, $regexp, $names, $default, $params);
return array($route, '#^' . join('', $parsed) . '[\/]*$#', $names, $default, $params);
}
return $_this->routes;
}
/**
* Parses given URL and returns an array of controllers, action and parameters
@ -223,57 +220,17 @@ class Router extends Overloadable {
*/
function parse($url) {
$_this =& Router::getInstance();
if ($url && ('/' != $url[0])) {
if (!defined('SERVER_IIS')) {
$url = '/' . $url;
}
}
$_this->__connectDefaultRoutes();
$out = array();
$r = null;
$default_route = array(
'/:controller/:action/*',
'/^(?:\/(?:([a-zA-Z0-9_\\-\\.\\;\\:]+)(?:\\/([a-zA-Z0-9_\\-\\.\\;\\:]+)(?:[\\/\\?](.*))?)?))[\\/]*$/',
array('controller', 'action'), array()
);
$r = $ext = null;
if (defined('CAKE_ADMIN') && $_this->__admin != null) {
$_this->routes[] = $_this->__admin;
$_this->__admin = null;
if ($url && strpos($url, '/') !== 0 && !defined('SERVER_IIS')) {
$url = '/' . $url;
}
$_this->connect('/bare/:controller/:action/*', array('bare' => '1'));
$_this->connect('/ajax/:controller/:action/*', array('bare' => '1'));
if (defined('WEBSERVICES') && WEBSERVICES == 'on') {
$_this->connect('/rest/:controller/:action/*', array('webservices' => 'Rest'));
$_this->connect('/rss/:controller/:action/*', array('webservices' => 'Rss'));
$_this->connect('/soap/:controller/:action/*', array('webservices' => 'Soap'));
$_this->connect('/xml/:controller/:action/*', array('webservices' => 'Xml'));
$_this->connect('/xmlrpc/:controller/:action/*', array('webservices' => 'XmlRpc'));
}
$_this->routes[] = $default_route;
$ext = array();
if (strpos($url, '?') !== false) {
$url = substr($url, 0, strpos($url, '?'));
}
if ($_this->__parseExtensions) {
if(preg_match('/\.[0-9a-zA-Z]*$/', $url, $match) == 1) {
$match = substr($match[0], 1);
if(empty($_this->__validExtensions)) {
$url = substr($url, 0, strpos($url, '.' . $match));
$ext = $match;
} else {
foreach($_this->__validExtensions AS $name) {
if(strcasecmp($name, $match) === 0) {
$url = substr($url, 0, strpos($url, '.' . $name));
$ext = $match;
}
}
}
}
}
extract($_this->__parseExtension($url));
foreach($_this->routes as $route) {
list($route, $regexp, $names, $defaults) = $route;
@ -298,11 +255,11 @@ class Router extends Overloadable {
}
}
foreach($r as $key => $found) {
foreach($_this->__filter($r, true) as $key => $found) {
// if $found is a named url element (i.e. ':action')
if (isset($names[$key]) && !empty($found)) {
if (isset($names[$key])) {
$out[$names[$key]] = $found;
} else if (isset($names[$key]) && empty($names[$key]) && empty($out[$names[$key]])){
} else if (isset($names[$key]) && empty($names[$key]) && empty($out[$names[$key]])) {
break; //leave the default values;
} else {
// unnamed elements go in as 'pass'
@ -317,6 +274,65 @@ class Router extends Overloadable {
}
return $out;
}
/**
* Parses a file extension out of a URL, if Router::parseExtensions() is enabled.
*
* @param string $url
* @return array Returns an array containing the altered URL and the parsed extension.
*/
function __parseExtension($url) {
$ext = null;
$_this =& Router::getInstance();
if ($_this->__parseExtensions) {
if(preg_match('/\.[0-9a-zA-Z]*$/', $url, $match) == 1) {
$match = substr($match[0], 1);
if(empty($_this->__validExtensions)) {
$url = substr($url, 0, strpos($url, '.' . $match));
$ext = $match;
} else {
foreach($_this->__validExtensions as $name) {
if(strcasecmp($name, $match) === 0) {
$url = substr($url, 0, strpos($url, '.' . $name));
$ext = $match;
}
}
}
}
}
return compact('ext', 'url');
}
/**
* Connects the default, built-in routes, including admin routes, and (deprecated) web services
* routes.
*
* @return void
*/
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;
$_this->__admin = null;
}
$_this->connect('/bare/:controller/:action/*', array('bare' => '1'));
$_this->connect('/ajax/:controller/:action/*', array('bare' => '1'));
if (defined('WEBSERVICES') && WEBSERVICES == 'on') {
trigger_error('Deprecated: webservices routes are deprecated and will not be supported in future versions. Use Router::parseExtensions() instead.', E_USER_WARNING);
$_this->connect('/rest/:controller/:action/*', array('webservices' => 'Rest'));
$_this->connect('/rss/:controller/:action/*', array('webservices' => 'Rss'));
$_this->connect('/soap/:controller/:action/*', array('webservices' => 'Soap'));
$_this->connect('/xml/:controller/:action/*', array('webservices' => 'Xml'));
$_this->connect('/xmlrpc/:controller/:action/*', array('webservices' => 'XmlRpc'));
}
$_this->routes[] = $default_route;
}
/**
* Takes parameter and path information back from the Dispatcher
*
@ -382,12 +398,21 @@ class Router extends Overloadable {
$_this->{$key} = $val;
}
}
function __notEmpty($var){
if($var === '0' || !empty($var)){
return true;
/**
* Filters empty elements out of a route array, excluding '0'.
*
* @return mixed
*/
function __filter($var, $isArray = false) {
if (is_array($var) && (!empty($var) || $isArray)) {
$_this =& Router::getInstance();
return array_filter($var, array(&$_this, '__filter'));
} else {
return false;
if($var === '0' || !empty($var)) {
return true;
} else {
return false;
}
}
}
/**
@ -409,12 +434,12 @@ class Router extends Overloadable {
function url($url = null, $full = false) {
$_this =& Router::getInstance();
$params = array('plugin'=> null, 'controller'=>null, 'action'=> 'index');
$defaults = $params = array('plugin' => null, 'controller' => null, 'action' => 'index');
if(!empty($_this->__params[0])) {
$params = $_this->__params[0];
}
$path = array('base'=> null);
$path = array('base' => null);
if(!empty($_this->__paths[0])) {
$path = $_this->__paths[0];
}
@ -423,27 +448,23 @@ class Router extends Overloadable {
$extension = $output = $mapped = $q = null;
if (is_array($url) && !empty($url)) {
if (isset($url['full_base']) && $url['full_base'] == true) {
$full = true;
unset($url['full_base']);
}
if (isset($url['?'])) {
$q = $url['?'];
unset($url['?']);
}
if (!isset($url['action'])) {
if (!isset($url['controller']) || $params['controller'] == $url['controller']) {
$url['action'] = $params['action'];
} else {
$url['action'] = 'index';
}
}
$url = am(array('controller' => $params['controller'], 'plugin' => $params['plugin']), $url);
$url = am(
array('controller' => $params['controller'], 'plugin' => $params['plugin']),
$url
);
if (isset($url['ext'])) {
$extension = '.' . $url['ext'];
}
@ -454,11 +475,11 @@ class Router extends Overloadable {
unset($url[CAKE_ADMIN]);
}
$match = false;
foreach ($_this->routes as $route) {
$match = $_this->mapRouteElements($route, $url);
if ($match !== false) {
if ($match = $_this->mapRouteElements($route, $url)) {
list($output, $url) = $match;
if ($output{0} == '/') {
if (strpos($output, '/') === 0) {
$output = substr($output, 1);
}
break;
@ -470,15 +491,16 @@ class Router extends Overloadable {
if(defined('CAKE_ADMIN')) {
$skip[] = CAKE_ADMIN;
}
$keys = array_values(array_diff(array_keys($url), $skip));
$count = count($keys);
for ($i = 0; $i < $count; $i++) {
if (is_numeric($keys[$i]) || $keys[$i] == 'id') {
$args[] = $url[$keys[$i]];
} else if(is_array($path['namedArgs']) && in_array($keys[$i], array_keys($path['namedArgs']))){
} else if(is_array($path['namedArgs']) && in_array($keys[$i], array_keys($path['namedArgs']))) {
$named[] = array($keys[$i], $url[$keys[$i]]);
} else if ($match === false) {
$args[] = $keys[$i] . $path['argSeparator'] .$url[$keys[$i]];
$args[] = $keys[$i] . $path['argSeparator'] . $url[$keys[$i]];
}
}
if ($match === false) {
@ -498,7 +520,7 @@ class Router extends Overloadable {
if(!isset($url['action'])) {
$url['action'] = null;
}
$urlOut = array_filter(array($url['plugin'], $url['controller'], $url['action'], join('/', array_filter($args, array($_this, "__notEmpty"))), $named), array($_this, "__notEmpty"));
$urlOut = $_this->__filter(array($url['plugin'], $url['controller'], $url['action'], join('/', $_this->__filter($args, true)), $named));
if($url['plugin'] == $url['controller']) {
array_shift($urlOut);
@ -541,22 +563,42 @@ class Router extends Overloadable {
* @return mixed
*/
function mapRouteElements($route, $url) {
$_this =& Router::getInstance();
$params = $route[2];
$defaults = am(array('plugin' => null, 'controller'=> null), $route[3]);
foreach ($defaults as $key=>$default) {
if(!array_key_exists($key, $url)) {
$defaults = am(array('plugin' => null, 'controller' => null, 'action' => null), $route[3]);
foreach (array('plugin', 'controller', 'action') as $key) {
if (empty($defaults[$key])) {
$defaults[$key] = $url[$key];
}
}
$pass = array();
foreach ($url as $key => $val) {
if (is_numeric($key)) {
if (!isset($defaults[count($pass)]) || $defaults[count($pass)] != $val) {
$pass[] = $val;
}
unset($url[$key]);
}
}
if (!strpos($route[0], '*') && !empty($pass)) {
return false;
}
foreach ($defaults as $key => $default) {
if(!array_key_exists($key, $url) && (!is_numeric($key) || !isset($pass[$key]))) {
$url[$key] = $default;
}
}
krsort($defaults);
krsort($url);
if ($defaults == $url) {
return array(Router::__mapRoute($route, $url), array());
} elseif (!empty($params) && !empty($route[3])) {
if(array_key_exists(0, $url)) {
return false;
}
if (Set::diff($defaults, $url) == array()) {
return array(Router::__mapRoute($route, am($url, array('pass' => $pass))), array());
} elseif (!empty($params) && !empty($route[3])) {
$required = array_diff(array_keys($defaults), array_keys($url));
if(!empty($required)) {
return false;
@ -566,35 +608,34 @@ class Router extends Overloadable {
$keysFilled = array_keys($filled);
sort($params);
sort($keysFilled);
if ($keysFilled != $params) {
return false;
}
if (!empty($url['plugin']) && $keysFilled === $params) {
if (Set::diff($keysFilled, $params) != array()) {
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']) {
if(isset($url['0']) && isset($defaults['0']) && ($url['0'] != $defaults['0'])){
return false;
}
return array(Router::__mapRoute($route, $url), $url);
return array(Router::__mapRoute($route, am($url, array('pass' => $pass))), $url);
}
return false;
}
if($url['controller'] != $route[3]['controller']) {
if(isset($route[3]['controller']) && !empty($route[3]['controller']) && $url['controller'] != $route[3]['controller']) {
return false;
}
if(!empty($route[4])){
if(!empty($route[4])) {
foreach ($route[4] as $key => $reg) {
if (isset($url[$key]) && !preg_match('/' . $reg . '/', $url[$key])) {
return false;
}
}
}
return array(Router::__mapRoute($route, $url), $url);
return array(Router::__mapRoute($route, am($url, array('pass' => $pass))), $url);
}
/**
* Merges URL parameters into a route string
@ -604,8 +645,10 @@ class Router extends Overloadable {
* @return string
*/
function __mapRoute($route, $params = array()) {
$_this =& Router::getInstance();
if (isset($params['pass']) && is_array($params['pass'])) {
$params['pass'] = implode('/', array_filter($params['pass']));
$params['pass'] = implode('/', $_this->__filter($params['pass'], true));
} elseif (!isset($params['pass'])) {
$params['pass'] = '';
}
@ -613,30 +656,32 @@ class Router extends Overloadable {
if (strpos($route[0], '*')) {
$out = str_replace('*', $params['pass'], $route[0]);
} else {
$out = $route[0] . $params['pass'];
$out = $route[0];
}
foreach ($route[2] as $key) {
$out = str_replace(':' . $key, $params[$key], $out);
unset($params[$key]);
}
// Do something else here for leftover params
$skip = array('action', 'controller', 'plugin', 'ext', '?', 'pass');
if(defined('CAKE_ADMIN')) {
$skip[] = CAKE_ADMIN;
}
$args = array();
$keys = array_filter(array_values(array_diff(array_keys($params), $skip)));
$keys = $_this->__filter(array_values(array_diff(array_keys($params), $skip)), true);
$count = count($keys);
for ($i = 0; $i < $count; $i++) {
$args[] = $keys[$i] . ':' .$params[$keys[$i]];
}
if(isset($params['0']) && !isset($route['3']['0'])){
return $out . $params['0'] . join('/', array_filter($args));
$args = join('/', $_this->__filter($args, true));
if(isset($params['0']) && !isset($route['3']['0'])) {
return $out . $params['0'] . $args;
}
return $out . join('/', array_filter($args));
return $out . $args;
}
/**
* Generates a well-formed querystring from $q
@ -646,13 +691,25 @@ class Router extends Overloadable {
* @return array
*/
function queryString($q, $extra = array()) {
if (empty($q)) {
if (empty($q) && empty($extra)) {
return null;
}
return '?' . $q;
$out = '';
if (is_array($q)) {
$q = am($extra, $q);
} else {
$out = $q;
$q = $extra;
}
$out .= http_build_query($q);
if (strpos($out, '?') !== 0) {
$out = '?' . $out;
}
return $out;
}
/**
* Returns the route matching the current request URL
* Returns the route matching the current request URL.
*
* @return array
*/
@ -670,7 +727,7 @@ class Router extends Overloadable {
return $_this->__currentRoute[count($_this->__currentRoute) - 1];
}
/**
* removes the plugin name from the base url
* Removes the plugin name from the base URL.
*
* @param string $base
* @param string $plugin
@ -697,8 +754,9 @@ class Router extends Overloadable {
* automatically switch to alternate layouts and templates, and load helpers
* corresponding to the given content, i.e. RssHelper.
*
* An array of valid extension can be passed to this method. $extensions = array('rss', 'xml')
* If null is passed anything after a . in the url will be considered an extension
* A list of valid extension can be passed to this method, i.e. Router::parseExtensions('rss', 'xml');
* If no parameters are given, anything after the first . (dot) after the last / in the URL will be
* parsed, excluding querystring parameters (i.e. ?q=...).
*
* @param string $ext
* @param string $ext
@ -714,5 +772,44 @@ class Router extends Overloadable {
}
}
}
/**
* Implements http_build_query for PHP4.
*
* @param string $data
* @param string $prefix
* @param string $argSep
* @param string $baseKey
* @return string
* @see http://php.net/http_build_query
*/
if(!function_exists('http_build_query')) {
function http_build_query($data, $prefix = null, $argSep = null, $baseKey = null) {
if(empty($argSep)) {
$argSep = ini_get('arg_separator.output');
}
if (is_object($data)) {
$data = get_object_vars($data);
}
$out = array();
?>
foreach((array)$data as $key => $val) {
if(is_numeric($key) && !empty($prefix)) {
$key = $prefix . $key;
}
$key = urlencode($key);
if(!empty($baseKey)) {
$key = $baseKey . '[' . $key . ']';
}
if(is_array($v) || is_object($v)) {
$out[] = http_build_query($v, $prefix, $argSep, $key);
} else {
$out[] = $k . '=' . urlencode($v);
}
}
return implode($argSep, $out);
}
}
?>

View file

@ -26,7 +26,11 @@
* @lastmodified $Date$
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
require_once LIBS.'router.php';
uses('router', 'debugger');
if (!defined('CAKE_ADMIN')) {
define('CAKE_ADMIN', 'admin');
}
/**
* Short description for class.
*
@ -37,6 +41,7 @@ class RouterTest extends UnitTestCase {
function setUp() {
$this->router =& Router::getInstance();
//$this->router->reload();
}
function testReturnedInstanceReference() {
@ -85,61 +90,127 @@ class RouterTest extends UnitTestCase {
}
function testRouterIdentity() {
$router =& Router::getInstance();
$this->vars = get_object_vars($router);
$this->router->routes = $this->router->__paths = $this->router->__params = $this->router->__currentRoute = array();
$this->router->__parseExtensions = false;
$this->router->reload();
$this->router->__admin = array(
'/:' . CAKE_ADMIN . '/:controller/:action/*',
'/^(?:\/(?:(' . CAKE_ADMIN . ')(?:\\/([a-zA-Z0-9_\\-\\.\\;\\:]+)(?:\\/([a-zA-Z0-9_\\-\\.\\;\\:]+)(?:[\\/\\?](.*))?)?)?))[\/]*$/',
array(CAKE_ADMIN, 'controller', 'action'), array()
);
$router2 = new Router();
$this->assertEqual(get_object_vars($router), get_object_vars($router2));
$this->assertEqual(get_object_vars($this->router), get_object_vars($router2));
}
function testUrlGeneration() {
$router =& Router::getInstance();
foreach ($this->vars as $var => $val) {
$this->router->{$var} = $val;
}
$this->router->routes = array();
$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->assertEqual($out, '/');
$this->router->connect('/pages/*', array('controller'=>'pages', 'action'=>'display'));
$out = $this->router->url(array('controller'=>'pages', 'action'=>'display', 'about'));
$this->router->connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
$result = $this->router->url(array('controller' => 'pages', 'action' => 'display', 'about'));
$expected = '/pages/about';
$this->assertEqual($out, $expected);
$this->assertEqual($result, $expected);
$this->router->reload();
$this->router->connect('/:plugin/:id/*', array('controller' => 'posts', 'action' => 'view'), array('id' => $ID));
$result = $this->router->url(array('plugin' => 'cake_plugin', 'controller' => 'posts', 'action' => 'view', 'id' => '1'));
$expected = '/cake_plugin/1/';
$this->assertEqual($result, $expected);
$this->router->connect('/:plugin/:controller/*', array('plugin'=>'cake_plugin', 'controller'=>'posts', 'action'=>'view', '1'));
$out = $this->router->url(array('plugin'=>'cake_plugin', 'controller'=>'posts', '1'));
$expected = '/cake_plugin/posts/';
$this->assertEqual($out, $expected);
$result = $this->router->url(array('plugin' => 'cake_plugin', 'controller' => 'posts', 'action' => 'view', 'id' => '1', '0'));
$expected = '/cake_plugin/1/0';
$this->assertEqual($result, $expected);
$this->router->connect('/:controller/:action/:id', array(), array('id' => '1'));
$out = $this->router->url(array('controller'=>'posts', 'action'=>'view', '1'));
$this->router->reload();
$this->router->connect('/:controller/:action/:id', array(), array('id' => $ID));
$result = $this->router->url(array('controller' => 'posts', 'action' => 'view', 'id' => '1'));
$expected = '/posts/view/1';
$this->assertEqual($out, $expected);
$this->assertEqual($result, $expected);
$this->router->connect('/:controller/:id', array('action' => 'view'), array('id' => '1'));
$out = $this->router->url(array('controller'=>'posts', '1'));
$this->router->reload();
$this->router->connect('/:controller/:id', array('action' => 'view', 'id' => '1'));
$result = $this->router->url(array('controller' => 'posts', 'action' => 'view', 'id' => '1'));
$expected = '/posts/1';
$this->assertEqual($out, $expected);
$this->assertEqual($result, $expected);
$out = $this->router->url(array('controller' => 'posts', 'action'=>'index', '0'));
$result = $this->router->url(array('controller' => 'posts', 'action' => 'index', '0'));
$expected = '/posts/index/0';
$this->assertEqual($result, $expected);
$result = $this->router->url(array('controller' => 'posts', 'action'=>'index', '0', '?' => 'var=test&var2=test2'));
$expected = '/posts/index/0?var=test&var2=test2';
$this->assertEqual($result, $expected);
$result = $this->router->url(array('controller' => 'posts', '0', '?' => 'var=test&var2=test2'));
$this->assertEqual($result, $expected);
}
function testAdminRouting() {
$out = $this->router->url(array(CAKE_ADMIN => true, 'controller' => 'posts', 'action'=>'index', '0', '?' => 'var=test&var2=test2'));
$expected = '/' . CAKE_ADMIN . '/posts/index/0?var=test&var2=test2';
$this->assertEqual($out, $expected);
}
function testExtensionParsingSetting() {
if (PHP5) {
$router = Router::getInstance();
$this->router->reload();
$this->assertFalse($this->router->__parseExtensions);
$router = Router::getInstance();
$this->router->reload();
$this->assertFalse($this->router->__parseExtensions);
$this->router->parseExtensions();
$this->assertTrue($this->router->__parseExtensions);
}
$router->parseExtensions();
$this->assertTrue($this->router->__parseExtensions);
}
function testExtensionParsing() {
$this->router->reload();
$this->router->parseExtensions();
$result = $this->router->parse('/posts.rss');
$expected = array('controller' => 'posts', 'action' => null, 'url' => array ('ext' => 'rss'));
$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'));
$this->assertEqual($result, $expected);
$result = $this->router->parse('/posts/view/1.rss?query=test');
$this->assertEqual($result, $expected);
$result = $this->router->parse('/posts/view/1.atom');
$expected['url'] = array('ext' => 'atom');
$this->assertEqual($result, $expected);
$this->router->reload();
$this->router->parseExtensions('rss', 'xml');
$result = $this->router->parse('/posts.xml');
$expected = array('controller' => 'posts', 'action' => null, 'url' => array ('ext' => 'xml'));
$this->assertEqual($result, $expected);
$result = $this->router->parse('/posts.atom?hello=goodbye');
$expected = array('controller' => 'posts.atom', 'action' => null);
$this->assertEqual($result, $expected);
$this->router->reload();
$this->router->parseExtensions();
$result = $this->router->__parseExtension('/posts.atom');
$expected = array('ext' => 'atom', 'url' => '/posts');
$this->assertEqual($result, $expected);
}
function testQuerystringGeneration() {
$result = $this->router->url(array('controller' => 'posts', 'action'=>'index', '0', '?' => 'var=test&var2=test2'));
$expected = '/posts/index/0?var=test&var2=test2';
$this->assertEqual($result, $expected);
$result = $this->router->url(array('controller' => 'posts', 'action'=>'index', '0', '?' => array('var' => 'test', 'var2' => 'test2')));
$this->assertEqual($result, $expected);
$expected .= '&more=test+data';
$result = $this->router->url(array('controller' => 'posts', 'action'=>'index', '0', '?' => array('var' => 'test', 'var2' => 'test2', 'more' => 'test data')));
$this->assertEqual($result, $expected);
}
}
?>