diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/gallery/helpers/gallery_rest.php | 249 | ||||
-rw-r--r-- | modules/gallery/tests/Gallery_Rest_Helper_Test.php | 262 | ||||
-rw-r--r-- | modules/image_block/helpers/image_block_rest.php | 62 | ||||
-rw-r--r-- | modules/organize/css/organize.css | 30 | ||||
-rw-r--r-- | modules/organize/js/organize.js | 8 | ||||
-rw-r--r-- | modules/organize/views/organize_dialog.html.php | 6 | ||||
-rw-r--r-- | modules/organize/views/organize_thumb_grid.html.php | 4 | ||||
-rw-r--r-- | modules/organize/views/organize_tree.html.php | 2 | ||||
-rw-r--r-- | modules/rest/controllers/rest.php | 68 | ||||
-rw-r--r-- | modules/rest/helpers/rest.php | 105 | ||||
-rw-r--r-- | modules/rest/helpers/rest_event.php | 75 | ||||
-rw-r--r-- | modules/rest/helpers/rest_installer.php | 37 | ||||
-rw-r--r-- | modules/rest/libraries/Rest_Exception.php | 41 | ||||
-rw-r--r-- | modules/rest/models/user_access_token.php | 21 | ||||
-rw-r--r-- | modules/rest/module.info | 4 | ||||
-rw-r--r-- | modules/rest/tests/Rest_Controller_Test.php | 217 | ||||
-rw-r--r-- | modules/tag/helpers/tag_rest.php | 160 | ||||
-rw-r--r-- | modules/tag/tests/Tag_Rest_Helper_Test.php | 276 |
18 files changed, 1589 insertions, 38 deletions
diff --git a/modules/gallery/helpers/gallery_rest.php b/modules/gallery/helpers/gallery_rest.php new file mode 100644 index 00000000..563a2c7c --- /dev/null +++ b/modules/gallery/helpers/gallery_rest.php @@ -0,0 +1,249 @@ +<?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 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)) { + Rest_Exception::trigger(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(); + + log::success("content", "Updated $item->type", + "<a href=\"{$item->type}s/$item->id\">view</a>"); + + return rest::success(); + } else { + return rest::validation_error($errors); + } + } + + static function post($request) { + if (empty($request->arguments)) { + Rest_Exception::trigger(400, "Bad request"); + } + + $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($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"); + } else { + $new_item = + photo::create($parent, $temp_filename, $new_values["name"], $new_values["title"]); + $log_message = t("Added a photo"); + } + } + + 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)) { + Rest_Exception::trigger(400, "Bad request", $log_message); + return rest::invalid_request(); + } + $path = implode("/", $request->arguments); + + $item = gallery_rest::_get_item($path, "edit"); + + if ($item->id == 1) { + Rest_Exception::trigger(400, "Bad request", "Attempt to delete the root album"); + } + + $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))); + } + log::success("content", $msg); + + return rest::success(array("resource" => array("parent_path" => $parent->relative_url()))); + } + + 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(); + } + + return $item; + } + + 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; + } + + private static function _validate($request, $parent_id, $item_id=0) { + $item = ORM::factory("item", $item_id); + + // 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]"); + } + + 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"); + } + } + + return $new_values; + } + + 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; + } + } + + return $errors; + } +} diff --git a/modules/gallery/tests/Gallery_Rest_Helper_Test.php b/modules/gallery/tests/Gallery_Rest_Helper_Test.php new file mode 100644 index 00000000..4cd3f2a6 --- /dev/null +++ b/modules/gallery/tests/Gallery_Rest_Helper_Test.php @@ -0,0 +1,262 @@ +<?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 Gallery_Rest_Helper_Test extends Unit_Test_Case { + public function setup() { + $this->_save = array($_GET, $_POST, $_SERVER, $_FILES); + $this->_saved_active_user = identity::active_user(); + } + + public function teardown() { + list($_GET, $_POST, $_SERVER, $_FILES) = $this->_save; + identity::set_active_user($this->_saved_active_user); + } + + private function _create_user() { + $user = identity::create_user("access_test" . rand(), "Access Test", "password"); + $key = ORM::factory("user_access_token"); + $key->access_key = md5($user->name . rand()); + $key->user_id = $user->id; + $key->save(); + identity::set_active_user($user); + return $user; + } + private function _create_album($parent=null) { + $album_name = "album_" . rand(); + if (empty($parent)) { + $parent = ORM::factory("item", 1); + } + return album::create($parent, $album_name, $album_name, $album_name); + } + + private function _create_image($parent=null) { + $filename = MODPATH . "gallery/tests/test.jpg"; + $image_name = "image_" . rand(); + if (empty($parent)) { + $parent = ORM::factory("item", 1); + } + return photo::create($parent, $filename, "$image_name.jpg", $image_name); + } + + public function gallery_rest_get_album_test() { + $album = $this->_create_album(); + $child = $this->_create_album($album); + $photo = $this->_create_image($child); + $request = (object)array("arguments" => explode("/", $child->relative_url())); + + $this->assert_equal( + json_encode(array("status" => "OK", + "resource" => + array("type" => $child->type, + "name" => $child->name, + "path" => $child->relative_url(), + "parent_path" => $album->relative_url(), + "title" => $child->title, + "thumb_url" => $child->thumb_url(), + "thumb_size" => array("height" => $child->thumb_height, + "width" => $child->thumb_width), + "resize_url" => $child->resize_url(), + "resize_size" => array("height" => 0, + "width" => 0), + "url" => $child->file_url(), + "size" => array("height" => $child->height, + "width" => $child->width), + "description" => $child->description, + "slug" => $child->slug, + "children" => array(array( + "type" => "photo", + "has_children" => false, + "path" => $photo->relative_url(), + "thumb_url" => $photo->thumb_url(), + "thumb_dimensions" => array( + "width" => $photo->thumb_width, + "height" => $photo->thumb_height), + "has_thumb" => true, + "title" => $photo->title))))), + gallery_rest::get($request)); + } + + public function gallery_rest_get_photo_test() { + $child = $this->_create_album(); + $photo = $this->_create_image($child); + $request = (object)array("arguments" => explode("/", $photo->relative_url())); + + $this->assert_equal( + json_encode(array("status" => "OK", + "resource" => + array("type" => $photo->type, + "name" => $photo->name, + "path" => $photo->relative_url(), + "parent_path" => $child->relative_url(), + "title" => $photo->title, + "thumb_url" => $photo->thumb_url(), + "thumb_size" => array("height" => $photo->thumb_height, + "width" => $photo->thumb_width), + "resize_url" => $photo->resize_url(), + "resize_size" => array("height" => $photo->resize_height, + "width" => $photo->resize_width), + "url" => $photo->file_url(), + "size" => array("height" => $photo->height, + "width" => $photo->width), + "description" => $photo->description, + "slug" => $photo->slug))), + gallery_rest::get($request)); + } + + public function gallery_rest_put_album_no_path_test() { + $request = (object)array("description" => "Updated description", + "title" => "Updated Title", + "name" => "new name"); + + $this->assert_equal(json_encode(array("status" => "ERROR", "message" => "Invalid request")), + gallery_rest::put($request)); + } + + public function gallery_rest_put_album_not_found_test() { + $photo = $this->_create_image(); + $request = (object)array("arguments" => explode("/", $photo->relative_url() . rand()), + "description" => "Updated description", + "title" => "Updated Title", + "name" => "new name"); + + try { + gallery_rest::put($request); + } catch (Kohana_404_Exception $k404) { + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + } + + public function gallery_rest_put_album_no_edit_permission_test() { + $child = $this->_create_album(); + $this->_create_user(); + $request = (object)array("arguments" => explode("/", $child->relative_url()), + "description" => "Updated description", + "title" => "Updated Title", + "name" => "new name"); + + try { + gallery_rest::put($request); + } catch (Kohana_404_Exception $k404) { + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + } + + public function gallery_rest_put_album_rename_conflict_test() { + $child = $this->_create_album(); + $sibling = $this->_create_image(); + $this->_create_user(); + access::allow(identity::registered_users(), "edit", $child); + $request = (object)array("arguments" => explode("/", $child->relative_url()), + "description" => "Updated description", + "title" => "Updated Title", + "name" => $sibling->name); + + $this->assert_equal( + json_encode(array("status" => "VALIDATE_ERROR", + "fields" => array("slug" => "Duplicate Internet address"))), + gallery_rest::put($request)); + } + + public function gallery_rest_put_album_test() { + $child = $this->_create_album(); + $sibling = $this->_create_image(); + $this->_create_user(); + access::allow(identity::registered_users(), "edit", $child); + + $request = (object)array("arguments" => explode("/", $child->relative_url()), + "description" => "Updated description", + "title" => "Updated Title", + "name" => "new name"); + + $this->assert_equal(json_encode(array("status" => "OK")), gallery_rest::put($request)); + $child->reload(); + $this->assert_equal("Updated description", $child->description); + $this->assert_equal("Updated Title", $child->title); + $this->assert_equal("new name", $child->name); + } + + public function gallery_rest_put_photo_test() { + $child = $this->_create_album(); + $photo = $this->_create_image($child); + $this->_create_user(); + access::allow(identity::registered_users(), "edit", $child); + + $request = (object)array("arguments" => explode("/", $photo->relative_url()), + "description" => "Updated description", + "title" => "Updated Title", + "name" => "new name"); + + $this->assert_equal(json_encode(array("status" => "OK")), gallery_rest::put($request)); + $photo->reload(); + $this->assert_equal("Updated description", $photo->description); + $this->assert_equal("Updated Title", $photo->title); + $this->assert_equal("new name", $photo->name); + } + + public function gallery_rest_delete_album_test() { + $album = $this->_create_album(); + $child = $this->_create_album($album); + $this->_create_user(); + access::allow(identity::registered_users(), "edit", $album); + + $request = (object)array("arguments" => explode("/", $child->relative_url())); + + $this->assert_equal(json_encode(array("status" => "OK", + "resource" => array( + "parent_path" => $album->relative_url()))), + gallery_rest::delete($request)); + $child->reload(); + $this->assert_false($child->loaded()); + } + + public function gallery_rest_delete_photo_test() { + $album = $this->_create_album(); + $photo = $this->_create_image($album); + $this->_create_user(); + access::allow(identity::registered_users(), "edit", $album); + + $request = (object)array("arguments" => explode("/", $photo->relative_url())); + + $this->assert_equal(json_encode(array("status" => "OK", + "resource" => array( + "parent_path" => $album->relative_url()))), + gallery_rest::delete($request)); + $photo->reload(); + $this->assert_false($photo->loaded()); + } + + public function gallery_rest_post_album_test() { + $album = $this->_create_album(); + $this->_create_user(); + access::allow(identity::registered_users(), "edit", $album); + + $new_path = $album->relative_url() . "/new%20child"; + $request = (object)array("arguments" => explode("/", $new_path)); + + $this->assert_equal(json_encode(array("status" => "OK", "path" => $new_path)), + gallery_rest::post($request)); + $album = ORM::factory("item") + ->where("relative_url_cache", "=", $new_path) + ->find(); + $this->assert_true($album->loaded()); + $this->assert_equal("new child", $album->slug); + } +} diff --git a/modules/image_block/helpers/image_block_rest.php b/modules/image_block/helpers/image_block_rest.php new file mode 100644 index 00000000..7afd974c --- /dev/null +++ b/modules/image_block/helpers/image_block_rest.php @@ -0,0 +1,62 @@ +<?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/organize/css/organize.css b/modules/organize/css/organize.css index 16645c37..d8923ea7 100644 --- a/modules/organize/css/organize.css +++ b/modules/organize/css/organize.css @@ -30,9 +30,8 @@ width: 19%; } -#g-organize-album-tree .g-selected { - background-color: #eee; - border-bottom: 1px solid #999; +#g-organize-album-tree { + overflow: auto; } #g-organize-album-tree ul li { @@ -50,10 +49,6 @@ width: auto; } -.g-organize-album-text:hover { - background: #eee; -} - /******************************************************************* * Album panel styles */ @@ -77,8 +72,6 @@ } #g-organize-microthumb-panel { - background-color: #eee; - border: 1px solid #999; height: 100%; margin: 0 !important; position: relative; @@ -100,8 +93,6 @@ } .g-organize-microthumb { - background-color: #fff; - border: 1px solid #ccc; display: block; height: 100px; margin: 0; @@ -111,16 +102,7 @@ width: 110px; } -.g-organize-microthumb-grid-cell.ui-selecting, -.g-organize-microthumb-grid-cell.ui-selected { - border: 2px solid #13A; - margin: 4px; -} - .ui-selectable-helper { - background: #13A; - border: 1px dashed #00F; - opacity: 0.25; z-index: 2000 !important; } @@ -131,21 +113,13 @@ z-index: 4000; } -.g-organize-microthumb-grid-cell:hover { - border: 2px solid #13A; - margin: 4px; -} - /**************************************************************** * Controls styles */ #g-organize-controls { - background-color: #666; - color: #eee; margin: 0 !important; padding: .2em .4em; - width: 100%; } #g-organize-controls select { diff --git a/modules/organize/js/organize.js b/modules/organize/js/organize.js index 9164d143..76eadf85 100644 --- a/modules/organize/js/organize.js +++ b/modules/organize/js/organize.js @@ -203,7 +203,7 @@ */ show_album: function(event) { event.preventDefault(); - if ($(event.currentTarget).hasClass("g-selected")) { + if ($(event.currentTarget).hasClass("ui-state-focus")) { return; } var parent = $(event.currentTarget).parents(".g-organize-branch"); @@ -212,8 +212,8 @@ } $("#g-organize-microthumb-panel").selectable("destroy"); var id = $(event.currentTarget).attr("ref"); - $("#g-organize-album-tree .g-selected").removeClass("g-selected"); - $(".g-organize-album-text[ref=" + id + "]").addClass("g-selected"); + $(".g-organize-album-text.ui-state-focus").removeClass("ui-state-focus"); + $(".g-organize-album-text[ref=" + id + "]").addClass("ui-state-focus"); var url = $("#g-organize-microthumb-panel").attr("ref").replace("__ITEM_ID__", id).replace("__OFFSET__", 0); $.get(url, {}, function(data) { @@ -230,7 +230,7 @@ */ resort: function(column, dir) { var url = sort_order_url - .replace("__ALBUM_ID__", $("#g-organize-album-tree .g-selected").attr("ref")) + .replace("__ALBUM_ID__", $("#g-organize-album-tree .ui-state-focus").attr("ref")) .replace("__COL__", column) .replace("__DIR__", dir); $.get(url, {}, diff --git a/modules/organize/views/organize_dialog.html.php b/modules/organize/views/organize_dialog.html.php index 31f788ad..435f5ae3 100644 --- a/modules/organize/views/organize_dialog.html.php +++ b/modules/organize/views/organize_dialog.html.php @@ -15,16 +15,16 @@ </ul> </div> <div id="g-organize-detail" class="g-left ui-helper-clearfix"> - <div id="g-organize-microthumb-panel" + <div id="g-organize-microthumb-panel" class="ui-widget" ref="<?= url::site("organize/album/__ITEM_ID__/__OFFSET__") ?>"> <ul id="g-action-status" class="g-message-block"> <li class="g-info"><?= t("Drag and drop photos to re-order or move between albums") ?></li> </ul> - <ul id="g-organize-microthumb-grid"> + <ul id="g-organize-microthumb-grid" class="ui-widget-content"> <?= $micro_thumb_grid ?> </ul> </div> - <div id="g-organize-controls"> + <div id="g-organize-controls" class="ui-widget-header"> <a id="g-organize-close" href="#" ref="done" class="g-button g-right ui-corner-all ui-state-default"><?= t("Close") ?></a> <form> diff --git a/modules/organize/views/organize_thumb_grid.html.php b/modules/organize/views/organize_thumb_grid.html.php index 3ac32ce0..9a9cd819 100644 --- a/modules/organize/views/organize_thumb_grid.html.php +++ b/modules/organize/views/organize_thumb_grid.html.php @@ -1,8 +1,8 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <? foreach ($album->children(25, $offset) as $child): ?> -<li class="g-organize-microthumb-grid-cell g-left" ref="<?= $child->id ?>"> +<li class="g-organize-microthumb-grid-cell g-left ui-state-default" ref="<?= $child->id ?>"> <div id="g-organize-microthumb-<?= $child->id ?>" - class="g-organize-microthumb <?= $child->is_album() ? "g-album" : "g-photo" ?>"> + class="g-organize-microthumb <?= $child->is_album() ? "g-album" : "g-photo" ?> ui-state-active"> <?= $child->thumb_img(array("class" => "g-thumbnail", "ref" => $child->id), 90, true) ?> <span<?= $child->is_album() ? " class=\"ui-icon ui-icon-note\"" : "" ?>></span> </div> diff --git a/modules/organize/views/organize_tree.html.php b/modules/organize/views/organize_tree.html.php index c5257956..513c0625 100644 --- a/modules/organize/views/organize_tree.html.php +++ b/modules/organize/views/organize_tree.html.php @@ -3,7 +3,7 @@ ref="<?= $album->id ?>"> <span class="ui-icon ui-icon-minus"> </span> - <span class="g-organize-album-text <?= $selected && $album->id == $selected->id ? "selected" : "" ?>" + <span class="g-organize-album-text <?= $selected && $album->id == $selected->id ? "ui-state-focus" : "" ?>" ref="<?= $album->id ?>"> <?= html::clean($album->title) ?> </span> diff --git a/modules/rest/controllers/rest.php b/modules/rest/controllers/rest.php new file mode 100644 index 00000000..446ec7cb --- /dev/null +++ b/modules/rest/controllers/rest.php @@ -0,0 +1,68 @@ +<?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 Rest_Controller extends Controller { + public function access_key() { + $request = (object)Input::instance()->get(); + if (empty($request->user) || empty($request->password)) { + Rest_Exception::trigger(403, "Forbidden", "No user or password supplied"); + } + + $user = identity::lookup_user_by_name($request->user); + if (empty($user)) { + Rest_Exception::trigger(403, "Forbidden", "User '{$request->user}' not found"); + return; + } + + if (!identity::is_correct_password($user, $request->password)) { + Rest_Exception::trigger(403, "Forbidden", "Invalid password for '{$request->user}'."); + return; + } + + $key = ORM::factory("user_access_token") + ->where("user_id", "=", $user->id) + ->find(); + if (!$key->loaded()) { + $key->user_id = $user->id; + $key->access_key = md5($user->name . rand()); + $key->save(); + } + print rest::success(array("token" => $key->access_key)); + } + + public function __call($function, $args) { + $request = rest::normalize_request($args); + try { + if (rest::set_active_user($request->access_token)) { + $handler_class = "{$function}_rest"; + $handler_method = $request->method; + + if (!method_exists($handler_class, $handler_method)) { + Rest_Exception::trigger(501, "Not implemented", "$handler_class::$handler_method"); + } + + print call_user_func(array($handler_class, $handler_method), $request); + } + } catch (Rest_Exception $e) { + $e->sendHeaders(); + } catch (Exception $e) { + Kohana_Log::add("error", $e->__toString()); + header("HTTP/1.1 500 Internal Error"); + } + } +}
\ No newline at end of file diff --git a/modules/rest/helpers/rest.php b/modules/rest/helpers/rest.php new file mode 100644 index 00000000..7e2445e4 --- /dev/null +++ b/modules/rest/helpers/rest.php @@ -0,0 +1,105 @@ +<?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 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 + 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; + } + $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 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 ($method != "get") { + foreach (array_keys($input->post()) as $key) { + $request->$key = $input->post($key); + } + foreach (array_keys($_FILES) as $key) { + $request->$key = $_FILES[$key]; + } + } + + $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 + + return $request; + } + + 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(); + + if ($key->loaded()) { + $user = identity::lookup_user($key->user_id); + if (empty($user)) { + Rest_Exception::trigger(403, "Forbidden", $log_message, + "User not found: {$key->user_id}"); + } + } else { + Rest_Exception::trigger(403, "Forbidden", $log_message, + "Invalid user access token supplied: {$key->user_id}"); + } + } + identity::set_active_user($user); + return true; + } +} diff --git a/modules/rest/helpers/rest_event.php b/modules/rest/helpers/rest_event.php new file mode 100644 index 00000000..a06f43ea --- /dev/null +++ b/modules/rest/helpers/rest_event.php @@ -0,0 +1,75 @@ +<?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 rest_event { + /** + * Called just before a user is deleted. This will remove the user from + * the user_homes directory. + */ + static function user_before_delete($user) { + ORM::factory("user_access_token") + ->where("id", "=", $user->id) + ->delete_all(); + } + + /** + * Called after a user has been added. Just add a remote access key + * on every add. + */ + static function user_add_form_admin_completed($user, $form) { + $key = ORM::factory("user_access_token"); + $key->user_id = $user->id; + $key->access_key = md5($user->name . rand()); + $key->save(); + } + + /** + * Called when admin is editing a user + */ + static function user_edit_form_admin($user, $form) { + self::_get_access_key_form($user, $form); + } + + /** + * Called when user is editing their own form + */ + static function user_edit_form($user, $form) { + self::_get_access_key_form($user, $form); + } + + /** + * Get the form fields for user edit + */ + static function _get_access_key_form($user, $form) { + $key = ORM::factory("user_access_token") + ->where("user_id", "=", $user->id) + ->find(); + + if (!$key->loaded()) { + $key->user_id = $user->id; + $key->access_key = md5($user->name . rand()); + $key->save(); + } + + $form->edit_user->input("user_access_token") + ->value($key->access_key) + ->readonly("readonly") + ->class("g-form-static") + ->label(t("Remote access key")); + } +} diff --git a/modules/rest/helpers/rest_installer.php b/modules/rest/helpers/rest_installer.php new file mode 100644 index 00000000..9fbc5b2e --- /dev/null +++ b/modules/rest/helpers/rest_installer.php @@ -0,0 +1,37 @@ +<?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 rest_installer { + static function install() { + Database::instance() + ->query("CREATE TABLE {user_access_tokens} ( + `id` int(9) NOT NULL auto_increment, + `user_id` int(9) NOT NULL, + `access_key` char(32) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY(`access_key`), + UNIQUE KEY(`user_id`)) + DEFAULT CHARSET=utf8;"); + module::set_version("rest", 1); + } + + static function uninstall() { + Database::instance()->query("DROP TABLE IF EXISTS {user_access_tokens}"); + } +} diff --git a/modules/rest/libraries/Rest_Exception.php b/modules/rest/libraries/Rest_Exception.php new file mode 100644 index 00000000..acdcb568 --- /dev/null +++ b/modules/rest/libraries/Rest_Exception.php @@ -0,0 +1,41 @@ +<?php defined('SYSPATH') OR die('No direct access allowed.'); +/** + * Creates a "Page Not Found" exception. + * + * $Id: Kohana_404_Exception.php 4679 2009-11-10 01:45:52Z isaiah $ + * + * @package Core + * @author Kohana Team + * @copyright (c) 2007-2009 Kohana Team + * @license http://kohanaphp.com/license + */ + +class Rest_Exception_Core extends Exception { + /** + * Set internal properties. + */ + public function __construct($code, $text) { + parent::__construct("$code $text"); + } + + /** + * Throws a new Rest exception. + * + * @throws Rest_Exception + * @return void + */ + public static function trigger($code, $text, $log_message=null) { + $message = "$code: $text" . (!empty($log_message) ? "\n$log_message" : ""); + Kohana_Log::add("info", $message); + throw new Rest_Exception($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 diff --git a/modules/rest/models/user_access_token.php b/modules/rest/models/user_access_token.php new file mode 100644 index 00000000..5669d8d1 --- /dev/null +++ b/modules/rest/models/user_access_token.php @@ -0,0 +1,21 @@ +<?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 User_Access_Token_Model extends ORM { +} diff --git a/modules/rest/module.info b/modules/rest/module.info new file mode 100644 index 00000000..45bd79e4 --- /dev/null +++ b/modules/rest/module.info @@ -0,0 +1,4 @@ +name = "REST Access Module" +description = "The RESTful implementation/interface to Gallery3" + +version = 1 diff --git a/modules/rest/tests/Rest_Controller_Test.php b/modules/rest/tests/Rest_Controller_Test.php new file mode 100644 index 00000000..3e0c4063 --- /dev/null +++ b/modules/rest/tests/Rest_Controller_Test.php @@ -0,0 +1,217 @@ +<?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 Rest_Controller_Test extends Unit_Test_Case { + public function setup() { + $this->_save = array($_GET, $_POST, $_SERVER); + } + + private function _create_user() { + $user = identity::create_user("access_test" . rand(), "Access Test", "password"); + $key = ORM::factory("user_access_token"); + $key->access_key = md5($user->name . rand()); + $key->user_id = $user->id; + $key->save(); + return array($key->access_key, $user); + } + + private function _create_image($parent=null) { + $filename = MODPATH . "gallery/tests/test.jpg"; + $image_name = "image_" . rand(); + if (empty($parent)) { + $parent = ORM::factory("item", 1); + } + return photo::create($parent, $filename, "$image_name.jpg", $image_name); + } + + + public function teardown() { + list($_GET, $_POST, $_SERVER) = $this->_save; + } + + public function rest_access_key_exists_test() { + list ($access_key, $user) = $this->_create_user(); + $_SERVER["REQUEST_METHOD"] = "GET"; + $_GET["user"] = $user->name;; + $_GET["password"] = "password"; + + $this->assert_equal( + json_encode(array("status" => "OK", "token" => $access_key)), + $this->_call_controller()); + } + + public function rest_access_key_generated_test() { + list ($access_key, $user) = $this->_create_user(); + ORM::factory("user_access_token") + ->where("access_key", $access_key) + ->delete(); + $_SERVER["REQUEST_METHOD"] = "GET"; + $_GET["user"] = $user->name; + $_GET["password"] = "password"; + + $results = json_decode($this->_call_controller()); + + $this->assert_equal("OK", $results->status); + $this->assert_false(empty($results->token)); + } + + public function rest_access_key_no_parameters_test() { + $_SERVER["REQUEST_METHOD"] = "GET"; + + try { + $this->_call_controller(); + } catch (Rest_Exception $e) { + $this->assert_equal("403 Forbidden", $e->getMessage()); + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + } + + public function rest_access_key_user_not_found_test() { + $_SERVER["REQUEST_METHOD"] = "POST"; + $_POST["request"] = json_encode(array("user" => "access_test2", "password" => "password")); + + try { + $this->_call_controller(); + } catch (Rest_Exception $e) { + $this->assert_equal("403 Forbidden", $e->getMessage()); + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + } + + public function rest_access_key_invalid_password_test() { + $_SERVER["REQUEST_METHOD"] = "POST"; + + try { + $this->_call_controller(); + } catch (Rest_Exception $e) { + $this->assert_equal("403 Forbidden", $e->getMessage()); + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + } + + public function rest_get_resource_no_request_key_test() { + $_SERVER["REQUEST_METHOD"] = "GET"; + $photo = $this->_create_image(); + + $this->assert_equal( + json_encode(array("status" => "OK", "message" => (string)t("Processed"), + "photo" => array("path" => $photo->relative_url(), + "title" => $photo->title, + "thumb_url" => $photo->thumb_url(), + "description" => $photo->description, + "internet_address" => $photo->slug))), + $this->_call_controller("rest", explode("/", $photo->relative_url()))); + } + + public function rest_get_resource_invalid_key_test() { + list ($access_key, $user) = $this->_create_user(); + $_SERVER["HTTP_X_GALLERY_REQUEST_KEY"] = md5($access_key); // screw up the access key; + $_SERVER["REQUEST_METHOD"] = "GET"; + + try { + $this->_call_controller(); + } catch (Rest_Exception $e) { + $this->assert_equal("403 Forbidden", $e->getMessage()); + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + } + + public function rest_get_resource_no_user_for_key_test() { + list ($access_key, $user) = $this->_create_user(); + $_SERVER["REQUEST_METHOD"] = "GET"; + $_SERVER["HTTP_X_GALLERY_REQUEST_KEY"] = $access_key; + + $user->delete(); + + $photo = $this->_create_image(); + + try { + $this->_call_controller("rest", explode("/", $photo->relative_url())); + } catch (Rest_Exception $e) { + $this->assert_equal("403 Forbidden", $e->getMessage()); + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + } + + public function rest_get_resource_no_handler_test() { + list ($access_key, $user) = $this->_create_user(); + $_SERVER["REQUEST_METHOD"] = "GET"; + $_SERVER["HTTP_X_GALLERY_REQUEST_KEY"] = $access_key; + $_SERVER["HTTP_X_GALLERY_REQUEST_METHOD"] = "PUT"; + $photo = $this->_create_image(); + + try { + $this->_call_controller("rest", explode("/", $photo->relative_url())); + } catch (Rest_Exception $e) { + $this->assert_equal("501 Not Implemented", $e->getMessage()); + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + } + + public function rest_get_resource_test() { + list ($access_key, $user) = $this->_create_user(); + $_SERVER["REQUEST_METHOD"] = "GET"; + $_SERVER["HTTP_X_GALLERY_REQUEST_KEY"] = $access_key; + + $photo = $this->_create_image(); + $this->assert_equal( + json_encode(array("status" => "OK", "message" => (string)t("Processed"), + "photo" => array("path" => $photo->relative_url(), + "title" => $photo->title, + "thumb_url" => $photo->thumb_url(), + "description" => $photo->description, + "internet_address" => $photo->slug))), + $this->_call_controller("rest", explode("/", $photo->relative_url()))); + } + + private function _call_controller($method="access_key", $arg=null) { + $controller = new Rest_Controller(); + + ob_start(); + call_user_func_array(array($controller, $method), $arg); + $results = ob_get_contents(); + ob_end_clean(); + + return $results; + } +} + +class rest_rest { + static $request = null; + + static function get($request) { + self::$request = $request; + $item = ORM::factory("item") + ->where("relative_url_cache", "=", implode("/", $request->arguments)) + ->find(); + $response["path"] = $item->relative_url(); + $response["title"] = $item->title; + $response["thumb_url"] = $item->thumb_url(); + $response["description"] = $item->description; + $response["internet_address"] = $item->slug; + return rest::success(array($item->type => $response), t("Processed")); + } + +} diff --git a/modules/tag/helpers/tag_rest.php b/modules/tag/helpers/tag_rest.php new file mode 100644 index 00000000..29b74510 --- /dev/null +++ b/modules/tag/helpers/tag_rest.php @@ -0,0 +1,160 @@ +<?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 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)); + } + } + + return rest::success($resources); + } + + static function post($request) { + if (empty($request->arguments) || count($request->arguments) != 1 || empty($request->path)) { + Rest_Exception::trigger(400, "Bad request"); + } + $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(); + } + + if (!access::can("edit", $item)) { + throw new Kohana_404_Exception(); + } + + foreach ($tags as $tag) { + tag::add($item, $tag); + } + return rest::success(); + } + + static function put($request) { + if (empty($request->arguments[0]) || empty($request->new_name)) { + Rest_Exception::trigger(400, "Bad request"); + } + + $name = $request->arguments[0]; + + $tag = ORM::factory("tag") + ->where("name", "=", $name) + ->find(); + if (!$tag->loaded()) { + throw new Kohana_404_Exception(); + } + + $tag->name = $request->new_name; + $tag->save(); + + return rest::success(); + } + + static function delete($request) { + if (empty($request->arguments[0])) { + Rest_Exception::trigger(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(); + } + + foreach ($tag_list as $row) { + $row->delete(); + }; + + tag::compact(); + return rest::success(); + } + + 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); + } + + return $resources; + } +} diff --git a/modules/tag/tests/Tag_Rest_Helper_Test.php b/modules/tag/tests/Tag_Rest_Helper_Test.php new file mode 100644 index 00000000..ac64470c --- /dev/null +++ b/modules/tag/tests/Tag_Rest_Helper_Test.php @@ -0,0 +1,276 @@ +<?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 Tag_Rest_Helper_Test extends Unit_Test_Case { + public function setup() { + $this->_save = array($_GET, $_POST, $_SERVER, $_FILES); + $this->_saved_active_user = identity::active_user(); + } + + public function teardown() { + list($_GET, $_POST, $_SERVER, $_FILES) = $this->_save; + identity::set_active_user($this->_saved_active_user); + + try { + Database::instance()->query("TRUNCATE {tags}"); + Database::instance()->query("TRUNCATE {items_tags}"); + + } catch (Exception $e) { } + } + + private function _create_user() { + $user = identity::create_user("access_test" . rand(), "Access Test", "password"); + $key = ORM::factory("user_access_token"); + $key->access_key = md5($user->name . rand()); + $key->user_id = $user->id; + $key->save(); + identity::set_active_user($user); + return $user; + } + private function _create_album($tags=array(), $parent=null) { + $album_name = "album_" . rand(); + if (empty($parent)) { + $parent = ORM::factory("item", 1); + } + $album = album::create($parent, $album_name, $album_name, $album_name); + foreach ($tags as $tag) { + tag::add($album, $tag); + } + return $album; + } + + private function _create_image($tags=array(), $parent=null) { + $filename = MODPATH . "gallery/tests/test.jpg"; + $image_name = "image_" . rand(); + if (empty($parent)) { + $parent = ORM::factory("item", 1); + } + $photo = photo::create($parent, $filename, "$image_name.jpg", $image_name); + foreach ($tags as $tag) { + tag::add($photo, $tag); + } + return $photo; + } + + public function tag_rest_get_all_test() { + $album = $this->_create_album(array("albums", "A1", "T1")); + $child = $this->_create_album(array("albums", "C1", "T1"), $album); + $photo = $this->_create_image(array("photos", "P1", "T1"), $child); + $sibling = $this->_create_image(array("photos", "P3"), $album); + + $request = (object)array("arguments" => array(), "limit" => 2, "offset" => 1); + + $this->assert_equal( + json_encode(array("status" => "OK", + "tags" => array(array("name" => "albums", "count" => 2), + array("name" => "photos", "count" => 2)))), + tag_rest::get($request)); + } + + public function tag_rest_get_tags_for_item_test() { + $photo = $this->_create_image(array("photos", "P1", "T1")); + + $request = (object)array("arguments" => explode("/", $photo->relative_url())); + + $this->assert_equal( + json_encode(array("status" => "OK", + "tags" => array("photos", "P1", "T1"))), + tag_rest::get($request)); + } + + public function tag_rest_get_items_test() { + $album = $this->_create_album(array("albums", "A1", "T1")); + $child = $this->_create_album(array("albums", "A1", "T1"), $album); + $photo = $this->_create_image(array("photos", "P1", "T1"), $child); + $sibling = $this->_create_image(array("photos", "P3"), $album); + $request = (object)array("arguments" => array("albums")); + + $resources = array(); + foreach (array($album, $child) as $resource) { + $resources[] = array("type" => $resource->type, + "has_children" => $resource->children_count() > 0, + "path" => $resource->relative_url(), + "thumb_url" => $resource->thumb_url(), + "thumb_dimensions" => array( + "width" => $resource->thumb_width, + "height" => $resource->thumb_height), + "has_thumb" => $resource->has_thumb(), + "title" => $resource->title); + + } + $this->assert_equal(json_encode(array("status" => "OK", "resources" => $resources)), + tag_rest::get($request)); + } + + public function tag_rest_add_tags_for_item_no_path_test() { + $request = (object)array("arguments" => array("new,one")); + + try { + tag_rest::post($request); + } catch (Rest_Exception $e) { + $this->assert_equal("400 Bad request", $e->getMessage()); + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + } + + public function tag_rest_add_tags_for_item_not_found_test() { + $photo = $this->_create_image(array("photos", "P1", "T1")); + $request = (object)array("path" => $photo->relative_url() . "b", + "arguments" => array("new,one")); + try { + tag_rest::post($request); + } catch (Kohana_404_Exception $k404) { + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + } + + public function tag_rest_add_tags_for_item_no_access_test() { + $photo = $this->_create_image(array("photos", "P1", "T1")); + $this->_create_user(); + $request = (object)array("path" => $photo->relative_url(), + "arguments" => array("new,one")); + + try { + tag_rest::post($request); + } catch (Kohana_404_Exception $k404) { + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + } + + public function tag_rest_add_tags_for_item_test() { + $album = $this->_create_album(array("albums", "A1", "T1")); + $child = $this->_create_album(array("albums", "A1", "T1"), $album); + $photo = $this->_create_image(array("photos", "P1", "T1"), $child); + $sibling = $this->_create_image(array("photos", "P3"), $album); + access::allow(identity::registered_users(), "edit", $child); + $this->_create_user(); + $request = (object)array("path" => $photo->relative_url(), + "arguments" => array("new,one")); + + $this->assert_equal( + json_encode(array("status" => "OK")), + tag_rest::post($request)); + $request = (object)array("arguments" => explode("/", $photo->relative_url())); + $this->assert_equal( + json_encode(array("status" => "OK", + "tags" => array("photos", "P1", "T1", "new", "one"))), + tag_rest::get($request)); + } + + public function tag_rest_update_tag_no_arguments_test() { + $request = (object)array("arguments" => array()); + + try { + tag_rest::put($request); + } catch (Rest_Exception $e) { + $this->assert_equal("400 Bad request", $e->getMessage()); + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + } + + public function tag_rest_update_tag_one_arguments_test() { + $request = (object)array("arguments" => array("photos")); + try { + tag_rest::put($request); + } catch (Rest_Exception $e) { + $this->assert_equal("400 Bad request", $e->getMessage()); + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + + $request = (object)array("arguments" => array(), "new_name" => "valid"); + try { + tag_rest::put($request); + } catch (Rest_Exception $e) { + $this->assert_equal("400 Bad request", $e->getMessage()); + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + } + + public function tag_rest_update_tags_not_found_test() { + $request = (object)array("arguments" => array("not"), "new_name" => "found"); + + try { + tag_rest::put($request); + } catch (Kohana_404_Exception $k404) { + } catch (Exception $e) { + $this->assert_false(true, $e->__toString()); + } + } + + public function tag_rest_update_tags_test() { + $album = $this->_create_album(array("albums", "A1", "T1")); + $child = $this->_create_album(array("albums", "A1", "T1"), $album); + $photo = $this->_create_image(array("photos", "P1", "T1"), $child); + $sibling = $this->_create_image(array("photos", "P3"), $album); + $request = (object)array("arguments" => array("albums"), "new_name" => "new name"); + + $this->assert_equal(json_encode(array("status" => "OK")), tag_rest::put($request)); + + $request = (object)array("arguments" => array("new name")); + $resources = array(); + foreach (array($album, $child) as $resource) { + $resources[] = array("type" => $resource->type, + "has_children" => $resource->children_count() > 0, + "path" => $resource->relative_url(), + "thumb_url" => $resource->thumb_url(), + "thumb_dimensions" => array( + "width" => $resource->thumb_width, + "height" => $resource->thumb_height), + "has_thumb" => $resource->has_thumb(), + "title" => $resource->title); + + } + $this->assert_equal( + json_encode(array("status" => "OK", "resources" => $resources)), + tag_rest::get($request)); + } + + public function tag_rest_delete_tag_test() { + $album = $this->_create_album(array("albums", "A1", "T1")); + $child = $this->_create_album(array("albums", "A1", "T1"), $album); + $photo = $this->_create_image(array("photos", "P1", "T1"), $child); + + $request = (object)array("arguments" => array("T1,P1")); + $this->assert_equal(json_encode(array("status" => "OK")), tag_rest::delete($request)); + + $request = (object)array("arguments" => array("T1,P1")); + $this->assert_equal(json_encode(array("status" => "OK")), + tag_rest::get($request)); + } + + public function tag_rest_delete_tagc_from_item_test() { + $album = $this->_create_album(array("albums", "A1", "T1")); + $child = $this->_create_album(array("albums", "A1", "T1"), $album); + $photo = $this->_create_image(array("photos", "P1", "T1"), $child); + $request = (object)array("arguments" => array("T1,P1"), + $photo->relative_url()); + + $this->assert_equal(json_encode(array("status" => "OK")), tag_rest::delete($request)); + + $request = (object)array("arguments" => explode("/", $photo->relative_url())); + $this->assert_equal(json_encode(array("status" => "OK", "tags" => array("photos"))), + tag_rest::get($request)); + } +} |