diff --git a/lib/Cake/Routing/Router.php b/lib/Cake/Routing/Router.php index b464728c8..3c0688240 100644 --- a/lib/Cake/Routing/Router.php +++ b/lib/Cake/Routing/Router.php @@ -1087,6 +1087,40 @@ class Router { return $out; } +/** + * Reverses a parsed parameter array into an array. + * + * Works similarly to Router::url(), but since parsed URL's contain additional + * 'pass' and 'named' as well as 'url.url' keys. Those keys need to be specially + * handled in order to reverse a params array into a string URL. + * + * This will strip out 'autoRender', 'bare', 'requested', and 'return' param names as those + * are used for CakePHP internals and should not normally be part of an output URL. + * + * @param CakeRequest|array $params The params array or CakeRequest object that needs to be reversed. + * @return array The URL array ready to be used for redirect or HTML link. + */ + public static function reverseToArray($params) { + if ($params instanceof CakeRequest) { + $url = $params->query; + $params = $params->params; + } else { + $url = $params['url']; + } + $pass = isset($params['pass']) ? $params['pass'] : array(); + $named = isset($params['named']) ? $params['named'] : array(); + unset( + $params['pass'], $params['named'], $params['paging'], $params['models'], $params['url'], $url['url'], + $params['autoRender'], $params['bare'], $params['requested'], $params['return'], + $params['_Token'] + ); + $params = array_merge($params, $pass, $named); + if (!empty($url)) { + $params['?'] = $url; + } + return $params; + } + /** * Reverses a parsed parameter array into a string. * @@ -1103,24 +1137,7 @@ class Router { * @return string The string that is the reversed result of the array */ public static function reverse($params, $full = false) { - if ($params instanceof CakeRequest) { - $url = $params->query; - $params = $params->params; - } else { - $url = $params['url']; - } - $pass = isset($params['pass']) ? $params['pass'] : array(); - $named = isset($params['named']) ? $params['named'] : array(); - - unset( - $params['pass'], $params['named'], $params['paging'], $params['models'], $params['url'], $url['url'], - $params['autoRender'], $params['bare'], $params['requested'], $params['return'], - $params['_Token'] - ); - $params = array_merge($params, $pass, $named); - if (!empty($url)) { - $params['?'] = $url; - } + $params = Router::reverseToArray($params, $full); return Router::url($params, $full); } diff --git a/lib/Cake/Test/Case/Routing/RouterTest.php b/lib/Cake/Test/Case/Routing/RouterTest.php index fc4298246..46d89fac6 100644 --- a/lib/Cake/Test/Case/Routing/RouterTest.php +++ b/lib/Cake/Test/Case/Routing/RouterTest.php @@ -2464,9 +2464,8 @@ class RouterTest extends CakeTestCase { * * @return void */ - public function testRouterReverse() { + public function testReverseToken() { Router::$initialized = true; - $params = array( 'controller' => 'posts', 'action' => 'view', @@ -2481,17 +2480,21 @@ class RouterTest extends CakeTestCase { ); $result = Router::reverse($params); $this->assertEquals('/posts/view/1', $result); + } + public function testReverseNamed() { $params = array( 'controller' => 'posts', 'action' => 'index', 'pass' => array(1), 'named' => array('page' => 1, 'sort' => 'Article.title', 'direction' => 'desc'), - 'url' => array() + 'url' => array(), ); $result = Router::reverse($params); $this->assertEquals('/posts/index/1/page:1/sort:Article.title/direction:desc', $result); + } + public function testReverseLocalized() { Router::connect('/:lang/:controller/:action/*', array(), array('lang' => '[a-z]{3}')); $params = array( 'lang' => 'eng', @@ -2499,11 +2502,14 @@ class RouterTest extends CakeTestCase { 'action' => 'view', 'pass' => array(1), 'named' => array(), - 'url' => array('url' => 'eng/posts/view/1') + 'url' => array('url' => 'eng/posts/view/1'), ); $result = Router::reverse($params); $this->assertEquals('/eng/posts/view/1', $result); + } + public function testReverseArrayQuery() { + Router::connect('/:lang/:controller/:action/*', array(), array('lang' => '[a-z]{3}')); $params = array( 'lang' => 'eng', 'controller' => 'posts', @@ -2512,11 +2518,14 @@ class RouterTest extends CakeTestCase { 'named' => array(), 'url' => array('url' => 'eng/posts/view/1', 'foo' => 'bar', 'baz' => 'quu'), 'paging' => array(), - 'models' => array() + 'models' => array(), ); $result = Router::reverse($params); $this->assertEquals('/eng/posts/view/1?foo=bar&baz=quu', $result); + } + public function testReverseCakeRequestQuery() { + Router::connect('/:lang/:controller/:action/*', array(), array('lang' => '[a-z]{3}')); $request = new CakeRequest('/eng/posts/view/1'); $request->addParams(array( 'lang' => 'eng', @@ -2529,19 +2538,64 @@ class RouterTest extends CakeTestCase { $result = Router::reverse($request); $expected = '/eng/posts/view/1?test=value'; $this->assertEquals($expected, $result); + } + public function testReverseFull() { + Router::connect('/:lang/:controller/:action/*', array(), array('lang' => '[a-z]{3}')); $params = array( 'lang' => 'eng', 'controller' => 'posts', 'action' => 'view', 'pass' => array(1), 'named' => array(), - 'url' => array('url' => 'eng/posts/view/1') + 'url' => array('url' => 'eng/posts/view/1'), ); $result = Router::reverse($params, true); $this->assertRegExp('/^http(s)?:\/\//', $result); } + public function testReverseToArrayNamed() { + $params = array( + 'controller' => 'posts', + 'action' => 'index', + 'pass' => array(123), + 'named' => array('page' => 123, 'sort' => 'Article.title', 'direction' => 'desc'), + 'url' => array(), + ); + $result = Router::reverseToArray($params); + $expected = array( + 'controller' => 'posts', + 'action' => 'index', + 123, + 'page' => 123, + 'sort' => 'Article.title', + 'direction' => 'desc', + ); + $this->assertEquals($expected, $result); + } + + public function testReverseToArrayCakeRequestQuery() { + $request = new CakeRequest('/posts/view/123'); + $request->addParams(array( + 'controller' => 'posts', + 'action' => 'view', + 'pass' => array(123), + 'named' => array(), + )); + $request->query = array('url' => 'eng/posts/view/123', 'test' => 'value'); + $result = Router::reverseToArray($request); + $expected = array( + 'plugin' => null, + 'controller' => 'posts', + 'action' => 'view', + 123, + '?' => array( + 'test' => 'value', + ), + ); + $this->assertEquals($expected, $result); + } + /** * Test that extensions work with Router::reverse() *