Skip to content
Permalink
Browse files

Add automatic query string support.

Any url keys that are not in the defaults or route
keys are now treated as query string parameters.
  • Loading branch information...
markstory committed Apr 26, 2012
1 parent 98b3bfe commit b7df5c074fea816d616dab91d2e9ebcf32fa18fb
Showing with 55 additions and 27 deletions.
  1. +19 −12 lib/Cake/Routing/Route/Route.php
  2. +36 −15 lib/Cake/Test/TestCase/Routing/Route/RouteTest.php
@@ -369,7 +369,7 @@ public function match($url, $context = array()) {
unset($hostOptions['_port']);
}
}
// If no base is set, copy one in.
if (!isset($hostOptions['_base']) && isset($context['_base'])) {
$hostOptions['_base'] = $context['_base'];
@@ -390,17 +390,19 @@ public function match($url, $context = array()) {
if (array_diff_key($defaults, $url) !== array()) {
return false;
}
// Defaults with different values are a fail.
if (array_intersect_key($url, $defaults) !== $defaults) {
return false;
}
$prefixes = Router::prefixes();
$pass = array();
$query = array();
foreach ($url as $key => $value) {
// keys that exist in the defaults and have different values is a match failure.
$defaultExists = array_key_exists($key, $defaults);
if ($defaultExists && $defaults[$key] != $value) {
return false;
} elseif ($defaultExists) {
continue;
}
// If the key is a routed key, its not different yet.
if (array_key_exists($key, $keyNames)) {
@@ -418,25 +420,26 @@ public function match($url, $context = array()) {
}
// keys that don't exist are different.
if (!$defaultExists && !empty($value)) {
return false;
if (!$defaultExists && ($value !== null && $value !== false && $value !== '')) {
$query[$key] = $value;
unset($url[$key]);
}
}
//if a not a greedy route, no extra params are allowed.
// if not a greedy route, no extra params are allowed.
if (!$this->_greedy && !empty($pass)) {
return false;
}
//check patterns for routed params
if (!empty($this->options)) {
foreach ($this->options as $key => $pattern) {
if (array_key_exists($key, $url) && !preg_match('#^' . $pattern . '$#', $url[$key])) {
if (isset($url[$key]) && !preg_match('#^' . $pattern . '$#', $url[$key])) {
return false;
}
}
}
return $this->_writeUrl($url, $pass, $hostOptions);
return $this->_writeUrl($url, $pass, $hostOptions, $query);
}
/**
@@ -447,7 +450,7 @@ public function match($url, $context = array()) {
* @param array $pass The additional passed arguments.
* @return string Composed route string.
*/
protected function _writeUrl($params, $pass = array(), $hostOptions = array()) {
protected function _writeUrl($params, $pass = array(), $hostOptions = array(), $query = array()) {
if (isset($params['prefix'], $params['action'])) {
$params['action'] = str_replace($params['prefix'] . '_', '', $params['action']);
unset($params['prefix']);
@@ -495,6 +498,10 @@ protected function _writeUrl($params, $pass = array(), $hostOptions = array()) {
$out
);
}
if (!empty($query)) {
$out = rtrim($out, '/');
$out .= '?' . http_build_query($query);
}
return $out;
}
@@ -269,15 +269,15 @@ public function testMatchBasic() {
$result = $route->match(array('controller' => 'posts', 'action' => 'view'));
$this->assertEquals('/blog/view', $result);
$result = $route->match(array('controller' => 'posts', 'action' => 'view', 'id' => 2));
$this->assertEquals('/blog/view?id=2', $result);
$result = $route->match(array('controller' => 'nodes', 'action' => 'view'));
$this->assertFalse($result);
$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 Route('/foo/:controller/:action', array('action' => 'index'));
$result = $route->match(array('controller' => 'posts', 'action' => 'view'));
$this->assertEquals('/foo/posts/view', $result);
@@ -348,7 +348,7 @@ public function testMatchWithHostKeys() {
array('controller' => 'posts', 'action' => 'index', '_base' => '/dir'),
$context
);
$this->assertEquals('http://foo.com/dir/posts/index', $result);
$this->assertEquals('/dir/posts/index', $result);
$result = $route->match(
array(
@@ -379,17 +379,6 @@ public function testGreedyRouteFailurePassedArg() {
$this->assertFalse($result);
}
/**
* test that non-greedy routes fail with extra passed args
*
* @return void
*/
public function testGreedyRouteFailureNamedParam() {
$route = new Route('/:controller/:action', array('plugin' => null));
$result = $route->match(array('controller' => 'posts', 'action' => 'view', 'page' => 1));
$this->assertFalse($result);
}
/**
* test that falsey values do not interrupt a match.
*
@@ -454,6 +443,38 @@ public function testMatchWithPatterns() {
$this->assertFalse($result);
}
/**
* Test that match() pulls out extra arguments as query string params.
*
* @return void
*/
public function testMatchExtractQueryStringArgs() {
$route = new Route('/:controller/:action/*');
$result = $route->match(array(
'controller' => 'posts',
'action' => 'index',
'page' => 1
));
$this->assertEquals('/posts/index?page=1', $result);
$result = $route->match(array(
'controller' => 'posts',
'action' => 'index',
'page' => 0
));
$this->assertEquals('/posts/index?page=0', $result);
$result = $route->match(array(
'controller' => 'posts',
'action' => 'index',
1,
'page' => 1,
'dir' => 'desc',
'order' => 'title'
));
$this->assertEquals('/posts/index/1?page=1&dir=desc&order=title', $result);
}
/**
* test persistParams ability to persist parameters from $params and remove params.
*

0 comments on commit b7df5c0

Please sign in to comment.
You can’t perform that action at this time.