diff options
Diffstat (limited to 'modules/gallery/helpers')
-rw-r--r-- | modules/gallery/helpers/access.php | 17 | ||||
-rw-r--r-- | modules/gallery/helpers/album.php | 2 | ||||
-rw-r--r-- | modules/gallery/helpers/gallery.php | 14 | ||||
-rw-r--r-- | modules/gallery/helpers/gallery_event.php | 66 | ||||
-rw-r--r-- | modules/gallery/helpers/gallery_installer.php | 10 | ||||
-rw-r--r-- | modules/gallery/helpers/gallery_task.php | 287 | ||||
-rw-r--r-- | modules/gallery/helpers/gallery_theme.php | 3 | ||||
-rw-r--r-- | modules/gallery/helpers/graphics.php | 13 | ||||
-rw-r--r-- | modules/gallery/helpers/item.php | 14 | ||||
-rw-r--r-- | modules/gallery/helpers/json.php | 33 | ||||
-rw-r--r-- | modules/gallery/helpers/l10n_client.php | 16 | ||||
-rw-r--r-- | modules/gallery/helpers/movie.php | 2 |
12 files changed, 387 insertions, 90 deletions
diff --git a/modules/gallery/helpers/access.php b/modules/gallery/helpers/access.php index 87b6b313..f1ea00c0 100644 --- a/modules/gallery/helpers/access.php +++ b/modules/gallery/helpers/access.php @@ -222,7 +222,7 @@ class access_Core { self::_update_access_non_view_cache($group, $perm_name, $album); } - self::_update_htaccess_files($album, $group, $perm_name, $value); + self::update_htaccess_files($album, $group, $perm_name, $value); model_cache::clear(); } @@ -623,11 +623,18 @@ class access_Core { } /** - * Maintain .htacccess files to prevent direct access to albums, resizes and thumbnails when we - * apply the view and view_full permissions to guest users. + * Rebuild the .htaccess files that prevent direct access to albums, resizes and thumbnails. We + * call this internally any time we change the view or view_full permissions for guest users. + * This function is only public because we use it in maintenance tasks. + * + * @param Item_Model the album + * @param Group_Model the group whose permission is changing + * @param string the permission name + * @param string the new permission value (eg access::DENY) */ - private static function _update_htaccess_files($album, $group, $perm_name, $value) { - if ($group->id != 1 || !($perm_name == "view" || $perm_name == "view_full")) { + static function update_htaccess_files($album, $group, $perm_name, $value) { + if ($group->id != identity::everybody()->id || + !($perm_name == "view" || $perm_name == "view_full")) { return; } diff --git a/modules/gallery/helpers/album.php b/modules/gallery/helpers/album.php index 0baae631..0ac5e8b0 100644 --- a/modules/gallery/helpers/album.php +++ b/modules/gallery/helpers/album.php @@ -58,7 +58,7 @@ class album_Core { static function get_edit_form($parent) { $form = new Forge( "albums/update/{$parent->id}", "", "post", array("id" => "g-edit-album-form")); - $form->hidden("from_id"); + $form->hidden("from_id")->value($parent->id); $group = $form->group("edit_item")->label(t("Edit Album")); $group->input("title")->label(t("Title"))->value($parent->title) diff --git a/modules/gallery/helpers/gallery.php b/modules/gallery/helpers/gallery.php index d4078209..54d16322 100644 --- a/modules/gallery/helpers/gallery.php +++ b/modules/gallery/helpers/gallery.php @@ -25,12 +25,14 @@ class gallery_Core { * down for maintenance" page. */ static function maintenance_mode() { - $maintenance_mode = Kohana::config("core.maintenance_mode", false, false); - - if (Router::$controller != "login" && !empty($maintenance_mode) && !identity::active_user()->admin) { - Router::$controller = "maintenance"; - Router::$controller_path = MODPATH . "gallery/controllers/maintenance.php"; - Router::$method = "index"; + if (Router::$controller != "login" && + Router::$controller != "combined" && + module::get_var("gallery", "maintenance_mode", 0) && + !identity::active_user()->admin) { + Session::instance()->set("continue_url", url::abs_site("admin/maintenance")); + Router::$controller = "login"; + Router::$controller_path = MODPATH . "gallery/controllers/login.php"; + Router::$method = "html"; } } diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php index 272fd205..e3fa5e08 100644 --- a/modules/gallery/helpers/gallery_event.php +++ b/modules/gallery/helpers/gallery_event.php @@ -109,18 +109,44 @@ class gallery_event_Core { $parent = $item->parent(); if (!$parent->album_cover_item_id) { - // Assume we deleted the album cover and pick a new one. Choosing the first photo in the - // album is logical, but it's not the most efficient in the case where we're deleting all - // the photos in the album one at a time since we'll probably delete them in order which - // means that we'll be resetting the album cover each time. - if ($child = $parent->children(1)->current()) { - item::make_album_cover($child); + // Assume that we deleted the album cover + if (batch::in_progress()) { + // Remember that this parent is missing an album cover, for later. + $batch_missing_album_cover = Session::instance()->get("batch_missing_album_cover", array()); + $batch_missing_album_cover[$parent->id] = 1; + Session::instance()->set("batch_missing_album_cover", $batch_missing_album_cover); + } else { + // Choose the first child as the new cover. + if ($child = $parent->children(1)->current()) { + item::make_album_cover($child); + } } } } + static function batch_complete() { + // Set the album covers for any items that where we probably deleted the album cover during + // this batch. The item may have been deleted, so don't count on it being around. Choose the + // first child as the new album cover. + // NOTE: if the first child doesn't have an album cover, then this won't work. + foreach (array_keys(Session::instance()->get("batch_missing_album_cover", array())) as $id) { + $item = ORM::factory("item", $id); + if ($item->loaded() && !$item->album_cover_item_id) { + if ($child = $item->children(1)->current()) { + item::make_album_cover($child); + } + } + } + Session::instance()->delete("batch_missing_album_cover"); + } + static function item_moved($item, $old_parent) { access::recalculate_permissions($item->parent()); + + // If the new parent doesn't have an album cover, make this it. + if (!$item->parent()->album_cover_item_id) { + item::make_album_cover($item); + } } static function user_login($user) { @@ -167,7 +193,9 @@ class gallery_event_Core { ->url(user_profile::url($user->id)) ->label($user->display_name())); - if (isset($theme->item)) { + if (Router::$controller == "admin") { + $continue_url = url::site(""); + } else if (isset($theme->item)) { if (access::user_can(identity::guest(), "view", $theme->item)) { $continue_url = $theme->item->abs_url(); } else { @@ -180,8 +208,7 @@ class gallery_event_Core { $menu->append(Menu::factory("link") ->id("user_menu_logout") ->css_id("g-logout-link") - ->url(url::site("logout?csrf=$csrf&continue_url=" . - urlencode($continue_url))) + ->url(url::site("logout?csrf=$csrf&continue_url=" . urlencode($continue_url))) ->label(t("Logout"))); } } @@ -211,7 +238,7 @@ class gallery_event_Core { $add_menu->append(Menu::factory("dialog") ->id("add_photos_item") ->label(t("Add photos")) - ->url(url::site("flash_uploader/app/$item->id"))); + ->url(url::site("uploader/index/$item->id"))); if ($item->is_album()) { $add_menu->append(Menu::factory("dialog") ->id("add_album_item") @@ -249,7 +276,7 @@ class gallery_event_Core { $options_menu->append(Menu::factory("dialog") ->id("edit_item") ->label($edit_text) - ->url(url::site("form/edit/{$item->type}s/$item->id"))); + ->url(url::site("form/edit/{$item->type}s/$item->id?from_id={$item->id}"))); } if ($item->is_album()) { @@ -263,7 +290,6 @@ class gallery_event_Core { } $csrf = access::csrf_token(); - $theme_item = $theme->item(); $page_type = $theme->page_type(); if ($can_edit && $item->is_photo() && graphics::can("rotate")) { $options_menu @@ -274,7 +300,7 @@ class gallery_event_Core { ->css_class("ui-icon-rotate-ccw") ->ajax_handler("function(data) { " . "\$.gallery_replace_image(data, \$('$item_css_selector')) }") - ->url(url::site("quick/rotate/$item->id/ccw?csrf=$csrf&from_id=$theme_item->id&page_type=$page_type"))) + ->url(url::site("quick/rotate/$item->id/ccw?csrf=$csrf&from_id={$item->id}&page_type=$page_type"))) ->append( Menu::factory("ajax_link") ->id("rotate_cw") @@ -282,7 +308,7 @@ class gallery_event_Core { ->css_class("ui-icon-rotate-cw") ->ajax_handler("function(data) { " . "\$.gallery_replace_image(data, \$('$item_css_selector')) }") - ->url(url::site("quick/rotate/$item->id/cw?csrf=$csrf&from_id=$theme_item->id&page_type=$page_type"))); + ->url(url::site("quick/rotate/$item->id/cw?csrf=$csrf&from_id={$item->id}&page_type=$page_type"))); } if ($item->id != item::root()->id) { @@ -315,7 +341,7 @@ class gallery_event_Core { ->label($delete_text) ->css_class("ui-icon-trash") ->css_class("g-quick-delete") - ->url(url::site("quick/form_delete/$item->id?csrf=$csrf&from_id=$theme_item->id&page_type=$page_type"))); + ->url(url::site("quick/form_delete/$item->id?csrf=$csrf&from_id={$item->id}&page_type=$page_type"))); } } } @@ -416,7 +442,7 @@ class gallery_event_Core { ->id("edit") ->label($edit_title) ->css_class("ui-icon-pencil") - ->url(url::site("quick/form_edit/$item->id?from_id=$theme_item->id"))); + ->url(url::site("quick/form_edit/$item->id?from_id={$theme_item->id}"))); if ($item->is_photo() && graphics::can("rotate")) { $options_menu @@ -427,7 +453,7 @@ class gallery_event_Core { ->css_class("ui-icon-rotate-ccw") ->ajax_handler("function(data) { " . "\$.gallery_replace_image(data, \$('$thumb_css_selector')) }") - ->url(url::site("quick/rotate/$item->id/ccw?csrf=$csrf&from_id=$theme_item->id&page_type=$page_type"))) + ->url(url::site("quick/rotate/$item->id/ccw?csrf=$csrf&from_id={$theme_item->id}&page_type=$page_type"))) ->append( Menu::factory("ajax_link") ->id("rotate_cw") @@ -435,7 +461,7 @@ class gallery_event_Core { ->css_class("ui-icon-rotate-cw") ->ajax_handler("function(data) { " . "\$.gallery_replace_image(data, \$('$thumb_css_selector')) }") - ->url(url::site("quick/rotate/$item->id/cw?csrf=$csrf&from_id=$theme_item->id&page_type=$page_type"))); + ->url(url::site("quick/rotate/$item->id/cw?csrf=$csrf&from_id={$theme_item->id}&page_type=$page_type"))); } // @todo Don't move photos from the photo page; we don't yet have a good way of redirecting @@ -474,7 +500,7 @@ class gallery_event_Core { ->id("delete") ->label($delete_title) ->css_class("ui-icon-trash") - ->url(url::site("quick/form_delete/$item->id?csrf=$csrf&from_id=$theme_item->id&page_type=$page_type"))); + ->url(url::site("quick/form_delete/$item->id?csrf=$csrf&from_id={$theme_item->id}&page_type=$page_type"))); } if ($item->is_album()) { @@ -483,7 +509,7 @@ class gallery_event_Core { ->id("add_item") ->label(t("Add a photo")) ->css_class("ui-icon-plus") - ->url(url::site("flash_uploader/app/$item->id"))) + ->url(url::site("uploader/index/$item->id"))) ->append(Menu::factory("dialog") ->id("add_album") ->label(t("Add an album")) diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php index 39c35711..f5589618 100644 --- a/modules/gallery/helpers/gallery_installer.php +++ b/modules/gallery/helpers/gallery_installer.php @@ -295,7 +295,8 @@ class gallery_installer { module::set_var("gallery", "credits", (string) $powered_by_string); module::set_var("gallery", "simultaneous_upload_limit", 5); module::set_var("gallery", "admin_area_timeout", 90 * 60); - module::set_version("gallery", 30); + module::set_var("gallery", "maintenance_mode", 0); + module::set_version("gallery", 31); } static function upgrade($version) { @@ -554,7 +555,12 @@ class gallery_installer { if ($version == 29) { $db->query("ALTER TABLE {caches} ADD KEY (`key`);"); module::set_version("gallery", $version = 30); - } + } + + if ($version == 30) { + module::set_var("gallery", "maintenance_mode", 0); + module::set_version("gallery", $version = 31); + } } static function uninstall() { diff --git a/modules/gallery/helpers/gallery_task.php b/modules/gallery/helpers/gallery_task.php index bc128b3e..bf1355b8 100644 --- a/modules/gallery/helpers/gallery_task.php +++ b/modules/gallery/helpers/gallery_task.php @@ -18,8 +18,15 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class gallery_task_Core { - const MPTT_LEFT = 0; - const MPTT_RIGHT = 1; + const FIX_STATE_START_MPTT = 0; + const FIX_STATE_RUN_MPTT = 1; + const FIX_STATE_START_ALBUMS = 2; + const FIX_STATE_RUN_ALBUMS = 3; + const FIX_STATE_START_DUPE_SLUGS = 4; + const FIX_STATE_RUN_DUPE_SLUGS = 5; + const FIX_STATE_START_DUPE_NAMES = 6; + const FIX_STATE_RUN_DUPE_NAMES = 7; + const FIX_STATE_DONE = 8; static function available_tasks() { $dirty_count = graphics::find_dirty_images_query()->count_records(); @@ -47,10 +54,10 @@ class gallery_task_Core { ->severity(log::SUCCESS); $tasks[] = Task_Definition::factory() - ->callback("gallery_task::fix_mptt") - ->name(t("Fix Album/Photo hierarchy")) - ->description(t("Fix problems where your album/photo breadcrumbs are out of " . - "sync with your actual hierarchy.")) + ->callback("gallery_task::fix") + ->name(t("Fix your Gallery")) + ->description(t("Fix a variety of problems that might cause your Gallery to act " . + "strangely. Requires maintenance mode.")) ->severity(log::SUCCESS); return $tasks; @@ -310,78 +317,274 @@ class gallery_task_Core { } } - static function fix_mptt($task) { + static function fix($task) { $start = microtime(true); $total = $task->get("total"); if (empty($total)) { - $task->set("total", $total = db::build()->count_records("items")); - $task->set("stack", "1:" . self::MPTT_LEFT); + // mptt: 2 operations for every item + // album audit (permissions and bogus album covers): 1 operation for every album + // dupe slugs: 1 operation for each unique conflicted slug + $total = 2 * db::build()->count_records("items"); + $total += db::build()->where("type", "=", "album")->count_records("items"); + foreach (self::find_dupe_slugs() as $row) { + $total++; + } + foreach (self::find_dupe_names() as $row) { + $total++; + } + + $task->set("total", $total); + $task->set("state", $state = self::FIX_STATE_START_MPTT); $task->set("ptr", 1); $task->set("completed", 0); } - $ptr = $task->get("ptr"); - $stack = explode(" ", $task->get("stack")); $completed = $task->get("completed"); + $state = $task->get("state"); - // Implement a depth-first tree walk using a stack. Not the most efficient, but it's simple. - while ($stack && microtime(true) - $start < 1.5) { - list($id, $state) = explode(":", array_pop($stack)); + if (!module::get_var("gallery", "maintenance_mode")) { + module::set_var("gallery", "maintenance_mode", 1); + } + + // This is a state machine that checks each item in the database. It verifies the following + // attributes for an item. + // 1. Left and right MPTT pointers are correct + // 2. The .htaccess permission files for restricted items exist and are well formed. + // 3. The relative_path_cache and relative_url_cache values are set to null. + // 4. there are no album_cover_item_ids pointing to missing items + // + // We'll do a depth-first tree walk over our hierarchy using only the adjacency data because + // we don't trust MPTT here (that might be what we're here to fix!). Avoid avoid using ORM + // calls as much as possible since they're expensive. + // + // NOTE: the MPTT check will only traverse items that have valid parents. It's possible that + // we have some tree corruption where there are items with parent ids to non-existent items. + // We should probably do something about that. + while ($state != self::FIX_STATE_DONE && microtime(true) - $start < 1.5) { switch ($state) { - case self::MPTT_LEFT: - self::fix_mptt_set_left($id, $ptr++); - $item = ORM::factory("item", $id); - array_push($stack, $id . ":" . self::MPTT_RIGHT); - foreach (self::fix_mptt_children($id) as $child) { - array_push($stack, $child->id . ":" . self::MPTT_LEFT); + case self::FIX_STATE_START_MPTT: + $task->set("ptr", $ptr = 1); + $task->set("stack", item::root()->id . ":L"); + $state = self::FIX_STATE_RUN_MPTT; + break; + + case self::FIX_STATE_RUN_MPTT: + $ptr = $task->get("ptr"); + $stack = explode(" ", $task->get("stack")); + list ($id, $ptr_mode) = explode(":", array_pop($stack)); + if ($ptr_mode == "L") { + $stack[] = "$id:R"; + db::build() + ->update("items") + ->set("left_ptr", $ptr++) + ->where("id", "=", $id) + ->execute(); + + foreach (db::build() + ->select(array("id")) + ->from("items") + ->where("parent_id", "=", $id) + ->order_by("left_ptr", "ASC") + ->execute() as $child) { + array_push($stack, "{$child->id}:L"); + } + } else if ($ptr_mode == "R") { + db::build() + ->update("items") + ->set("right_ptr", $ptr++) + ->set("relative_path_cache", null) + ->set("relative_url_cache", null) + ->where("id", "=", $id) + ->execute(); + } + $task->set("ptr", $ptr); + $task->set("stack", implode(" ", $stack)); + $completed++; + + if (empty($stack)) { + $state = self::FIX_STATE_START_DUPE_SLUGS; + } + break; + + + case self::FIX_STATE_START_DUPE_SLUGS: + $stack = array(); + foreach (self::find_dupe_slugs() as $row) { + list ($parent_id, $slug) = explode(":", $row->parent_slug, 2); + $stack[] = join(":", array($parent_id, $slug)); + } + if ($stack) { + $task->set("stack", implode(" ", $stack)); + $state = self::FIX_STATE_RUN_DUPE_SLUGS; + } else { + $state = self::FIX_STATE_START_DUPE_NAMES; } break; - case self::MPTT_RIGHT: - self::fix_mptt_set_right($id, $ptr++); + case self::FIX_STATE_RUN_DUPE_SLUGS: + $stack = explode(" ", $task->get("stack")); + list ($parent_id, $slug) = explode(":", array_pop($stack)); + + // We want to leave the first one alone and update all conflicts to be random values. + $fixed = 0; + $conflicts = ORM::factory("item") + ->where("parent_id", "=", $parent_id) + ->where("slug", "=", $slug) + ->find_all(1, 1); + if ($conflicts->count() && $conflict = $conflicts->current()) { + $task->log("Fixing conflicting slug for item id {$conflict->id}"); + db::build() + ->update("items") + ->set("slug", $slug . "-" . (string)rand(1000, 9999)) + ->where("id", "=", $conflict->id) + ->execute(); + + // We fixed one conflict, but there might be more so put this parent back on the stack + // and try again. We won't consider it completed when we don't fix a conflict. This + // guarantees that we won't spend too long fixing one set of conflicts, and that we + // won't stop before all are fixed. + $stack[] = "$parent_id:$slug"; + break; + } + $task->set("stack", implode(" ", $stack)); $completed++; + + if (empty($stack)) { + $state = self::FIX_STATE_START_DUPE_NAMES; + } + break; + + case self::FIX_STATE_START_DUPE_NAMES: + $stack = array(); + foreach (self::find_dupe_names() as $row) { + list ($parent_id, $name) = explode(":", $row->parent_name, 2); + $stack[] = join(":", array($parent_id, $name)); + } + if ($stack) { + $task->set("stack", implode(" ", $stack)); + $state = self::FIX_STATE_RUN_DUPE_NAMES; + } else { + $state = self::FIX_STATE_START_ALBUMS; + } + break; + + case self::FIX_STATE_RUN_DUPE_NAMES: + $stack = explode(" ", $task->get("stack")); + list ($parent_id, $name) = explode(":", array_pop($stack)); + + $fixed = 0; + // We want to leave the first one alone and update all conflicts to be random values. + $conflicts = ORM::factory("item") + ->where("parent_id", "=", $parent_id) + ->where("name", "=", $name) + ->find_all(1, 1); + if ($conflicts->count() && $conflict = $conflicts->current()) { + $task->log("Fixing conflicting name for item id {$conflict->id}"); + db::build() + ->update("items") + ->set("name", $name . "-" . (string)rand(1000, 9999)) + ->where("id", "=", $conflict->id) + ->execute(); + + // We fixed one conflict, but there might be more so put this parent back on the stack + // and try again. We won't consider it completed when we don't fix a conflict. This + // guarantees that we won't spend too long fixing one set of conflicts, and that we + // won't stop before all are fixed. + $stack[] = "$parent_id:$name"; + break; + } + $task->set("stack", implode(" ", $stack)); + $completed++; + + if (empty($stack)) { + $state = self::FIX_STATE_START_ALBUMS; + } + break; + + case self::FIX_STATE_START_ALBUMS: + $stack = array(); + foreach (db::build() + ->select("id") + ->from("items") + ->where("type", "=", "album") + ->execute() as $row) { + $stack[] = $row->id; + } + $task->set("stack", implode(" ", $stack)); + $state = self::FIX_STATE_RUN_ALBUMS; + break; + + case self::FIX_STATE_RUN_ALBUMS: + $stack = explode(" ", $task->get("stack")); + $id = array_pop($stack); + + $item = ORM::factory("item", $id); + if ($item->album_cover_item_id) { + $album_cover_item = ORM::factory("item", $item->album_cover_item_id); + if (!$album_cover_item->loaded()) { + $item->album_cover_item_id = null; + $item->save(); + } + } + + $everybody = identity::everybody(); + $view_col = "view_{$everybody->id}"; + $view_full_col = "view_full_{$everybody->id}"; + $intent = ORM::factory("access_intent")->where("item_id", "=", $id)->find(); + if ($intent->$view_col === access::DENY) { + access::update_htaccess_files($item, $everybody, "view", access::DENY); + } + if ($intent->$view_full_col === access::DENY) { + access::update_htaccess_files($item, $everybody, "view_full", access::DENY); + } + $task->set("stack", implode(" ", $stack)); + $completed++; + + if (empty($stack)) { + $state = self::FIX_STATE_DONE; + } break; } } - $task->set("stack", implode(" ", $stack)); - $task->set("ptr", $ptr); + $task->set("state", $state); $task->set("completed", $completed); - if ($total == $completed) { + if ($state == self::FIX_STATE_DONE) { $task->done = true; $task->state = "success"; $task->percent_complete = 100; + module::set_var("gallery", "maintenance_mode", 0); } else { $task->percent_complete = round(100 * $completed / $total); } - $task->status = t2("One row updated", "%count / %total rows updated", $completed, + $task->status = t2("One operation complete", "%count / %total operations complete", $completed, array("total" => $total)); } - static function fix_mptt_children($parent_id) { + static function find_dupe_slugs() { return db::build() + ->select_distinct( + array("parent_slug" => new Database_Expression("CONCAT(`parent_id`, ':', `slug`)"))) ->select("id") + ->select(array("C" => "COUNT(\"*\")")) ->from("items") - ->where("parent_id", "=", $parent_id) - ->order_by("left_ptr", "ASC") + ->having("C", ">", 1) + ->group_by("parent_slug") ->execute(); } - static function fix_mptt_set_left($id, $value) { - db::build() - ->update("items") - ->set("left_ptr", $value) - ->where("id", "=", $id) - ->execute(); - } - - static function fix_mptt_set_right($id, $value) { - db::build() - ->update("items") - ->set("right_ptr", $value) - ->where("id", "=", $id) + static function find_dupe_names() { + return db::build() + ->select_distinct( + array("parent_name" => new Database_Expression("CONCAT(`parent_id`, ':', `name`)"))) + ->select("id") + ->select(array("C" => "COUNT(\"*\")")) + ->from("items") + ->where("type", "<>", "album") + ->having("C", ">", 1) + ->group_by("parent_name") ->execute(); } }
\ No newline at end of file diff --git a/modules/gallery/helpers/gallery_theme.php b/modules/gallery/helpers/gallery_theme.php index 62deb831..0d7cc44a 100644 --- a/modules/gallery/helpers/gallery_theme.php +++ b/modules/gallery/helpers/gallery_theme.php @@ -79,8 +79,7 @@ class gallery_theme_Core { return L10n_Client_Controller::l10n_form(); } - if ($session->get("after_install")) { - $session->delete("after_install"); + if ($session->get_once("after_install")) { return new View("welcome_message_loader.html"); } } diff --git a/modules/gallery/helpers/graphics.php b/modules/gallery/helpers/graphics.php index 7ff09d13..cc4d2e76 100644 --- a/modules/gallery/helpers/graphics.php +++ b/modules/gallery/helpers/graphics.php @@ -117,7 +117,18 @@ class graphics_Core { static function generate($item) { if ($item->is_album()) { if (!$cover = $item->album_cover()) { - // This album has no cover; there's nothing to generate. + // This album has no cover; there's nothing to generate. Because of an old bug, it's + // possible that there's an album cover item id that points to an invalid item. In that + // case, just null out the album cover item id. It's not optimal to do that at this low + // level, but it's not trivial to find these cases quickly in an upgrade script and if we + // don't do this, the album may be permanently marked as "needs rebuilding" + // + // ref: http://sourceforge.net/apps/trac/gallery/ticket/1172 + // http://gallery.menalto.com/node/96926 + if ($item->album_cover_item_id) { + $item->album_cover_item_id = null; + $item->save(); + } return; } $input_file = $cover->file_path(); diff --git a/modules/gallery/helpers/item.php b/modules/gallery/helpers/item.php index aef68c6e..092904a5 100644 --- a/modules/gallery/helpers/item.php +++ b/modules/gallery/helpers/item.php @@ -105,9 +105,15 @@ class item_Core { model_cache::clear(); $parent->album_cover_item_id = $item->is_album() ? $item->album_cover_item_id : $item->id; - $parent->thumb_dirty = 1; + if ($item->thumb_dirty) { + $parent->thumb_dirty = 1; + graphics::generate($parent); + } else { + copy($item->thumb_path(), $parent->thumb_path()); + $parent->thumb_width = $item->thumb_width; + $parent->thumb_height = $item->thumb_height; + } $parent->save(); - graphics::generate($parent); $grand_parent = $parent->parent(); if ($grand_parent && access::can("edit", $grand_parent) && $grand_parent->album_cover_item_id == null) { @@ -158,8 +164,10 @@ class item_Core { */ static function get_delete_form($item) { $page_type = Input::instance()->get("page_type"); + $from_id = Input::instance()->get("from_id"); $form = new Forge( - "quick/delete/$item->id?page_type=$page_type", "", "post", array("id" => "g-confirm-delete")); + "quick/delete/$item->id?page_type=$page_type&from_id=$from_id", "", + "post", array("id" => "g-confirm-delete")); $group = $form->group("confirm_delete")->label(t("Confirm Deletion")); $group->submit("")->value(t("Delete")); $form->script("") diff --git a/modules/gallery/helpers/json.php b/modules/gallery/helpers/json.php new file mode 100644 index 00000000..a39db27a --- /dev/null +++ b/modules/gallery/helpers/json.php @@ -0,0 +1,33 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2010 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 json_Core { + /** + * JSON Encode a reply to the browser and set the content type to specify that it's a JSON + * payload. + * + * @param mixed $message string or object to json encode and print + */ + static function reply($message) { + if (!headers_sent()) { + header("Content-Type: application/json; charset=" . Kohana::CHARSET); + } + print json_encode($message); + } +}
\ No newline at end of file diff --git a/modules/gallery/helpers/l10n_client.php b/modules/gallery/helpers/l10n_client.php index f45f502d..43cc2036 100644 --- a/modules/gallery/helpers/l10n_client.php +++ b/modules/gallery/helpers/l10n_client.php @@ -20,13 +20,12 @@ class l10n_client_Core { - private static function _server_url() { - return "http://gallery.menalto.com/index.php"; + private static function _server_url($path) { + return "http://gallery.menalto.com/translations/$path"; } static function server_api_key_url() { - return self::_server_url() . "?q=translations/userkey/" . - self::client_token(); + return self::_server_url("userkey/" . self::client_token()); } static function client_token() { @@ -53,7 +52,7 @@ class l10n_client_Core { static function validate_api_key($api_key) { $version = "1.0"; - $url = self::_server_url() . "?q=translations/status"; + $url = self::_server_url("status"); $signature = self::_sign($version, $api_key); list ($response_data, $response_status) = remote::post( @@ -123,7 +122,7 @@ class l10n_client_Core { } $request_data = json_encode($request); - $url = self::_server_url() . "?q=translations/fetch"; + $url = self::_server_url("fetch"); list ($response_data, $response_status) = remote::post($url, array("data" => $request_data)); if (!remote::success($response_status)) { throw new Exception("@todo TRANSLATIONS_FETCH_REQUEST_FAILED " . $response_status); @@ -195,12 +194,15 @@ class l10n_client_Core { // @todo Batch requests (max request size) // @todo include base_revision in submission / how to handle resubmissions / edit fights? + $request = new stdClass(); foreach (db::build() ->select("key", "message", "locale", "base_revision", "translation") ->from("outgoing_translations") ->execute() as $row) { $key = $row->key; if (!isset($request->{$key})) { + $request->{$key} = new stdClass(); + $request->{$key}->translations = new stdClass(); $request->{$key}->message = json_encode(unserialize($row->message)); } $request->{$key}->translations->{$row->locale} = json_encode(unserialize($row->translation)); @@ -208,7 +210,7 @@ class l10n_client_Core { // @todo reduce memory consumption, e.g. free $request $request_data = json_encode($request); - $url = self::_server_url() . "?q=translations/submit"; + $url = self::_server_url("submit"); $signature = self::_sign($request_data); list ($response_data, $response_status) = remote::post( diff --git a/modules/gallery/helpers/movie.php b/modules/gallery/helpers/movie.php index 6333eaf2..bbb5b66c 100644 --- a/modules/gallery/helpers/movie.php +++ b/modules/gallery/helpers/movie.php @@ -26,7 +26,7 @@ class movie_Core { static function get_edit_form($movie) { $form = new Forge("movies/update/$movie->id", "", "post", array("id" => "g-edit-movie-form")); - $form->hidden("from_id"); + $form->hidden("from_id")->value($movie->id); $group = $form->group("edit_item")->label(t("Edit Movie")); $group->input("title")->label(t("Title"))->value($movie->title) ->error_messages("required", t("You must provide a title")) |