summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/controllers/albums.php135
-rw-r--r--core/controllers/items.php118
-rw-r--r--core/controllers/photos.php53
-rw-r--r--core/controllers/rest.php2
-rw-r--r--core/helpers/access.php13
-rw-r--r--core/helpers/album.php23
-rw-r--r--core/helpers/core_block.php4
-rw-r--r--core/helpers/core_menu.php37
-rw-r--r--core/helpers/photo.php16
-rw-r--r--core/helpers/rest.php2
-rw-r--r--core/models/item.php18
-rw-r--r--core/views/in_place_edit.html.php42
12 files changed, 244 insertions, 219 deletions
diff --git a/core/controllers/albums.php b/core/controllers/albums.php
index 0947e913..8d2b5b77 100644
--- a/core/controllers/albums.php
+++ b/core/controllers/albums.php
@@ -22,15 +22,13 @@ class Albums_Controller extends Items_Controller {
/**
* @see Rest_Controller::_show($resource)
*/
- public function _show($item) {
- if (!access::can("view", $item)) {
- Kohana::show_404();
- }
+ public function _show($album) {
+ access::required("view", $album);
$theme_name = module::get_var("core", "active_theme", "default");
$page_size = module::get_var("core", "page_size", 9);
$page = $this->input->get("page", "1");
- $children_count = $item->viewable()->children_count();
+ $children_count = $album->viewable()->children_count();
$offset = ($page-1) * $page_size;
// Make sure that the page references a valid offset
@@ -40,25 +38,136 @@ class Albums_Controller extends Items_Controller {
$template = new Theme_View("page.html", "album", $theme_name);
$template->set_global("page_size", $page_size);
- $template->set_global("item", $item);
- $template->set_global("children", $item->viewable()->children($page_size, $offset));
+ $template->set_global("item", $album);
+ $template->set_global("children", $album->viewable()->children($page_size, $offset));
$template->set_global("children_count", $children_count);
- $template->set_global("parents", $item->parents());
+ $template->set_global("parents", $album->parents());
$template->content = new View("album.html");
- $item->view_count++;
- $item->save();
+ $album->view_count++;
+ $album->save();
print $template;
}
/**
+ * @see Rest_Controller::_create($resource)
+ */
+ public function _create($album) {
+ access::required("edit", $album);
+
+ switch ($this->input->post("type")) {
+ case "album":
+ return $this->_create_album($album);
+
+ case "photo":
+ return $this->_create_photo($album);
+
+ default:
+ access::forbidden();
+ }
+ }
+
+ private function _create_album($album) {
+ access::required("edit", $album);
+
+ $form = album::get_add_form($album);
+ if ($form->validate()) {
+ $new_album = album::create(
+ $album,
+ $this->input->post("name"),
+ $this->input->post("title", $this->input->post("name")),
+ $this->input->post("description"),
+ user::active()->id);
+
+ log::add("content", "Created an album", log::INFO,
+ html::anchor("albums/$new_album->id", "view album"));
+ message::add(_("Successfully created album"));
+ rest::http_status(rest::CREATED);
+ rest::http_location(url::site("albums/$new_album->id"));
+ } else {
+ print $form;
+ }
+ }
+
+ private function _create_photo($album) {
+ access::required("edit", $album);
+
+ $form = photo::get_add_form($album);
+ if ($form->validate()) {
+ $photo = photo::create(
+ $album,
+ $this->input->post("file"),
+ $_FILES["file"]["name"],
+ $this->input->post("title", $this->input->post("name")),
+ $this->input->post("description"),
+ user::active()->id);
+
+ log::add("content", "Added a photo", log::INFO,
+ html::anchor("photos/$photo->id", "view photo"));
+ message::add(_("Successfully added photo"));
+ //rest::http_status(rest::CREATED);
+ //rest::http_location(url::site("photos/$photo->id"));
+ print "<h1>this is a response</h1>";
+ } else {
+ print $form;
+ }
+ }
+
+ /**
+ * @see Rest_Controller::_update($resource)
+ */
+ public function _update($album) {
+ access::required("edit", $album);
+
+ $form = album::get_edit_form($album);
+ if ($form->validate()) {
+ // @todo implement changing the name. This is not trivial, we have
+ // to check for conflicts and rename the album itself, etc. Needs an
+ // api method.
+ $album->title = $form->edit_album->title->value;
+ $album->description = $form->edit_album->description->value;
+ $album->save();
+
+ module::event("album_changed", $album);
+
+ log::add("content", "Updated album", log::INFO, "<a href=\"albums/$album->id\">view</a>");
+ message::add(_("Successfully saved album"));
+ rest::http_status(rest::CREATED);
+ rest::http_location(url::site("albums/$album->id"));
+ } else {
+ rest::html($form);
+ }
+ rest::respond();
+ }
+
+ /**
* @see Rest_Controller::_form_add($parameters)
*/
- public function _form_add($parent_id) {
- $parent = ORM::factory("item", $parent_id);
+ public function _form_add($album_id) {
+ $album = ORM::factory("item", $album_id);
+ access::required("edit", $album);
+
+ switch ($this->input->get("type")) {
+ case "album":
+ print album::get_add_form($album)->render();
+ break;
+
+ case "photo":
+ print photo::get_add_form($album)->render();
+ break;
- print album::get_add_form($parent)->render();
+ default:
+ kohana::show_404();
+ }
}
+ /**
+ * @see Rest_Controller::_form_add($parameters)
+ */
+ public function _form_edit($album) {
+ access::required("edit", $album);
+
+ print album::get_edit_form($album);
+ }
}
diff --git a/core/controllers/items.php b/core/controllers/items.php
index b79d28d2..1cb24324 100644
--- a/core/controllers/items.php
+++ b/core/controllers/items.php
@@ -45,125 +45,19 @@ class Items_Controller extends REST_Controller {
// Redirect to the more specific resource type, since it will render
// differently. We could also just delegate here, but it feels more appropriate
// to have a single canonical resource mapping.
+ access::required("view", $item);
return url::redirect("{$item->type}s/$item->id");
}
- public function _create($item) {
- // @todo Productionize this code
- // 1) Add security checks
- $owner_id = user::active()->id;
-
- switch ($this->input->post("type")) {
- case "album":
- $album = album::create(
- $item,
- $this->input->post("name"),
- $this->input->post("title", $this->input->post("name")),
- $this->input->post("description"),
- $owner_id);
- log::add("content", "Created an album", log::INFO,
- html::anchor("albums/$album->id", "view album"));
- message::add(_("Successfully created album"));
- if (request::is_ajax()) {
- rest::http_status(rest::CREATED);
- rest::http_location(url::site("albums/$album->id"));
- } else {
- url::redirect("albums/$album->id");
- }
- break;
-
- case "photo":
- if (is_array($_FILES["file"]["name"])) {
- $count = count($_FILES["file"]["name"]);
- for ($i = 0; $i < $count - 1; $i++) {
- if ($_FILES["file"]["error"][$i] == 0) {
- $photo = photo::create(
- $item,
- $_FILES["file"]["tmp_name"][$i],
- $_FILES["file"]["name"][$i],
- $_FILES["file"]["name"][$i],
- "", $owner_id);
- } else {
- log::add("content", "Error uploading photo", log::WARNING);
- message::add(sprintf(_("Error uploading photo %s"),
- html::specialchars($_FILES["file"]["name"][$i])));
- }
- }
- log::add("content", "Added $count photos", log::INFO,
- html::anchor("albums/$item->id", "view album"));
- if (request::is_ajax()) {
- rest::http_status(rest::CREATED);
- rest::http_location(url::site("albums/$item->id"));
- } else {
- url::redirect("albums/$item->id");
- }
- } else {
- $photo = photo::create(
- $item,
- $_FILES["file"]["tmp_name"],
- $_FILES["file"]["name"],
- $this->input->post("title", $this->input->post("name")),
- $this->input->post("description"),
- $owner_id);
- log::add("content", "Added a photo", log::INFO,
- html::anchor("photos/$photo->id", "view photo"));
- message::add(_("Successfully added photo"));
- if (request::is_ajax()) {
- rest::http_status(rest::CREATED);
- rest::http_location(url::site("photos/$photo->id"));
- } else {
- url::redirect("photos/$photo->id");
- }
- }
- break;
- }
- }
-
public function _delete($item) {
- // @todo Productionize this code
- // 1) Add security checks
- $parent = $item->parent();
- if ($parent->id) {
- module::event("{$item->type}_before_delete", $item);
-
- $item->delete();
- }
+ throw new Exception("@todo Item_Controller::_delete NOT IMPLEMENTED");
+ }
- url::redirect("{$parent->type}s/{$parent->id}");
+ public function _create($item) {
+ throw new Exception("@todo Item_Controller::_create NOT IMPLEMENTED");
}
public function _update($item) {
- // @todo Productionize this
- // 1) Figure out how to do the right validation here. Validate the form input and apply it to
- // the model as appropriate.
- // 2) Figure out how to dispatch according to the needs of the client. Ajax requests from
- // jeditable will want the changed field back, and possibly the whole item in json.
- //
- // For now let's establish a simple protocol where the client passes in a __return parameter
- // that specifies which field it wants back from the item. Later on we can expand that to
- // include a data format, etc.
-
- // These fields are safe to change
- $post = $this->input->post();
- foreach ($post as $key => $value) {
- switch ($key) {
- case "title":
- case "description":
- $item->$key = $value;
- break;
- }
- }
-
- // @todo Support additional fields
- // These fields require additional work if you change them
- // parent_id, owner_id
-
- $item->save();
-
- module::event("{$item->type}_changed", $item);
-
- if (array_key_exists("_return", $post)) {
- print $item->{$post["_return"]};
- }
+ throw new Exception("@todo Item_Controller::_update NOT IMPLEMENTED");
}
}
diff --git a/core/controllers/photos.php b/core/controllers/photos.php
index 465c291d..730cfd2c 100644
--- a/core/controllers/photos.php
+++ b/core/controllers/photos.php
@@ -22,34 +22,59 @@ class Photos_Controller extends Items_Controller {
/**
* @see Rest_Controller::_show($resource)
*/
- public function _show($item) {
- if (!access::can("view", $item)) {
- return Kohana::show_404();
- }
+ public function _show($photo) {
+ access::required("view", $photo);
$theme_name = module::get_var("core", "active_theme", "default");
$template = new Theme_View("page.html", "photo", $theme_name);
- $template->set_global('item', $item);
- $template->set_global('children', $item->children());
- $template->set_global('children_count', $item->children_count());
- $template->set_global('parents', $item->parents());
+ $template->set_global('item', $photo);
+ $template->set_global('children', array());
+ $template->set_global('children_count', $photo->children_count());
+ $template->set_global('parents', $photo->parents());
$template->content = new View("photo.html");
- $item->view_count++;
- $item->save();
+ $photo->view_count++;
+ $photo->save();
print $template;
}
/**
- * @see Rest_Controller::_form_add($parameters)
+ * @see Rest_Controller::_update($resource)
*/
- public function _form_add($parent_id) {
- $parent = ORM::factory("item", $parent_id);
+ public function _update($photo) {
+ access::required("edit", $photo);
+
+ $form = photo::get_edit_form($photo);
+ if ($form->validate()) {
+ // @todo implement changing the name. This is not trivial, we have
+ // to check for conflicts and rename the album itself, etc. Needs an
+ // api method.
+ $photo->title = $form->edit_photo->title->value;
+ $photo->description = $form->edit_photo->description->value;
+ $photo->save();
+
+ module::event("photo_changed", $photo);
- print photo::get_add_form($parent)->render();
+ log::add("content", "Updated photo", log::INFO, "<a href=\"photos/$photo->id\">view</a>");
+ message::add(_("Successfully saved photo"));
+
+ rest::http_status(rest::FOUND);
+ rest::http_location(url::site("photos/$photo->id"));
+ } else {
+ rest::html($form);
+ }
+ rest::respond();
+ }
+
+ /**
+ * @see Rest_Controller::_form_edit($resource)
+ */
+ public function _form_edit($photo) {
+ access::required("edit", $photo);
+ print photo::get_edit_form($photo);
}
}
diff --git a/core/controllers/rest.php b/core/controllers/rest.php
index c10bbcdb..0ac7a1c9 100644
--- a/core/controllers/rest.php
+++ b/core/controllers/rest.php
@@ -118,7 +118,7 @@ abstract class REST_Controller extends Controller {
/* We're adding a new item, pass along any additional parameters. */
public function form_add($parameters) {
- return $this->_form_add($parameters);
+ return $this->_form_add($parameters);
}
/**
diff --git a/core/helpers/access.php b/core/helpers/access.php
index ab113375..c6ee1fcc 100644
--- a/core/helpers/access.php
+++ b/core/helpers/access.php
@@ -107,6 +107,19 @@ class access_Core {
}
/**
+ * If the active user does not have this permission, failed with an access::forbidden().
+ *
+ * @param string $perm_name
+ * @param Item_Model $item
+ * @return boolean
+ */
+ public static function required($perm_name, $item) {
+ if (!access::can($perm_name, $item)) {
+ access::forbidden();
+ }
+ }
+
+ /**
* Terminate immediately with an HTTP 503 Forbidden response.
*/
public static function forbidden() {
diff --git a/core/helpers/album.php b/core/helpers/album.php
index 70b05006..82697254 100644
--- a/core/helpers/album.php
+++ b/core/helpers/album.php
@@ -65,13 +65,28 @@ class album_Core {
static function get_add_form($parent) {
$form = new Forge("albums/{$parent->id}", "", "post", array("id" => "gAddAlbumForm"));
- $group = $form->group(sprintf(_("Add Album to %s"), $parent->title));
- $group->input("name")->label(true);
- $group->input("title")->label(true);
- $group->input("description")->label(true);
+ $group = $form->group("add_album")->label(sprintf(_("Add Album to %s"), $parent->title));
+ $group->input("name")->label(_("Name"));
+ $group->input("title")->label(_("Title"));
+ $group->textarea("description")->label(_("Description"));
$group->hidden("type")->value("album");
$group->submit(_("Create"));
$form->add_rules_from(ORM::factory("item"));
return $form;
}
+
+ static function get_edit_form($parent) {
+ $form = new Forge("albums/{$parent->id}", "", "post", array("id" => "gEditAlbumForm"));
+ $form->hidden("_method")->value("put");
+ $group = $form->group("edit_album")->label(_("Edit Album"));
+ if ($parent->id != 1) {
+ $group->input("name")->label(_("Name"))->value($parent->name);
+ }
+ $group->input("title")->label(_("Title"))->value($parent->title);
+ $group->textarea("description")->label(_("Description"))->value($parent->description);
+ $group->hidden("type")->value("album");
+ $group->submit(_("Modify"));
+ $form->add_rules_from(ORM::factory("item"));
+ return $form;
+ }
}
diff --git a/core/helpers/core_block.php b/core/helpers/core_block.php
index ec1ee066..b7e4ad44 100644
--- a/core/helpers/core_block.php
+++ b/core/helpers/core_block.php
@@ -24,10 +24,6 @@ class core_block_Core {
$profiler = new Profiler();
$profiler->render();
}
-
- if ($theme->item() && access::can("edit", $theme->item())) {
- return new View("in_place_edit.html");
- }
}
public static function admin_page_bottom($theme) {
diff --git a/core/helpers/core_menu.php b/core/helpers/core_menu.php
index 63a742ee..685ccf64 100644
--- a/core/helpers/core_menu.php
+++ b/core/helpers/core_menu.php
@@ -32,24 +32,31 @@ class core_menu_Core {
$item = $theme->item();
if (!user::active()->guest) {
- $admin_menu = Menu::factory("submenu")
- ->id("admin_menu")
- ->label(_("Admin"));
- $menu->append($admin_menu);
+ $menu->append($admin_menu = Menu::factory("submenu")
+ ->id("admin_menu")
+ ->label(_("Admin")));
}
if ($item && access::can("edit", $item)) {
- $menu->append(Menu::factory("submenu")
- ->id("options_menu")
- ->label(_("Options"))
- ->append(Menu::factory("dialog")
- ->id("add_item")
- ->label(_("Add an item"))
- ->url(url::site("form/add/photos/$item->id")))
- ->append(Menu::factory("dialog")
- ->id("add_album")
- ->label(_("Add album"))
- ->url(url::site("form/add/albums/$item->id"))));
+ $menu->append($options_menu = Menu::factory("submenu")
+ ->id("options_menu")
+ ->label(_("Options"))
+ ->append(Menu::factory("dialog")
+ ->id("edit_item")
+ ->label($item->type == "album" ? _("Edit album") : _("Edit photo"))
+ ->url(url::site("form/edit/{$item->type}s/$item->id"))));
+
+ if ($item->type == "album") {
+ $options_menu
+ ->append(Menu::factory("dialog")
+ ->id("add_item")
+ ->label(_("Add a photo"))
+ ->url(url::site("form/add/albums/$item->id?type=photo")))
+ ->append(Menu::factory("dialog")
+ ->id("add_album")
+ ->label(_("Add an album"))
+ ->url(url::site("form/add/albums/$item->id?type=album")));
+ }
$admin_menu->append(Menu::factory("dialog")
->id("edit")
diff --git a/core/helpers/photo.php b/core/helpers/photo.php
index e5ed2b22..29f2ac6f 100644
--- a/core/helpers/photo.php
+++ b/core/helpers/photo.php
@@ -99,14 +99,26 @@ class photo_Core {
$group = $form->group("add_photo")->label(sprintf(_("Add Photo to %s"), $parent->title));
$group->input("name")->label(_("Name"));
$group->input("title")->label(_("Title"));
- $group->textarea("description")->label(_("Description"))->rules("length[0, 255");
- $group->upload("file")->label(_("File"))->rules("allow[jpg,png,gif,tiff]");
+ $group->textarea("description")->label(_("Description"));
+ $group->upload("file")->label(_("File"))->rules("required|allow[jpg,png,gif]");
$group->hidden("type")->value("photo");
$group->submit(_("Upload"));
$form->add_rules_from(ORM::factory("item"));
return $form;
}
+ static function get_edit_form($photo) {
+ $form = new Forge("photos/$photo->id", "", "post", array("id" => "gEditPhotoForm"));
+ $form->hidden("_method")->value("put");
+ $group = $form->group("edit_photo")->label(_("Edit Photo"));
+ $group->input("name")->label(_("Name"))->value($photo->name);
+ $group->input("title")->label(_("Title"))->value($photo->title);
+ $group->textarea("description")->label(_("Description"))->value($photo->description);
+ $group->submit(_("Modify"));
+ $form->add_rules_from(ORM::factory("item"));
+ return $form;
+ }
+
/**
* Return scaled width and height.
*
diff --git a/core/helpers/rest.php b/core/helpers/rest.php
index a0d6e732..061c2f6b 100644
--- a/core/helpers/rest.php
+++ b/core/helpers/rest.php
@@ -23,8 +23,10 @@ class rest_Core {
const CREATED = "201 Created";
const ACCEPTED = "202 Accepted";
const NO_CONTENT = "204 No Content";
+ const RESET_CONTENT = "205 Reset Content";
const PARTIAL_CONTENT = "206 Partial Content";
const MOVED_PERMANENTLY = "301 Moved Permanently";
+ const FOUND = "302 Found";
const SEE_OTHER = "303 See Other";
const NOT_MODIFIED = "304 Not Modified";
const TEMPORARY_REDIRECT = "307 Temporary Redirect";
diff --git a/core/models/item.php b/core/models/item.php
index cd2e1670..a21aaf16 100644
--- a/core/models/item.php
+++ b/core/models/item.php
@@ -22,7 +22,11 @@ class Item_Model extends ORM_MPTT {
private $relative_path = null;
private $view_restrictions = array();
- var $rules = array();
+ var $rules = array(
+ "name" => "required|length[0,255]",
+ "title" => "required|length[0,255]",
+ "description" => "length[0,255]"
+ );
/**
* Add a set of restrictions to any following queries to restrict access only to items
@@ -173,17 +177,7 @@ class Item_Model extends ORM_MPTT {
* @see ORM::__get()
*/
public function __get($column) {
- if (substr($column, -5) == "_edit") {
- $real_column = substr($column, 0, strlen($column) - 5);
- $editable = $this->type == "album" ?
- access::can("edit", $this) : access::can("edit", $this->parent());
- if ($editable) {
- return "<span class=\"gInPlaceEdit gEditField-{$this->id}-{$real_column}\">" .
- "{$this->$real_column}</span>";
- } else {
- return parent::__get($real_column);
- }
- } else if ($column == "owner") {
+ if ($column == "owner") {
// This relationship depends on an outside module, which may not be present so handle
// failures gracefully.
try {
diff --git a/core/views/in_place_edit.html.php b/core/views/in_place_edit.html.php
deleted file mode 100644
index 02f41e19..00000000
--- a/core/views/in_place_edit.html.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<? defined("SYSPATH") or die("No direct script access."); ?>
-<script type="text/javascript">
-// <![CDATA[
-$(document).ready(function() {
- ajax_update = function(className, id) {
- return function(value, settings) {
- var post_data = {'_method': 'put', '_return': settings.name};
- post_data[settings.name] = value;
- $.post("<?= url::site("items/__ID__") ?>".replace("__ID__", id),
- post_data,
- function(data, textStatus) {
- if (textStatus == "success") {
- $(className).html(data);
- }
- },
- "html");
- }
- }
-
- var seen_before = {};
- var editable = $("span.gInPlaceEdit");
- for (i = 0; i < editable.length; i++) {
- var matches = editable[i].className.match(/gEditField-(\d+)-(\S+)/);
- if (matches && matches.length == 3) {
- var className = "." + matches[0];
- if (!seen_before[className]) {
- $(className).editable(
- ajax_update(className, matches[1]),
- {indicator : "<?= _("Saving...") ?>",
- tooltip : "<?= _("Double-click to edit...") ?>",
- event : "dblclick",
- style : "inherit",
- name : matches[2],
- select : true}
- );
- seen_before[className] = 1;
- }
- }
- }
-});
-// ]]>
-</script>