diff options
-rw-r--r-- | core/config/routes.php | 3 | ||||
-rw-r--r-- | core/controllers/rest.php | 2 | ||||
-rw-r--r-- | core/helpers/MY_url.php | 2 | ||||
-rw-r--r-- | core/helpers/rest.php | 59 | ||||
-rw-r--r-- | core/libraries/MY_Forge.php | 21 | ||||
-rw-r--r-- | core/tests/Items_Controller_Test.php (renamed from core/tests/Item_Controller_Test.php) | 10 | ||||
-rw-r--r-- | core/tests/REST_Controller_Test.php | 128 | ||||
-rw-r--r-- | modules/comment/controllers/comments.php | 12 | ||||
-rw-r--r-- | modules/comment/helpers/comment.php | 2 | ||||
-rw-r--r-- | modules/user/tests/User_Installer_Test.php | 2 |
10 files changed, 222 insertions, 19 deletions
diff --git a/core/config/routes.php b/core/config/routes.php index 9e86def6..9e36f881 100644 --- a/core/config/routes.php +++ b/core/config/routes.php @@ -21,5 +21,8 @@ // The abstract REST_Controller is not directly routable. $config['^rest\b.*'] = null; +// Redirect /form/add and /form/edit to REST_Controller. +$config['^form/(edit|add)/(\w+)/(.*)$'] = '$2/form_$1/$3'; + // For now our default page is the scaffolding. $config['_default'] = 'welcome'; diff --git a/core/controllers/rest.php b/core/controllers/rest.php index 25f71299..f0fb5e5c 100644 --- a/core/controllers/rest.php +++ b/core/controllers/rest.php @@ -84,7 +84,7 @@ abstract class REST_Controller extends Controller { // @todo this needs security checks $id = $function; $resource = ORM::factory($this->resource_type, $id); - if (!$resource->loaded && $request_method == "post") { + if (!$resource->loaded && !$request_method == "post") { return Kohana::show_404(); } diff --git a/core/helpers/MY_url.php b/core/helpers/MY_url.php index bcdef4c5..a7746ff0 100644 --- a/core/helpers/MY_url.php +++ b/core/helpers/MY_url.php @@ -32,4 +32,4 @@ class url extends url_Core { public static function abs_site($path) { return url::site($path, "http"); } -}
\ No newline at end of file +} diff --git a/core/helpers/rest.php b/core/helpers/rest.php index 154ef6f6..dabff770 100644 --- a/core/helpers/rest.php +++ b/core/helpers/rest.php @@ -19,12 +19,41 @@ */ class REST_Core { + const OK = "200 OK"; + const CREATED = "201 Created"; + const ACCEPTED = "202 Accepted"; + const NO_CONTENT = "204 No Content"; + const PARTIAL_CONTENT = "206 Partial Content"; + const MOVED_PERMANENTLY = "301 Moved Permanently"; + const SEE_OTHER = "303 See Other"; + const NOT_MODIFIED = "304 Not Modified"; + const TEMPORARY_REDIRECT = "307 Temporary Redirect"; + const BAD_REQUEST = "400 Bad Request"; + const UNAUTHORIZED = "401 Unauthorized"; + const FORBIDDEN = "403 Forbidden"; + const NOT_FOUND = "404 Not Found"; + const METHOD_NOT_ALLOWED = "405 Method Not Allowed"; + const NOT_ACCEPTABLE = "406 Not Acceptable"; + const CONFLICT = "409 Conflict"; + const GONE = "410 Gone"; + const LENGTH_REQUIRED = "411 Length Required"; + const PRECONDITION_FAILED = "412 Precondition Failed"; + const UNSUPPORTED_MEDIA_TYPE = "415 Unsupported Media Type"; + const EXPECTATION_FAILED = "417 Expectation Failed"; + const INTERNAL_SERVER_ERROR = "500 Internal Server Error"; + const SERVICE_UNAVAILABLE = "503 Service Unavailable"; + + const XML = "application/xml"; + const ATOM = "application/atom+xml"; + const RSS = "application/rss+xml"; + const JSON = "application/json"; + const HTML = "text/html"; + /** * We're expecting to run in an environment that only supports GET/POST, so expect to tunnel * PUT and DELETE through POST. * * Returns the HTTP request method taking into consideration PUT/DELETE tunneling. - * @todo Move this to a MY_request helper? * @return string HTTP request method */ public static function request_method() { @@ -32,7 +61,7 @@ class REST_Core { return "get"; } else { $input = Input::instance(); - switch ($input->post("_method", $input->get("_method"))) { + switch (strtolower($input->post("_method", $input->get("_method")))) { case "put": return "put"; case "delete": return "delete"; default: return "post"; @@ -46,10 +75,34 @@ class REST_Core { */ public static function output_format() { // Pick a format, but let it be overridden. - $input = Input::instance(); + $input = Input::instance(); return $input->get( "_format", $input->post( "_format", request::preferred_accept( array("html", "xml", "json")))); } + + /** + * Set HTTP response code. + * @param string Use one of status code constants defined in this class. + */ + public static function http_status($status_code) { + header("HTTP 1.1 " . $status_code); + } + + /** + * Set HTTP Location header. + * @param string URL + */ + public static function http_location($url) { + header("Location: " . $url); + } + + /** + * Set HTTP Content-Type header. + * @param string content type + */ + public static function http_content_type($type) { + header("Content-Type: " . $type); + } } diff --git a/core/libraries/MY_Forge.php b/core/libraries/MY_Forge.php index 0aedac86..4840da1e 100644 --- a/core/libraries/MY_Forge.php +++ b/core/libraries/MY_Forge.php @@ -1,4 +1,23 @@ -<?php +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2008 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + class Forge extends Forge_Core { public function render($template="form.html", $custom=false) { return parent::render($template, $custom); diff --git a/core/tests/Item_Controller_Test.php b/core/tests/Items_Controller_Test.php index 114664d1..784177b5 100644 --- a/core/tests/Item_Controller_Test.php +++ b/core/tests/Items_Controller_Test.php @@ -17,26 +17,26 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -class Item_Controller_Test extends Unit_Test_Case { +class Items_Controller_Test extends Unit_Test_Case { public function change_item_test() { - $controller = new Item_Controller(); + $controller = new Items_Controller(); $album = album::create(1, "test", "test"); $_POST["title"] = "new title"; $_POST["description"] = "new description"; - $controller->_post($album); + $controller->_update($album); $this->assert_equal("new title", $album->title); $this->assert_equal("new description", $album->description); } public function change_item_test_with_return() { - $controller = new Item_Controller(); + $controller = new Items_Controller(); $album = album::create(1, "test", "test"); $_POST["title"] = "item_title"; $_POST["description"] = "item_description"; $_POST["__return"] = "item_description"; - $tihs->assert_equal("item_description", $controller->_post($album)); + $this->assert_equal("item_description", $controller->_post($album)); $this->assert_equal("item_title", $album->title); $this->assert_equal("item_description", $album->description); } diff --git a/core/tests/REST_Controller_Test.php b/core/tests/REST_Controller_Test.php new file mode 100644 index 00000000..5478aa70 --- /dev/null +++ b/core/tests/REST_Controller_Test.php @@ -0,0 +1,128 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2008 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +class REST_Controller_Test extends Unit_Test_Case { + public function dispatch_test() { + $mock_controller = new Mock_RESTful_Controller("mock"); + $mock_not_loaded_controller = new Mock_RESTful_Controller("mock_not_loaded"); + + /* index() */ + $_SERVER["REQUEST_METHOD"] = "GET"; + $_POST["_method"] = ""; + $mock_controller->__call("index", ""); + $this->assert_equal("index", $mock_controller->method_called); + + /* show() */ + $_SERVER["REQUEST_METHOD"] = "GET"; + $_POST["_method"] = ""; + $mock_controller->__call("3", ""); + $this->assert_equal("show", $mock_controller->method_called); + $this->assert_equal("Mock_Model", get_class($mock_controller->resource)); + + /* update() */ + $_SERVER["REQUEST_METHOD"] = "POST"; + $_POST["_method"] = "PUT"; + $mock_controller->__call("3", ""); + $this->assert_equal("update", $mock_controller->method_called); + $this->assert_equal("Mock_Model", get_class($mock_controller->resource)); + + /* delete */ + $_SERVER["REQUEST_METHOD"] = "POST"; + $_POST["_method"] = "DELETE"; + $mock_controller->__call("3", ""); + $this->assert_equal("delete", $mock_controller->method_called); + $this->assert_equal("Mock_Model", get_class($mock_controller->resource)); + + /* create */ + $_SERVER["REQUEST_METHOD"] = "POST"; + $_POST["_method"] = ""; + $mock_not_loaded_controller->__call("", ""); + $this->assert_equal("create", $mock_not_loaded_controller->method_called); + $this->assert_equal( + "Mock_Not_Loaded_Model", get_class($mock_not_loaded_controller->resource)); + + /* form_add */ + $mock_controller->form_add("args"); + $this->assert_equal("form_add", $mock_controller->method_called); + $this->assert_equal("args", $mock_controller->resource); + + /* form_edit */ + $mock_controller->form_edit("1"); + $this->assert_equal("form_edit", $mock_controller->method_called); + $this->assert_equal("Mock_Model", get_class($mock_controller->resource)); + } + + public function routes_test() { + $this->assert_equal("mock/form_add/args", router::routed_uri("form/add/mock/args")); + $this->assert_equal("mock/form_edit/args", router::routed_uri("form/edit/mock/args")); + $this->assert_equal(null, router::routed_uri("rest/args")); + } +} + +class Mock_RESTful_Controller extends REST_Controller { + public $method_called; + public $resource; + + public function __construct($type) { + $this->resource_type = $type; + parent::__construct(); + } + + public function _index() { + $this->method_called = "index"; + } + + public function _create($resource) { + $this->method_called = "create"; + $this->resource = $resource; + } + + public function _show($resource) { + $this->method_called = "show"; + $this->resource = $resource; + } + + public function _update($resource) { + $this->method_called = "update"; + $this->resource = $resource; + } + + public function _delete($resource) { + $this->method_called = "delete"; + $this->resource = $resource; + } + + public function _form_add($args) { + $this->method_called = "form_add"; + $this->resource = $args; + } + + public function _form_edit($resource) { + $this->method_called = "form_edit"; + $this->resource = $resource; + } +} + +class Mock_Model { + public $loaded = true; +} + +class Mock_Not_Loaded_Model { + public $loaded = false; +} diff --git a/modules/comment/controllers/comments.php b/modules/comment/controllers/comments.php index 11a9c2a1..511a8eda 100644 --- a/modules/comment/controllers/comments.php +++ b/modules/comment/controllers/comments.php @@ -29,7 +29,7 @@ class Comments_Controller extends REST_Controller { if (empty($item_id)) { /* We currently do not support getting all comments from the entire gallery. */ - header("HTTP/1.1 400 Bad Request"); + rest::http_status(rest::BAD_REQUEST); return; } print comment::get_comments($item_id); @@ -49,8 +49,8 @@ class Comments_Controller extends REST_Controller { $comment->item_id = $this->input->post('item_id'); $comment->save(); - header("HTTP/1.1 201 Created"); - header("Location: " . url::site("comments/{$comment->id}")); + rest::http_status(rest::CREATED); + rest::http_location(url::site("comments/{$comment->id}")); } // @todo Return appropriate HTTP status code indicating error. print $form; @@ -65,12 +65,12 @@ class Comments_Controller extends REST_Controller { $output_format = rest::output_format(); switch ($output_format) { case "xml": - header("Content-Type: application/xml"); + rest::http_content_type(rest::XML); print xml::to_xml($comment->as_array(), array("comment")); break; case "json": - header("Content-Type: application/json"); + rest::http_content_type(rest::JSON); print json_encode($comment->as_array()); break; @@ -103,7 +103,7 @@ class Comments_Controller extends REST_Controller { * @see Rest_Controller::_delete($resource) */ public function _delete($comment) { - throw new Exception("@todo Comment_Controller::_delete NOT IMPLEMENTED"); + rest::http_status(rest::METHOD_NOT_ALLOWED); } /** diff --git a/modules/comment/helpers/comment.php b/modules/comment/helpers/comment.php index 1739497c..2d25df3f 100644 --- a/modules/comment/helpers/comment.php +++ b/modules/comment/helpers/comment.php @@ -112,7 +112,7 @@ class Comment_Core { ->find_all(); if (!$comments->count()) { - header("HTTP/1.1 400 Bad Request"); + rest::http_status(rest::BAD_REQUEST); return; } diff --git a/modules/user/tests/User_Installer_Test.php b/modules/user/tests/User_Installer_Test.php index c7b6afbe..e3c6c7d6 100644 --- a/modules/user/tests/User_Installer_Test.php +++ b/modules/user/tests/User_Installer_Test.php @@ -48,7 +48,7 @@ class User_Installer_Test extends Unit_Test_Case { $this->assert_equal("registered", $group->name); $this->assert_equal( - array("admin"), + array("admin", "joe"), array_keys($group->users->select_list("name"))); } } |