From 5b3b675b6d8a1cd9a5f2b9455c551791e18d88ff Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Thu, 16 Jul 2009 11:19:34 -0700 Subject: Non-trivial changes to the event handling code: 1) The item_updated event no longer takes the old and new items. Instead we overload ORM to track the original data and make that available via the item. This will allow us to move event publishing down into the API methods which in turn will give us more stability since we won't require each controller to remember to do it. 2) ORM class now tracks the original values. It doesn't track the original relationships (no need for that, yet) 3) Added new events: item_deleted group_deleted user_deleted --- modules/gallery/models/item.php | 3 +++ 1 file changed, 3 insertions(+) (limited to 'modules/gallery/models') diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php index 51037073..80f19d26 100644 --- a/modules/gallery/models/item.php +++ b/modules/gallery/models/item.php @@ -93,6 +93,7 @@ class Item_Model extends ORM_MPTT { } public function delete() { + $old = clone $this; module::event("item_before_delete", $this); $parent = $this->parent(); @@ -114,6 +115,8 @@ class Item_Model extends ORM_MPTT { @unlink($resize_path); @unlink($thumb_path); } + + module::event("item_deleted", $old); } /** -- cgit v1.2.3 From 0f766b149d0cee7af664f2321fddc6f04cda70ac Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Thu, 16 Jul 2009 12:29:16 -0700 Subject: Second non-trivial change to the event code. We now publish model related events from within the model handling code. The only exception to this currently is item_created which is challenging because we have to save the item using ORM_MPTT::add_to_parent() before the object itself is fully set up. When we get that down to one call to save() we can publish that event from within the model also. --- modules/comment/controllers/admin_comments.php | 4 ---- modules/comment/controllers/comments.php | 1 - modules/comment/helpers/comment.php | 5 ----- modules/comment/models/comment.php | 17 ++++++++++++++++- modules/exif/helpers/exif_event.php | 4 +++- modules/gallery/controllers/albums.php | 3 --- modules/gallery/controllers/movies.php | 3 --- modules/gallery/controllers/photos.php | 3 --- modules/gallery/helpers/album.php | 2 ++ modules/gallery/helpers/movie.php | 2 ++ modules/gallery/helpers/photo.php | 2 ++ modules/gallery/models/item.php | 7 ++++++- modules/organize/controllers/organize.php | 4 ---- modules/user/helpers/group.php | 1 - modules/user/helpers/user.php | 1 - modules/user/models/group.php | 13 +++++++++++++ modules/user/models/user.php | 13 +++++++++++++ 17 files changed, 57 insertions(+), 28 deletions(-) (limited to 'modules/gallery/models') diff --git a/modules/comment/controllers/admin_comments.php b/modules/comment/controllers/admin_comments.php index ea76b188..a164f79f 100644 --- a/modules/comment/controllers/admin_comments.php +++ b/modules/comment/controllers/admin_comments.php @@ -113,10 +113,6 @@ class Admin_Comments_Controller extends Admin_Controller { if ($comment->loaded) { $comment->state = $state; $comment->save(); - module::event("comment_updated", $comment); - if ($comment->original("state") == "published" || $comment->state == "published") { - module::event("item_related_update", $comment->item()); - } } } diff --git a/modules/comment/controllers/comments.php b/modules/comment/controllers/comments.php index 02c38491..9fb4796e 100644 --- a/modules/comment/controllers/comments.php +++ b/modules/comment/controllers/comments.php @@ -152,7 +152,6 @@ class Comments_Controller extends REST_Controller { $comment->url = $form->edit_comment->url->value; $comment->text = $form->edit_comment->text->value; $comment->save(); - module::event("comment_updated", $comment); print json_encode( array("result" => "success", diff --git a/modules/comment/helpers/comment.php b/modules/comment/helpers/comment.php index 08cba096..3d743325 100644 --- a/modules/comment/helpers/comment.php +++ b/modules/comment/helpers/comment.php @@ -61,11 +61,6 @@ class comment_Core { $comment->server_remote_port = substr($input->server("REMOTE_PORT"), 0, 16); $comment->save(); - module::event("comment_created", $comment); - if ($comment->state == "published") { - module::event("item_related_update", $comment->item()); - } - return $comment; } diff --git a/modules/comment/models/comment.php b/modules/comment/models/comment.php index 22c465df..551fb245 100644 --- a/modules/comment/models/comment.php +++ b/modules/comment/models/comment.php @@ -61,8 +61,23 @@ class Comment_Model extends ORM { $this->updated = time(); if (!$this->loaded && empty($this->created)) { $this->created = $this->updated; + $created = true; } } - return parent::save(); + parent::save(); + + if (isset($created)) { + module::event("comment_created", $this); + } else { + module::event("comment_updated", $this); + } + + // We only notify on the related items if we're making a visible change, which means moving in + // or out of a published state + if ($this->original("state") == "published" || $this->state == "published") { + module::event("item_related_update", $this->item()); + } + + return $this; } } diff --git a/modules/exif/helpers/exif_event.php b/modules/exif/helpers/exif_event.php index 24243f4d..826ec959 100644 --- a/modules/exif/helpers/exif_event.php +++ b/modules/exif/helpers/exif_event.php @@ -19,7 +19,9 @@ */ class exif_event_Core { static function item_created($item) { - exif::extract($item); + if (!$item->is_album()) { + exif::extract($item); + } } static function item_deleted($item) { diff --git a/modules/gallery/controllers/albums.php b/modules/gallery/controllers/albums.php index c378e3ce..9980b676 100644 --- a/modules/gallery/controllers/albums.php +++ b/modules/gallery/controllers/albums.php @@ -182,7 +182,6 @@ class Albums_Controller extends Items_Controller { } if ($valid) { - $orig = clone $album; $album->title = $form->edit_album->title->value; $album->description = $form->edit_album->description->value; $album->sort_column = $form->edit_album->sort_order->column->value; @@ -192,8 +191,6 @@ class Albums_Controller extends Items_Controller { } $album->save(); - module::event("item_updated", $album); - log::success("content", "Updated album", "id\">view"); message::success( t("Saved album %album_title", array("album_title" => p::clean($album->title)))); diff --git a/modules/gallery/controllers/movies.php b/modules/gallery/controllers/movies.php index fc511082..d954ad8d 100644 --- a/modules/gallery/controllers/movies.php +++ b/modules/gallery/controllers/movies.php @@ -85,14 +85,11 @@ class Movies_Controller extends Items_Controller { } if ($valid) { - $orig = clone $photo; $photo->title = $form->edit_photo->title->value; $photo->description = $form->edit_photo->description->value; $photo->rename($form->edit_photo->filename->value); $photo->save(); - module::event("item_updated", $photo); - log::success("content", "Updated photo", "id\">view"); message::success( t("Saved photo %photo_title", array("photo_title" => p::clean($photo->title)))); diff --git a/modules/gallery/controllers/photos.php b/modules/gallery/controllers/photos.php index 77627009..9ce6ed23 100644 --- a/modules/gallery/controllers/photos.php +++ b/modules/gallery/controllers/photos.php @@ -78,14 +78,11 @@ class Photos_Controller extends Items_Controller { } if ($valid) { - $orig = clone $photo; $photo->title = $form->edit_photo->title->value; $photo->description = $form->edit_photo->description->value; $photo->rename($form->edit_photo->filename->value); $photo->save(); - module::event("item_updated", $photo); - log::success("content", "Updated photo", "id\">view"); message::success( t("Saved photo %photo_title", array("photo_title" => p::clean($photo->title)))); diff --git a/modules/gallery/helpers/album.php b/modules/gallery/helpers/album.php index 1197f243..f1a6c060 100644 --- a/modules/gallery/helpers/album.php +++ b/modules/gallery/helpers/album.php @@ -71,6 +71,8 @@ class album_Core { mkdir(dirname($album->thumb_path())); mkdir(dirname($album->resize_path())); + // @todo: publish this from inside Item_Model::save() when we refactor to the point where + // there's only one save() happening here. module::event("item_created", $album); return $album; diff --git a/modules/gallery/helpers/movie.php b/modules/gallery/helpers/movie.php index d62ead76..4f4169d5 100644 --- a/modules/gallery/helpers/movie.php +++ b/modules/gallery/helpers/movie.php @@ -102,6 +102,8 @@ class movie_Core { copy($filename, $movie->file_path()); + // @todo: publish this from inside Item_Model::save() when we refactor to the point where + // there's only one save() happening here. module::event("item_created", $movie); // Build our thumbnail diff --git a/modules/gallery/helpers/photo.php b/modules/gallery/helpers/photo.php index e8a4f357..ce964c14 100644 --- a/modules/gallery/helpers/photo.php +++ b/modules/gallery/helpers/photo.php @@ -105,6 +105,8 @@ class photo_Core { copy($filename, $photo->file_path()); + // @todo: publish this from inside Item_Model::save() when we refactor to the point where + // there's only one save() happening here. module::event("item_created", $photo); // Build our thumbnail/resizes diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php index 80f19d26..94e2fcf7 100644 --- a/modules/gallery/models/item.php +++ b/modules/gallery/models/item.php @@ -350,9 +350,14 @@ class Item_Model extends ORM_MPTT { $this->created = $this->updated; $r = ORM::factory("item")->select("MAX(weight) as max_weight")->find(); $this->weight = $r->max_weight + 1; + $created = 1; } } - return parent::save(); + parent::save(); + if (!isset($created)) { + module::event("item_updated", $this); + } + return $this; } /** diff --git a/modules/organize/controllers/organize.php b/modules/organize/controllers/organize.php index 54e04071..27852904 100644 --- a/modules/organize/controllers/organize.php +++ b/modules/organize/controllers/organize.php @@ -279,8 +279,6 @@ class Organize_Controller extends Controller { $item->rename($form->dirname->value); $item->save(); - module::event("item_updated", $item); - if ($item->is_album()) { log::success("content", "Updated album", "id\">view"); $message = t("Saved album %album_title", array("album_title" => p::purify($item->title))); @@ -322,8 +320,6 @@ class Organize_Controller extends Controller { $item->sort_order = $form->direction->value; $item->save(); - module::event("item_updated", $item); - log::success("content", "Updated album", "id\">view"); $message = t("Saved album %album_title", array("album_title" => p::purify($item->title))); print json_encode(array("form" => $form->__toString(), "message" => $message)); diff --git a/modules/user/helpers/group.php b/modules/user/helpers/group.php index 1dace840..04e6efd6 100644 --- a/modules/user/helpers/group.php +++ b/modules/user/helpers/group.php @@ -39,7 +39,6 @@ class group_Core { $group->name = $name; $group->save(); - module::event("group_created", $group); return $group; } diff --git a/modules/user/helpers/user.php b/modules/user/helpers/user.php index a59588f8..4105d745 100644 --- a/modules/user/helpers/user.php +++ b/modules/user/helpers/user.php @@ -202,7 +202,6 @@ class user_Core { $user->add(group::registered_users()); $user->save(); - module::event("user_created", $user); return $user; } diff --git a/modules/user/models/group.php b/modules/user/models/group.php index e0724e30..bb3fb58b 100644 --- a/modules/user/models/group.php +++ b/modules/user/models/group.php @@ -32,4 +32,17 @@ class Group_Model extends ORM { parent::delete($id); module::event("group_deleted", $old); } + + public function save() { + if (!$this->loaded) { + $created = 1; + } + parent::save(); + if (isset($created)) { + module::event("group_created", $this); + } else { + module::event("group_updated", $this); + } + return $this; + } } \ No newline at end of file diff --git a/modules/user/models/user.php b/modules/user/models/user.php index e3260270..0234f186 100644 --- a/modules/user/models/user.php +++ b/modules/user/models/user.php @@ -59,4 +59,17 @@ class User_Model extends ORM { return sprintf("http://www.gravatar.com/avatar/%s.jpg?s=%d&r=pg%s", md5($this->email), $size, $default ? "&d=" . urlencode($default) : ""); } + + public function save() { + if (!$this->loaded) { + $created = 1; + } + parent::save(); + if (isset($created)) { + module::event("user_created", $this); + } else { + module::event("user_updated", $this); + } + return $this; + } } \ No newline at end of file -- cgit v1.2.3 From 8a6556b30bc34d69284df6246f4010a8835f3bc2 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Fri, 17 Jul 2009 08:14:08 -0700 Subject: Fix a bug where moved items don't properly inherit permissions from their new target. After each move, recalculate the permissions for the new parent's hierarchy. Fixes ticket #552 --- modules/gallery/helpers/access.php | 15 ++++++++++++ modules/gallery/helpers/gallery_event.php | 4 ++++ modules/gallery/models/item.php | 6 +++-- modules/gallery/tests/Access_Helper_Test.php | 36 ++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) (limited to 'modules/gallery/models') diff --git a/modules/gallery/helpers/access.php b/modules/gallery/helpers/access.php index c48f0b79..5dd1e465 100644 --- a/modules/gallery/helpers/access.php +++ b/modules/gallery/helpers/access.php @@ -243,6 +243,21 @@ class access_Core { self::_set($group, $perm_name, $item, null); } + /** + * Recalculate the permissions for a given item and its hierarchy. $item must be an album. + */ + static function recalculate_permissions($item) { + foreach (self::_get_all_groups() as $group) { + foreach (ORM::factory("permission")->find_all() as $perm) { + if ($perm->name == "view") { + self::_update_access_view_cache($group, $item); + } else { + self::_update_access_non_view_cache($group, $perm->name, $item); + } + } + } + } + /** * Register a permission so that modules can use it. * diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php index 2f3a64d3..1cd96372 100644 --- a/modules/gallery/helpers/gallery_event.php +++ b/modules/gallery/helpers/gallery_event.php @@ -35,6 +35,10 @@ class gallery_event_Core { access::delete_item($item); } + static function item_moved($item, $old_parent) { + access::recalculate_permissions($item->parent()); + } + static function user_login($user) { // If this user is an admin, check to see if there are any post-install tasks that we need // to run and take care of those now. diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php index 94e2fcf7..6512e9e5 100644 --- a/modules/gallery/models/item.php +++ b/modules/gallery/models/item.php @@ -122,8 +122,8 @@ class Item_Model extends ORM_MPTT { /** * Move this item to the specified target. * @chainable - * @param Item_Model $target Target item (must be an album - * @return ORM_MTPP + * @param Item_Model $target Target item (must be an album) + * @return ORM_MPTT */ function move_to($target) { if (!$target->is_album()) { @@ -137,6 +137,7 @@ class Item_Model extends ORM_MPTT { $original_path = $this->file_path(); $original_resize_path = $this->resize_path(); $original_thumb_path = $this->thumb_path(); + $original_parent = $this->parent(); parent::move_to($target, true); $this->relative_path_cache = null; @@ -154,6 +155,7 @@ class Item_Model extends ORM_MPTT { @rename($original_thumb_path, $this->thumb_path()); } + module::event("item_moved", $this, $original_parent); return $this; } diff --git a/modules/gallery/tests/Access_Helper_Test.php b/modules/gallery/tests/Access_Helper_Test.php index d71bf971..1352b493 100644 --- a/modules/gallery/tests/Access_Helper_Test.php +++ b/modules/gallery/tests/Access_Helper_Test.php @@ -324,4 +324,40 @@ class Access_Helper_Test extends Unit_Test_Case { $this->assert_false(file_exists($album->resize_path() . "/.htaccess")); $this->assert_false(file_exists($album->thumb_path() . "/.htaccess")); } + + public function moved_items_inherit_new_permissions_test() { + user::set_active(user::lookup_by_name("admin")); + + $root = ORM::factory("item", 1); + $public_album = album::create($root, rand(), "public album"); + $public_photo = photo::create($public_album, MODPATH . "gallery/images/gallery.png", "", ""); + access::allow(group::everybody(), "view", $public_album); + + $root->reload(); // Account for MPTT changes + + $private_album = album::create($root, rand(), "private album"); + access::deny(group::everybody(), "view", $private_album); + $private_photo = photo::create($private_album, MODPATH . "gallery/images/gallery.png", "", ""); + + // Make sure that we now have a public photo and private photo. + $this->assert_true(access::group_can(group::everybody(), "view", $public_photo)); + $this->assert_false(access::group_can(group::everybody(), "view", $private_photo)); + + // Swap the photos + item::move($public_photo, $private_album); + $private_album->reload(); // Reload to get new MPTT pointers and cached perms. + $public_album->reload(); + $private_photo->reload(); + $public_photo->reload(); + + item::move($private_photo, $public_album); + $private_album->reload(); // Reload to get new MPTT pointers and cached perms. + $public_album->reload(); + $private_photo->reload(); + $public_photo->reload(); + + // Make sure that the public_photo is now private, and the private_photo is now public. + $this->assert_false(access::group_can(group::everybody(), "view", $public_photo)); + $this->assert_true(access::group_can(group::everybody(), "view", $private_photo)); + } } -- cgit v1.2.3 From cd907c2b42f8b50ebe6d490aab42365e16deb258 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Fri, 17 Jul 2009 12:51:27 -0700 Subject: Change model_cache::clear() API to clear everything. This prevents old ORM relationships from hanging around, which was causing problems when doing MPTT manipulations (resulting in incorrect permission propagation-- very bad!) --- modules/gallery/helpers/access.php | 4 ++++ modules/gallery/helpers/item.php | 4 ++-- modules/gallery/helpers/model_cache.php | 6 ++---- modules/gallery/libraries/MY_ORM.php | 2 +- modules/gallery/libraries/ORM_MPTT.php | 1 + modules/gallery/models/item.php | 1 + 6 files changed, 11 insertions(+), 7 deletions(-) (limited to 'modules/gallery/models') diff --git a/modules/gallery/helpers/access.php b/modules/gallery/helpers/access.php index 5dd1e465..63324e5d 100644 --- a/modules/gallery/helpers/access.php +++ b/modules/gallery/helpers/access.php @@ -205,6 +205,7 @@ class access_Core { } self::_update_htaccess_files($album, $group, $perm_name, $value); + model_cache::clear(); } /** @@ -256,6 +257,7 @@ class access_Core { } } } + model_cache::clear(); } /** @@ -426,6 +428,7 @@ class access_Core { $cache_table = $perm_name == "view" ? "items" : "access_caches"; $db->query("ALTER TABLE {{$cache_table}} DROP `$field`"); $db->query("ALTER TABLE {access_intents} DROP `$field`"); + model_cache::clear(); ORM::factory("access_intent")->clear_cache(); } @@ -443,6 +446,7 @@ class access_Core { $db->query("ALTER TABLE {{$cache_table}} ADD `$field` SMALLINT NOT NULL DEFAULT 0"); $db->query("ALTER TABLE {access_intents} ADD `$field` BOOLEAN DEFAULT NULL"); $db->update("access_intents", array($field => 0), array("item_id" => 1)); + model_cache::clear(); ORM::factory("access_intent")->clear_cache(); } diff --git a/modules/gallery/helpers/item.php b/modules/gallery/helpers/item.php index f40b5c97..80c25862 100644 --- a/modules/gallery/helpers/item.php +++ b/modules/gallery/helpers/item.php @@ -53,7 +53,7 @@ class item_Core { access::required("view", $parent); access::required("edit", $parent); - model_cache::clear("item", $parent->album_cover_item_id); + model_cache::clear(); $parent->album_cover_item_id = $item->is_album() ? $item->album_cover_item_id : $item->id; $parent->thumb_dirty = 1; $parent->save(); @@ -69,7 +69,7 @@ class item_Core { access::required("edit", $album); @unlink($album->thumb_path()); - model_cache::clear("item", $album->album_cover_item_id) ; + model_cache::clear(); $album->album_cover_item_id = null; $album->thumb_width = 0; $album->thumb_height = 0; diff --git a/modules/gallery/helpers/model_cache.php b/modules/gallery/helpers/model_cache.php index 2649fdbd..a3e09862 100644 --- a/modules/gallery/helpers/model_cache.php +++ b/modules/gallery/helpers/model_cache.php @@ -32,10 +32,8 @@ class model_cache_Core { return self::$cache->$model_name->$field_name->$id; } - static function clear($model_name, $id, $field_name="id") { - if (!empty(self::$cache->$model_name->$field_name->$id)) { - unset(self::$cache->$model_name->$field_name->$id); - } + static function clear() { + self::$cache = new stdClass(); } static function set($model) { diff --git a/modules/gallery/libraries/MY_ORM.php b/modules/gallery/libraries/MY_ORM.php index 319cbe09..1d3c1ef3 100644 --- a/modules/gallery/libraries/MY_ORM.php +++ b/modules/gallery/libraries/MY_ORM.php @@ -32,7 +32,7 @@ class ORM extends ORM_Core { } public function save() { - model_cache::clear($this->object_name, $this->{$this->primary_key}, $this->primary_key); + model_cache::clear(); $result = parent::save(); $this->original = $this->object; return $result; diff --git a/modules/gallery/libraries/ORM_MPTT.php b/modules/gallery/libraries/ORM_MPTT.php index 46280d95..e371f159 100644 --- a/modules/gallery/libraries/ORM_MPTT.php +++ b/modules/gallery/libraries/ORM_MPTT.php @@ -285,6 +285,7 @@ class ORM_MPTT_Core extends ORM { // Lets reload to get the changes. $this->reload(); + $target->reload(); return $this; } diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php index 6512e9e5..05c4e656 100644 --- a/modules/gallery/models/item.php +++ b/modules/gallery/models/item.php @@ -140,6 +140,7 @@ class Item_Model extends ORM_MPTT { $original_parent = $this->parent(); parent::move_to($target, true); + model_cache::clear(); $this->relative_path_cache = null; rename($original_path, $this->file_path()); -- cgit v1.2.3