summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/gallery/helpers/gallery_rest.php299
-rw-r--r--modules/gallery/helpers/item.php16
-rw-r--r--modules/gallery/libraries/ORM_MPTT.php20
-rw-r--r--modules/gallery/tests/Gallery_Rest_Helper_Test.php3
-rw-r--r--modules/image_block/helpers/image_block_block.php24
-rw-r--r--modules/image_block/helpers/image_block_rest.php62
-rw-r--r--modules/kohana23_compat/libraries/MY_Database_Builder.php12
-rw-r--r--modules/rest/controllers/rest.php60
-rw-r--r--modules/rest/helpers/rest.php104
-rw-r--r--modules/rest/libraries/Rest_Exception.php17
-rw-r--r--modules/rest/tests/Rest_Controller_Test.php20
-rw-r--r--modules/tag/helpers/tag.php2
-rw-r--r--modules/tag/helpers/tag_rest.php161
-rw-r--r--modules/tag/helpers/tags_rest.php48
-rw-r--r--modules/tag/tests/Tag_Rest_Helper_Test.php12
15 files changed, 328 insertions, 532 deletions
diff --git a/modules/gallery/helpers/gallery_rest.php b/modules/gallery/helpers/gallery_rest.php
index a87ebb4e..0de5da2b 100644
--- a/modules/gallery/helpers/gallery_rest.php
+++ b/modules/gallery/helpers/gallery_rest.php
@@ -17,232 +17,139 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class gallery_rest_Core {
- static function get($request) {
- $path = implode("/", $request->arguments);
-
- $item = gallery_rest::_get_item($path);
-
- $parent = $item->parent();
- $response_data = array("type" => $item->type,
- "name" => $item->name,
- "path" => $item->relative_url(),
- "parent_path" => empty($parent) ? null : $parent->relative_url(),
- "title" => $item->title,
- "thumb_url" => $item->thumb_url(true),
- "thumb_size" => array("height" => $item->thumb_height,
- "width" => $item->thumb_width),
- "resize_url" => $item->resize_url(true),
- "resize_size" => array("height" => (int)$item->resize_height,
- "width" => (int)$item->resize_width),
- "url" => $item->file_url(true),
- "size" => array("height" => $item->height,
- "width" => $item->width),
- "description" => $item->description,
- "slug" => $item->slug);
-
- $children = self::_get_children($item, $request);
- if (!empty($children) || $item->is_album()) {
- $response_data["children"] = $children;
- }
- return rest::success(array("resource" => $response_data));
- }
- static function put($request) {
- if (empty($request->arguments)) {
- throw new Rest_Exception(400, "Bad request");
- }
- $path = implode("/", $request->arguments);
- $item = gallery_rest::_get_item($path, "edit");
-
- // Validate the request data
- $new_values = gallery_rest::_validate($request, $item->parent_id, $item->id);
- $errors = $new_values->errors();
- if (empty($errors)) {
- $item->title = $new_values->title;
- $item->description = $new_values->description;
- if ($item->id != 1) {
- $item->rename($new_values->name);
- }
- $item->slug = $new_values->slug;
- $item->save();
+// @todo Add logging
+// @todo VALIDATION
+
+// Validation questions
+//
+// We need to be able to properly validate anything we want to enter here. But all of our
+// validation currently happens at the controller / form level, and we're not using the same
+// controllers or forms.
+//
+// Possible solutions:
+// 1) Move validation into the model and use it both here and in the regular controllers. But
+// if we do that, how do we translate validation failures into a user-consumable output which
+// we need so that we can return proper error responses to form submissions?
+//
+// 2) Create some kind of validation helper that can validate every field. Wait, isn't this
+// just like #1 except in a helper instead of in the model?
- log::success("content", "Updated $item->type",
- "<a href=\"{$item->type}s/$item->id\">view</a>");
+class gallery_rest_Core {
- return rest::success();
- } else {
- return rest::validation_error($errors);
- }
- }
+ /**
+ * For items that are collections, you can specify the following additional query parameters to
+ * query the collection. You can specify them in any combination.
+ *
+ * scope=direct
+ * only return items that are immediately under this one
+ * scope=all
+ * return items anywhere under this one
+ *
+ * name=<substring>
+ * only return items where the name contains this substring
+ *
+ * random=true
+ * return a single random item
+ *
+ * type=<comma separate list of photo, movie or album>
+ * limit the type to types in this list. eg, "type=photo,movie"
+ */
+ static function get($request) {
+ $item = rest::resolve($request->url);
+ access::required("view", $item);
- static function post($request) {
- if (empty($request->arguments)) {
- throw new Rest_Exception(400, "Bad request");
+ $p = $request->params;
+ if (isset($p->random)) {
+ $orm = item::random_query()->offset(0)->limit(1);
+ } else {
+ $orm = ORM::factory("item")->viewable();
}
- $components = $request->arguments;
- $name = urldecode(array_pop($components));
-
- $parent = gallery_rest::_get_item(implode("/", $components), "edit");
-
- // Validate the request data
- $request->name = $name;
- $new_values = gallery_rest::_validate($request, $parent->id);
- $errors = $new_values->errors();
- if (!empty($errors)) {
- return rest::validation_error($errors);
+ if (!empty($p->scope) && !in_array($p->scope, array("direct", "all"))) {
+ throw new Exception("Bad Request", 400);
}
-
- if (empty($new_values["image"])) {
- $new_item = album::create(
- $parent,
- $name,
- empty($new_values["title"]) ? $name : $new_values["title"],
- empty($new_values["description"]) ? null : $new_values["description"],
- identity::active_user()->id,
- empty($new_values["slug"]) ? $name : $new_values["slug"]);
- $log_message = t("Added an album");
- } else {
- $temp_filename = upload::save("image");
- $path_info = @pathinfo($temp_filename);
- if (array_key_exists("extension", $path_info) &&
- in_array(strtolower($path_info["extension"]), array("flv", "mp4"))) {
- $new_item =
- movie::create($parent, $temp_filename, $new_values["name"], $new_values["title"]);
- $log_message = t("Added a movie");
+ if (!empty($p->scope)) {
+ if ($p->scope == "direct") {
+ $orm->where("parent_id", "=", $item->id);
} else {
- $new_item =
- photo::create($parent, $temp_filename, $new_values["name"], $new_values["title"]);
- $log_message = t("Added a photo");
+ $orm->where("left_ptr", ">=", $item->left_ptr);
+ $orm->where("right_ptr", "<=", $item->left_ptr);
+ $orm->where("id", "<>", $item->id);
}
}
- log::success("content", $log_message, "<a href=\"{$new_item->type}s/$new_item->id\">view</a>");
-
- return rest::success(array("path" => $new_item->relative_url()));
- }
-
- static function delete($request) {
- if (empty($request->arguments)) {
- throw new Rest_Exception(400, "Bad request");
+ if (isset($p->name)) {
+ $orm->where("name", "LIKE", "%{$p->name}%");
}
- $path = implode("/", $request->arguments);
-
- $item = gallery_rest::_get_item($path, "edit");
- if ($item->id == 1) {
- throw new Rest_Exception(400, "Bad request");
+ if (isset($p->type)) {
+ $orm->where("type", "IN", explode(",", $p->type));
}
- $parent = $item->parent();
- $item->delete();
-
- if ($item->is_album()) {
- $msg = t("Deleted album <b>%title</b>", array("title" => html::purify($item->title)));
- } else {
- $msg = t("Deleted photo <b>%title</b>", array("title" => html::purify($item->title)));
+ $members = array();
+ foreach ($orm->find_all() as $child) {
+ $members[] = url::abs_site("rest/gallery/" . $child->relative_url());
}
- log::success("content", $msg);
- return rest::success(array("resource" => array("parent_path" => $parent->relative_url())));
+ return rest::reply(array("resource" => $item->as_array(), "members" => $members));
}
- private static function _get_item($path, $permission="view") {
- $item = url::get_item_from_uri($path);
-
- if (!$item->loaded()) {
- throw new Kohana_404_Exception();
- }
-
- if (!access::can($permission, $item)) {
- throw new Kohana_404_Exception();
+ static function put($request) {
+ $item = rest::resolve($request->url);
+ access::required("edit", $item);
+
+ $params = $request->params;
+ foreach (array("captured", "description", "slug", "sort_column", "sort_order",
+ "title", "view_count", "weight") as $key) {
+ if (isset($params->$key)) {
+ $item->$key = $params->$key;
+ }
}
+ $item->save();
- return $item;
+ return rest::reply(array("url" => url::abs_site("/rest/gallery/" . $item->relative_url())));
}
- private static function _get_children($item, $request) {
- $children = array();
- $limit = empty($request->limit) ? null : $request->limit;
- $offset = empty($request->offset) ? null : $request->offset;
- $where = empty($request->filter) ? array() : array("type" => $request->filter);
- foreach ($item->viewable()->children($limit, $offset, $where) as $child) {
- $children[] = array("type" => $child->type,
- "has_children" => $child->children_count() > 0,
- "path" => $child->relative_url(),
- "thumb_url" => $child->thumb_url(true),
- "thumb_dimensions" => array("width" => $child->thumb_width,
- "height" => $child->thumb_height),
- "has_thumb" => $child->has_thumb(),
- "title" => $child->title);
- }
-
- return $children;
- }
+ static function post($request) {
+ $parent = rest::resolve($request->url);
+ access::required("edit", $parent);
- private static function _validate($request, $parent_id, $item_id=0) {
- $item = ORM::factory("item", $item_id);
+ $params = $request->params;
+ switch ($params->type) {
+ case "album":
+ $item = album::create(
+ $parent,
+ $params->name,
+ isset($params->title) ? $params->title : $name,
+ isset($params->description) ? $params->description : null);
+ break;
- // Normalize the inputs so all fields have a value
- $new_values = Validation::factory(array());
- foreach ($item->form_rules as $field => $rule_set) {
- if (isset($request->$field)) {
- $new_values[$field] = $request->$field;
- } else if (isset($item->$field)) {
- $new_values[$field] = $item->$field;
- }
- foreach (explode("|", $rule_set) as $rule) {
- $new_values->add_rules($field, $rule);
- }
- }
- $name = $new_values["name"];
- $new_values["title"] = empty($new_values["title"]) ? $name : $new_values["title"];
- $new_values["description"] =
- empty($new_values["description"]) ? null : $new_values["description"];
- $new_values["slug"] = empty($new_values["slug"]) ? $name : $new_values["slug"];
-
- if (!empty($request->image)) {
- $new_values["image"] = $request->image;
- $new_values->add_rules(
- "image", "upload::valid", "upload::required", "upload::type[gif,jpg,jpeg,png,flv,mp4]");
- }
+ case "photo":
+ $item = photo::create(
+ $parent,
+ $request->file,
+ $params->name,
+ isset($params->title) ? $params->title : $name,
+ isset($params->description) ? $params->description : null);
+ break;
- if ($new_values->validate() && $item_id != 1) {
- $errors = gallery_rest::_check_for_conflicts($parent_id, $item_id,
- $new_values["name"], $new_values["slug"]);
- if (!empty($errors)) {
- !empty($errors["name_conflict"]) OR $new_values->add_error("name", "Duplicate name");
- !empty($errors["slug_conflict"]) OR
- $new_values->add_error("slug", "Duplicate Internet address");
- }
+ default:
+ throw new Rest_Exception("Invalid type: $args->type", 400);
}
- return $new_values;
+ return rest::reply(array("url" => url::abs_site("/rest/gallery/" . $item->relative_url())));
}
- private static function _check_for_conflicts($parent_id, $item_id, $new_name, $new_slug) {
- $errors = array();
-
- if ($row = db::build()
- ->select(array("name", "slug"))
- ->from("items")
- ->where("parent_id", "=", $parent_id)
- ->where("id", "<>", $item_id)
- ->and_open()
- ->where("name", "=", $new_name)
- ->or_where("slug", "=", $new_slug)
- ->close()
- ->execute()
- ->current()) {
- if ($row->name == $new_name) {
- $errors["name_conflict"] = 1;
- }
- if ($row->slug == $new_slug) {
- $errors["slug_conflict"] = 1;
- }
- }
+ static function delete($request) {
+ $item = rest::resolve($request->url);
+ access::required("edit", $item);
+
+ $item->delete();
+ return rest::reply();
+ }
- return $errors;
+ static function resolve($path) {
+ return url::get_item_from_uri($path);
}
}
diff --git a/modules/gallery/helpers/item.php b/modules/gallery/helpers/item.php
index f6181f8a..1fd9ef16 100644
--- a/modules/gallery/helpers/item.php
+++ b/modules/gallery/helpers/item.php
@@ -173,4 +173,20 @@ class item_Core {
static function root() {
return model_cache::get("item", 1);
}
+
+ /**
+ * Return a query to get a random Item_Model, with optional filters
+ *
+ * @param array (optional) where tuple
+ */
+ static function random_query($where=null) {
+ // Pick a random number and find the item that's got nearest smaller number.
+ // This approach works best when the random numbers in the system are roughly evenly
+ // distributed so this is going to be more efficient with larger data sets.
+ return ORM::factory("item")
+ ->viewable()
+ ->where("rand_key", "<", ((float)mt_rand()) / (float)mt_getrandmax())
+ ->merge_where($where)
+ ->order_by("rand_key", "DESC");
+ }
} \ No newline at end of file
diff --git a/modules/gallery/libraries/ORM_MPTT.php b/modules/gallery/libraries/ORM_MPTT.php
index 0ea519c9..ed77cac9 100644
--- a/modules/gallery/libraries/ORM_MPTT.php
+++ b/modules/gallery/libraries/ORM_MPTT.php
@@ -165,11 +165,8 @@ class ORM_MPTT_Core extends ORM {
* @return array ORM
*/
function children($limit=null, $offset=null, $where=null, $order_by=array("id" => "ASC")) {
- if ($where) {
- $this->merge_where($where);
- }
-
return $this
+ ->merge_where($where)
->where("parent_id", "=", $this->id)
->order_by($order_by)
->find_all($limit, $offset);
@@ -183,11 +180,8 @@ class ORM_MPTT_Core extends ORM {
* @return array ORM
*/
function children_count($where=null) {
- if ($where) {
- $this->merge_where($where);
- }
-
return $this
+ ->merge_where($where)
->where("parent_id", "=", $this->id)
->count_all();
}
@@ -202,11 +196,8 @@ class ORM_MPTT_Core extends ORM {
* @return object ORM_Iterator
*/
function descendants($limit=null, $offset=null, $where=null, $order_by=array("id" => "ASC")) {
- if ($where) {
- $this->merge_where($where);
- }
-
return $this
+ ->merge_where($where)
->where("left_ptr", ">", $this->left_ptr)
->where("right_ptr", "<=", $this->right_ptr)
->order_by($order_by)
@@ -220,11 +211,8 @@ class ORM_MPTT_Core extends ORM {
* @return integer child count
*/
function descendants_count($where=null) {
- if ($where) {
- $this->merge_where($where);
- }
-
return $this
+ ->merge_where($where)
->where("left_ptr", ">", $this->left_ptr)
->where("right_ptr", "<=", $this->right_ptr)
->count_all();
diff --git a/modules/gallery/tests/Gallery_Rest_Helper_Test.php b/modules/gallery/tests/Gallery_Rest_Helper_Test.php
index cd0aabae..c5c8a890 100644
--- a/modules/gallery/tests/Gallery_Rest_Helper_Test.php
+++ b/modules/gallery/tests/Gallery_Rest_Helper_Test.php
@@ -136,7 +136,8 @@ class Gallery_Rest_Helper_Test extends Unit_Test_Case {
try {
gallery_rest::put($request);
} catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
+ $this->assert_equal("Bad request", $e->getMessage());
+ $this->assert_equal(400, $e->getCode());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
diff --git a/modules/image_block/helpers/image_block_block.php b/modules/image_block/helpers/image_block_block.php
index f591e8d1..f28e775f 100644
--- a/modules/image_block/helpers/image_block_block.php
+++ b/modules/image_block/helpers/image_block_block.php
@@ -30,29 +30,9 @@ class image_block_block_Core {
$block->css_id = "g-image-block";
$block->title = t("Random image");
$block->content = new View("image_block_block.html");
+ $block->content->items = item::random_query(array(array("type", "!=", "album")))->find_all(1);
- $random = ((float)mt_rand()) / (float)mt_getrandmax();
-
- $items = ORM::factory("item")
- ->viewable()
- ->where("type", "!=", "album")
- ->where("rand_key", "<", $random)
- ->order_by(array("rand_key" => "DESC"))
- ->find_all(1);
-
- if ($items->count() == 0) {
- // Try once more. If this fails, just ditch the block altogether
- $items = ORM::factory("item")
- ->viewable()
- ->where("type", "!=", "album")
- ->where("rand_key", ">=", $random)
- ->order_by(array("rand_key" => "DESC"))
- ->find_all(1);
- }
-
- if ($items->count() > 0) {
- $block->content->item = $items->current();
- } else {
+ if ($block->content->items->count() == 0) {
$block = "";
}
break;
diff --git a/modules/image_block/helpers/image_block_rest.php b/modules/image_block/helpers/image_block_rest.php
deleted file mode 100644
index 7afd974c..00000000
--- a/modules/image_block/helpers/image_block_rest.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php defined("SYSPATH") or die("No direct script access.");
-/**
- * Gallery - a web based photo album viewer and editor
- * Copyright (C) 2000-2009 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 image_block_rest_Core {
- static function get($request) {
- $type = empty($request->type) ? "random" : $request->type;
- switch ($type) {
- case "random":
- $random = ((float)mt_rand()) / (float)mt_getrandmax();
-
- $items = ORM::factory("item")
- ->viewable()
- ->where("type", "!=", "album")
- ->where("rand_key", "<", $random)
- ->order_by(array("rand_key" => "DESC"))
- ->find_all(1);
-
- if ($items->count() == 0) {
- // Try once more. If this fails, just ditch the block altogether
- $items = ORM::factory("item")
- ->viewable()
- ->where("type", "!=", "album")
- ->where("rand_key", ">= ", $random)
- ->order_by(array("rand_key" => "DESC"))
- ->find_all(1);
- }
- break;
- default:
- return rest::fail("Unsupported image block type: '{$type}'");
- }
-
- if ($items->count() > 0) {
- $item = $items->current();
- $response_data = array("name" => $item->name,
- "path" => $item->relative_url(),
- "title" => $item->title,
- "thumb_url" => $item->thumb_url(true),
- "thumb_size" => array("height" => $item->thumb_height,
- "width" => $item->thumb_width));
-
- return rest::success(array("resource" => $response_data));
- } else {
- return rest::fail("No Image found");
- }
- }
-}
diff --git a/modules/kohana23_compat/libraries/MY_Database_Builder.php b/modules/kohana23_compat/libraries/MY_Database_Builder.php
index c82b6ac4..b2a5c92a 100644
--- a/modules/kohana23_compat/libraries/MY_Database_Builder.php
+++ b/modules/kohana23_compat/libraries/MY_Database_Builder.php
@@ -23,8 +23,10 @@ class Database_Builder extends Database_Builder_Core {
* @chainable
*/
public function merge_where($tuples) {
- foreach ($tuples as $tuple) {
- $this->where($tuple[0], $tuple[1], $tuple[2]);
+ if ($tuples) {
+ foreach ($tuples as $tuple) {
+ $this->where($tuple[0], $tuple[1], $tuple[2]);
+ }
}
return $this;
}
@@ -34,8 +36,10 @@ class Database_Builder extends Database_Builder_Core {
* @chainable
*/
public function merge_or_where($tuples) {
- foreach ($tuples as $tuple) {
- $this->or_where($tuple[0], $tuple[1], $tuple[2]);
+ if ($tuples) {
+ foreach ($tuples as $tuple) {
+ $this->or_where($tuple[0], $tuple[1], $tuple[2]);
+ }
}
return $this;
}
diff --git a/modules/rest/controllers/rest.php b/modules/rest/controllers/rest.php
index 26e5b31a..5ef9eb84 100644
--- a/modules/rest/controllers/rest.php
+++ b/modules/rest/controllers/rest.php
@@ -18,20 +18,14 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class Rest_Controller extends Controller {
- public function access_key() {
+ public function index() {
try {
- $request = (object)Input::instance()->get();
- if (empty($request->user) || empty($request->password)) {
- throw new Rest_Exception(403, "Forbidden");
- }
-
- $user = identity::lookup_user_by_name($request->user);
- if (empty($user)) {
- throw new Rest_Exception(403, "Forbidden");
- }
+ $username = Input::instance()->post("user");
+ $password = Input::instance()->post("password");
- if (!identity::is_correct_password($user, $request->password)) {
- throw new Rest_Exception(403, "Forbidden");
+ $user = identity::lookup_user_by_name($username);
+ if (empty($user) || !identity::is_correct_password($user, $password)) {
+ throw new Rest_Exception("Forbidden", 403);
}
$key = ORM::factory("user_access_token")
@@ -42,27 +36,45 @@ class Rest_Controller extends Controller {
$key->access_key = md5($user->name . rand());
$key->save();
}
- print rest::success(array("token" => $key->access_key));
- } catch (Rest_Exception $e) {
- $e->sendHeaders();
+
+ rest::reply($key->access_key);
+ } catch (Exception $e) {
+ rest::send_headers($e);
}
}
public function __call($function, $args) {
- $request = rest::normalize_request($args);
+ $input = Input::instance();
+ switch ($method = strtolower($input->server("REQUEST_METHOD"))) {
+ case "get":
+ $request->params = (object) Input::instance()->get();
+ break;
+
+ case "post":
+ $request->params = (object) Input::instance()->post();
+ if (isset($_FILES["file"])) {
+ $request->file = upload::save("file");
+ }
+ break;
+ }
+
+ $request->method = strtolower($input->server("HTTP_X_GALLERY_REQUEST_METHOD", $method));
+ $request->access_token = $input->server("HTTP_X_GALLERY_REQUEST_KEY");
+ $request->url = url::abs_current(true);
+
try {
- if (rest::set_active_user($request->access_token)) {
- $handler_class = "{$function}_rest";
- $handler_method = $request->method;
+ rest::set_active_user($request->access_token);
- if (!method_exists($handler_class, $handler_method)) {
- throw new Rest_Exception(403, "Forbidden");
- }
+ $handler_class = "{$function}_rest";
+ $handler_method = $request->method;
- print call_user_func(array($handler_class, $handler_method), $request);
+ if (!method_exists($handler_class, $handler_method)) {
+ throw new Rest_Exception("Forbidden", 403);
}
+
+ print call_user_func(array($handler_class, $handler_method), $request);
} catch (Rest_Exception $e) {
- $e->sendHeaders();
+ rest::send_headers($e);
}
}
} \ No newline at end of file
diff --git a/modules/rest/helpers/rest.php b/modules/rest/helpers/rest.php
index be0644f2..121191f2 100644
--- a/modules/rest/helpers/rest.php
+++ b/modules/rest/helpers/rest.php
@@ -18,87 +18,57 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class rest_Core {
- /**
- * Request failed
- */
- static function fail($log_message=null) {
- if (!empty($log_message)) {
- Kohana_Log::add("info", $log_message);
- }
- // We don't need to save the session for this request
+ static function reply($data=array()) {
Session::abort_save();
- return json_encode(array("status" => "ERROR", "message" => (string)$message));
- }
- /**
- * Success
- */
- static function success($response_data=array(), $message=null) {
- $response = array("status" => "OK");
- if (!empty($message)) {
- $response["message"] = (string)$message;
+ if ($data) {
+ print json_encode($data);
}
- $response = array_merge($response, $response_data);
-
- // We don't need to save the session for this request
- Session::abort_save();
- return json_encode($response);
}
- /**
- * Validation Error
- */
- static function validation_error($error_data) {
- $response = array("status" => "VALIDATE_ERROR");
- $response = array_merge($response, array("fields" => $error_data));
-
- // We don't need to save the session for this request
- Session::abort_save();
- return json_encode($response);
- }
+ static function set_active_user($access_token) {
+ if (empty($access_token)) {
+ identity::set_active_user(identity::guest());
+ return;
+ }
+ $key = ORM::factory("user_access_token")
+ ->where("access_key", "=", $access_token)
+ ->find();
- static function normalize_request($args=array()) {
- $input = Input::instance();
- $method = strtolower($input->server("REQUEST_METHOD"));
- $request = new stdClass();
- foreach (array_keys($input->get()) as $key) {
- $request->$key = $input->get($key);
+ if (!$key->loaded()) {
+ throw new Rest_Exception("Forbidden", 403);
}
- if ($method != "get") {
- foreach (array_keys($input->post()) as $key) {
- $request->$key = $input->post($key);
- }
- foreach (array_keys($_FILES) as $key) {
- $request->$key = $_FILES[$key];
- }
+
+ $user = identity::lookup_user($key->user_id);
+ if (empty($user)) {
+ throw new Rest_Exception("Forbidden", 403);
}
- $request->method = strtolower($input->server("HTTP_X_GALLERY_REQUEST_METHOD", $method));
- $request->access_token = $input->server("HTTP_X_GALLERY_REQUEST_KEY");
- $request->arguments = $args; // Let the rest handler figure out what the arguments mean
+ identity::set_active_user($user);
+ }
- return $request;
+ static function send_headers($exception) {
+ header("HTTP/1.1 " . $exception->getCode() . " " . $exception->getMessage());
}
- static function set_active_user($access_token) {
- if (empty($access_token)) {
- $user = identity::guest();
- } else {
- $key = ORM::factory("user_access_token")
- ->where("access_key", "=", $access_token)
- ->find();
+ /**
+ * Convert a REST url into an object.
+ * Eg: "http://example.com/gallery3/index.php/rest/gallery/Family/Wedding" -> Item_Model
+ *
+ * @param string the fully qualified REST url
+ * @return mixed the corresponding object (usually a model of some kind)
+ */
+ static function resolve($url) {
+ $relative_url = substr($url, strlen(url::abs_site("rest")));
+ $path = parse_url($relative_url, PHP_URL_PATH);
+ $components = explode("/", $path, 3);
- if ($key->loaded()) {
- $user = identity::lookup_user($key->user_id);
- if (empty($user)) {
- throw new Rest_Exception(403, "Forbidden");
- }
- } else {
- throw new Rest_Exception(403, "Forbidden");
- }
+ $class = "$components[1]_rest";
+ if (!method_exists($class, "resolve")) {
+ throw new Kohana_404_Exception($url);
}
- identity::set_active_user($user);
- return true;
+
+ return call_user_func(array($class, "resolve"), !empty($components[2]) ? $components[2] : null);
}
}
diff --git a/modules/rest/libraries/Rest_Exception.php b/modules/rest/libraries/Rest_Exception.php
index 905b94a0..596b3712 100644
--- a/modules/rest/libraries/Rest_Exception.php
+++ b/modules/rest/libraries/Rest_Exception.php
@@ -18,19 +18,4 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class Rest_Exception_Core extends Exception {
- /**
- * Set internal properties.
- */
- public function __construct($code, $text) {
- parent::__construct("$code $text");
- }
-
- /**
- * Sends the headers, to emulate server behavior.
- *
- * @return void
- */
- public function sendHeaders() {
- header('HTTP/1.1 {$this->getMessage()}');
- }
-} // End Rest Exception \ No newline at end of file
+} \ No newline at end of file
diff --git a/modules/rest/tests/Rest_Controller_Test.php b/modules/rest/tests/Rest_Controller_Test.php
index 83bd9db6..c881583c 100644
--- a/modules/rest/tests/Rest_Controller_Test.php
+++ b/modules/rest/tests/Rest_Controller_Test.php
@@ -84,7 +84,8 @@ class Rest_Controller_Test extends Unit_Test_Case {
try {
$this->_call_controller();
} catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
+ $this->assert_equal(403, $e->getCode());
+ $this->assert_equal("Forbidden", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -97,7 +98,8 @@ class Rest_Controller_Test extends Unit_Test_Case {
try {
$this->_call_controller();
} catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
+ $this->assert_equal(403, $e->getCode());
+ $this->assert_equal("Forbidden", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -109,7 +111,8 @@ class Rest_Controller_Test extends Unit_Test_Case {
try {
$this->_call_controller();
} catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
+ $this->assert_equal(403, $e->getCode());
+ $this->assert_equal("Forbidden", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -137,7 +140,8 @@ class Rest_Controller_Test extends Unit_Test_Case {
try {
$this->_call_controller();
} catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
+ $this->assert_equal(403, $e->getCode());
+ $this->assert_equal("Forbidden", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -155,7 +159,8 @@ class Rest_Controller_Test extends Unit_Test_Case {
try {
$this->_call_controller("rest", explode("/", $photo->relative_url()));
} catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
+ $this->assert_equal(403, $e->getCode());
+ $this->assert_equal("Forbidden", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -171,7 +176,8 @@ class Rest_Controller_Test extends Unit_Test_Case {
try {
$this->_call_controller("rest", explode("/", $photo->relative_url()));
} catch (Rest_Exception $e) {
- $this->assert_equal("501 Not Implemented", $e->getMessage());
+ $this->assert_equal(501, $e->getCode());
+ $this->assert_equal("Not Implemented", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -218,7 +224,7 @@ class rest_rest {
$response["thumb_url"] = $item->thumb_url();
$response["description"] = $item->description;
$response["internet_address"] = $item->slug;
- return rest::success(array($item->type => $response), t("Processed"));
+ return rest::reply(array($item->type => $response));
}
}
diff --git a/modules/tag/helpers/tag.php b/modules/tag/helpers/tag.php
index 8075afe4..d895e08f 100644
--- a/modules/tag/helpers/tag.php
+++ b/modules/tag/helpers/tag.php
@@ -41,7 +41,7 @@ class tag_Core {
}
if (!$tag->has($item)) {
- if (!$tag->add($item, $tag)) {
+ if (!$tag->add($item)) {
throw new Exception("@todo {$tag->name} WAS_NOT_ADDED_TO {$item->id}");
}
$tag->count++;
diff --git a/modules/tag/helpers/tag_rest.php b/modules/tag/helpers/tag_rest.php
index cd1ca6c6..c1bbf4fb 100644
--- a/modules/tag/helpers/tag_rest.php
+++ b/modules/tag/helpers/tag_rest.php
@@ -18,143 +18,80 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class tag_rest_Core {
- // If no arguments just return all the tags. If 2 or more then it is a path then
- // return the tags for that item. But if its only 1, then is it a path or a tag?
- // Assume a tag first, if nothing is found then try finding the item.
static function get($request) {
- $resources = array();
- switch (count($request->arguments)) {
- case 0:
- $tags = ORM::factory("tag")
- ->select("name", "count")
- ->order_by("count", "DESC");
- if (!empty($request->limit)) {
- $tags->limit($request->limit);
- }
- if (!empty($request->offset)) {
- $tags->offset($request->offset);
- }
- $resources = array("tags" => array());
- foreach ($tags->find_all() as $row) {
- $resources["tags"][] = array("name" => $row->name, "count" => $row->count);
- }
- break;
- case 1:
- $resources = tag_rest::_get_items($request);
- if (!empty($resources)) {
- $resources = array("resources" => $resources);
- break;
- }
- default:
- $item = ORM::factory("item")
- ->where("relative_url_cache", "=", implode("/", $request->arguments))
- ->viewable()
- ->find();
- if ($item->loaded()) {
- $resources = array("tags" => tag::item_tags($item));
- }
+ $tag = rest::resolve($request->url);
+ $items = array();
+ foreach ($tag->items() as $item) {
+ $items[] = url::abs_site("rest/gallery/" . $item->relative_url());
}
- return rest::success($resources);
+ return rest::reply(array("resource" => $tag->as_array(), "members" => $items));
}
static function post($request) {
- if (empty($request->arguments) || count($request->arguments) != 1 || empty($request->path)) {
- throw new Rest_Exception(400, "Bad request");
+ if (empty($request->params->url)) {
+ throw new Rest_Exception("Bad request", 400);
}
- $path = $request->path;
- $tags = explode(",", $request->arguments[0]);
- $item = ORM::factory("item")
- ->where("relative_url_cache", "=", $path)
- ->viewable()
- ->find();
- if (!$item->loaded()) {
- throw new Kohana_404_Exception();
- }
+ $tag = rest::resolve($request->url);
+ $item = rest::resolve($request->params->url);
+ access::required("edit", $item);
- if (!access::can("edit", $item)) {
- throw new Kohana_404_Exception();
- }
-
- foreach ($tags as $tag) {
- tag::add($item, $tag);
- }
- return rest::success();
+ tag::add($item, $tag->name);
+ return rest::reply(array("url" => url::abs_site("rest/tag/" . rawurlencode($tag->name))));
}
static function put($request) {
- if (empty($request->arguments[0]) || empty($request->new_name)) {
- throw new Rest_Exception(400, "Bad request");
- }
+ $tag = rest::resolve($request->url);
- $name = $request->arguments[0];
+ // @todo: what permission should be required to edit a tag?
+ // for now, require edit at the top level. Perhaps later, just require any edit perms,
+ // anywhere in the gallery?
- $tag = ORM::factory("tag")
- ->where("name", "=", $name)
- ->find();
- if (!$tag->loaded()) {
- throw new Kohana_404_Exception();
+ if (isset($request->params->remove)) {
+ if (!is_array($request->params->remove)) {
+ throw new Exception("Bad request", 400);
+ }
+
+ foreach ($request->params->remove as $item_url) {
+ $item = rest::resolve($item_url);
+ access::required("edit", $item);
+ $tag->remove($item);
+ }
}
- $tag->name = $request->new_name;
- $tag->save();
+ if (isset($request->params->name)) {
+ $tag->name = $request->params->name;
+ }
- return rest::success();
+ $tag->save();
+ return rest::reply(array("url" => url::abs_site("rest/tag/" . rawurlencode($tag->name))));
}
static function delete($request) {
- if (empty($request->arguments[0])) {
- throw new Rest_Exception(400, "Bad request");
- }
- $tags = explode(",", $request->arguments[0]);
- if (!empty($request->path)) {
- $tag_list = ORM::factory("tag")
- ->join("items_tags", "tags.id", "items_tags.tag_id")
- ->join("items", "items.id", "items_tags.item_id")
- ->where("tags.name", "IN", $tags)
- ->where("relative_url_cache", "=", $request->path)
- ->viewable()
- ->find_all();
- } else {
- $tag_list = ORM::factory("tag")
- ->where("name", "IN", $tags)
- ->find_all();
- }
+ $tag = rest::resolve($request->url);
- foreach ($tag_list as $row) {
- $row->delete();
- };
+ if (empty($request->params->url)) {
+ // Delete the tag
+ $tag->delete();
+ return rest::reply();
+ } else {
+ // Remove an item from the tag
+ $item = rest::resolve($request->params->url);
+ $tag->remove($item);
+ $tag->save();
- tag::compact();
- return rest::success();
+ tag::compact();
+ return rest::reply(array("url" => url::abs_site("rest/tag/" . rawurlencode($tag->name))));
+ }
}
- private static function _get_items($request) {
- $tags = explode(",", $request->arguments[0]);
- $items = ORM::factory("item")
- ->select_distinct("*")
- ->join("items_tags", "items.id", "items_tags.item_id")
- ->join("tags", "tags.id", "items_tags.tag_id")
- ->where("tags.name", "IN", $tags);
- if (!empty($request->limit)) {
- $items->limit($request->limit);
- }
- if (!empty($request->offset)) {
- $items->offset($request->offset);
- }
- $resources = array();
- foreach ($items->find_all() as $item) {
- $resources[] = array("type" => $item->type,
- "has_children" => $item->children_count() > 0,
- "path" => $item->relative_url(),
- "thumb_url" => $item->thumb_url(true),
- "thumb_dimensions" => array("width" => $item->thumb_width,
- "height" => $item->thumb_height),
- "has_thumb" => $item->has_thumb(),
- "title" => $item->title);
+ static function resolve($tag_name) {
+ $tag = ORM::factory("tag")->where("name", "=", $tag_name)->find();
+ if (!$tag->loaded()) {
+ throw new Kohana_404_Exception();
}
- return $resources;
+ return $tag;
}
}
diff --git a/modules/tag/helpers/tags_rest.php b/modules/tag/helpers/tags_rest.php
new file mode 100644
index 00000000..3ef897fd
--- /dev/null
+++ b/modules/tag/helpers/tags_rest.php
@@ -0,0 +1,48 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2009 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 tags_rest_Core {
+ static function get($request) {
+ $tags = array();
+ foreach (ORM::factory("tag")->find_all() as $tag) {
+ $tags[$tag->name] = url::abs_site("rest/tags/" . rawurlencode($tag->name));
+ }
+ return rest::reply(array("members" => $tags));
+ }
+
+ static function post($request) {
+ // @todo: what permission should be required to create a tag here?
+ // for now, require edit at the top level. Perhaps later, just require any edit perms,
+ // anywhere in the gallery?
+ access::required("edit", item::root());
+
+ if (empty($request->params->name)) {
+ throw new Rest_Exception("Bad Request", 400);
+ }
+
+ $tag = ORM::factory("tag")->where("name", "=", $request->params->name)->find();
+ if (!$tag->loaded()) {
+ $tag->name = $request->params->name;
+ $tag->count = 0;
+ $tag->save();
+ }
+
+ return rest::reply(array("url" => url::abs_site("rest/tag/" . rawurlencode($tag->name))));
+ }
+}
diff --git a/modules/tag/tests/Tag_Rest_Helper_Test.php b/modules/tag/tests/Tag_Rest_Helper_Test.php
index 4e8dd527..185953ab 100644
--- a/modules/tag/tests/Tag_Rest_Helper_Test.php
+++ b/modules/tag/tests/Tag_Rest_Helper_Test.php
@@ -133,7 +133,8 @@ class Tag_Rest_Helper_Test extends Unit_Test_Case {
try {
tag_rest::post($request);
} catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
+ $this->assert_equal(400, $e->getCode());
+ $this->assert_equal("Bad request", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -191,7 +192,8 @@ class Tag_Rest_Helper_Test extends Unit_Test_Case {
try {
tag_rest::put($request);
} catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
+ $this->assert_equal(400, $e->getCode());
+ $this->assert_equal("Bad request", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -202,7 +204,8 @@ class Tag_Rest_Helper_Test extends Unit_Test_Case {
try {
tag_rest::put($request);
} catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
+ $this->assert_equal(400, $e->getCode());
+ $this->assert_equal("Bad request", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -211,7 +214,8 @@ class Tag_Rest_Helper_Test extends Unit_Test_Case {
try {
tag_rest::put($request);
} catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
+ $this->assert_equal(400, $e->getCode());
+ $this->assert_equal("Bad request", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}