From d9691a19c82d782a3710fce5d1ec3a255eda94de Mon Sep 17 00:00:00 2001 From: nate Date: Sat, 26 Jan 2008 08:50:06 +0000 Subject: [PATCH] Refactoring Router::mapResources(), adding tests for REST routing and HTTP method overrides git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6409 3807eeeb-6ff5-0310-8944-8be069107fe0 --- cake/dispatcher.php | 24 +++++++++------ cake/libs/controller/controller.php | 2 +- cake/libs/http_socket.php | 2 +- cake/libs/router.php | 10 +++++-- cake/tests/cases/dispatcher.test.php | 43 +++++++++++++++++++++------ cake/tests/cases/libs/router.test.php | 11 +++++++ 6 files changed, 69 insertions(+), 23 deletions(-) diff --git a/cake/dispatcher.php b/cake/dispatcher.php index 07b426372..2af1f337e 100644 --- a/cake/dispatcher.php +++ b/cake/dispatcher.php @@ -263,14 +263,15 @@ class Dispatcher extends Object { )); } else { $output = call_user_func_array(array(&$controller, $params['action']), empty($params['pass'])? array(): $params['pass']); + if (empty($controller->output)) { + $controller->output = $output; + } } if ($controller->autoRender) { - $output = $controller->render(); + $controller->output = $controller->render(); } - $controller->output =& $output; - foreach ($controller->components as $c) { $path = preg_split('/\/|\./', $c); $c = $path[count($path) - 1]; @@ -327,15 +328,15 @@ class Dispatcher extends Object { * @access public */ function parseParams($fromUrl) { - extract(Router::getNamedExpressions()); - include CONFIGS . 'routes.php'; - $params = Router::parse($fromUrl); + $params = array(); if (isset($_POST)) { + $params['form'] = $_POST; if (ini_get('magic_quotes_gpc') == 1) { - $params['form'] = stripslashes_deep($_POST); - } else { - $params['form'] = $_POST; + $params['form'] = stripslashes_deep($params['form']); + } + if (env('HTTP_X_HTTP_METHOD_OVERRIDE')) { + $params['form']['_method'] = env('HTTP_X_HTTP_METHOD_OVERRIDE'); } if (isset($params['form']['_method'])) { if (isset($_SERVER) && !empty($_SERVER)) { @@ -347,6 +348,10 @@ class Dispatcher extends Object { } } + extract(Router::getNamedExpressions()); + include CONFIGS . 'routes.php'; + $params = array_merge(Router::parse($fromUrl), $params); + if (isset($params['form']['data'])) { $params['data'] = Router::stripEscape($params['form']['data']); unset($params['form']['data']); @@ -396,6 +401,7 @@ class Dispatcher extends Object { */ function baseUrl() { + $dir = $webroot = null; $config = Configure::read('App'); extract($config); diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index f05b303eb..ba3a54e8c 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -313,7 +313,7 @@ class Controller extends Object { * * @access protected */ - function __mergeVars () { + function __mergeVars() { $pluginName = Inflector::camelize($this->plugin); $pluginController = $pluginName . 'AppController'; diff --git a/cake/libs/http_socket.php b/cake/libs/http_socket.php index c7180a0e0..a8c04a123 100644 --- a/cake/libs/http_socket.php +++ b/cake/libs/http_socket.php @@ -24,7 +24,7 @@ * @lastmodified $Date$ * @license http://www.opensource.org/licenses/mit-license.php The MIT License */ -App::import('Core', array('Socket', 'Set')); +App::import('Core', array('Socket', 'Set', 'Router')); /** * Cake network socket connection class. diff --git a/cake/libs/router.php b/cake/libs/router.php index 77c9ea4b8..5f8ee93b2 100644 --- a/cake/libs/router.php +++ b/cake/libs/router.php @@ -185,6 +185,7 @@ class Router extends Object { * * @return array Named route elements * @access public + * @see Router::$__named * @static */ function getNamedExpressions() { @@ -252,13 +253,16 @@ class Router extends Object { * Creates REST resource routes for the given controller(s) * * @param mixed $controller A controller name or array of controller names (i.e. "Posts" or "ListItems") - * @param array $options + * @param array $options Options to use when generating REST routes + * 'id' - The regular expression fragment to use when matching IDs. By default, matches + * integer values and UUIDs. + * 'prefix' - URL prefix to use for the generated routes. Defaults to '/'. * @access public * @static */ function mapResources($controller, $options = array()) { $_this =& Router::getInstance(); - $options = array_merge(array('prefix' => '/'), $options); + $options = array_merge(array('prefix' => '/', 'id' => $_this->__named['ID'] . '|' . $_this->__named['UUID']), $options); $prefix = $options['prefix']; foreach ((array)$controller as $ctlName) { @@ -270,7 +274,7 @@ class Router extends Object { Router::connect( "{$prefix}{$urlName}{$id}", array('controller' => $urlName, 'action' => $action, '[method]' => $params['method']), - array('id' => $_this->__named['ID'] . '|' . $_this->__named['UUID']) + array('id' => $options['id']) ); } $this->__resourceMapped[] = $urlName; diff --git a/cake/tests/cases/dispatcher.test.php b/cake/tests/cases/dispatcher.test.php index 6a89ade7a..e83d76f50 100644 --- a/cake/tests/cases/dispatcher.test.php +++ b/cake/tests/cases/dispatcher.test.php @@ -994,6 +994,40 @@ class DispatcherTest extends UnitTestCase { unlink($filename); } + function testHttpMethodOverrides() { + Router::reload(); + Router::mapResources('Posts'); + + $_SERVER['REQUEST_METHOD'] = 'POST'; + $dispatcher =& new Dispatcher(); + $dispatcher->base = false; + + $result = $dispatcher->parseParams('/posts'); + $expected = array('pass' => array(), 'named' => array(), 'plugin' => null, 'controller' => 'posts', 'action' => 'add', '[method]' => 'POST', 'form' => array(), 'url' => array(), 'bare' => 0, 'webservices' => null); + $this->assertEqual($result, $expected); + + $_SERVER['REQUEST_METHOD'] = 'GET'; + $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'; + + $result = $dispatcher->parseParams('/posts/5'); + $expected = array('pass' => array(), 'named' => array(), 'id' => '5', 'plugin' => null, 'controller' => 'posts', 'action' => 'edit', '[method]' => 'PUT', 'form' => array(), 'url' => array(), 'bare' => 0, 'webservices' => null); + $this->assertEqual($result, $expected); + + unset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']); + $_SERVER['REQUEST_METHOD'] = 'GET'; + + $result = $dispatcher->parseParams('/posts/5'); + $expected = array('pass' => array(), 'named' => array(), 'id' => '5', 'plugin' => null, 'controller' => 'posts', 'action' => 'view', '[method]' => 'GET', 'form' => array(), 'url' => array(), 'bare' => 0, 'webservices' => null); + $this->assertEqual($result, $expected); + + $_POST['_method'] = 'PUT'; + + $result = $dispatcher->parseParams('/posts/5'); + $expected = array('pass' => array(), 'named' => array(), 'id' => '5', 'plugin' => null, 'controller' => 'posts', 'action' => 'edit', '[method]' => 'PUT', 'form' => array(), 'url' => array(), 'bare' => 0, 'webservices' => null); + $this->assertEqual($result, $expected); + unset($_POST['_method']); + } + function testEnvironmentDetection() { $dispatcher =& new Dispatcher(); @@ -1001,8 +1035,6 @@ class DispatcherTest extends UnitTestCase { 'IIS' => array( 'No rewrite base path' => array( 'App' => array('base' => false, 'baseUrl' => '/index.php?', 'server' => 'IIS'), - 'GET' => array(), - 'POST' => array(), 'SERVER' => array('HTTPS' => 'off', 'SCRIPT_NAME' => '/index.php', 'PATH_TRANSLATED' => 'C:\\Inetpub\\wwwroot', 'QUERY_STRING' => '', 'REMOTE_ADDR' => '127.0.0.1', 'REMOTE_HOST' => '127.0.0.1', 'REQUEST_METHOD' => 'GET', 'SERVER_NAME' => 'localhost', 'SERVER_PORT' => '80', 'SERVER_PROTOCOL' => 'HTTP/1.1', 'SERVER_SOFTWARE' => 'Microsoft-IIS/5.1', 'APPL_PHYSICAL_PATH' => 'C:\\Inetpub\\wwwroot\\', 'REQUEST_URI' => '/index.php', 'URL' => '/index.php', 'SCRIPT_FILENAME' => 'C:\\Inetpub\\wwwroot\\index.php', 'ORIG_PATH_INFO' => '/index.php', 'PATH_INFO' => '', 'ORIG_PATH_TRANSLATED' => 'C:\\Inetpub\\wwwroot\\index.php', 'DOCUMENT_ROOT' => 'C:\\Inetpub\\wwwroot', 'PHP_SELF' => '/index.php', 'HTTP_ACCEPT' => '*/*', 'HTTP_ACCEPT_LANGUAGE' => 'en-us', 'HTTP_CONNECTION' => 'Keep-Alive', 'HTTP_HOST' => 'localhost', 'HTTP_USER_AGENT' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)', 'HTTP_ACCEPT_ENCODING' => 'gzip, deflate', 'argv' => array(), 'argc' => 0), 'reload' => true, 'path' => '' @@ -1014,14 +1046,12 @@ class DispatcherTest extends UnitTestCase { ), 'No rewrite sub dir 1' => array( 'GET' => array(), - 'POST' => array(), 'SERVER' => array('QUERY_STRING' => '', 'REQUEST_URI' => '/index.php', 'URL' => '/index.php', 'SCRIPT_FILENAME' => 'C:\\Inetpub\\wwwroot\\index.php', 'ORIG_PATH_INFO' => '/index.php', 'PATH_INFO' => '', 'ORIG_PATH_TRANSLATED' => 'C:\\Inetpub\\wwwroot\\index.php', 'DOCUMENT_ROOT' => 'C:\\Inetpub\\wwwroot', 'PHP_SELF' => '/index.php', 'argv' => array(), 'argc' => 0), 'reload' => false, 'path' => '' ), 'No rewrite sub dir 1 with path' => array( 'GET' => array('/posts/add' => ''), - 'POST' => array(), 'SERVER' => array('QUERY_STRING' => '/posts/add', 'REQUEST_URI' => '/index.php?/posts/add', 'URL' => '/index.php?/posts/add', 'SCRIPT_FILENAME' => 'C:\\Inetpub\\wwwroot\\index.php', 'argv' => array('/posts/add'), 'argc' => 1), 'reload' => false, 'path' => '/posts/add' @@ -1036,7 +1066,6 @@ class DispatcherTest extends UnitTestCase { ), 'No rewrite sub dir 2 with path' => array( 'GET' => array('/posts/add' => ''), - 'POST' => array(), 'SERVER' => array('SCRIPT_NAME' => '/site/index.php', 'PATH_TRANSLATED' => 'C:\\Inetpub\\wwwroot', 'QUERY_STRING' => '/posts/add', 'REQUEST_URI' => '/site/index.php?/posts/add', 'URL' => '/site/index.php?/posts/add', 'ORIG_PATH_TRANSLATED' => 'C:\\Inetpub\\wwwroot\\site\\index.php', 'DOCUMENT_ROOT' => 'C:\\Inetpub\\wwwroot', 'PHP_SELF' => '/site/index.php', 'argv' => array('/posts/add'), 'argc' => 1), 'reload' => false, 'path' => '/posts/add' @@ -1045,15 +1074,11 @@ class DispatcherTest extends UnitTestCase { 'Apache' => array( 'No rewrite base path' => array( 'App' => array('base' => false, 'baseUrl' => '/index.php', 'dir' => 'app', 'webroot' => 'webroot'), - 'GET' => array(), - 'POST' => array(), 'SERVER' => array('SERVER_NAME' => 'localhost', 'SERVER_ADDR' => '::1', 'SERVER_PORT' => '80', 'REMOTE_ADDR' => '::1', 'DOCUMENT_ROOT' => '/Library/WebServer/Documents/officespace/app/webroot', 'SCRIPT_FILENAME' => '/Library/WebServer/Documents/site/app/webroot/index.php', 'REQUEST_METHOD' => 'GET', 'QUERY_STRING' => '', 'REQUEST_URI' => '/', 'SCRIPT_NAME' => '/index.php', 'PHP_SELF' => '/index.php', 'argv' => array(), 'argc' => 0), 'reload' => true, 'path' => '' ), 'No rewrite with path' => array( - 'GET' => array(), - 'POST' => array(), 'SERVER' => array('UNIQUE_ID' => 'VardGqn@17IAAAu7LY8AAAAK', 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-us) AppleWebKit/523.10.5 (KHTML, like Gecko) Version/3.0.4 Safari/523.10.6', 'HTTP_ACCEPT' => 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5', 'HTTP_ACCEPT_LANGUAGE' => 'en-us', 'HTTP_ACCEPT_ENCODING' => 'gzip, deflate', 'HTTP_CONNECTION' => 'keep-alive', 'HTTP_HOST' => 'localhost', 'DOCUMENT_ROOT' => '/Library/WebServer/Documents/officespace/app/webroot', 'SCRIPT_FILENAME' => '/Library/WebServer/Documents/officespace/app/webroot/index.php', 'QUERY_STRING' => '', 'REQUEST_URI' => '/index.php/posts/add', 'SCRIPT_NAME' => '/index.php', 'PATH_INFO' => '/posts/add', 'PHP_SELF' => '/index.php/posts/add', 'argv' => array(), 'argc' => 0), 'reload' => false, 'path' => '/posts/add' diff --git a/cake/tests/cases/libs/router.test.php b/cake/tests/cases/libs/router.test.php index 17c083f32..a763e5d6b 100644 --- a/cake/tests/cases/libs/router.test.php +++ b/cake/tests/cases/libs/router.test.php @@ -121,6 +121,17 @@ class RouterTest extends UnitTestCase { $_SERVER['REQUEST_METHOD'] = 'GET'; $result = $this->router->parse('/posts/add'); $this->assertEqual($result, array('pass' => array(), 'named' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'add')); + + $this->router->reload(); + $this->router->mapResources('Posts', array('id' => '[a-z0-9_]+')); + + $_SERVER['REQUEST_METHOD'] = 'GET'; + $result = $this->router->parse('/posts/add'); + $this->assertEqual($result, array('pass' => array(), 'named' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'view', 'id' => 'add', '[method]' => 'GET')); + + $_SERVER['REQUEST_METHOD'] = 'PUT'; + $result = $this->router->parse('/posts/name'); + $this->assertEqual($result, array('pass' => array(), 'named' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'edit', 'id' => 'name', '[method]' => 'PUT')); } function testUrlNormalization() {