diff options
Diffstat (limited to 'modules')
97 files changed, 1483 insertions, 2530 deletions
diff --git a/modules/akismet/views/admin_akismet.html.php b/modules/akismet/views/admin_akismet.html.php index cc5e3cfc..009d8810 100644 --- a/modules/akismet/views/admin_akismet.html.php +++ b/modules/akismet/views/admin_akismet.html.php @@ -3,12 +3,12 @@ <h1> <?= t("Akismet Spam Filtering") ?> </h1> <p> <?= t("Akismet is a free, automated spam filtering service. In order to use it, you need to sign up for a <a href=\"%api_key_url\">Wordpress.com API Key</a>, which is also free. Your comments will be automatically relayed to <a href=\"%akismet_url\">Akismet.com</a> where they'll be scanned for spam. Spam messages will be flagged accordingly and hidden from your vistors until you approve or delete them.", - array("api_key_url" => "http://wordpress.com/api-keys", - "akismet_url" => "http://akismet.com")) ?> + array("api_key_url" => "http://wordpress.com/api-keys", + "akismet_url" => "http://akismet.com")) ?> </p> <? if ($valid_key): ?> - <div class="gSuccess"> + <div class="gModuleStatus gSuccess"> <?= t("Your API Key is valid. Your comments will be filtered!") ?> </div> <? endif ?> diff --git a/modules/comment/helpers/comment.php b/modules/comment/helpers/comment.php index 3d743325..f74a8644 100644 --- a/modules/comment/helpers/comment.php +++ b/modules/comment/helpers/comment.php @@ -35,7 +35,7 @@ class comment_Core { * @return Comment_Model */ static function create($item, $author, $text, $guest_name=null, - $guest_email=ull, $guest_url=null) { + $guest_email=null, $guest_url=null) { $comment = ORM::factory("comment"); $comment->author_id = $author->id; $comment->guest_email = $guest_email; diff --git a/modules/comment/helpers/comment_installer.php b/modules/comment/helpers/comment_installer.php index f54913c3..80594c16 100644 --- a/modules/comment/helpers/comment_installer.php +++ b/modules/comment/helpers/comment_installer.php @@ -44,7 +44,7 @@ class comment_installer { `text` text, `updated` int(9) NOT NULL, PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); block_manager::add("dashboard_center", "comment", "recent_comments"); module::set_var("comment", "spam_caught", 0); @@ -52,8 +52,8 @@ class comment_installer { } static function upgrade($version) { + $db = Database::instance(); if ($version == 1) { - $db = Database::instance(); $db->query("ALTER TABLE {comments} CHANGE `state` `state` varchar(15) default 'unpublished'"); module::set_version("comment", 2); } @@ -61,9 +61,16 @@ class comment_installer { static function uninstall() { $db = Database::instance(); - $sql = "SELECT `item_id` FROM {comments}"; - module::event("item_related_update_batch", $sql); + // Notify listeners that we're deleting some data. This is probably going to be very + // inefficient for large uninstalls, and we could make it better by doing things like passing + // a SQL fragment through so that the listeners could use subselects. But by using a single, + // simple event API we lighten the load on module developers. + foreach (ORM::factory("item") + ->join("comments", "items.id", "comments.item_id") + ->find_all() as $item) { + module::event("item_related_update", $item); + } $db->query("DROP TABLE IF EXISTS {comments};"); } } diff --git a/modules/comment/helpers/comment_rss.php b/modules/comment/helpers/comment_rss.php index d0f15010..4151dcd0 100644 --- a/modules/comment/helpers/comment_rss.php +++ b/modules/comment/helpers/comment_rss.php @@ -34,41 +34,36 @@ class comment_rss_Core { } $comments = ORM::factory("comment") - ->where("state", "published") - ->orderby("created", "DESC"); - $all_comments = ORM::factory("comment") + ->viewable() ->where("state", "published") ->orderby("created", "DESC"); if ($feed_id == "item") { $comments->where("item_id", $id); - $all_comments->where("item_id", $id); } - if (!empty($comments)) { - $feed->view = "comment.mrss"; - $comments = $comments->find_all($limit, $offset); - $feed->children = array(); - foreach ($comments as $comment) { - $item = $comment->item(); - $feed->children[] = new ArrayObject( - array("pub_date" => date("D, d M Y H:i:s T", $comment->created), - "text" => nl2br(SafeString::purify($comment->text)), - "thumb_url" => $item->thumb_url(), - "thumb_height" => $item->thumb_height, - "thumb_width" => $item->thumb_width, - "item_uri" => url::abs_site("{$item->type}s/$item->id"), - "title" => SafeString::purify($item->title), - "author" => SafeString::of($comment->author_name())), - ArrayObject::ARRAY_AS_PROPS); - } + $comments = $comments->find_all($limit, $offset); + $feed->view = "comment.mrss"; + $feed->children = array(); + foreach ($comments as $comment) { + $item = $comment->item(); + $feed->children[] = new ArrayObject( + array("pub_date" => date("D, d M Y H:i:s T", $comment->created), + "text" => nl2br(SafeString::purify($comment->text)), + "thumb_url" => $item->thumb_url(), + "thumb_height" => $item->thumb_height, + "thumb_width" => $item->thumb_width, + "item_uri" => url::abs_site("{$item->type}s/$item->id"), + "title" => SafeString::purify($item->title), + "author" => SafeString::of($comment->author_name())), + ArrayObject::ARRAY_AS_PROPS); + } - $feed->max_pages = ceil($all_comments->find_all()->count() / $limit); - $feed->title = htmlspecialchars(t("Recent Comments")); - $feed->uri = url::abs_site("albums/" . (empty($id) ? "1" : $id)); - $feed->description = t("Recent Comments"); + $feed->max_pages = ceil($comments->count_all() / $limit); + $feed->title = htmlspecialchars(t("Recent Comments")); + $feed->uri = url::abs_site("albums/" . (empty($id) ? "1" : $id)); + $feed->description = t("Recent Comments"); - return $feed; - } + return $feed; } -}
\ No newline at end of file +} diff --git a/modules/comment/helpers/comment_theme.php b/modules/comment/helpers/comment_theme.php index b807e2cf..38a00b5c 100644 --- a/modules/comment/helpers/comment_theme.php +++ b/modules/comment/helpers/comment_theme.php @@ -26,7 +26,6 @@ class comment_theme_Core { static function photo_bottom($theme) { $block = new Block; $block->css_id = "gComments"; - $block->anchor = t("comments"); $block->title = t("Comments"); $view = new View("comments.html"); @@ -37,7 +36,6 @@ class comment_theme_Core { ->find_all(); $block->content = $view; - $block->content .= comment::get_add_form($theme->item())->render("form.html"); return $block; } }
\ No newline at end of file diff --git a/modules/comment/js/comment.js b/modules/comment/js/comment.js index 00fc6027..9fd63c1a 100644 --- a/modules/comment/js/comment.js +++ b/modules/comment/js/comment.js @@ -1,5 +1,13 @@ $("document").ready(function() { - ajaxify_comment_form(); + $("#gAddCommentButton").click(function(event) { + event.preventDefault(); + $.get($(this).attr("href"), + {}, + function(data) { + $("#gCommentDetail").append(data); + ajaxify_comment_form(); + }); + }); }); function ajaxify_comment_form() { diff --git a/modules/comment/models/comment.php b/modules/comment/models/comment.php index 83d0888a..de9b0cd6 100644 --- a/modules/comment/models/comment.php +++ b/modules/comment/models/comment.php @@ -80,4 +80,14 @@ class Comment_Model extends ORM { return $this; } + + /** + * Add a set of restrictions to any following queries to restrict access only to items + * viewable by the active user. + * @chainable + */ + public function viewable() { + $this->join("items", "items.id", "comments.item_id"); + return item::viewable($this); + } } diff --git a/modules/comment/tests/Comment_Model_Test.php b/modules/comment/tests/Comment_Model_Test.php new file mode 100644 index 00000000..f4c68b15 --- /dev/null +++ b/modules/comment/tests/Comment_Model_Test.php @@ -0,0 +1,40 @@ +<?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 Comment_Model_Test extends Unit_Test_Case { + + public function cant_view_comments_for_unviewable_items_test() { + $root = ORM::factory("item", 1); + $album = album::create($root, rand(), rand(), rand()); + $comment = comment::create($album, user::guest(), "text", "name", "email", "url"); + user::set_active(user::guest()); + + // We can see the comment when permissions are granted on the album + access::allow(group::everybody(), "view", $album); + $this->assert_equal( + 1, + ORM::factory("comment")->viewable()->where("comments.id", $comment->id)->count_all()); + + // We can't see the comment when permissions are denied on the album + access::deny(group::everybody(), "view", $album); + $this->assert_equal( + 0, + ORM::factory("comment")->viewable()->where("comments.id", $comment->id)->count_all()); + } +} diff --git a/modules/comment/views/admin_comments.html.php b/modules/comment/views/admin_comments.html.php index b27e3166..8b0b4c29 100644 --- a/modules/comment/views/admin_comments.html.php +++ b/modules/comment/views/admin_comments.html.php @@ -103,7 +103,7 @@ </th> </tr> <? foreach ($comments as $i => $comment): ?> - <tr id="gComment-<?= $comment->id ?>" class="<?= ($i % 2 == 0) ? "gEvenRow" : "gOddRow" ?>"> + <tr id="gComment-<?= $comment->id ?>" class="<?= ($i % 2 == 0) ? "gOddRow" : "gEvenRow" ?>"> <td> <a href="#"> <img src="<?= $comment->author()->avatar_url(40, $theme->url("images/avatar.jpg", true)) ?>" diff --git a/modules/comment/views/comments.html.php b/modules/comment/views/comments.html.php index 7941b7da..9eac0502 100644 --- a/modules/comment/views/comments.html.php +++ b/modules/comment/views/comments.html.php @@ -1,11 +1,17 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> + <a href="<?= url::site("form/add/comments/{$item->id})") ?>" id="gAddCommentButton" + class="gButtonLink ui-corner-all ui-icon-left ui-state-default right"> + <span class="ui-icon ui-icon-comment"></span> + <?= t("Add a comment") ?> +</a> +<div id="gCommentDetail"> <? if (!$comments->count()): ?> <p id="gNoCommentsYet"> <?= t("No comments yet. Be the first to <a %attrs>comment</a>!", array("attrs" => "href=\"#add_comment_form\" class=\"showCommentForm\"")) ?> </p> <? endif ?> -<ul id="gComments"> +<ul> <? foreach ($comments as $comment): ?> <li id="gComment-<?= $comment->id ?>"> <p class="gAuthor"> @@ -26,4 +32,4 @@ </li> <? endforeach ?> </ul> -<a name="add_comment_form"></a> +</div> diff --git a/modules/digibug/helpers/digibug_event.php b/modules/digibug/helpers/digibug_event.php index c4f9e560..d2830b80 100644 --- a/modules/digibug/helpers/digibug_event.php +++ b/modules/digibug/helpers/digibug_event.php @@ -28,23 +28,23 @@ class digibug_event_Core { static function photo_menu($menu, $theme) { $item = $theme->item(); - $menu->append( - Menu::factory("link") - ->id("digibug") - ->label(t("Print with Digibug")) - ->url(url::site("digibug/print_photo/$item->id?csrf=$theme->csrf")) - ->css_id("gDigibugLink")); + $menu->append(Menu::factory("link") + ->id("digibug") + ->label(t("Print with Digibug")) + ->url(url::site("digibug/print_photo/$item->id?csrf=$theme->csrf")) + ->css_id("gDigibugLink") + ->css_class("ui-icon-print")); } - static function thumb_menu($menu, $theme, $item) { + static function context_menu($menu, $theme, $item) { if ($item->type == "photo") { $menu->get("options_menu") - ->append( - Menu::factory("link") - ->id("digibug") - ->label(t("Print with Digibug")) - ->url(url::site("digibug/print_photo/$item->id?csrf=$theme->csrf")) - ->css_id("gDigibugLink")); + ->append(Menu::factory("link") + ->id("digibug") + ->label(t("Print with Digibug")) + ->url(url::site("digibug/print_photo/$item->id?csrf=$theme->csrf")) + ->css_id("gDigibugLink") + ->css_class("ui-icon-print")); } } } diff --git a/modules/digibug/helpers/digibug_installer.php b/modules/digibug/helpers/digibug_installer.php index 1cd78b44..7e8145d2 100644 --- a/modules/digibug/helpers/digibug_installer.php +++ b/modules/digibug/helpers/digibug_installer.php @@ -26,7 +26,7 @@ class digibug_installer { `request_date` TIMESTAMP NOT NULL DEFAULT current_timestamp, `item_id` int(9) NOT NULL, PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_var("digibug", "company_id", "3153"); module::set_var("digibug", "event_id", "8491"); diff --git a/modules/exif/helpers/exif_installer.php b/modules/exif/helpers/exif_installer.php index 0233f2bb..66226061 100644 --- a/modules/exif/helpers/exif_installer.php +++ b/modules/exif/helpers/exif_installer.php @@ -28,7 +28,7 @@ class exif_installer { `dirty` BOOLEAN default 1, PRIMARY KEY (`id`), KEY(`item_id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("exif", 1); } diff --git a/modules/g2_import/helpers/g2_import_installer.php b/modules/g2_import/helpers/g2_import_installer.php index 0f87da6c..feacb518 100644 --- a/modules/g2_import/helpers/g2_import_installer.php +++ b/modules/g2_import/helpers/g2_import_installer.php @@ -26,7 +26,7 @@ class g2_import_installer { `g3_id` int(9) NOT NULL, PRIMARY KEY (`id`), KEY (`g2_id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("g2_import", 1); mkdir(VARPATH . "modules/g2_import"); diff --git a/modules/gallery/controllers/admin_graphics.php b/modules/gallery/controllers/admin_graphics.php index 72f8d8e1..c59dd38e 100644 --- a/modules/gallery/controllers/admin_graphics.php +++ b/modules/gallery/controllers/admin_graphics.php @@ -21,41 +21,24 @@ class Admin_Graphics_Controller extends Admin_Controller { public function index() { $view = new Admin_View("admin.html"); $view->content = new View("admin_graphics.html"); - $view->content->available = ""; - - $tk = new ArrayObject(graphics::detect_toolkits(), ArrayObject::ARRAY_AS_PROPS); - $active = module::get_var("gallery", "graphics_toolkit", "none"); - foreach (array("gd", "imagemagick", "graphicsmagick", "none") as $id) { - if ($id == $active) { - $view->content->active = new View("admin_graphics_$id.html"); - $view->content->active->tk = $tk; - $view->content->active->is_active = true; - } else if ($id != "none") { - $v = new View("admin_graphics_$id.html"); - $v->tk = $tk; - $v->is_active = false; - $view->content->available .= $v; - } - } - + $view->content->tk = graphics::detect_toolkits(); + $view->content->active = module::get_var("gallery", "graphics_toolkit", "none"); print $view; } - public function choose($toolkit) { + public function choose($toolkit_id) { access::verify_csrf(); - if ($toolkit != module::get_var("gallery", "graphics_toolkit")) { - module::set_var("gallery", "graphics_toolkit", $toolkit); - - $toolkit_info = graphics::detect_toolkits(); - if ($toolkit == "graphicsmagick" || $toolkit == "imagemagick") { - module::set_var("gallery", "graphics_toolkit_path", $toolkit_info[$toolkit]); - } + if ($toolkit_id != module::get_var("gallery", "graphics_toolkit")) { + $tk = graphics::detect_toolkits(); + module::set_var("gallery", "graphics_toolkit", $toolkit_id); + module::set_var("gallery", "graphics_toolkit_path", $tk->$toolkit_id->dir); site_status::clear("missing_graphics_toolkit"); - message::success(t("Updated Graphics Toolkit")); - log::success("graphics", t("Changed graphics toolkit to: %toolkit", - array("toolkit" => $toolkit))); + + $msg = t("Changed graphics toolkit to: %toolkit", array("toolkit" => $tk->$toolkit_id->name)); + message::success($msg); + log::success("graphics", $msg); } url::redirect("admin/graphics"); diff --git a/modules/gallery/controllers/admin_languages.php b/modules/gallery/controllers/admin_languages.php index ae90ad07..6dc242c6 100644 --- a/modules/gallery/controllers/admin_languages.php +++ b/modules/gallery/controllers/admin_languages.php @@ -21,7 +21,10 @@ class Admin_Languages_Controller extends Admin_Controller { public function index($share_translations_form=null) { $v = new Admin_View("admin.html"); $v->content = new View("admin_languages.html"); - $v->content->settings_form = $this->_languages_form(); + $v->content->available_locales = locales::available(); + $v->content->installed_locales = locales::installed(); + $v->content->default_locale = module::get_var("gallery", "default_locale"); + if (empty($share_translations_form)) { $share_translations_form = $this->_share_translations_form(); } @@ -32,14 +35,21 @@ class Admin_Languages_Controller extends Admin_Controller { public function save() { access::verify_csrf(); - - $form = $this->_languages_form(); - if ($form->validate()) { - module::set_var("gallery", "default_locale", $form->choose_language->locale->value); - locales::update_installed($form->choose_language->installed_locales->value); - message::success(t("Settings saved")); - } - url::redirect("admin/languages"); + + locales::update_installed($this->input->post("installed_locales")); + + $installed_locales = array_keys(locales::installed()); + $new_default_locale = $this->input->post("default_locale"); + if (!in_array($new_default_locale, $installed_locales)) { + if (!empty($installed_locales)) { + $new_default_locale = $installed_locales[0]; + } else { + $new_default_locale = "en_US"; + } + } + module::set_var("gallery", "default_locale", $new_default_locale); + + print json_encode(array("result" => "success")); } public function share() { @@ -88,30 +98,6 @@ class Admin_Languages_Controller extends Admin_Controller { } } - private function _languages_form() { - $all_locales = locales::available(); - $installed_locales = locales::installed(); - $form = new Forge("admin/languages/save", "", "post", array("id" => "gLanguageSettingsForm")); - $group = $form->group("choose_language") - ->label(t("Language settings")); - $group->dropdown("locale") - ->options($installed_locales) - ->selected(module::get_var("gallery", "default_locale")) - ->label(t("Default language")) - ->rules('required'); - - $installation_options = array(); - foreach ($all_locales as $code => $display_name) { - $installation_options[$code] = array($display_name, isset($installed_locales->$code)); - } - $group->checklist("installed_locales") - ->label(t("Installed Languages")) - ->options($installation_options) - ->rules("required"); - $group->submit("save")->value(t("Save settings")); - return $form; - } - private function _outgoing_translations_count() { return ORM::factory("outgoing_translation")->count_all(); } diff --git a/modules/gallery/controllers/combined.php b/modules/gallery/controllers/combined.php index 9a790fdf..c1f42bfe 100644 --- a/modules/gallery/controllers/combined.php +++ b/modules/gallery/controllers/combined.php @@ -42,22 +42,23 @@ class Combined_Controller extends Controller { private function _emit($type, $key) { $input = Input::instance(); + // We don't need to save the session for this request + Session::abort_save(); + // Our data is immutable, so if they already have a copy then it needs no updating. if ($input->server("HTTP_IF_MODIFIED_SINCE")) { header('HTTP/1.0 304 Not Modified'); header("Expires: Tue, 19 Jan 2038 00:00:00 GMT"); header("Cache-Control: max-age=2678400"); header('Pragma: public'); - return; + Kohana::close_buffers(false); + return ""; } if (empty($key)) { Kohana::show_404(); } - // We don't need to save the session for this request - Session::abort_save(); - $cache = Cache::instance(); $use_gzip = function_exists("gzencode") && stripos($input->server("HTTP_ACCEPT_ENCODING"), "gzip") !== false && diff --git a/modules/gallery/controllers/file_proxy.php b/modules/gallery/controllers/file_proxy.php index a85f0a85..8cb90c50 100644 --- a/modules/gallery/controllers/file_proxy.php +++ b/modules/gallery/controllers/file_proxy.php @@ -119,7 +119,7 @@ class File_Proxy_Controller extends Controller { if (in_array($item->mime_type, array("video/x-flv", "video/mp4"))) { header("Content-type: image/jpeg"); } else { - print("Content-Type: $item->mime_type"); + header("Content-Type: $item->mime_type"); } Kohana::close_buffers(false); diff --git a/modules/gallery/controllers/l10n_client.php b/modules/gallery/controllers/l10n_client.php index 831c79c1..0775791e 100644 --- a/modules/gallery/controllers/l10n_client.php +++ b/modules/gallery/controllers/l10n_client.php @@ -90,10 +90,15 @@ class L10n_Client_Controller extends Controller { } $session = Session::instance(); - $session->set("l10n_mode", - !$session->get("l10n_mode", false)); - - url::redirect("albums/1"); + $l10n_mode = $session->get("l10n_mode", false); + $session->set("l10n_mode", !$l10n_mode); + + $redirect_url = "admin/languages"; + if (!$l10n_mode) { + $redirect_url .= "#l10n-client"; + } + + url::redirect($redirect_url); } private static function _l10n_client_search_form() { diff --git a/modules/gallery/controllers/packager.php b/modules/gallery/controllers/packager.php index 7b4d68f6..fbb1d07d 100644 --- a/modules/gallery/controllers/packager.php +++ b/modules/gallery/controllers/packager.php @@ -123,6 +123,10 @@ class Packager_Controller extends Controller { // Normalize dates $line = preg_replace("/,$root_created_timestamp,/", ",UNIX_TIMESTAMP(),", $line); $line = preg_replace("/,$root_updated_timestamp,/", ",UNIX_TIMESTAMP(),", $line); + + // Remove ENGINE= specifications + $line = preg_replace("/ENGINE=\S+ /", "", $line); + $buf .= $line; } $fd = fopen($sql_file, "wb"); diff --git a/modules/gallery/controllers/quick.php b/modules/gallery/controllers/quick.php index 98a5bf9f..8fddb563 100644 --- a/modules/gallery/controllers/quick.php +++ b/modules/gallery/controllers/quick.php @@ -18,20 +18,6 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class Quick_Controller extends Controller { - public function pane($id) { - $item = model_cache::get("item", $id); - if (!access::can("view", $item) || !access::can("edit", $item)) { - return ""; - } - - $view = new View("quick_pane.html"); - $page_type = Input::instance()->get("page_type"); - $view->button_list = gallery_quick::get_quick_buttons($item, $page_type); - $view->item = $item; - $view->page_type = $page_type; - print $view; - } - public function rotate($id, $dir) { access::verify_csrf(); $item = model_cache::get("item", $id); diff --git a/modules/gallery/controllers/simple_uploader.php b/modules/gallery/controllers/simple_uploader.php index e7c0bd6f..156d18ac 100644 --- a/modules/gallery/controllers/simple_uploader.php +++ b/modules/gallery/controllers/simple_uploader.php @@ -71,7 +71,7 @@ class Simple_Uploader_Controller extends Controller { unlink($temp_filename); } header("HTTP/1.1 500 Internal Server Error"); - print "ERROR:" . $e->getMessage(); + print "ERROR: " . $e->getMessage(); return; } unlink($temp_filename); diff --git a/modules/gallery/css/l10n_client.css b/modules/gallery/css/l10n_client.css index 51cbc753..9c1b12d0 100644 --- a/modules/gallery/css/l10n_client.css +++ b/modules/gallery/css/l10n_client.css @@ -42,9 +42,17 @@ cursor:pointer; display:block; position:absolute; right:0em; - padding: 0em .75em; height:2em; line-height:2em; + height:2em; line-height:2em; text-transform:uppercase; - text-align:center; background:#000;} + text-align:center; background:#000; +} +#l10n-client-toggler a { + font-size: 1em; + padding: .5em; +} +#l10n-client-toggler #gMinimizeL10n { + border-right: 1px solid #ffffff; +} /* Panel labels */ #l10n-client h2 { diff --git a/modules/gallery/css/quick.css b/modules/gallery/css/quick.css deleted file mode 100644 index f153d475..00000000 --- a/modules/gallery/css/quick.css +++ /dev/null @@ -1,52 +0,0 @@ -.gQuickPane { - position: absolute; - top: 0; - left: 0; - text-align: center; - width: 100%; - height: auto; -} - -.gItem:hover { - background-color: #cfdeff; -} - -.gQuick { - border: none !important; - margin: 0 !important; - padding: 0 !important; -} - -.gQuickPane { - background: #000; - border-bottom: 1px solid #ccc; - opacity: 0.9; - position: absolute; - top: 0; - left: 0; -} - -.gQuickPane a { - cursor: pointer; - float: left; - margin: 4px; -} - -.gQuickPaneOptions { - background: #000; - float: left; - width: 100%; -} - -.gQuickPaneOptions li a { - display: block; - float: none; - width: auto; - margin: 0; - padding: .5em .5em .5em .8em; - text-align: left; -} - -.gQuickPaneOptions li a:hover { - background-color: #4d4d4d; -} diff --git a/modules/gallery/helpers/album.php b/modules/gallery/helpers/album.php index 8a7c9951..d46f21ac 100644 --- a/modules/gallery/helpers/album.php +++ b/modules/gallery/helpers/album.php @@ -56,7 +56,7 @@ class album_Core { $album->thumb_dirty = 1; $album->resize_dirty = 1; $album->rand_key = ((float)mt_rand()) / (float)mt_getrandmax(); - $album->sort_column = "weight"; + $album->sort_column = "created"; $album->sort_order = "ASC"; while (ORM::factory("item") @@ -116,13 +116,7 @@ class album_Core { $sort_order->dropdown("column", array("id" => "gAlbumSortColumn")) ->label(t("Sort by")) - ->options(array("weight" => t("Order Added"), - "captured" => t("Capture Date"), - "created" => t("Creation Date"), - "title" => t("Title"), - "updated" => t("Updated Date"), - "view_count" => t("Number of views"), - "rand_key" => t("Random"))) + ->options(album::get_sort_order_options()) ->selected($parent->sort_column); $sort_order->dropdown("direction", array("id" => "gAlbumSortDirection")) ->label(t("Order")) @@ -137,4 +131,17 @@ class album_Core { $form->add_rules_from(ORM::factory("item")); return $form; } + + /** + * Return a structured set of all the possible sort orders. + */ + static function get_sort_order_options() { + return array("weight" => t("Manual"), + "captured" => t("Date captured"), + "created" => t("Date uploaded"), + "title" => t("Title"), + "updated" => t("Date modified"), + "view_count" => t("Number of views"), + "rand_key" => t("Random")); + } } diff --git a/modules/gallery/helpers/gallery.php b/modules/gallery/helpers/gallery.php index 476e9cbe..122227fc 100644 --- a/modules/gallery/helpers/gallery.php +++ b/modules/gallery/helpers/gallery.php @@ -82,9 +82,9 @@ class gallery_Core { static function site_menu($menu, $theme) { if ($theme->page_type != "login") { $menu->append(Menu::factory("link") - ->id("home") - ->label(t("Home")) - ->url(url::site("albums/1"))); + ->id("home") + ->label(t("Home")) + ->url(url::site("albums/1"))); $item = $theme->item(); @@ -92,48 +92,47 @@ class gallery_Core { $can_add = $item && access::can("add", $item); if ($can_add) { - $menu->append(Menu::factory("dialog") - ->id("add_photos_item") - ->label(t("Add photos")) - ->url(url::site("simple_uploader/app/$item->id"))); + $menu->append($add_menu = Menu::factory("submenu") + ->id("add_menu") + ->label(t("Add"))); + $add_menu->append(Menu::factory("dialog") + ->id("add_photos_item") + ->label(t("Add photos")) + ->url(url::site("simple_uploader/app/$item->id"))); + if ($item->is_album()) { + $add_menu->append(Menu::factory("dialog") + ->id("add_album_item") + ->label(t("Add an album")) + ->url(url::site("form/add/albums/$item->id?type=album"))); + } } $menu->append($options_menu = Menu::factory("submenu") - ->id("options_menu") - ->label(t("Options"))); + ->id("options_menu") + ->label(t("Photo options"))); if ($item && ($can_edit || $can_add)) { if ($can_edit) { - $options_menu - ->append(Menu::factory("dialog") - ->id("edit_item") - ->label($item->is_album() ? t("Edit album") : t("Edit photo")) - ->url(url::site("form/edit/{$item->type}s/$item->id"))); + $options_menu->append(Menu::factory("dialog") + ->id("edit_item") + ->label($item->is_album() ? t("Edit album") : t("Edit photo")) + ->url(url::site("form/edit/{$item->type}s/$item->id"))); } - // @todo Move album options menu to the album quick edit pane if ($item->is_album()) { - if ($can_add) { - $options_menu - ->append(Menu::factory("dialog") - ->id("add_album") - ->label(t("Add an album")) - ->url(url::site("form/add/albums/$item->id?type=album"))); - } - + $options_menu->label(t("Album options")); if ($can_edit) { - $options_menu - ->append(Menu::factory("dialog") - ->id("edit_permissions") - ->label(t("Edit permissions")) - ->url(url::site("permissions/browse/$item->id"))); + $options_menu->append(Menu::factory("dialog") + ->id("edit_permissions") + ->label(t("Edit permissions")) + ->url(url::site("permissions/browse/$item->id"))); } } } if (user::active()->admin) { $menu->append($admin_menu = Menu::factory("submenu") - ->id("admin_menu") - ->label(t("Admin"))); + ->id("admin_menu") + ->label(t("Admin"))); gallery::admin_menu($admin_menu, $theme); module::event("admin_menu", $admin_menu, $theme); } @@ -160,12 +159,6 @@ class gallery_Core { ->label(t("Languages")) ->url(url::site("admin/languages"))) ->append(Menu::factory("link") - ->id("l10n_mode") - ->label(Session::instance()->get("l10n_mode", false) - ? t("Stop translating") : t("Start translating")) - ->url(url::site("l10n_client/toggle_l10n_mode?csrf=" . - access::csrf_token()))) - ->append(Menu::factory("link") ->id("advanced") ->label(t("Advanced")) ->url(url::site("admin/advanced_settings")))) @@ -196,4 +189,118 @@ class gallery_Core { ->url(url::site("admin/maintenance"))); return $menu; } + + static function context_menu($menu, $theme, $item, $thumb_css_selector) { + $menu->append($options_menu = Menu::factory("submenu") + ->id("options_menu") + ->label(t("Options")) + ->css_class("ui-icon-carat-1-n")); + + if (access::can("edit", $item)) { + $page_type = $theme->page_type(); + switch ($item->type) { + case "movie": + $edit_title = t("Edit this movie"); + $delete_title = t("Delete this movie"); + break; + + case "album": + $edit_title = t("Edit this album"); + $delete_title = t("Delete this album"); + break; + + default: + $edit_title = t("Edit this photo"); + $delete_title = t("Delete this photo"); + break; + } + $cover_title = t("Choose as the album cover"); + $move_title = t("Move to another album"); + + $csrf = access::csrf_token(); + + $options_menu->append(Menu::factory("dialog") + ->id("edit") + ->label($edit_title) + ->css_class("ui-icon-pencil") + ->url(url::site("quick/form_edit/$item->id?page_type=$page_type"))); + + + if ($item->is_photo() && graphics::can("rotate")) { + $options_menu + ->append( + Menu::factory("ajax_link") + ->id("rotate_ccw") + ->label(t("Rotate 90° counter clockwise")) + ->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&page_type=$page_type"))) + ->append( + Menu::factory("ajax_link") + ->id("rotate_cw") + ->label(t("Rotate 90° clockwise")) + ->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&page_type=$page_type"))); + } + + // Don't move photos from the photo page; we don't yet have a good way of redirecting after + // move + if ($page_type == "album") { + $options_menu + ->append(Menu::factory("dialog") + ->id("move") + ->label($move_title) + ->css_class("ui-icon-folder-open") + ->url(url::site("move/browse/$item->id"))); + } + + $parent = $item->parent(); + if (access::can("edit", $parent)) { + // We can't make this item the highlight if it's an album with no album cover, or if it's + // already the album cover. + if (($item->type == "album" && empty($item->album_cover_item_id)) || + ($item->type == "album" && $parent->album_cover_item_id == $item->album_cover_item_id) || + $parent->album_cover_item_id == $item->id) { + $disabledState = " ui-state-disabled"; + } else { + $disabledState = " "; + } + $options_menu + ->append(Menu::factory("ajax_link") + ->id("make_album_cover") + ->label($cover_title) + ->css_class("ui-icon-star") + ->ajax_handler("function(data) { window.location.reload() }") + ->url(url::site("quick/make_album_cover/$item->id?csrf=$csrf"))) + ->append(Menu::factory("dialog") + ->id("delete") + ->label($delete_title) + ->css_class("ui-icon-trash") + ->css_id("gQuickDelete") + ->url(url::site("quick/form_delete/$item->id?csrf=$csrf&page_type=$page_type"))); + } + + if ($item->is_album()) { + $options_menu + ->append(Menu::factory("dialog") + ->id("add_item") + ->label(t("Add a photo")) + ->css_class("add_item") + ->url(url::site("simple_uploader/app/$item->id"))) + ->append(Menu::factory("dialog") + ->id("add_album") + ->label(t("Add an album")) + ->css_class("add_album") + ->url(url::site("form/add/albums/$item->id?type=album"))) + ->append(Menu::factory("dialog") + ->id("edit_permissions") + ->label(t("Edit permissions")) + ->css_class("permissions") + ->url(url::site("permissions/browse/$item->id"))); + } + } + } }
\ No newline at end of file diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php index d12dad70..a212ef85 100644 --- a/modules/gallery/helpers/gallery_installer.php +++ b/modules/gallery/helpers/gallery_installer.php @@ -24,13 +24,13 @@ class gallery_installer { `id` int(9) NOT NULL auto_increment, `item_id` int(9), PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {access_intents} ( `id` int(9) NOT NULL auto_increment, `item_id` int(9), PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {caches} ( `id` int(9) NOT NULL auto_increment, @@ -40,7 +40,7 @@ class gallery_installer { `cache` longblob, PRIMARY KEY (`id`), KEY (`tags`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {graphics_rules} ( `id` int(9) NOT NULL auto_increment, @@ -51,7 +51,7 @@ class gallery_installer { `priority` int(9) NOT NULL, `target` varchar(32) NOT NULL, PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {incoming_translations} ( `id` int(9) NOT NULL auto_increment, @@ -63,7 +63,7 @@ class gallery_installer { PRIMARY KEY (`id`), UNIQUE KEY(`key`, `locale`), KEY `locale_key` (`locale`, `key`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {items} ( `id` int(9) NOT NULL auto_increment, @@ -100,7 +100,7 @@ class gallery_installer { KEY `type` (`type`), KEY `random` (`rand_key`), KEY `weight` (`weight` DESC)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {logs} ( `id` int(9) NOT NULL auto_increment, @@ -113,7 +113,7 @@ class gallery_installer { `url` varchar(255) default NULL, `user_id` int(9) default 0, PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {messages} ( `id` int(9) NOT NULL auto_increment, @@ -122,7 +122,7 @@ class gallery_installer { `value` varchar(255) default NULL, PRIMARY KEY (`id`), UNIQUE KEY(`key`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {modules} ( `id` int(9) NOT NULL auto_increment, @@ -131,7 +131,7 @@ class gallery_installer { `version` int(9) default NULL, PRIMARY KEY (`id`), UNIQUE KEY(`name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {outgoing_translations} ( `id` int(9) NOT NULL auto_increment, @@ -143,7 +143,7 @@ class gallery_installer { PRIMARY KEY (`id`), UNIQUE KEY(`key`, `locale`), KEY `locale_key` (`locale`, `key`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {permissions} ( `id` int(9) NOT NULL auto_increment, @@ -151,14 +151,14 @@ class gallery_installer { `name` varchar(64) default NULL, PRIMARY KEY (`id`), UNIQUE KEY(`name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {sessions} ( `session_id` varchar(127) NOT NULL, `data` text NOT NULL, `last_activity` int(10) UNSIGNED NOT NULL, PRIMARY KEY (`session_id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {tasks} ( `id` int(9) NOT NULL auto_increment, @@ -173,7 +173,7 @@ class gallery_installer { `updated` int(9) default NULL, PRIMARY KEY (`id`), KEY (`owner_id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {themes} ( `id` int(9) NOT NULL auto_increment, @@ -181,7 +181,7 @@ class gallery_installer { `version` int(9) default NULL, PRIMARY KEY (`id`), UNIQUE KEY(`name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {vars} ( `id` int(9) NOT NULL auto_increment, @@ -190,7 +190,7 @@ class gallery_installer { `value` text, PRIMARY KEY (`id`), UNIQUE KEY(`module_name`, `name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); foreach (array("albums", "logs", "modules", "resizes", "thumbs", "tmp", "uploads") as $dir) { @mkdir(VARPATH . $dir); @@ -284,7 +284,7 @@ class gallery_installer { `cache` text, PRIMARY KEY (`id`), KEY (`tags`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("gallery", $version = 4); } diff --git a/modules/gallery/helpers/gallery_quick.php b/modules/gallery/helpers/gallery_quick.php deleted file mode 100644 index 8a92890b..00000000 --- a/modules/gallery/helpers/gallery_quick.php +++ /dev/null @@ -1,152 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); -/** - * Gallery - a web based photo album viewer and editor - * Copyright (C) 2000-2009 Bharat Mediratta - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. - */ -class gallery_quick_Core { - static function get_quick_buttons($item, $page_type) { - $buttons = self::buttons($item, $page_type); - foreach (module::active() as $module) { - if ($module->name == "gallery") { - continue; - } - $class_name = "{$module->name}_quick"; - if (method_exists($class_name, "buttons")) { - $module_buttons = call_user_func(array($class_name, "buttons"), $item, $page_type); - foreach (array("left", "center", "right", "additional") as $position) { - if (!empty($module_buttons[$position])) { - $buttons[$position] = array_merge($buttons[$position], $module_buttons[$position]); - } - } - } - } - - $sorted_buttons->main = array(); - foreach (array("left", "center", "right") as $position) { - $sorted_buttons->main = array_merge($sorted_buttons->main, $buttons[$position]); - } - - $sorted_buttons->additional = $buttons["additional"]; - $max_display = empty($sorted_buttons->additional) ? 6 : 5; - if (count($sorted_buttons->main) >= $max_display) { - $to_move = array_slice($sorted_buttons->main, 5); - $sorted_buttons->additional = array_merge($to_move, $sorted_buttons->additional); - for ($i = count($sorted_buttons->main); $i >= 5; $i--) { - unset($sorted_buttons->main[$i]); - } - } - - return $sorted_buttons; - } - - static function buttons($item, $page_type) { - $elements = array("left" => array(), "center" => array(), "right" => array(), - "additional" => array()); - switch ($item->type) { - case "movie": - $edit_title = t("Edit this movie"); - $move_title = t("Move this movie to another album"); - $cover_title = t("Choose this movie as the album cover"); - $delete_title = t("Delete this movie"); - break; - case "album": - $edit_title = t("Edit this album"); - $move_title = t("Move this album to another album"); - $cover_title = t("Choose this album as the album cover"); - $delete_title = t("Delete this album"); - break; - default: - $edit_title = t("Edit this photo"); - $move_title = t("Move this photo to another album"); - $cover_title = t("Choose this photo as the album cover"); - $delete_title = t("Delete this photo"); - break; - } - - $csrf = access::csrf_token(); - $elements["left"][] = (object)array( - "title" => $edit_title, - "class" => "gDialogLink gButtonLink", - "icon" => "ui-icon-pencil", - "href" => url::site("quick/form_edit/$item->id?page_type=$page_type")); - - if ($item->is_photo() && graphics::can("rotate")) { - $elements["left"][] = - (object)array( - "title" => t("Rotate 90 degrees counter clockwise"), - "class" => "gButtonLink", - "icon" => "ui-icon-rotate-ccw", - "href" => url::site("quick/rotate/$item->id/ccw?csrf=$csrf&page_type=$page_type")); - $elements["left"][] = - (object)array( - "title" => t("Rotate 90 degrees clockwise"), - "class" => "gButtonLink", - "icon" => "ui-icon-rotate-cw", - "href" => url::site("quick/rotate/$item->id/cw?csrf=$csrf&page_type=$page_type")); - } - - // Don't move photos from the photo page; we don't yet have a good way of redirecting after move - if ($page_type == "album") { - $elements["left"][] = (object)array( - "title" => $move_title, - "class" => "gDialogLink gButtonLink", - "icon" => "ui-icon-folder-open", - "href" => url::site("move/browse/$item->id")); - } - - $parent = $item->parent(); - if (access::can("edit", $parent)) { - // We can't make this item the highlight if it's an album with no album cover, or if it's - // already the album cover. - if (($item->type == "album" && empty($item->album_cover_item_id)) || - ($item->type == "album" && $parent->album_cover_item_id == $item->album_cover_item_id) || - $parent->album_cover_item_id == $item->id) { - $disabledState = " ui-state-disabled"; - } else { - $disabledState = " "; - } - $elements["right"][] = (object)array( - "title" => $cover_title, - "class" => "gButtonLink$disabledState", - "icon" => "ui-icon-star", - "href" => url::site("quick/make_album_cover/$item->id?csrf=$csrf&page_type=$page_type")); - - $elements["right"][] = (object)array( - "title" => $delete_title, - "class" => "gDialogLink gButtonLink", - "icon" => "ui-icon-trash", - "id" => "gQuickDelete", - "href" => url::site("quick/form_delete/$item->id?csrf=$csrf&page_type=$page_type")); - } - - if ($item->is_album()) { - $elements["additional"][] = (object)array( - "title" => t("Add a photo"), - "class" => "add_item gDialogLink", - "href" => url::site("simple_uploader/app/$item->id")); - $elements["additional"][] = (object)array( - "title" => t("Add an album"), - "class" => "add_album gDialogLink", - "href" => url::site("form/add/albums/$item->id?type=album")); - $elements["additional"][] = (object)array( - "title" => t("Edit permissions"), - "class" => "permissions gDialogLink", - "href" => url::site("permissions/browse/$item->id")); - } - return $elements; - } -} diff --git a/modules/gallery/helpers/gallery_rss.php b/modules/gallery/helpers/gallery_rss.php index be555296..affb3101 100644 --- a/modules/gallery/helpers/gallery_rss.php +++ b/modules/gallery/helpers/gallery_rss.php @@ -50,8 +50,9 @@ class gallery_rss_Core { $feed->children = $item ->viewable() - ->descendants($limit, $offset, "photo"); - $feed->max_pages = ceil($item->viewable()->descendants_count("photo") / $limit); + ->descendants($limit, $offset, array("type" => "photo")); + $feed->max_pages = ceil( + $item->viewable()->descendants_count(array("type" => "photo")) / $limit); $feed->title = SafeString::purify($item->title); $feed->link = url::abs_site("albums/{$item->id}"); $feed->description = nl2br(SafeString::purify($item->description)); diff --git a/modules/gallery/helpers/gallery_theme.php b/modules/gallery/helpers/gallery_theme.php index d3751b80..69c5a091 100644 --- a/modules/gallery/helpers/gallery_theme.php +++ b/modules/gallery/helpers/gallery_theme.php @@ -24,11 +24,6 @@ class gallery_theme_Core { if ($session->get("debug")) { $theme->css("debug.css"); } - if (($theme->page_type == "album" || $theme->page_type == "photo") - && access::can("edit", $theme->item())) { - $theme->css("quick.css"); - $theme->script("quick.js"); - } if (module::is_active("rss")) { if ($item = $theme->item()) { @@ -51,33 +46,8 @@ class gallery_theme_Core { return $buf; } - static function resize_top($theme, $item) { - if (access::can("edit", $item)) { - $edit_link = url::site("quick/pane/$item->id?page_type=photo"); - return "<div class=\"gQuick\" href=\"$edit_link\">"; - } - } - - static function resize_bottom($theme, $item) { - if (access::can("edit", $item)) { - return "</div>"; - } - } - - static function thumb_top($theme, $child) { - if (access::can("edit", $child)) { - $edit_link = url::site("quick/pane/$child->id?page_type=album"); - return "<div class=\"gQuick\" href=\"$edit_link\">"; - } - } - - static function thumb_bottom($theme, $child) { - if (access::can("edit", $child)) { - return "</div>"; - } - } - static function admin_head($theme) { + $theme->script("gallery.panel.js"); $session = Session::instance(); if ($session->get("debug")) { $theme->css("debug.css"); diff --git a/modules/gallery/helpers/graphics.php b/modules/gallery/helpers/graphics.php index d506a982..7dc46eeb 100644 --- a/modules/gallery/helpers/graphics.php +++ b/modules/gallery/helpers/graphics.php @@ -339,15 +339,90 @@ class graphics_Core { * GraphicsMagick we return the path to the directory containing the appropriate binaries. */ static function detect_toolkits() { + $toolkits = new stdClass(); + + // GD is special, it doesn't use exec() $gd = function_exists("gd_info") ? gd_info() : array(); - $exec = function_exists("exec"); + $toolkits->gd->name = "GD"; if (!isset($gd["GD Version"])) { - $gd["GD Version"] = false; + $toolkits->gd->installed = false; + $toolkits->gd->error = t("GD is not installed"); + } else { + $toolkits->gd->installed = true; + $toolkits->gd->version = $gd["GD Version"]; + $toolkits->gd->rotate = function_exists("imagerotate"); + $toolkits->gd->binary = ""; + $toolkits->gd->dir = ""; + + if (!$toolkits->gd->rotate) { + $toolkits->gd->error = + t("You have GD version %version, but it lacks image rotation.", + array("version" => $gd["GD Version"])); + } + } + + if (!function_exists("exec")) { + $toolkits->imagemagick->installed = false; + $toolkits->imagemagick->error = t("ImageMagick requires the <b>exec</b> function"); + + $toolkits->graphicsmagick->installed = false; + $toolkits->graphicsmagick->error = t("GraphicsMagick requires the <b>exec</b> function"); + } else { + putenv("PATH=" . getenv("PATH") . ":/usr/local/bin:/opt/local/bin:/opt/bin"); + + // @todo: consider refactoring the two segments below into a loop since they are so + // similar. + + // ImageMagick + $path = exec("which convert"); + $toolkits->imagemagick->name = "ImageMagick"; + if ($path) { + if (@is_file($path)) { + preg_match('/Version: \S+ (\S+)/', `convert -v`, $matches); + $version = $matches[1]; + + $toolkits->imagemagick->installed = true; + $toolkits->imagemagick->version = $version; + $toolkits->imagemagick->binary = $path; + $toolkits->imagemagick->dir = dirname($path); + $toolkits->imagemagick->rotate = true; + } else { + $toolkits->imagemagick->installed = false; + $toolkits->imagemagick->error = + t("ImageMagick is installed, but PHP's open_basedir restriction " . + "prevents Gallery from using it."); + } + } else { + $toolkits->imagemagick->installed = false; + $toolkits->imagemagick->error = t("We could not locate ImageMagick on your system."); + } + + // GraphicsMagick + $path = exec("which gm"); + $toolkits->graphicsmagick->name = "GraphicsMagick"; + if ($path) { + if (@is_file($path)) { + preg_match('/\S+ (\S+)/', `gm version`, $matches); + $version = $matches[1]; + + $toolkits->graphicsmagick->installed = true; + $toolkits->graphicsmagick->version = $version; + $toolkits->graphicsmagick->binary = $path; + $toolkits->graphicsmagick->dir = dirname($path); + $toolkits->graphicsmagick->rotate = true; + } else { + $toolkits->graphicsmagick->installed = false; + $toolkits->graphicsmagick->error = + t("GraphicsMagick is installed, but PHP's open_basedir restriction " . + "prevents Gallery from using it."); + } + } else { + $toolkits->graphicsmagick->installed = false; + $toolkits->graphicsmagick->error = t("We could not locate GraphicsMagick on your system."); + } } - putenv("PATH=" . getenv("PATH") . ":/usr/local/bin:/opt/local/bin:/opt/bin"); - return array("gd" => $gd, - "imagemagick" => $exec ? dirname(exec("which convert")) : false, - "graphicsmagick" => $exec ? dirname(exec("which gm")) : false); + + return $toolkits; } /** @@ -357,12 +432,13 @@ class graphics_Core { // Detect a graphics toolkit $toolkits = graphics::detect_toolkits(); foreach (array("imagemagick", "graphicsmagick", "gd") as $tk) { - if ($toolkits[$tk]) { + if ($toolkits->$tk->installed) { module::set_var("gallery", "graphics_toolkit", $tk); - module::set_var("gallery", "graphics_toolkit_path", $tk == "gd" ? "" : $toolkits[$tk]); + module::set_var("gallery", "graphics_toolkit_path", $toolkits->$tk->dir); break; } } + if (!module::get_var("gallery", "graphics_toolkit")) { site_status::warning( t("Graphics toolkit missing! Please <a href=\"%url\">choose a toolkit</a>", diff --git a/modules/gallery/helpers/item.php b/modules/gallery/helpers/item.php index 80c25862..8839861f 100644 --- a/modules/gallery/helpers/item.php +++ b/modules/gallery/helpers/item.php @@ -129,7 +129,7 @@ class item_Core { if (Input::instance()->get("page_type") == "album") { $page_type = "album"; } else { - $page_type = "item"; + $page_type = "photo"; } $form = new Forge("quick/delete/$item->id?page_type=$page_type", "", "post", array("id" => "gConfirmDelete")); $form->hidden("_method")->value("put"); @@ -137,4 +137,55 @@ class item_Core { $group->submit("")->value(t("Delete")); return $form; } + + /** + * Get the next weight value + */ + static function get_max_weight() { + // Guard against an empty result when we create the first item. It's unfortunate that we + // have to check this every time. + // @todo: figure out a better way to bootstrap the weight. + $result = Database::instance() + ->select("weight")->from("items") + ->orderby("weight", "desc")->limit(1) + ->get()->current(); + return ($result ? $result->weight : 0) + 1; + } + + /** + * Add a set of restrictions to any following queries to restrict access only to items + * viewable by the active user. + * @chainable + */ + static function viewable($model) { + $view_restrictions = array(); + if (!user::active()->admin) { + foreach (user::group_ids() as $id) { + // Separate the first restriction from the rest to make it easier for us to formulate + // our where clause below + if (empty($view_restrictions)) { + $view_restrictions[0] = "items.view_$id"; + } else { + $view_restrictions[1]["items.view_$id"] = access::ALLOW; + } + } + } + switch (count($view_restrictions)) { + case 0: + break; + + case 1: + $model->where($view_restrictions[0], access::ALLOW); + break; + + default: + $model->open_paren(); + $model->where($view_restrictions[0], access::ALLOW); + $model->orwhere($view_restrictions[1]); + $model->close_paren(); + break; + } + + return $model; + } }
\ No newline at end of file diff --git a/modules/gallery/helpers/module.php b/modules/gallery/helpers/module.php index 0d483206..03d538a9 100644 --- a/modules/gallery/helpers/module.php +++ b/modules/gallery/helpers/module.php @@ -274,11 +274,9 @@ class module_Core { array_shift($args); $function = str_replace(".", "_", $name); - foreach (self::$modules as $module) { - if (!$module->active) { - continue; - } - + // @todo: consider calling gallery_event first, since for things menus we need it to do some + // setup + foreach (self::$active as $module) { $class = "{$module->name}_event"; if (method_exists($class, $function)) { call_user_func_array(array($class, $function), $args); diff --git a/modules/gallery/helpers/photo.php b/modules/gallery/helpers/photo.php index 5cf37de1..96a66d29 100644 --- a/modules/gallery/helpers/photo.php +++ b/modules/gallery/helpers/photo.php @@ -109,8 +109,12 @@ class photo_Core { // there's only one save() happening here. module::event("item_created", $photo); - // Build our thumbnail/resizes - graphics::generate($photo); + // Build our thumbnail/resizes. If we fail to build thumbnail/resize we assume that the image + // is bad in some way and discard it. + if (!graphics::generate($photo)) { + $photo->delete(); + throw new Exception("@todo BAD_IMAGE_FILE"); + } // If the parent has no cover item, make this it. if (access::can("edit", $parent) && $parent->album_cover_item_id == null) { diff --git a/modules/gallery/helpers/task.php b/modules/gallery/helpers/task.php index 352fe522..9fa04305 100644 --- a/modules/gallery/helpers/task.php +++ b/modules/gallery/helpers/task.php @@ -84,6 +84,7 @@ class task_Core { } $task->save(); } catch (Exception $e) { + Kohana::log("error", $e->__toString()); $task->log($e->__toString()); $task->state = "error"; $task->done = true; diff --git a/modules/gallery/js/l10n_client.js b/modules/gallery/js/l10n_client.js index f5be5058..80fe166b 100644 --- a/modules/gallery/js/l10n_client.js +++ b/modules/gallery/js/l10n_client.js @@ -58,7 +58,8 @@ jQuery.extend(Gallery, { case 1: $('#l10n-client-string-select, #l10n-client-string-editor, #l10n-client .labels .label').show(); $('#l10n-client').height('22em').removeClass('hidden'); - $('#l10n-client-toggler').text(MSG_CLOSE_X); + //$('#l10n-client').slideUp(); + $('#gMinimizeL10n').text("_"); /* * This CSS clashes with Gallery's CSS, probably due to * YUI's grid / floats. @@ -72,7 +73,7 @@ jQuery.extend(Gallery, { $('#l10n-client-string-select, #l10n-client-string-editor, #l10n-client .labels .label').hide(); $('#l10n-client').height('2em').addClass('hidden'); // TODO: Localize this message - $('#l10n-client-toggler').text(MSG_TRANSLATE_TEXT); + $('#gMinimizeL10n').text(MSG_TRANSLATE_TEXT); /* if(!$.browser.msie) { $('body').css('border-bottom', '0px'); @@ -197,7 +198,7 @@ Gallery.behaviors.l10nClient = function(context) { }); // When l10n_client window is clicked, toggle based on current state. - $('#l10n-client-toggler').click(function() { + $('#gMinimizeL10n').click(function() { if($('#l10n-client').is('.hidden')) { Gallery.l10nClient.toggle(1); } else { diff --git a/modules/gallery/js/quick.js b/modules/gallery/js/quick.js deleted file mode 100644 index fda6470f..00000000 --- a/modules/gallery/js/quick.js +++ /dev/null @@ -1,78 +0,0 @@ -$(document).ready(function() { - if ($("#gAlbumGrid").length) { - // @todo Add quick edit pane for album (meta, move, permissions, delete) - $(".gItem").hover(show_quick, function() {}); - } - if ($("#gPhoto").length) { - $("#gPhoto").hover(show_quick, function() {}); - } -}); - -var show_quick = function() { - var cont = $(this); - var quick = $(this).find(".gQuick"); - var img = cont.find(".gThumbnail,.gResize"); - cont.find(".gQuickPane").remove(); - cont.append("<div class=\"gQuickPane\"></div>"); - cont.find(".gQuickPane").hide(); - cont.hover(function() {}, function() { cont.find(".gQuickPane").remove(); }); - $.get( - quick.attr("href"), - {}, - function(data, textStatus) { - cont.find(".gQuickPane").html(data).slideDown("fast"); - $(".ui-state-default").hover( - function() { - $(this).addClass("ui-state-hover"); - }, - function() { - $(this).removeClass("ui-state-hover"); - } - ); - cont.find(".gQuickPane a:not(.options)").click(function(e) { - e.preventDefault(); - quick_do(cont, $(this), img); - }); - cont.find(".gQuickPane a.options").click(function(e) { - e.preventDefault(); - cont.find(".gQuickPaneOptions").slideToggle("fast"); - }); - } - ); -}; - -var quick_do = function(cont, pane, img) { - if (pane.hasClass("ui-state-disabled")) { - return false; - } - if (pane.hasClass("gDialogLink")) { - openDialog(pane); - } else { - img.css("opacity", "0.1"); - cont.addClass("gLoadingLarge"); - $.ajax({ - type: "GET", - url: pane.attr("href"), - dataType: "json", - success: function(data) { - img.css("opacity", "1"); - cont.removeClass("gLoadingLarge"); - if (data.src) { - img.attr("width", data.width); - img.attr("height", data.height); - img.attr("src", data.src); - if (data.height > data.width) { - img.css("margin-top", -32); - } else { - img.css("margin-top", 0); - } - } else if (data.location) { - window.location = data.location; - } else if (data.reload) { - window.location.reload(); - } - } - }); - } - return false; -}; diff --git a/modules/gallery/libraries/I18n.php b/modules/gallery/libraries/I18n.php index a53d5ae9..c3336052 100644 --- a/modules/gallery/libraries/I18n.php +++ b/modules/gallery/libraries/I18n.php @@ -77,7 +77,12 @@ class I18n_Core { // TODO: See G2 for better fallack code. $locale_prefs = array($locale); $locale_prefs[] = 'en_US'; - setlocale(LC_ALL, $locale_prefs); + $new_locale = setlocale(LC_ALL, $locale_prefs); + if (is_string($new_locale) && strpos($new_locale, 'tr') === 0) { + // Make PHP 5 work with Turkish (the localization results are mixed though). + // Hack for http://bugs.php.net/18556 + setlocale(LC_CTYPE, 'C'); + } } return $this->_config['default_locale']; } @@ -184,7 +189,7 @@ class I18n_Core { static function is_plural_message($message) { return is_array($message); } - + private function interpolate($locale, $string, $key_values) { // TODO: Handle locale specific number formatting. diff --git a/modules/gallery/libraries/Menu.php b/modules/gallery/libraries/Menu.php index a39b59a5..07b2b2b8 100644 --- a/modules/gallery/libraries/Menu.php +++ b/modules/gallery/libraries/Menu.php @@ -91,12 +91,43 @@ class Menu_Element_Link extends Menu_Element { } else { $css_class = ""; } - return "<li><a$css_id class=\"gMenuElement$css_class\" href=\"$this->url\" " . + return "<li><a$css_id class=\"gMenuLink $css_class\" href=\"$this->url\" " . "title=\"$this->label\">$this->label</a></li>"; } } /** + * Menu element that provides an AJAX link. + */ +class Menu_Element_Ajax_Link extends Menu_Element { + public $ajax_handler; + + /** + * Set the AJAX handler + * @chainable + */ + public function ajax_handler($ajax_handler) { + $this->ajax_handler = $ajax_handler; + return $this; + } + + public function __toString() { + if (isset($this->css_id) && !empty($this->css_id)) { + $css_id = " id=\"$this->css_id\""; + } else { + $css_id = ""; + } + if (isset($this->css_class) && !empty($this->css_class)) { + $css_class = " $this->css_class"; + } else { + $css_class = ""; + } + return "<li><a$css_id class=\"gAjaxLink $css_class\" href=\"$this->url\" " . + "title=\"$this->label\" ajax_handler=\"$this->ajax_handler\">$this->label</a></li>"; + } +} + +/** * Menu element that provides a pop-up dialog */ class Menu_Element_Dialog extends Menu_Element { @@ -111,7 +142,7 @@ class Menu_Element_Dialog extends Menu_Element { } else { $css_class = ""; } - return "<li><a$css_id class=\"gMenuLink$css_class\" href=\"$this->url\" " . + return "<li><a$css_id class=\"gDialogLink $css_class\" href=\"$this->url\" " . "title=\"$this->label\">$this->label</a></li>"; } } @@ -132,6 +163,9 @@ class Menu_Core extends Menu_Element { case "link": return new Menu_Element_Link($type); + case "ajax_link": + return new Menu_Element_Ajax_Link($type); + case "dialog": return new Menu_Element_Dialog($type); diff --git a/modules/gallery/libraries/ORM_MPTT.php b/modules/gallery/libraries/ORM_MPTT.php index 1917d738..a7defba9 100644 --- a/modules/gallery/libraries/ORM_MPTT.php +++ b/modules/gallery/libraries/ORM_MPTT.php @@ -146,69 +146,62 @@ class ORM_MPTT_Core extends ORM { * @chainable * @param integer SQL limit * @param integer SQL offset + * @param array additional where clauses * @param array orderby * @return array ORM */ - function children($limit=null, $offset=0, $orderby=null) { - $this->where("parent_id", $this->id); - if (empty($orderby)) { - $this->orderby("id", "ASC"); - } else { - $this->orderby($orderby); - } - return $this->find_all($limit, $offset); + function children($limit=null, $offset=0, $where=array(), $orderby=array("id" => "ASC")) { + return $this + ->where("parent_id", $this->id) + ->where($where) + ->orderby($orderby) + ->find_all($limit, $offset); } /** * Return all of the children of this node, ordered by id. * * @chainable - * @param integer SQL limit - * @param integer SQL offset + * @param array additional where clauses * @return array ORM */ - function children_count() { - return $this->where("parent_id", $this->id)->count_all(); + function children_count($where=array()) { + return $this + ->where($where) + ->where("parent_id", $this->id) + ->count_all(); } /** - * Return all of the children of the specified type, ordered by id. + * Return all of the decendents of the specified type, ordered by id. * * @param integer SQL limit * @param integer SQL offset - * @param string type to return + * @param array additional where clauses * @param array orderby * @return object ORM_Iterator */ - function descendants($limit=null, $offset=0, $type=null, $orderby=null) { - $this->where("left_ptr >", $this->left_ptr) - ->where("right_ptr <=", $this->right_ptr); - if ($type) { - $this->where("type", $type); - } - - if (empty($orderby)) { - $this->orderby("id", "ASC"); - } else { - $this->orderby($orderby); - } - - return $this->find_all($limit, $offset); + function descendants($limit=null, $offset=0, $where=array(), $orderby=array("id" => "ASC")) { + return $this + ->where("left_ptr >", $this->left_ptr) + ->where("right_ptr <=", $this->right_ptr) + ->where($where) + ->orderby($orderby) + ->find_all($limit, $offset); } /** * Return the count of all the children of the specified type. * - * @param string type to count + * @param array additional where clauses * @return integer child count */ - function descendants_count($type=null) { - $this->where("left_ptr >", $this->left_ptr) - ->where("right_ptr <=", $this->right_ptr); - if ($type) { - $this->where("type", $type); - } - return $this->count_all(); + function descendants_count($where=array()) { + return $this + ->where("left_ptr >", $this->left_ptr) + ->where("right_ptr <=", $this->right_ptr) + ->where($where) + ->count_all(); } /** diff --git a/modules/gallery/libraries/Sendmail.php b/modules/gallery/libraries/Sendmail.php index 90998457..7bc21a67 100644 --- a/modules/gallery/libraries/Sendmail.php +++ b/modules/gallery/libraries/Sendmail.php @@ -52,6 +52,7 @@ class Sendmail_Core { break; case "header": if (count($value) != 2) { + Kohana::log("error", wordwrap("Invalid header parameters\n" . Kohana::debug($value))); throw new Exception("@todo INVALID_HEADER_PARAMETERS"); } $this->headers[$value[0]] = $value[1]; @@ -70,6 +71,7 @@ class Sendmail_Core { public function send() { if (empty($this->to)) { + Kohana::log("error", wordwrap("Sending mail failed:\nNo to address specified")); throw new Exception("@todo TO_IS_REQUIRED_FOR_MAIL"); } $to = implode(", ", $this->to); @@ -84,8 +86,6 @@ class Sendmail_Core { $headers = implode($this->header_separator, $headers); $message = wordwrap($this->message, $this->line_length, "\n"); if (!$this->mail($to, $this->subject, $message, $headers)) { - Kohana::log("error", wordwrap("Sending mail failed:\nTo: $to\n $this->subject\n" . - "Headers: $headers\n $this->message")); throw new Exception("@todo SEND_MAIL_FAILED"); } return $this; diff --git a/modules/gallery/libraries/Theme_View.php b/modules/gallery/libraries/Theme_View.php index 360e5e46..541bce88 100644 --- a/modules/gallery/libraries/Theme_View.php +++ b/modules/gallery/libraries/Theme_View.php @@ -111,14 +111,15 @@ class Theme_View_Core extends Gallery_View { return $menu->compact(); } - public function thumb_menu($item) { + public function context_menu($item, $thumbnail_css_selector) { $menu = Menu::factory("root") ->append(Menu::factory("submenu") - ->id("options_menu") + ->id("context_menu") ->label(t("Options"))) - ->css_class("gThumbMenu"); + ->css_class("gContextMenu"); - module::event("thumb_menu", $menu, $this, $item); + gallery::context_menu($menu, $this, $item, $thumbnail_css_selector); + module::event("context_menu", $menu, $this, $item, $thumbnail_css_selector); return $menu->compact(); } diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php index f3e6b8f3..68e89db6 100644 --- a/modules/gallery/models/item.php +++ b/modules/gallery/models/item.php @@ -19,7 +19,6 @@ */ class Item_Model extends ORM_MPTT { protected $children = 'items'; - private $view_restrictions = null; protected $sorting = array(); var $rules = array( @@ -34,38 +33,7 @@ class Item_Model extends ORM_MPTT { * @chainable */ public function viewable() { - if (is_null($this->view_restrictions)) { - if (user::active()->admin) { - $this->view_restrictions = array(); - } else { - foreach (user::group_ids() as $id) { - // Separate the first restriction from the rest to make it easier for us to formulate - // our where clause below - if (empty($this->view_restrictions)) { - $this->view_restrictions[0] = "view_$id"; - } else { - $this->view_restrictions[1]["view_$id"] = access::ALLOW; - } - } - } - } - switch (count($this->view_restrictions)) { - case 0: - break; - - case 1: - $this->where($this->view_restrictions[0], access::ALLOW); - break; - - default: - $this->open_paren(); - $this->where($this->view_restrictions[0], access::ALLOW); - $this->orwhere($this->view_restrictions[1]); - $this->close_paren(); - break; - } - - return $this; + return item::viewable($this); } /** @@ -351,14 +319,7 @@ class Item_Model extends ORM_MPTT { $this->updated = time(); if (!$this->loaded) { $this->created = $this->updated; - // Guard against an empty result when we create the first item. It's unfortunate that we - // have to check this every time. - // @todo: figure out a better way to bootstrap the weight. - $result = Database::instance() - ->select("weight")->from("items") - ->orderby("weight", "desc")->limit(1) - ->get()->current(); - $this->weight = ($result ? $result->weight : 0) + 1; + $this->weight = item::get_max_weight(); } else { $send_event = 1; } @@ -521,26 +482,38 @@ class Item_Model extends ORM_MPTT { } /** - * Return all of the children of this node, ordered by the defined sort order. + * Return all of the children of this album. Unless you specify a specific sort order, the + * results will be ordered by this album's sort order. * * @chainable * @param integer SQL limit * @param integer SQL offset + * @param array additional where clauses + * @param array orderby * @return array ORM */ - function children($limit=null, $offset=0) { - return parent::children($limit, $offset, array($this->sort_column => $this->sort_order)); + function children($limit=null, $offset=0, $where=array(), $orderby=null) { + if (empty($orderby)) { + $orderby = array($this->sort_column => $this->sort_order); + } + return parent::children($limit, $offset, $where, $orderby); } /** - * Return all of the children of the specified type, ordered by the defined sort order. + * Return the children of this album, and all of it's sub-albums. Unless you specify a specific + * sort order, the results will be ordered by this album's sort order. Note that this + * album's sort order is imposed on all sub-albums, regardless of their sort order. + * + * @chainable * @param integer SQL limit * @param integer SQL offset - * @param string type to return + * @param array additional where clauses * @return object ORM_Iterator */ - function descendants($limit=null, $offset=0, $type=null) { - return parent::descendants($limit, $offset, $type, - array($this->sort_column => $this->sort_order)); + function descendants($limit=null, $offset=0, $where=array(), $orderby=null) { + if (empty($orderby)) { + $orderby = array($this->sort_column => $this->sort_order); + } + return parent::descendants($limit, $offset, $where, $orderby); } } diff --git a/modules/gallery/tests/Item_Helper_Test.php b/modules/gallery/tests/Item_Helper_Test.php new file mode 100644 index 00000000..3f80733f --- /dev/null +++ b/modules/gallery/tests/Item_Helper_Test.php @@ -0,0 +1,49 @@ +<?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 Item_Helper_Test extends Unit_Test_Case { + + public function viewable_test() { + $root = ORM::factory("item", 1); + $album = album::create($root, rand(), rand(), rand()); + $item = self::_create_random_item($album); + user::set_active(user::guest()); + + // We can see the item when permissions are granted + access::allow(group::everybody(), "view", $album); + $this->assert_equal( + 1, + ORM::factory("item")->viewable()->where("id", $item->id)->count_all()); + + // We can't see the item when permissions are denied + access::deny(group::everybody(), "view", $album); + $this->assert_equal( + 0, + ORM::factory("item")->viewable()->where("id", $item->id)->count_all()); + } + + + private static function _create_random_item($album) { + // Set all required fields (values are irrelevant) + $item = ORM::factory("item"); + $item->name = rand(); + $item->type = "photo"; + return $item->add_to_parent($album); + } +} diff --git a/modules/gallery/tests/Item_Model_Test.php b/modules/gallery/tests/Item_Model_Test.php index 0940d076..585e247c 100644 --- a/modules/gallery/tests/Item_Model_Test.php +++ b/modules/gallery/tests/Item_Model_Test.php @@ -19,12 +19,12 @@ */ class Item_Model_Test extends Unit_Test_Case { public function saving_sets_created_and_updated_dates_test() { - $item = self::create_random_item(); + $item = self::_create_random_item(); $this->assert_true(!empty($item->created)); $this->assert_true(!empty($item->updated)); } - private function create_random_item() { + private static function _create_random_item() { $item = ORM::factory("item"); /* Set all required fields (values are irrelevant) */ $item->name = rand(); @@ -33,7 +33,7 @@ class Item_Model_Test extends Unit_Test_Case { } public function updating_doesnt_change_created_date_test() { - $item = self::create_random_item(); + $item = self::_create_random_item(); // Force the creation date to something well known $db = Database::instance(); @@ -47,7 +47,7 @@ class Item_Model_Test extends Unit_Test_Case { } public function updating_view_count_only_doesnt_change_updated_date_test() { - $item = self::create_random_item(); + $item = self::_create_random_item(); $item->reload(); $this->assert_same(0, $item->view_count); @@ -64,7 +64,7 @@ class Item_Model_Test extends Unit_Test_Case { public function move_photo_test() { // Create a test photo - $item = self::create_random_item(); + $item = self::_create_random_item(); file_put_contents($item->thumb_path(), "thumb"); file_put_contents($item->resize_path(), "resize"); @@ -128,7 +128,7 @@ class Item_Model_Test extends Unit_Test_Case { public function item_rename_wont_accept_slash_test() { // Create a test photo - $item = self::create_random_item(); + $item = self::_create_random_item(); $new_name = rand() . "/"; @@ -142,7 +142,7 @@ class Item_Model_Test extends Unit_Test_Case { } public function save_original_values_test() { - $item = $this->create_random_item(); + $item = self::_create_random_item(); $item->title = "ORIGINAL_VALUE"; $item->save(); $item->title = "NEW_VALUE"; diff --git a/modules/gallery/tests/ORM_MPTT_Test.php b/modules/gallery/tests/ORM_MPTT_Test.php index 943810c3..f77f1f34 100644 --- a/modules/gallery/tests/ORM_MPTT_Test.php +++ b/modules/gallery/tests/ORM_MPTT_Test.php @@ -177,8 +177,8 @@ class ORM_MPTT_Test extends Unit_Test_Case { $parent->reload(); $this->assert_equal(3, $parent->descendants()->count()); - $this->assert_equal(2, $parent->descendants(null, 0, "photo")->count()); - $this->assert_equal(1, $parent->descendants(null, 0, "album")->count()); + $this->assert_equal(2, $parent->descendants(null, 0, array("type" => "photo"))->count()); + $this->assert_equal(1, $parent->descendants(null, 0, array("type" => "album"))->count()); } public function descendant_limit_test() { @@ -215,7 +215,7 @@ class ORM_MPTT_Test extends Unit_Test_Case { $parent->reload(); $this->assert_equal(3, $parent->descendants_count()); - $this->assert_equal(2, $parent->descendants_count("photo")); - $this->assert_equal(1, $parent->descendants_count("album")); + $this->assert_equal(2, $parent->descendants_count(array("type" => "photo"))); + $this->assert_equal(1, $parent->descendants_count(array("type" => "album"))); } } diff --git a/modules/gallery/views/admin_graphics.html.php b/modules/gallery/views/admin_graphics.html.php index 08374471..c4a2f5c6 100644 --- a/modules/gallery/views/admin_graphics.html.php +++ b/modules/gallery/views/admin_graphics.html.php @@ -9,8 +9,8 @@ }; $("#gAdminGraphics div.gAvailable .gBlock").click(select_toolkit); }); - </script> + <div id="gAdminGraphics"> <h1> <?= t("Graphics Settings") ?> </h1> <p> @@ -18,11 +18,19 @@ </p> <h2> <?= t("Active Toolkit") ?> </h2> - <?= $active ?> + <? if ($active == "none"): ?> + <?= new View("admin_graphics_none.html") ?> + <? else: ?> + <?= new View("admin_graphics_$active.html", array("tk" => $tk->$active, "is_active" => true)) ?> + <? endif ?> <div class="gAvailable"> <h2> <?= t("Available Toolkits") ?> </h2> - <?= $available ?> + <? foreach (array_keys((array)$tk) as $id): ?> + <? if ($id != $active): ?> + <?= new View("admin_graphics_$id.html", array("tk" => $tk->$id, "is_active" => false)) ?> + <? endif ?> + <? endforeach ?> </div> </div> diff --git a/modules/gallery/views/admin_graphics_gd.html.php b/modules/gallery/views/admin_graphics_gd.html.php index b77da8e3..010a31b4 100644 --- a/modules/gallery/views/admin_graphics_gd.html.php +++ b/modules/gallery/views/admin_graphics_gd.html.php @@ -1,29 +1,30 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<div id="gd" class="gBlock<?= $is_active ? " gSelected" : "" ?><?= $tk->gd["GD Version"] ? " gInstalledToolkit" : " gUnavailable" ?>"> +<div id="gd" class="gBlock<?= $is_active ? " gSelected" : "" ?><?= $tk->installed ? " gInstalledToolkit" : " gUnavailable" ?>"> <img class="logo" width="170" height="110" src="<?= url::file("modules/gallery/images/gd.png"); ?>" alt="<? t("Visit the GD lib project site") ?>" /> <h3> <?= t("GD") ?> </h3> <p> <?= t("The GD graphics library is an extension to PHP commonly installed most webservers. Please refer to the <a href=\"%url\">GD website</a> for more information.", array("url" => "http://www.boutell.com/gd")) ?> </p> - <? if ($tk->gd["GD Version"] && function_exists('imagerotate')): ?> - <p class="gSuccess"> - <?= t("You have GD version %version.", array("version" => $tk->gd["GD Version"])) ?> - </p> + <? if ($tk->installed && $tk->rotate): ?> + <div class="gModuleStatus gInfo"> + <?= t("You have GD version %version.", array("version" => $tk->version)) ?> + </div> <p> <a class="gButtonLink ui-state-default ui-corner-all"><?= t("Activate GD") ?></a> </p> - <? elseif ($tk->gd["GD Version"]): ?> - <p class="gWarning"> - <?= t("You have GD version %version, but it lacks image rotation.", - array("version" => $tk->gd["GD Version"])) ?> + <? elseif ($tk->installed): ?> + <? if ($tk->error): ?> + <p class="gModuleStatus gWarning"> + <?= $tk->error ?> </p> + <? endif ?> <p> <a class="gButtonLink ui-state-default ui-corner-all"><?= t("Activate GD") ?></a> </p> <? else: ?> - <p class="gInfo"> + <div class="gModuleStatus gInfo"> <?= t("You do not have GD installed.") ?> - </p> + </div> <? endif ?> </div> diff --git a/modules/gallery/views/admin_graphics_graphicsmagick.html.php b/modules/gallery/views/admin_graphics_graphicsmagick.html.php index e2cd0777..97624850 100644 --- a/modules/gallery/views/admin_graphics_graphicsmagick.html.php +++ b/modules/gallery/views/admin_graphics_graphicsmagick.html.php @@ -1,21 +1,21 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<div id="graphicsmagick" class="gBlock<?= $is_active ? " gSelected" : "" ?><?= $tk->graphicsmagick ? " gInstalledToolkit" : " gUnavailable" ?>"> - <h3> <?= t("GraphicsMagick") ?> </h3> +<div id="graphicsmagick" class="gBlock<?= $is_active ? " gSelected" : "" ?><?= $tk->installed ? " gInstalledToolkit" : " gUnavailable" ?>"> <img class="logo" width="107" height="76" src="<?= url::file("modules/gallery/images/graphicsmagick.png"); ?>" alt="<? t("Visit the GraphicsMagick project site") ?>" /> + <h3> <?= t("GraphicsMagick") ?> </h3> <p> <?= t("GraphicsMagick is a standalone graphics program available on most Linux systems. Please refer to the <a href=\"%url\">GraphicsMagick website</a> for more information.", array("url" => "http://www.graphicsmagick.org")) ?> </p> - <? if ($tk->graphicsmagick): ?> - <p class="gSuccess"> - <?= t("GraphicsMagick is available in %path", array("path" => $tk->graphicsmagick)) ?> - </p> + <? if ($tk->installed): ?> + <div class="gModuleStatus gInfo"> + <?= t("GraphicsMagick version %version is available in %dir", array("version" => $tk->version, "dir" => $tk->dir)) ?> + </div> <p> <a class="gButtonLink ui-state-default ui-corner-all"><?= t("Activate Graphics Magic") ?></a> </p> <? else: ?> - <p class="gInfo"> - <?= t("GraphicsMagick is not available on your system.") ?> - </p> + <div class="gModuleStatus gWarning"> + <?= $tk->error ?> + </div> <? endif ?> </div> diff --git a/modules/gallery/views/admin_graphics_imagemagick.html.php b/modules/gallery/views/admin_graphics_imagemagick.html.php index 081ddc15..cdff7c2c 100644 --- a/modules/gallery/views/admin_graphics_imagemagick.html.php +++ b/modules/gallery/views/admin_graphics_imagemagick.html.php @@ -1,21 +1,21 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<div id="imagemagick" class="gBlock<?= $is_active ? " gSelected" : "" ?><?= $tk->imagemagick ? " gInstalledToolkit" : " gUnavailable" ?>"> - <h3> <?= t("ImageMagick") ?> </h3> +<div id="imagemagick" class="gBlock<?= $is_active ? " gSelected" : "" ?><?= $tk->installed ? " gInstalledToolkit" : " gUnavailable" ?>"> <img class="logo" width="114" height="118" src="<?= url::file("modules/gallery/images/imagemagick.jpg"); ?>" alt="<? t("Visit the ImageMagick project site") ?>" /> + <h3> <?= t("ImageMagick") ?> </h3> <p> <?= t("ImageMagick is a standalone graphics program available on most Linux systems. Please refer to the <a href=\"%url\">ImageMagick website</a> for more information.", array("url" => "http://www.imagemagick.org")) ?> </p> - <? if ($tk->imagemagick): ?> - <p class="gSuccess"> - <?= t("ImageMagick is available in %path", array("path" => $tk->imagemagick)) ?> - </p> + <? if ($tk->installed): ?> + <div class="gModuleStatus gInfo"> + <?= t("ImageMagick version %version is available in %dir", array("version" => $tk->version, "dir" => $tk->dir)) ?> + </div> <p> <a class="gButtonLink ui-state-default ui-corner-all"><?= t("Activate ImageMagick") ?></a> </p> - <? else: ?> - <p class="gInfo"> - <?= t("ImageMagick is not available on your system.") ?> - </p> + <? elseif ($tk->error): ?> + <div class="gModuleStatus gWarning"> + <?= $tk->error ?> + </div> <? endif ?> </div> diff --git a/modules/gallery/views/admin_graphics_none.html.php b/modules/gallery/views/admin_graphics_none.html.php index 5306a70d..e6923a5a 100644 --- a/modules/gallery/views/admin_graphics_none.html.php +++ b/modules/gallery/views/admin_graphics_none.html.php @@ -1,7 +1,8 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<div id="none" class="gBlock"> - <h3 class="gWarning"> <?= t("No Active Toolkit") ?> </h3> + +<div id="none" class="gModuleStatus gWarning gBlock"> + <h3> <?= t("No Active Toolkit") ?> </h3> <p> - <?= t("We were unable to detect a graphics program. You must install one of the toolkits below in order to many Gallery features.") ?> + <?= t("We were unable to detect a graphics program. You must install one of the toolkits below in order to use many Gallery features.") ?> </p> </div> diff --git a/modules/gallery/views/admin_languages.html.php b/modules/gallery/views/admin_languages.html.php index f41694b4..4025437a 100644 --- a/modules/gallery/views/admin_languages.html.php +++ b/modules/gallery/views/admin_languages.html.php @@ -1,15 +1,100 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <div id="gLanguages"> - <h2> <?= t("Languages") ?> </h2> + <h1> <?= t("Languages") ?> </h1> + <p> + <?= t("Install new languages, update installed ones and set the default language for your Gallery.") ?> + </p> - <?= $settings_form ?> - - <h2> <?= t("Download translations") ?> </h2> - <a href="<?= url::site("admin/maintenance/start/gallery_task::update_l10n?csrf=$csrf") ?>" - class="gDialogLink"> - <?= t("Get updates") ?> - </a> + <form id="gLanguagesForm" method="post" action="<?= url::site("admin/languages/save") ?>"> + <?= access::csrf_form_field() ?> + <table> + <tr> + <th> <?= t("Installed") ?> </th> + <th> <?= t("Language") ?> </th> + <th> <?= t("Default language") ?> </th> + </tr> + <? $i = 0 ?> + <? foreach ($available_locales as $code => $display_name): ?> + + <? if ($i == (count($available_locales)/2)): ?> + <table> + <tr> + <th> <?= t("Installed") ?> </th> + <th> <?= t("Language") ?> </th> + <th> <?= t("Default language") ?> </th> + </tr> + <? endif ?> + + <tr class="<?= (isset($installed_locales[$code])) ? "installed" : "" ?><?= ($default_locale == $code) ? " default" : "" ?>"> + <td> <?= form::checkbox("installed_locales[]", $code, isset($installed_locales[$code])) ?> </td> + <td> <?= $display_name ?> </td> + <td> + <?= form::radio("default_locale", $code, ($default_locale == $code), ((isset($installed_locales[$code]))?'':'disabled="disabled"') ) ?> + </td> + </tr> + <? $i++ ?> + + <? endforeach ?> + </table> + <input type="submit" value="<?= t("Update languages") ?>" /> + </form> + + <script type="text/javascript"> + var old_default_locale = "<?= $default_locale ?>"; + + $("input[name='installed_locales[]']").change(function (event) { + if (this.checked) { + $("input[type='radio'][value='" + this.value + "']").enable(); + } else { + if ($("input[type='radio'][value='" + this.value + "']").selected()) { // if you deselect your default language, switch to some other installed language + $("input[type='radio'][value='" + old_default_locale + "']").attr("checked", "checked"); + } + $("input[type='radio'][value='" + this.value + "']").attr("disabled", "disabled"); + } + }); + + $("#gLanguagesForm").ajaxForm({ + dataType: "json", + success: function(data) { + if (data.result == "success") { + el = $('<a href="<?= url::site("admin/maintenance/start/gallery_task::update_l10n?csrf=$csrf") ?>"></a>'); // this is a little hack to trigger the update_l10n task in a dialog + el.gallery_dialog(); + el.trigger('click'); + } + } + }); + </script> +</div> - <h2> <?= t("Your Own Translations") ?> </h2> +<div id="gTranslations"> + <h1> <?= t("Translations") ?> </h1> + <p> + <?= t("Create your own translations and share them with the rest of the Gallery community.") ?> + </p> + + <h3><?= t("Translating Gallery") ?></h3> + + <div class="gBlock"> + <a href="http://codex.gallery2.org/Gallery3:Localization" target="_blank" + class="gDocLink ui-state-default ui-corner-all ui-icon ui-icon-help" + title="<?= t("Localization documentation") ?>"> + <?= t("Localization documentation") ?> + </a> + + <p><strong><?= t("Step 1") ?>:</strong> <?= t("Make sure the target language is installed and updated (check above).") ?></p> + + <p><strong><?= t("Step 2") ?>:</strong> <?= t("Make sure the target language is the active one (currently '").locales::display_name()."')." ?></p> + + <p><strong><?= t("Step 3") ?>:</strong> <?= t("Start the translation mode and the translation interface will appear at the bottom of each Gallery page.") ?></p> + + <a href="<?= url::site("l10n_client/toggle_l10n_mode?csrf=".access::csrf_token()) ?>" + class="gButtonLink ui-state-default ui-corner-all ui-icon-left"> + <span class="ui-icon ui-icon-power"></span> + <?= t((Session::instance()->get("l10n_mode", false)) ? "Stop translation mode" : "Start translation mode") ?> + </a> + </div> + + <h3>Sharing your translations</h3> + <?= $share_translations_form ?> </div> diff --git a/modules/gallery/views/admin_maintenance.html.php b/modules/gallery/views/admin_maintenance.html.php index a4db38ce..a0a6a19e 100644 --- a/modules/gallery/views/admin_maintenance.html.php +++ b/modules/gallery/views/admin_maintenance.html.php @@ -7,7 +7,7 @@ <div id="gAvailableTasks"> <h2> <?= t("Available Tasks") ?> </h2> - <table> + <table class="gMessages"> <tr> <th> <?= t("Name") ?> @@ -19,8 +19,9 @@ <?= t("Action") ?> </th> </tr> + <? $i = 0; ?> <? foreach ($task_definitions as $task): ?> - <tr class="<?= log::severity_class($task->severity) ?>"> + <tr class="<?= log::severity_class($task->severity) ?> <?= ($i % 2 == 0) ? "gOddRow" : "gEvenRow" ?>"> <td> <?= $task->name ?> </td> @@ -34,17 +35,18 @@ </a> </td> </tr> + <? $i++ ?> <? endforeach ?> </table> </div> <? if ($running_tasks->count()): ?> <div id="gRunningTasks"> - <h2> <?= t("Running Tasks") ?> </h2> <a href="<?= url::site("admin/maintenance/cancel_running_tasks?csrf=$csrf") ?>" class="gButtonLink ui-icon-left ui-state-default ui-corner-all right"> <?= t("cancel all") ?></a> + <h2> <?= t("Running Tasks") ?> </h2> <table> <tr> <th> @@ -66,8 +68,9 @@ <?= t("Action") ?> </th> </tr> + <? $i = 0; ?> <? foreach ($running_tasks as $task): ?> - <tr class="<?= $task->state == "stalled" ? "gWarning" : "" ?>"> + <tr class="<?= $task->state == "stalled" ? "gWarning" : "" ?> <?= ($i % 2 == 0) ? "gOddRow" : "gEvenRow" ?>"> <td> <?= gallery::date_time($task->updated) ?> </td> @@ -105,6 +108,7 @@ </a> </td> </tr> + <? $i++ ?> <? endforeach ?> </table> </div> @@ -138,8 +142,9 @@ <?= t("Action") ?> </th> </tr> + <? $i = 0; ?> <? foreach ($finished_tasks as $task): ?> - <tr class="<?= $task->state == "success" ? "gSuccess" : "gError" ?>"> + <tr class="<?= $task->state == "success" ? "gSuccess" : "gError" ?> <?= ($i % 2 == 0) ? "gOddRow" : "gEvenRow" ?>"> <td> <?= gallery::date_time($task->updated) ?> </td> @@ -183,6 +188,7 @@ </td> </tr> <? endforeach ?> + <? $i++ ?> </table> </div> <? endif ?> diff --git a/modules/gallery/views/admin_modules.html.php b/modules/gallery/views/admin_modules.html.php index 3fddd6cd..168e20d0 100644 --- a/modules/gallery/views/admin_modules.html.php +++ b/modules/gallery/views/admin_modules.html.php @@ -16,7 +16,7 @@ </tr> <? $i = 0 ?> <? foreach ($available as $module_name => $module_info): ?> - <tr class="<?= ($i % 2 == 0) ? "gEvenRow" : "gOddRow" ?>"> + <tr class="<?= ($i % 2 == 0) ? "gOddRow" : "gEvenRow" ?>"> <? $data = array("name" => $module_name); ?> <? if ($module_info->locked) $data["disabled"] = 1; ?> <td> <?= form::checkbox($data, '1', module::is_active($module_name)) ?> </td> diff --git a/modules/gallery/views/after_install.html.php b/modules/gallery/views/after_install.html.php index 2cf8ec8f..b77a1707 100644 --- a/modules/gallery/views/after_install.html.php +++ b/modules/gallery/views/after_install.html.php @@ -16,7 +16,7 @@ title="<?= t("Edit Your Profile") ?>" id="gAfterInstallChangePasswordLink" class="gButtonLink ui-state-default ui-corners-all"><?= t("Change Password Now") ?></a> <script> - $("#gAfterInstallChangePasswordLink").bind("click", handleDialogEvent); + $("#gAfterInstallChangePasswordLink").gallery_dialog(); </script> </p> diff --git a/modules/gallery/views/after_install_loader.html.php b/modules/gallery/views/after_install_loader.html.php index baf91eed..54484963 100644 --- a/modules/gallery/views/after_install_loader.html.php +++ b/modules/gallery/views/after_install_loader.html.php @@ -3,5 +3,5 @@ title="<?= t("Welcome to Gallery 3") ?>" href="<?= url::site("after_install") ?>"/> <script type="text/javascript"> - $(document).ready(function(){openDialog($("#gAfterInstall"));}); + $(document).ready(function(){$("#gAfterInstall").gallery_dialog({immediate: true});}); </script> diff --git a/modules/gallery/views/l10n_client.html.php b/modules/gallery/views/l10n_client.html.php index 523552c3..520fd79e 100644 --- a/modules/gallery/views/l10n_client.html.php +++ b/modules/gallery/views/l10n_client.html.php @@ -1,7 +1,10 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <div id="l10n-client" class="hidden"> <div class="labels"> - <span id="l10n-client-toggler">X</span> + <span id="l10n-client-toggler"> + <a id="gMinimizeL10n">_</a> + <a id="gCloseL10n" href="<?= url::site("l10n_client/toggle_l10n_mode?csrf=".access::csrf_token()) ?>">X</a> + </span> <div class="label strings"><h2><?= t("Page Text") ?> <? if (!Input::instance()->get('show_all_l10n_messages')): ?> <a style="background-color:#fff" href="<?= url::site("admin/languages?show_all_l10n_messages=1") ?>"><?= t("(Show All)") ?></a> diff --git a/modules/gallery/views/permissions_browse.html.php b/modules/gallery/views/permissions_browse.html.php index 9ea0da25..90970112 100644 --- a/modules/gallery/views/permissions_browse.html.php +++ b/modules/gallery/views/permissions_browse.html.php @@ -5,8 +5,9 @@ $.ajax({ url: form_url.replace("__ITEM__", id), success: function(data) { - $("div.form").slideUp(); - $("div#edit-" + id).html(data).slideDown(); + $("#gEditPermissionForm").html(data); + $(".active").removeClass("active"); + $("#item-" + id).addClass("active"); } }); } @@ -18,7 +19,7 @@ url: action_url.replace("__CMD__", cmd).replace("__GROUP__", group_id). replace("__PERM__", perm_id).replace("__ITEM__", item_id), success: function(data) { - $("div#edit-" + item_id).load(form_url.replace("__ITEM__", item_id)); + $("#gEditPermissionForm").load(form_url.replace("__ITEM__", item_id)); } }); } @@ -31,26 +32,25 @@ </li> </ul> <? endif ?> - <ul> + + <p><?= t("Edit permissions for album:") ?></p> + + <ul class="gBreadcrumbs"> <? foreach ($parents as $parent): ?> - <li> + <li id="item-<?= $parent->id ?>"> <a href="javascript:show(<?= $parent->id ?>)"> - <?= SafeString::of($parent->title) ?> + <?= SafeString::purify($parent->title) ?> + </a> + </li> + <? endforeach ?> + <li class="active" id="item-<?= $item->id ?>"> + <a href="javascript:show(<?= $item->id ?>)"> + <?= SafeString::purify($item->title) ?> </a> - <div class="form" id="edit-<?= $parent->id ?>"></div> - <ul> - <? endforeach ?> - <li> - <a href="javascript:show(<?= $item->id ?>)"> - <?= SafeString::purify($item->title) ?> - </a> - <div class="form" id="edit-<?= $item->id ?>"> - <?= $form ?> - </div> - </li> - <? foreach ($parents as $parent): ?> - </ul> </li> </ul> - <? endforeach ?> -</div> + + <div id="gEditPermissionForm"> + <?= $form ?> + </div> +</div>
\ No newline at end of file diff --git a/modules/gallery/views/quick_pane.html.php b/modules/gallery/views/quick_pane.html.php deleted file mode 100644 index e5469696..00000000 --- a/modules/gallery/views/quick_pane.html.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<? foreach ($button_list->main as $button): ?> -<a class="<?= $button->class ?> ui-corner-all ui-state-default" href="<?= $button->href ?>" - title="<?= $button->title ?>"> - <span class="ui-icon <?= $button->icon ?>"> - <?= $button->title ?> - </span> -</a> -<? endforeach ?> - -<? if (!empty($button_list->additional)): ?> -<a class="gButtonLink ui-corner-all ui-state-default options" href="#" title="<?= t("additional options") ?>"> - <span class="ui-icon ui-icon-triangle-1-s"> - <?= t("Additional options") ?> - </span> -</a> - -<ul class="gQuickPaneOptions" style="display: none"> - <? foreach ($button_list->additional as $button): ?> - <li><a class="<?= $button->class ?>" href="<?= $button->href ?>" - title="<?= $button->title ?>"> - <?= $button->title ?> - </a></li> - <? endforeach ?> -</ul> -<? endif ?> diff --git a/modules/gallery/views/simple_uploader.html.php b/modules/gallery/views/simple_uploader.html.php index fc426e8f..1f185780 100644 --- a/modules/gallery/views/simple_uploader.html.php +++ b/modules/gallery/views/simple_uploader.html.php @@ -217,7 +217,7 @@ var fp = new File_Progress(file); switch (error_code) { case SWFUpload.UPLOAD_ERROR.HTTP_ERROR: - fp.set_status("error", "<?= t("Upload error: ")->for_js() ?>" + message); + fp.set_status("error", "<?= t("Upload error: bad image file")->for_js() ?>"); break; case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED: fp.set_status("error", "<?= t("Upload failed")->for_js() ?>"); diff --git a/modules/info/views/info_block.html.php b/modules/info/views/info_block.html.php index 365a1021..bfaaee99 100644 --- a/modules/info/views/info_block.html.php +++ b/modules/info/views/info_block.html.php @@ -10,9 +10,9 @@ <?= nl2br(SafeString::purify($item->description)) ?> </li> <? endif ?> - <? if ($item->id != 1): ?> + <? if (!$item->is_album()): ?> <li> - <strong class="caption"><?= t("Folder name:") ?></strong> + <strong class="caption"><?= t("File name:") ?></strong> <?= SafeString::of($item->name) ?> </li> <? endif ?> diff --git a/modules/notification/helpers/notification.php b/modules/notification/helpers/notification.php index 92c40d4f..d95b3060 100644 --- a/modules/notification/helpers/notification.php +++ b/modules/notification/helpers/notification.php @@ -153,7 +153,7 @@ class notification { ->where("email", $email) ->find_all(); if ($result->count() == 1) { - $pending = $result->get(); + $pending = $result->current(); Sendmail::factory() ->to($email) ->subject($pending->subject) diff --git a/modules/notification/helpers/notification_event.php b/modules/notification/helpers/notification_event.php index d1b76e93..c50b04c4 100644 --- a/modules/notification/helpers/notification_event.php +++ b/modules/notification/helpers/notification_event.php @@ -18,42 +18,80 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class notification_event_Core { + // The assumption is that the exception was logged at a lower level, but we + // don't want to screw up the processing that was generating the notification + // so we don't pass the exception up the call stack static function item_updated($original, $new) { - notification::send_item_updated($new); + try { + notification::send_item_updated($new); + } catch (Exception $e) { + Kohana::log("error", "@todo notification_event::item_updated() failed"); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); + } } static function item_created($item) { - notification::send_item_add($item); + try { + notification::send_item_add($item); + } catch (Exception $e) { + Kohana::log("error", "@todo notification_event::item_created() failed"); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); + } } static function item_deleted($item) { - notification::send_item_deleted($item); + try { + notification::send_item_deleted($item); - if (notification::is_watching($item)) { - notification::remove_watch($item); + if (notification::is_watching($item)) { + notification::remove_watch($item); + } + } catch (Exception $e) { + Kohana::log("error", "@todo notification_event::item_deleted() failed"); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); } } static function comment_created($comment) { - if ($comment->state == "published") { - notification::send_comment_published($comment); + try { + if ($comment->state == "published") { + notification::send_comment_published($comment); + } + } catch (Exception $e) { + Kohana::log("error", "@todo notification_event::comment_created() failed"); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); } } static function comment_updated($original, $new) { - if ($new->state == "published" && $original->state != "published") { - notification::send_comment_published($new); + try { + if ($new->state == "published" && $original->state != "published") { + notification::send_comment_published($new); + } + } catch (Exception $e) { + Kohana::log("error", "@todo notification_event::comment_updated() failed"); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); } } static function user_before_delete($user) { - ORM::factory("subscription") - ->where("user_id", $user->id) - ->delete_all(); + try { + ORM::factory("subscription") + ->where("user_id", $user->id) + ->delete_all(); + } catch (Exception $e) { + Kohana::log("error", "@todo notification_event::user_before_delete() failed"); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); + } } static function batch_complete() { - notification::send_pending_notifications(); + try { + notification::send_pending_notifications(); + } catch (Exception $e) { + Kohana::log("error", "@todo notification_event::batch_complete() failed"); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); + } } static function site_menu($menu, $theme) { @@ -67,10 +105,10 @@ class notification_event_Core { $menu->get("options_menu") ->append(Menu::factory("link") - ->id("watch") - ->label($label) - ->css_id("gNotifyLink") - ->url(url::site("notification/watch/$item->id?csrf=" . access::csrf_token()))); + ->id("watch") + ->label($label) + ->css_id("gNotifyLink") + ->url(url::site("notification/watch/$item->id?csrf=" . access::csrf_token()))); } } } diff --git a/modules/notification/helpers/notification_installer.php b/modules/notification/helpers/notification_installer.php index 3d450258..aa2e09f7 100644 --- a/modules/notification/helpers/notification_installer.php +++ b/modules/notification/helpers/notification_installer.php @@ -27,14 +27,14 @@ class notification_installer { PRIMARY KEY (`id`), UNIQUE KEY (`item_id`, `user_id`), UNIQUE KEY (`user_id`, `item_id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE IF NOT EXISTS {pending_notifications} ( `id` int(9) NOT NULL auto_increment, `email` varchar(128) NOT NULL, `subject` varchar(255) NOT NULL, `text` text, PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("notification", 1); } diff --git a/modules/organize/controllers/organize.php b/modules/organize/controllers/organize.php index d60aa838..2b966657 100644 --- a/modules/organize/controllers/organize.php +++ b/modules/organize/controllers/organize.php @@ -18,523 +18,131 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class Organize_Controller extends Controller { - private static $_MICRO_THUMB_SIZE = 90; - private static $_MICRO_THUMB_PADDING = 5; - - function index($item_id=1) { - $item = ORM::factory("item", $item_id); - $root = ($item->id == 1) ? $item : ORM::factory("item", 1); - access::required("view", $item); - access::required("edit", $item); - - $v = new View("organize.html"); - $v->root = $root; - $v->item = $item; - $v->album_tree = $this->tree($item, $root); - $v->button_pane = new View("organize_button_pane.html"); + function dialog($album_id) { + $album = ORM::factory("item", $album_id); + access::required("view", $album); + access::required("edit", $album); + + $v = new View("organize_dialog.html"); + $v->album = $album; + $v->album_tree = self::_tree($album); + $v->micro_thumb_grid = self::_get_micro_thumb_grid($album, 0); print $v; } - function content($item_id) { - $item = ORM::factory("item", $item_id); - access::required("view", $item); - access::required("edit", $item); - - $width = $this->input->get("width"); - $height = $this->input->get("height"); - $offset = $this->input->get("offset", 0); - $thumbsize = self::$_MICRO_THUMB_SIZE + 2 * self::$_MICRO_THUMB_PADDING; - $page_size = ceil($width / $thumbsize) * ceil($height / $thumbsize); - - $v = new View("organize_thumb_grid.html"); - $v->children = $item->children($page_size, $offset); - $v->thumbsize = self::$_MICRO_THUMB_SIZE; - $v->padding = self::$_MICRO_THUMB_PADDING; - $v->offset = $offset; - - print json_encode(array("count" => $v->children->count(), - "data" => $v->__toString())); - } - - function header($item_id) { - $item = ORM::factory("item", $item_id); - access::required("view", $item); - access::required("edit", $item); - - print json_encode( - array("title" => SafeString::purify($item->title), - "description" => empty($item->description) ? "" : SafeString::purify($item->description))); - } - - function tree($item, $parent) { - access::required("view", $item); - access::required("edit", $item); - - $albums = ORM::factory("item") - ->where(array("parent_id" => $parent->id, "type" => "album")) - ->orderby(array("title" => "ASC")) - ->find_all(); - - $v = new View("organize_album.html"); - $v->album = $parent; - $v->selected = $parent->id == $item->id; - - if ($albums->count()) { - $v->album_icon = $parent->id == 1 || $v->selected ? "ui-icon-minus" : "ui-icon-plus"; - } else { - $v->album_icon = ""; - } - - $v->children = ""; - foreach ($albums as $album) { - $v->children .= $this->tree($item, $album); - } - return $v->__toString(); - } - - function startTask($operation, $id) { - access::verify_csrf(); - $items = $this->input->post("item"); - - $item = ORM::factory("item", $id); - access::required("view", $item); - access::required("edit", $item); - - $definition = $this->_getOperationDefinition($item, $operation); + function album($album_id, $offset) { + $album = ORM::factory("item", $album_id); + access::required("view", $album); + access::required("edit", $album); - $task_def = Task_Definition::factory() - ->callback("organize_task::run") - ->description($definition["description"]) - ->name($definition["name"]); - $task = task::create($task_def, array("items" => $items, "position" => 0, "target" => $id, - "type" => $definition["type"], - "batch" => ceil(count($items) * .1))); - // @todo If there is only one item then call task_run($task->id); Maybe even change js so - // we can call finish as well. - batch::start(); print json_encode( - array("result" => "started", - "runningMsg" => $definition["runningMsg"], - "pauseMsg" => "<div class=\"gWarning\">{$definition['pauseMsg']}</div>", - "resumeMsg" => "<div class=\"gWarning\">{$definition['resumeMsg']}</div>", - "task" => array("id" => $task->id, - "percent_complete" => $task->percent_complete, - "type" => $task->get("type"), - "status" => $task->status, - "state" => $task->state, - "done" => $task->done))); + array("grid" => self::_get_micro_thumb_grid($album, $offset)->__toString(), + "sort_column" => $album->sort_column, + "sort_order" => $album->sort_order)); } - function runTask($task_id) { + function move_to($album_id) { access::verify_csrf(); - $task = task::run($task_id); - if (!$task->loaded || $task->owner_id != user::active()->id) { - access::forbidden(); + $album = ORM::factory("item", $album_id); + foreach ($this->input->post("source_ids") as $source_id) { + item::move(ORM::factory("item", $source_id), $album); } - print json_encode(array("result" => $task->done ? $task->state : "in_progress", - "task" => array("id" => $task->id, - "percent_complete" => $task->percent_complete, - "type" => $task->get("type"), - "post_process" => $task->get("post_process"), - "status" => $task->status, - "state" => $task->state, - "done" => $task->done))); + print json_encode( + array("tree" => self::_tree($album)->__toString(), + "grid" => self::_get_micro_thumb_grid($album, 0)->__toString())); } - function finishTask($task_id) { + function rearrange($target_id, $before_or_after) { access::verify_csrf(); - $task = ORM::factory("task", $task_id); - if (!$task->loaded || $task->owner_id != user::active()->id) { - access::forbidden(); - } - - if ($task->done) { - $item = ORM::factory("item", (int)$task->get("target")); - $type = $task->get("type"); - switch ($type) { - case "albumCover": - $task->status = t("Album cover set for '%album'", array("album" => $item->title)); - break; - case "delete": - $task->status = t("Selection deleted"); - break; - case "move": - $task->status = t("Move to '%album' completed", array("album" => $item->title)); - break; - case "rearrange": - try { - $item->sort_column = "weight"; - $item->save(); - $task->status = t("Rearrange for '%album' completed", array("album" => $item->title)); - } catch (Exception $e) { - $task->state = "error"; - $task->status = $e->getMessage(); - } - break; - case "rotateCcw": - case "rotateCw": - $task->status = t("Rotation completed"); - break; - } - $task->save(); - } - - batch::stop(); - print json_encode(array("result" => "success", - "task" => array( - "id" => $task->id, - "percent_complete" => $task->percent_complete, - "status" => $task->status, - "state" => $task->state, - "done" => $task->done))); - } - - function cancelTask($task_id) { - access::verify_csrf(); + $target = ORM::factory("item", $target_id); + $album = $target->parent(); + access::required("view", $album); + access::required("edit", $album); - $task = ORM::factory("task", $task_id); - if (!$task->loaded || $task->owner_id != user::active()->id) { - access::forbidden(); - } + $source_ids = $this->input->post("source_ids", array()); - if (!$task->done) { - $task->done = 1; - $task->state = "cancelled"; - $type = $task->get("type"); - switch ($type) { - case "move": - $task->status = t("Move to album was cancelled prior to completion"); - break; - case "rearrange": - $task->status = t("Rearrange album was cancelled prior to completion"); - case "rotateCcw": - case "rotateCw": - $task->status = t("Rotation was cancelled prior to completion"); - break; + if ($album->sort_column != "weight") { + $i = 0; + foreach ($album->children() as $child) { + // Do this directly in the database to avoid sending notifications + Database::Instance()->update("items", array("weight" => ++$i), array("id" => $child->id)); } - $task->save(); + $album->sort_column = "weight"; + $album->sort_order = "ASC"; + $album->save(); + $target->reload(); } - batch::stop(); - print json_encode(array("result" => "success", - "task" => array( - "id" => $task->id, - "percent_complete" => $task->percent_complete, - "status" => $task->status, - "state" => $task->state, - "done" => $task->done))); - } - - function editForm() { - $event_parms = new stdClass(); - $event_parms->panes = array(); - $event_parms->itemids = $this->input->get("item"); - - // The following code should be done more dynamically i.e. use the event mechanism - if (count($event_parms->itemids) == 1) { - $item = ORM::factory("item") - ->in("id", $event_parms->itemids[0]) - ->find(); - - access::required("view", $item); - access::required("edit", $item); - - $event_parms->panes[] = array( - "label" => $item->is_album() ? t("Edit Album") : t("Edit Photo"), - "content" => organize::get_general_edit_form($item)); - - if ($item->is_album()) { - $event_parms->panes[] = array("label" => t("Sort Order"), - "content" => organize::get_sort_edit_form($item)); - } - } - - $event_parms->panes[] = array("label" => t("Manage Tags"), - "content" => organize::get_tag_form($event_parms->itemids)); - - $v = new View("organize_edit.html"); - $v->panes = $event_parms->panes; - print $v->render(); - } - - // Handlers for the album/photo edit. Probably should be in modules/gallery - public function general() { - access::verify_csrf(); - - $itemids = $this->input->post("item"); - $item = ORM::factory("item") - ->in("id", $itemids[0]) - ->find(); - access::required("view", $item); - access::required("edit", $item); - - $form = organize::get_general_edit_form($item); - if ($form->validate()) { - $orig = clone $item; - $item->title = $form->title->value; - $item->description = $form->description->value; - $item->rename($form->dirname->value); - $item->save(); - - if ($item->is_album()) { - log::success("content", "Updated album", "<a href=\"albums/$item->id\">view</a>"); - $message = t("Saved album %album_title", array("album_title" => SafeString::purify($item->title))); - } else { - log::success("content", "Updated photo", "<a href=\"photos/$item->id\">view</a>"); - $message = t("Saved photo %photo_title", array("photo_title" => SafeString::purify($item->title))); - } - print json_encode(array("form" => $form->__toString(), "message" => $message)); - } else { - print json_encode(array("form" => $form->__toString())); + // Find the insertion point + $target_weight = $target->weight; + if ($before_or_after == "after") { + $target_weight++; } - } - - public function reset_general() { - $itemids = Input::instance()->get("item"); - $item = ORM::factory("item") - ->in("id", $itemids[0]) - ->find(); - access::required("view", $item); - access::required("edit", $item); - - print organize::get_general_edit_form($item); - } - - public function sort() { - access::verify_csrf(); - $itemids = $this->input->post("item"); - $item = ORM::factory("item") - ->in("id", $itemids[0]) - ->find(); - access::required("view", $item); - access::required("edit", $item); + // Make a hole + $count = count($source_ids); + Database::Instance()->query( + "UPDATE {items} " . + "SET `weight` = `weight` + $count " . + "WHERE `weight` >= $target_weight AND `parent_id` = {$album->id}"); - $form = organize::get_sort_edit_form($item); - if ($form->validate()) { - $orig = clone $item; - $item->sort_column = $form->column->value; - $item->sort_order = $form->direction->value; - $item->save(); - - log::success("content", "Updated album", "<a href=\"albums/$item->id\">view</a>"); - $message = t("Saved album %album_title", array("album_title" => SafeString::purify($item->title))); - print json_encode(array("form" => $form->__toString(), "message" => $message)); - } else { - print json_encode(array("form" => $form->__toString())); + // Insert source items into the hole + foreach ($source_ids as $source_id) { + Database::Instance()->update( + "items", array("weight" => $target_weight++), array("id" => $source_id)); } - } - public function reset_sort() { - $itemids = Input::instance()->get("item"); - $item = ORM::factory("item") - ->in("id", $itemids[0]) - ->find(); - access::required("view", $item); - access::required("edit", $item); + module::event("album_rearrange", $album); - print organize::get_sort_edit_form($item); + print json_encode( + array("grid" => self::_get_micro_thumb_grid($album, 0)->__toString(), + "sort_column" => $album->sort_column, + "sort_order" => $album->sort_order)); } - public function edit_tags() { + function sort_order($album_id, $col, $dir) { access::verify_csrf(); - $itemids = explode("|", $this->input->post("item")); - $form = organize::get_tag_form($itemids); - $old_tags = $form->tags->value; - if ($form->validate()) { - - $old_tags = preg_split("/[;,\s]+/", $old_tags); - sort($old_tags); - $new_tags = preg_split("/[;,\s]+/", $form->tags->value); - sort($new_tags); + $album = ORM::factory("item", $album_id); + access::required("view", $album); + access::required("edit", $album); - $HIGH_VALUE_STRING = "\256"; - for ($old_index = $new_index = 0;;) { - $old_tag = $old_index >= count($old_tags) ? $HIGH_VALUE_STRING : $old_tags[$old_index]; - $new_tag = $new_index >= count($new_tags) ? $HIGH_VALUE_STRING : $new_tags[$new_index]; - if ($old_tag == $HIGH_VALUE_STRING && $new_tag == $HIGH_VALUE_STRING) { - break; - } - $matches = array(); - $old_star = false; - if (preg_match("/(.*)(\*)$/", $old_tag, $matches)) { - $old_star = true; - $old_tag = $matches[1]; - } - $new_star = false; - if (preg_match("/(.*)(\*)$/", $new_tag, $matches)) { - $new_star = true; - $new_tag = $matches[1]; - } - if ($old_tag > $new_tag) { - // Its missing in the old list so add it - $this->_add_tag($new_tag, $itemids); - $new_index++; - } else if ($old_tag < $new_tag) { - // Its missing in the new list so its been removed - $this->_delete_tag($old_tag, $itemids); - $old_index++; - } else { - if ($old_star && !$new_star) { - // User wants tag to apply to all items, originally only on some of selected - $this->_update_tag($old_tag, $itemids); - } // Not changed ignore - $old_index++; - $new_index++; - } - } + $options = album::get_sort_order_options(); + if (!isset($options[$col])) { + return; } - print json_encode(array("form" => $form->__toString(), "message" => t("Tags updated"))); - } - public function reset_edit_tags() { - $itemids = $this->input->get("item"); + $album->sort_column = $col; + $album->sort_order = $dir; + $album->save(); - print organize::get_tag_form($itemids); + print json_encode( + array("grid" => self::_get_micro_thumb_grid($album, 0)->__toString(), + "sort_column" => $album->sort_column, + "sort_order" => $album->sort_order)); } - private function _add_tag($new_tag, $itemids) { - // Super lame security stopgap. This code is going to get rewritten anyway. - foreach ($itemids as $item_id) { - $item = ORM::factory("item", $item_id); - access::required("view", $item); - access::required("edit", $item); - } - - $tag = ORM::factory("tag") - ->where("name", $new_tag) - ->find(); - if ($tag->loaded) { - $tag->count += count($itemids); - } else { - $tag->name = $new_tag; - $tag->count = count($itemids); - } - $tag->save(); - - $db = Database::instance(); - foreach ($itemids as $item_id) { - $db->query("INSERT INTO {items_tags} SET item_id = $item_id, tag_id = {$tag->id};"); - } + private static function _get_micro_thumb_grid($album, $offset) { + $v = new View("organize_thumb_grid.html"); + $v->album = $album; + $v->offset = $offset; + return $v; } - private function _delete_tag($new_tag, $itemids) { - // Super lame security stopgap. This code is going to get rewritten anyway. - foreach ($itemids as $item_id) { - $item = ORM::factory("item", $item_id); - access::required("view", $item); - access::required("edit", $item); - } + private static function _tree($album) { + $v = new View("organize_tree.html"); + $v->parents = $album->parents(); + $v->album = $album; - $tag = ORM::factory("tag") - ->where("name", $new_tag) - ->find(); - $tag->count -= count($itemids); - if ($tag->count > 0) { - $tag->save(); + if ($album->id == 1) { + $v->peers = array($album); } else { - $tag->delete(); + $v->peers = $album->parent()->children(null, 0, array("type" => "album")); } - $ids = implode(", ", $itemids); - Database::instance()->query( - "DELETE FROM {items_tags} WHERE tag_id = {$tag->id} AND item_id IN ($ids);"); - } - - private function _update_tag($new_tag, $itemids) { - // Super lame security stopgap. This code is going to get rewritten anyway. - foreach ($itemids as $item_id) { - $item = ORM::factory("item", $item_id); - access::required("view", $item); - access::required("edit", $item); - } - - $tag = ORM::factory("tag") - ->where("name", $new_tag) - ->find(); - - $db = Database::instance(); - $ids = implode(", ", $itemids); - $result = $db->query( - "SELECT item_id FROM {items_tags} - WHERE tag_id = {$tag->id} - AND item_id IN ($ids)"); - - $add_items = array_fill_keys($itemids, 1); - foreach($result as $row) { - unset($add_items[$row->item_id]); - } - $add_items = array_keys($add_items); - $tag->count += count($add_items); - $tag->save(); - foreach ($add_items as $item_id) { - $db->query("INSERT INTO {items_tags} SET item_id = $item_id, tag_id = {$tag->id};"); - } - } - - private function _getOperationDefinition($item, $operation) { - switch ($operation) { - case "move": - return array("description" => - t("Move albums and photos to '%name'", array("name" => $item->title)), - "name" => t("Move to '%name'", array("name" => $item->title)), - "type" => "move", - "runningMsg" => t("Move in progress"), - "pauseMsg" => t("The move operation was paused"), - "resumeMsg" => t("The move operation was resumed")); - break; - - case "rearrange": - return array("description" => t("Rearrange the order of albums and photos"), - "name" => t("Rearrange: %name", array("name" => $item->title)), - "type" => "rearrange", - "runningMsg" => t("Rearrange in progress"), - "pauseMsg" => t("The rearrange operation was paused"), - "resumeMsg" => t("The rearrange operation was resumed")); - break; - - case "rotateCcw": - return array("description" => t("Rotate the selected photos counter clockwise"), - "name" => t("Rotate images in %name", array("name" => $item->title)), - "type" => "rotateCcw", - "runningMsg" => t("Rotate Counter Clockwise in progress"), - "pauseMsg" => t("The rotate operation was paused"), - "resumeMsg" => t("The rotate operation was resumed")); - break; - - case "rotateCw": - return array("description" => t("Rotate the selected photos clockwise"), - "name" => t("Rotate images in %name", array("name" => $item->title)), - "type" => "rotateCw", - "runningMsg" => t("Rotate Clockwise in progress"), - "pauseMsg" => t("The rotate operation was paused"), - "resumeMsg" => t("The rotate operation was resumed")); - break; - - case "delete": - return array("description" => t("Delete selected photos / albums"), - "name" => t("Delete images in %name", array("name" => $item->title)), - "type" => "delete", - "runningMsg" => t("Delete images in progress"), - "pauseMsg" => t("The delete operation was paused"), - "resumeMsg" => t("The delete operation was resumed")); - break; - - case "albumCover": - return array("description" => t("Reset Album Cover"), - "name" => t("Reset Album cover for %name", array("name" => $item->title)), - "type" => "albumCover", - "runningMsg" => t("Reset Album Cover in progress"), - "pauseMsg" => t("Reset album cover was paused"), - "resumeMsg" => t("Reset album cover was resumed")); - break; - - default: - throw new Exception("Operation '$operation' is not implmented"); - } + return $v; } } diff --git a/modules/organize/css/organize.css b/modules/organize/css/organize.css index e58cd5a5..85168810 100644 --- a/modules/organize/css/organize.css +++ b/modules/organize/css/organize.css @@ -1,81 +1,79 @@ -/* @todo move to theme css */ + /******************************************************************* * Dialog wide stylings */ -#gMessage { - margin-bottom: .4em; +#gOrganizeDialog { + text-align: left; } -#gMessage .gInfo { - background-color: transparent; - background-image: none; - padding-left: .4em; +#gOrganize { + overflow: hidden; } -#gOrganizeProgressDialog { - text-align: left; +#gOrganize #bd { + height: 100%; +} + +#gOrganize .yui-u { + width: 75%; +} + +#gOrganize .yui-gf .first { + width: 25%; } -#gDialog .yui-gf div.first { - width: 20%; +#gOrganize .yui-gf #gMessage { + margin-bottom: .4em; + width: 75%; + white-space: nowrap; } -#gDialog .yui-gf .yui-u { - width: 80%; +#gOrganizeDetail { + height: 100%; +} + +#gMessage .gInfo { + font-weight: bold; + padding-left: 2em; } /******************************************************************* * Album Tree styling */ #gOrganizeTreeContainer { - overflow-y: auto; + height: 100%; + overflow: auto; margin: 0 !important; padding: 0 !important; } -#gOrganizeAlbumDescription { - height: 2em; - overflow-y: auto; +#gOrganizeTreeContainer ul ul li { + padding-left: 1.2em; +} + +.gAlbumText:hover { + border: 1px dashed #999; + padding: 1px; } -.gBranchSelected { +#gOrganizeAlbumTree .selected { background-color: #cfdeff !important; border-bottom: 1px solid #999 !important; display: block; padding: .3em 0; } -.gBranchDroppable { - border: 1px dotted; +.gOrganizeAlbum span { + cursor: pointer; } -.gBranchText { +.gAlbumText { cursor: pointer; width: auto; } - -.gBranchCollapsed { - display: none; -} - -.gBranchEmpty { - visibility: hidden; -} - -#gOrganizeTreeContainer ul ul li { - padding-left: 1.2em; -} - /******************************************************************* * Album Panel Styles */ - -#gMicroThumbUnselectAll, -#gMicroThumbSelectAll { - font-size: 1em; - font-weight: bold; -} - #gMicroThumbPanel { margin: 0 !important; padding: 0 !important; @@ -83,200 +81,66 @@ border: 1px solid #999 !important; border-top: none !important; border-left: none !important; - margin-left: -1em !important; overflow-x: hidden; overflow-y: auto; } #gMicroThumbGrid { - padding: .5em; + padding: 1em; } -.gMicroThumbContainer { - display: block; +.gMicroThumbGridCell { float: left; - font-size: .7em; - height: 9em; - margin-bottom: 1em; - margin-left: 1em; - opacity: .4; - padding: 0 .5em; + font-size: 0.8em; + padding: .5em !important; + opacity: .5; + border-left: 1px hidden #13A; + border-right: 1px hidden #13A; } .gMicroThumb { - height: 9em; - width: 9em; - background-color: #fff; display: block; - float: left; + height: 9em; text-align: center; + width: 9em; } -#gMicroThumbPanel #gMicroThumbGrid .gAlbum { - background-color: #e8e8e8; -} - -#gMicroThumbPanel #gMicroThumbGrid :hover { +.gMicroThumbGridCell.ui-state-selected { opacity: 1; } -.gMicroThumbContainer.ui-selected { - opacity: 1; +.ui-selectable-lasso { + z-index: 2000 !important; + border: 1px dashed #13A; } -#gDragHelper .gMicroThumbGrid { - background-color: transparent; - padding: 0; - overflow: visible; +.gThumbnail { + padding: .5em; } -#gDragHelper .gMicroThumbContainer { - display: block; - margin: 0; - padding: 0; +#gMicroThumbPanel #gMicroThumbGrid .gAlbum { + background-color: #e8e8e8; } -#gDragHelper .gMicroThumb { - background-color: transparent; - height: auto; - width: auto; +#gMicroThumbPanel #gMicroThumbGrid :hover { + opacity: 1; } - /**************************************************************** - * Organize Edit Drawer styling + * Organize Controls styling */ -#gOrganizeEditDrawer { +#gOrganizeControls { + padding-left: 8px; background-color: #13A; - width: 90%; -} - -#gOrganizeEditDrawerPanel { - background-color: #fff; - border: 1px solid #13A; - display: none; - height: 195px; -} - -#gOrganizeEditDrawerHandle { - height: 30px; -} - -#gOrganizeEditHandleLeft { - background-color: #FFF; - float: left; - height: 30px; - width: 15px; -} - -#gOrganizeEditHandleButtonsMiddle, -#gOrganizeEditHandleButtonsLeft { - float: left; - height: 20px; - padding: 2px 10px; -} - -#gOrganizeEditHandleButtonsMiddle { - margin-left: 20px; -} - -#gOrganizeEditHandleButtonsMiddle a, -#gOrganizeEditHandleButtonsLeft a { - float: left; - margin: 0 2.5px; -} - -#gOrganizeEditHandleButtonsRight { - float: right; - height: 20px; - padding: 2px 10px; -} - -#gOrganizeEditHandleButtonsRight a { - float: left; - margin: 0 2.5px; -} - -#gOrganizeEditHandleRight { - background-color: #FFF; - background-position: -15px 0; - float: right; - height: 30px; - width: 15px; + color: #ccc; + width: 100% !important; } -#gOrganizeFormButtons { - bottom: 0.5em; -} - -#gOrganizeFormButtons .submit { +#gOrganizeControls select { display: inline; - float: none; - left: 0.5em; - position: relative; } -/* yui-u gives 80% width, but then we wrap so do it ourselves */ -#gOrganizeEditForm { +#gOrganizeClose { float: right; - width: 79%; - // height: 100px; -} - -#gOrganizeFormThumbs { - overflow: hidden; -} - -#gOrganizeFormThumbs div { - margin: 0; - text-align: center; - background: transparent none repeat scroll 0 0; -} - -#gOrganizeFormThumbs .gMicroThumbContainer { - display: block; - float: left; - opacity: 1; - position: absolute; -} - -/**************************************************************** - * Organize Edit From tabs styling - */ -#gOrganizeEditForm.ui-tabs .ui-tabs-hide { - display: block !important; - left: -10000px; - position: absolute; -} - -#gOrganizeEditForm.ui-widget { - font-size: .75em; -} - -.gOrganizeEditPane { - height: 135px; - overflow-y: auto; -} - -.textbox, -.textarea { - border: 1px solid #e8e8e8; - border-top-color: #ccc; - border-left-color: #ccc; - color: #333; - width: 100%; -} - -.textarea { - height: 6em; -} - -.textbox { - height: 1.3em; - width: 50% -} - -.gTagGroup { - float:left; - margin: .5em; + margin-right: 12px; } diff --git a/modules/organize/helpers/organize.php b/modules/organize/helpers/organize.php deleted file mode 100644 index 25284771..00000000 --- a/modules/organize/helpers/organize.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); -/** - * Gallery - a web based photo album viewer and editor - * Copyright (C) 2000-2009 Bharat Mediratta - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. - */ -class organize_Core { - static function get_general_edit_form($item) { - $generalPane = new Forge("organize/__FUNCTION__", "", "post", - array("id" => "gEditGeneral", "ref" => "general")); - // In this case we know there is only 1 item, but in general we should loop - // and create multiple hidden items. - $generalPane->hidden("item[]")->value($item->id); - $generalPane->input("title")->label(t("Title"))->value($item->title); - $generalPane->textarea("description")->label(t("Description"))->value($item->description); - $generalPane->input("dirname")->label(t("Path Name"))->value($item->name) - ->callback("item::validate_no_slashes") - ->error_messages("no_slashes", t("The directory name can't contain a \"/\"")) - ->callback("item::validate_no_trailing_period") - ->error_messages("no_trailing_period", t("The directory name can't end in \".\"")) - ->callback("item::validate_no_name_conflict") - ->error_messages("conflict", t("The path name is not unique")); - - return $generalPane; - } - - static function get_sort_edit_form($item) { - $sortPane = new Forge("organize/__FUNCTION__", "", "post", - array("id" => "gEditSort", "ref" => "sort")); - $sortPane->hidden("item[]")->value($item->id); - $sortPane->dropdown("column", array("id" => "gAlbumSortColumn")) - ->label(t("Sort by")) - ->options(array("weight" => t("Order Added"), - "captured" => t("Capture Date"), - "created" => t("Creation Date"), - "title" => t("Title"), - "updated" => t("Updated Date"), - "view_count" => t("Number of views"), - "rand_key" => t("Random"))) - ->selected($item->sort_column); - $sortPane->dropdown("direction", array("id" => "gAlbumSortDirection")) - ->label(t("Order")) - ->options(array("ASC" => t("Ascending"), - "DESC" => t("Descending"))) - ->selected($item->sort_order); - - return $sortPane; - } - - static function get_tag_form($itemids) { - $tagPane = new Forge("organize/__FUNCTION__", "", "post", - array("id" => "gEditTags", "ref" => "edit_tags")); - $tagPane->hidden("item")->value(implode("|", $itemids)); - $item_count = count($itemids); - $ids = implode(", ", $itemids); - - // Lame stopgap security check. This code is going to get rewritten anyway. - foreach ($itemids as $id) { - $item = ORM::factory("item", $id); - access::required("view", $item); - access::required("edit", $item); - } - - $tags = Database::instance()->query( - "SELECT t.name, COUNT(it.item_id) as count - FROM {items_tags} it, {tags} t - WHERE it.tag_id = t.id - AND it.item_id in($ids) - GROUP BY it.tag_id - ORDER BY t.name ASC"); - $taglist = array(); - foreach ($tags as $tag) { - $taglist[] = $tag->name . ($item_count > $tag->count ? "*" : ""); - } - $taglist = implode("; ", $taglist); - $tagPane->textarea("tags")->label(t("Tags"))->value($taglist); - - return $tagPane; - } - -}
\ No newline at end of file diff --git a/modules/organize/helpers/organize_event.php b/modules/organize/helpers/organize_event.php index 99a28673..7d6b3e24 100644 --- a/modules/organize/helpers/organize_event.php +++ b/modules/organize/helpers/organize_event.php @@ -23,11 +23,11 @@ class organize_event_Core { if ($item && access::can("edit", $item) && $item->is_album()) { $menu->get("options_menu") - ->append(Menu::factory("link") + ->append(Menu::factory("dialog") ->id("organize") ->label(t("Organize Album")) ->css_id("gOrganizeLink") - ->url(url::site("organize/index/{$item->id}"))); + ->url(url::site("organize/dialog/{$item->id}"))); } } } diff --git a/modules/organize/helpers/organize_task.php b/modules/organize/helpers/organize_task.php deleted file mode 100644 index dc474818..00000000 --- a/modules/organize/helpers/organize_task.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); -/** - * Gallery - a web based photo album viewer and editor - * Copyright (C) 2000-2009 Bharat Mediratta - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. - */ -class organize_task_Core { - static function available_tasks() { - // Return empty array so nothing appears in the maintenance screen - return array(); - } - - static function run($task) { - $context = unserialize($task->context); - $taskType = $context["type"]; - - try { - $target = ORM::factory("item", $context["target"]); - $total = count($context["items"]); - $stop = min($total - $context["position"], $context["batch"]); - $context["post_process"] = array(); - for ($offset = 0; $offset < $stop; $offset++) { - $current_id = $context["position"] + $offset; - $id = $context["items"][$current_id]; - switch ($taskType) { - case "move": - $source = ORM::factory("item", $id); - access::required("view", $source); - access::required("view", $target); - access::required("edit", $source); - access::required("edit", $target); - - item::move($source, $target); - break; - - case "rearrange": - $item = ORM::factory("item", $id); - access::required("view", $item); - access::required("edit", $item); - - Database::instance() - ->query("Update {items} set weight = {$context["position"]} where id=$id;"); - break; - - case "rotateCcw": - case "rotateCw": - $item = ORM::factory("item", $id); - access::required("view", $item); - access::required("edit", $item); - - if ($item->is_photo()) { - $context["post_process"]["reload"][] = - self::_do_rotation($item, $taskType == "rotateCcw" ? -90 : 90); - } - break; - - case "albumCover": - $item = ORM::factory("item", $id); - access::required("view", $item); - access::required("view", $item->parent()); - access::required("edit", $item->parent()); - - item::make_album_cover($item); - break; - - case "delete": - $item = ORM::factory("item", $id); - access::required("view", $item); - access::required("edit", $item); - - $item->delete(); - $context["post_process"]["remove"][] = array("id" => $id); - break; - - default: - throw new Exception("Task '$taskType' is not implemented"); - } - } - $context["position"] += $stop; - $task->state = "success"; - } catch(Exception $e) { - $task->status = $e->getMessage(); - $task->state = "error"; - $task->save(); - throw $e; - } - $task->context = serialize($context); - $total = count($context["items"]); - $task->percent_complete = $context["position"] / (float)$total * 100; - $task->done = $context["position"] == $total || $task->state == "error"; - } - - private static function _do_rotation($item, $degrees) { - // This code is copied from Quick_Controller::rotate - graphics::rotate($item->file_path(), $item->file_path(), array("degrees" => $degrees)); - - list($item->width, $item->height) = getimagesize($item->file_path()); - $item->resize_dirty= 1; - $item->thumb_dirty= 1; - $item->save(); - - graphics::generate($item); - - $parent = $item->parent(); - if ($parent->album_cover_item_id == $item->id) { - copy($item->thumb_path(), $parent->thumb_path()); - $parent->thumb_width = $item->thumb_width; - $parent->thumb_height = $item->thumb_height; - $parent->save(); - } - list ($height, $width) = $item->scale_dimensions(90); - $margin_top = (90 - $height) / 20; - - return array("src" => $item->thumb_url() . "?rnd=" . rand(), - "id" => $item->id, - "marginTop" => "{$margin_top}em", "width" => $width, "height" => $height); - } -}
\ No newline at end of file diff --git a/modules/organize/helpers/organize_theme.php b/modules/organize/helpers/organize_theme.php index e4feba2b..61b6fe7d 100644 --- a/modules/organize/helpers/organize_theme.php +++ b/modules/organize/helpers/organize_theme.php @@ -19,9 +19,14 @@ */ class organize_theme { static function head($theme) { - // @tdo remove the addition css and organize.js (just here to test) - $theme->script("organize_init.js"); - $theme->script("organize.js"); - $theme->css("organize.css"); + $item = $theme->item(); + if ($item && access::can("edit", $item) && $item->is_album()) { + // @todo: Defer loading js/css until we're loading the organize dialog as <script> and + // <link> elements so that we're not forcing them to be downloaded on every page view (which + // is expensive in terms of browser latency). When we do that, we'll have to figure out an + // approach that lets us continue to use the Kohana cascading filesystem. + $theme->script("organize.js"); + $theme->css("organize.css"); + } } } diff --git a/modules/organize/js/organize.js b/modules/organize/js/organize.js index f10cbcc9..04e14a2f 100644 --- a/modules/organize/js/organize.js +++ b/modules/organize/js/organize.js @@ -1,621 +1,210 @@ -/* - * @todo Trap resize of dialog and resize the child areas (tree, grid and edit form) - */ -var url; -var paused = false; -var task = null; -var transitItems = []; -var heightMicroThumbPanel; - -// ************************************************************************** -// JQuery UI Widgets -// Draggable -var draggable = { - handle: ".gMicroThumbContainer.ui-selected", - revert: true, - zindex: 2000, - distance: 10, - helper: function(event, ui) { - if (!$(event.currentTarget).hasClass("ui-selected")) { - $(event.currentTarget).addClass("ui-selected"); - setDrawerButtonState(); - } - $("#gMicroThumbPanel").append("<div id=\"gDragHelper\"><ul></ul></div>"); - var beginTop = event.pageY; - var beginLeft = event.pageX; - var zindex = $(".gMicroThumbContainer").draggable("option", "zindex"); - $("#gDragHelper").css('top', event.pageY - 22.5); - $("#gDragHelper").css('left', event.pageX + 22.5); - var placeHolder = $(this).clone(); - $(placeHolder).attr("id", "gPlaceHolder"); - $(placeHolder).css("visibility", "hidden"); - $(placeHolder).removeClass("ui-selected"); - $(placeHolder).removeClass("ui-draggable"); - $(this).after(placeHolder); +(function($) { + $.organize = { + micro_thumb_draggable: { + handle: ".ui-state-selected", + distance: 10, + cursorAt: { left: -10, top: -10}, + appendTo: "#gMicroThumbPanel", + helper: function(event, ui) { + var selected = $(".ui-draggable.ui-state-selected img"); + if (selected.length) { + var set = $('<div class="gDragHelper"></div>') + .css({ + zIndex: 2000, + width: 80, + height: Math.ceil(selected.length / 5) * 16 + }); + var offset = $(this).offset(); + var click = {left: event.pageX - offset.left, top: event.pageY - offset.top}; + + selected.each(function(i) { + var row = parseInt(i / 5); + var j = i - (row * 5); + var o = $(this).offset(); + var copy = $(this).clone() + .css({ + width: $(this).width(), height: $(this).height(), display: "block", + margin: 0, position: 'absolute', outline: '5px solid #fff', + left: o.left - event.pageX, top: o.top - event.pageY + }) + .appendTo(set) + .animate({ width: 10, height: 10, outlineWidth: 1, margin: 1, + left: (20 * j), top: (row * 20) }, 500); + }); + return set; + } + return null; + }, - $("li.ui-selected").each(function(i) { - var clone = $(this).clone(); - $(clone).attr("id", "drag_clone_" + $(this).attr("ref")); - $("#gDragHelper ul").append(clone); - $(clone).css("position", "absolute"); - $(clone).css("top", beginTop); - $(clone).css("left", beginLeft); - $(clone).css("z-index", zindex--); - $(this).hide(); + start: function(event, ui) { + $("#gMicroThumbPanel .ui-state-selected").hide(); + }, - var children = $(clone).find(".gMicroThumb .gThumbnail"); - var width = new String(children.css("width")).replace(/[^0-9]/g,"") * .5; - var height = new String(children.css("height")).replace(/[^0-9]/g,"") * .5; - var marginTop = new String(children.css("margin-top")).replace(/[^\.0-9]/g,"") * .5; - children.attr("width", width); - children.attr("height", height); - children.css("margin-top", marginTop); - if (i < 9) { - beginTop -= 5; - beginLeft += 5; + drag: function(event, ui) { + var top = $("#gMicroThumbPanel").offset().top; + var height = $("#gMicroThumbPanel").height(); + if (ui.offset.top > height + top - 20) { + $("#gMicroThumbPanel").get(0).scrollTop += 100; + } else if (ui.offset.top < top + 20) { + $("#gMicroThumbPanel").get(0).scrollTop = Math.max(0, $("#gMicroThumbPanel").get(0).scrollTop - 100); + } } - }); - return $("#gDragHelper"); - }, - stop: function(event, ui) { - $("#gDragHelper li").each(function(i) { - $("#thumb_" + $(this).attr("ref")).show(); - }); - $(".gMicroThumbContainer.ui-selected").css("z-index", null); - $("#gDragHelper").remove(); - $("#gPlaceHolder").remove(); - } -}; - -// Thumbnail Grid Droppable -var thumbDroppable = { - tolerance: "pointer", - over: function(event, ui) { - $("#gPlaceHolder").show(); - }, - out: function(event, ui) { - $("#gPlaceHolder").hide(); - }, - drop: function(event, ui) { - $("#gDragHelper").hide(); - $("#gPlaceHolder").hide(); - var newOrder = ""; - $("#gMicroThumbGrid .gMicroThumbContainer").each(function(i) { - if ($(this).attr("id") == "gPlaceHolder") { - $("#gDragHelper li").each(function(i) { - newOrder += "&item[]=" + $(this).attr("ref"); + }, + + content_droppable: { + accept: "*", + tolerance: "pointer", + greedy: true, + drop: function(event, ui) { + var before_or_after = $(".currentDropTarget").css("borderLeftStyle") == "solid" ? "before" : "after"; + $.organize.do_drop({ + url: rearrange_url + .replace("__TARGET_ID__", $(".currentDropTarget").attr("ref")) + .replace("__ALBUM_ID__", $(".currentDropTarget").attr("ref")) + .replace("__BEFORE__", before_or_after), + source: $(ui.helper).children("img") }); - } else if ($(this).css("display") != "none") { - newOrder += "&item[]=" + $(this).attr("ref"); - } else { - // If its not displayed then its one of the ones being moved so ignore. } - }); - $("#gDragHelper li").each(function(i) { - $("#gPlaceHolder").before($("#thumb_" + $(this).attr("ref")).show()); - }); - $.ajax({ - data: newOrder, - dataType: "json", - success: operationCallback, - type: "POST", - url: get_organize_url("organize/startTask/rearrange", {item_id: item_id}) - }); - } -}; - -// Album Tree Droppable -var treeDroppable = { - tolerance: "pointer", - greedy: true, - hoverClass: "gBranchDroppable", - drop: function(event, ui) { - $("#gDragHelper").hide(); - var targetItemId = $(this).attr("ref"); - if ($(this).hasClass("gBranchSelected")) { - $("#gMessage").empty().append(INVALID_DROP_TARGET); - ui.draggable.trigger("stop", event); - return false; - } - var postData = serializeItemIds("#gDragHelper li"); - var okToMove = true; - $("#gDragHelper li").each(function(i) { - okToMove &= targetItemId != $(this).attr("ref"); - }); - if (!okToMove) { - $("#gMessage").empty().append(INVALID_DROP_TARGET); - ui.draggable.trigger("stop", event); - return false; - } - $("#gDragHelper li").each(function(i) { - $("#thumb_" + $(this).attr("ref")).remove(); - }); - $.ajax({ - data: postData, - dataType: "json", - success: operationCallback, - type: "POST", - url: get_organize_url("organize/startTask/move", {item_id: targetItemId}) - }); - return true; - } -}; - -// Selectable -var selectable = { - filter: ".gMicroThumbContainer", - selected: function(event, ui) { - setDrawerButtonState(); - }, - unselected: function(event, ui) { - setDrawerButtonState(); - }, - stop: function(event, ui) { - getEditForm(); - } -}; - -// ************************************************************************** -// Event Handlers -// MicroThumbContainer mouseup -var onMicroThumbContainerMouseup = function(event) { - // For simplicity always remove the ui-selected class. If it was unselected - // it will get added back - $(this).toggleClass("ui-selected"); - - setDrawerButtonState(); - if ($("#gMicroThumbGrid li.ui-selected").length > 0) { - getEditForm(); - } -}; - -// MicroThumbContainer mousemove -var onMicroThumbContainerMousemove = function(event) { - if ($("#gDragHelper").length > 0 && $(this).attr("id") != "gPlaceHolder") { - if (event.pageX < $(this).offset().left + $(this).width() / 2) { - $(this).before($("#gPlaceHolder")); - } else { - $(this).after($("#gPlaceHolder")); - } - var container = $("#gMicroThumbPanel").get(0); - var scrollHeight = container.scrollHeight; - var scrollTop = container.scrollTop; - var height = $(container).height(); - if (event.pageY > height + scrollTop) { - container.scrollTop = this.offsetTop; - } else if (event.pageY < scrollTop) { - container.scrollTop -= height; - } - } -}; - -// Handle click events on the buttons on the drawer handle -function drawerHandleButtonsClick(event) { - event.preventDefault(); - if (!$(this).attr("disabled")) { - var operation = $(this).attr("ref"); - switch (operation) { - case "edit": - case "close": - $("#gOrganizeEditDrawerPanel").animate( - {"height": "toggle", "display": "block"}, - {duration: "fast", - complete: function() { - setSelectedThumbs(); - if (operation == "close") { - $("#gOrganizeEditHandleButtonsLeft a[ref='edit']").css("display", "inline-block"); - $("#gOrganizeEditHandleButtonsLeft a[ref='close']").css("display", "none"); - $("#gOrganizeEditHandleButtonsMiddle a").css("display", "none"); - } else { - $("#gOrganizeEditHandleButtonsLeft a[ref='edit']").css("display", "none"); - $("#gOrganizeEditHandleButtonsLeft a[ref='close']").css("display", "inline-block"); - $("#gOrganizeEditHandleButtonsMiddle a").css("display", "inline-block"); - } - }, - step: function() { - $("#gMicroThumbPanel").height(heightMicroThumbPanel - $(this).height()); - } - }); - break; - case "select-all": - $("#gMicroThumbGrid li").addClass("ui-selected"); - $("#gMicroThumbSelectAll").hide(); - $("#gMicroThumbUnselectAll").show(); - setDrawerButtonState(); - getEditForm(); - break; - case "unselect-all": - $("#gMicroThumbGrid li").removeClass("ui-selected"); - $("#gMicroThumbSelectAll").show(); - $("#gMicroThumbUnselectAll").hide(); - setDrawerButtonState(); - break; - case "done": - $("#gDialog").dialog("close"); - break; - case "submit": - var currentTab = $("#gOrganizeEditForm").tabs("option", "selected"); - var form = $("#pane-"+currentTab+" form"); - var url = $(form).attr("action") - .replace("__FUNCTION__", $(form).attr("ref")); - $.ajax({ - data: $(form).serialize(), - dataType: "json", - success: function (data, textStatus) { - $("#pane-"+currentTab).children("form").replaceWith(data.form); - if (data.message) { - $("#gMessage").empty().append("<div class='gSuccess'>" + data.message + "</div>"); - } - }, - type: "POST", - url: url - }); - break; - case "reset": - currentTab = $("#gOrganizeEditForm").tabs("option", "selected"); - form = $("#pane-"+currentTab+" form"); - $.ajax({ - data: serializeItemIds("#gMicroThumbPanel li.ui-selected"), - dataType: "html", - success: function (data, textStatus) { - $("#pane-"+currentTab + " form").replaceWith(data); - }, - type: "GET", - url: $(form).attr("action").replace("__FUNCTION__", "reset_" + $(form).attr("ref")) - }); - break; - case "delete": - if (!confirm(CONFIRM_DELETE)) { - break; - } - default: - $.ajax({ - data: serializeItemIds("#gMicroThumbPanel li.ui-selected"), - dataType: "json", - success: operationCallback, - type: "POST", - url: get_organize_url("organize/startTask/" + operation, {item_id: item_id}) - }); - break; - } - } -}; - -// ************************************************************************** -// AJAX Callbacks -// MicroThumbContainer click -var getMicroThumbsCallback = function(json, textStatus) { - if (json.count > 0) { - $("#gMicroThumbGrid").append(json.data); - retrieveMicroThumbs(); - $(".gMicroThumbContainer").mouseup(onMicroThumbContainerMouseup); - $(".gMicroThumbContainer").mousemove(onMicroThumbContainerMousemove); - $(".gMicroThumbContainer").draggable(draggable); - } -}; - -var operationCallback = function (data, textStatus) { - var done = false; - if (!paused) { - createProgressDialog(data.runningMsg); - task = data.task; - task.pauseMsg = data.pauseMsg; - task.resumeMsg = data.resumeMsg; - done = data.task.done; - } - $(".gMicroThumbContainer").draggable("disable"); - paused = false; - while (!done && !paused) { - $.ajax({async: false, - success: function(data, textStatus) { - $(".gProgressBar").progressbar("value", data.task.percent_complete); - done = data.task.done; - if (data.task.post_process.reload) { - $.each(data.task.post_process.reload, function() { - var selector = "#gMicroThumb-" + this.id + " img"; - $(selector).attr("height", this.height); - $(selector).attr("width", this.width); - $(selector).attr("src", this.src); - $(selector).css("margin-top", this.marginTop); - }); - } - if (data.task.post_process.remove) { - $.each(data.task.post_process.remove, function() { - $("#thumb_" + this.id).remove(); + }, + + branch_droppable: { + accept: "*", + tolerance: "pointer", + greedy: true, + drop: function(event, ui) { + if ($(event.target).hasClass("gViewOnly")) { + $(".ui-state-selected").show(); + $(".gMicroThumbGridCell").css("borderStyle", "none"); + } else { + $.organize.do_drop({ + url: move_url.replace("__ALBUM_ID__", $(event.target).attr("ref")), + source: $(ui.helper).children("img") }); } - }, - error: function(XMLHttpRequest, textStatus, errorThrown) { - paused = true; - displayAjaxError(XMLHttpRequest.responseText); - }, - dataType: "json", - type: "POST", - url: get_organize_url("organize/runTask", {task_id: task.id}) - }); - } - if (!paused) { - $("#gOrganizeProgressDialog").dialog("destroy").remove(); - $.ajax({async: false, - success: function(data, textStatus) { - setDrawerButtonState(); - task = null; - $("#gMessage").empty().append("<div class='gSuccess'>" + data.task.status + "</div>"); - }, - dataType: "json", - type: "POST", - url: get_organize_url("organize/finishTask", {task_id: task.id}) - }); - } - $(".gMicroThumbContainer").draggable("enable"); -}; - -// ************************************************************************** - -/** - * Dynamically initialize the organize dialog when it is displayed - */ -function organize_dialog_init() { - var size = getViewportSize(); - heightMicroThumbPanel = size.height() - 100; - var width = size.width() - 100; - - // Deal with ui.jquery bug: http://dev.jqueryui.com/ticket/4475 - $(".sf-menu li.sfHover ul").css("z-index", 70); - - $("#gDialog").dialog("option", "width", width); - $("#gDialog").dialog("option", "height", heightMicroThumbPanel); - - $("#gDialog").dialog("open"); - if ($("#gDialog h1").length) { - $("#gDialog").dialog('option', 'title', $("#gDialog h1:eq(0)").html()); - } else if ($("#gDialog fieldset legend").length) { - $("#gDialog").dialog('option', 'title', $("#gDialog fieldset legend:eq(0)").html()); - } - - $("#gDialog").bind("organize_close", function(target) { - document.location.reload(); - }); - - heightMicroThumbPanel -= 2 * parseFloat($("#gDialog").css("padding-top")); - heightMicroThumbPanel -= 2 * parseFloat($("#gDialog").css("padding-bottom")); - heightMicroThumbPanel -= $("#gMicroThumbPanel").position().top; - heightMicroThumbPanel -= $("#gDialog #ft").height(); - heightMicroThumbPanel -= $("#gOrganizeEditDrawerHandle").height(); - heightMicroThumbPanel = Math.round(heightMicroThumbPanel); - - $("#gMicroThumbPanel").height(heightMicroThumbPanel); - $("#gOrganizeTreeContainer").height(heightMicroThumbPanel); - - $(".gOrganizeBranch .ui-icon").click(organizeToggleChildren); - $(".gBranchText").droppable(treeDroppable); - $(".gBranchText").click(organizeOpenFolder); - retrieveMicroThumbs(item_id); - //showLoading("#gDialog"); - - $("#gMicroThumbPanel").droppable(thumbDroppable); - $("#gMicroThumbPanel").selectable(selectable); - $("#gOrganizeEditDrawerHandle a").click(drawerHandleButtonsClick); -} - -function retrieveMicroThumbs() { - var offset = $("#gMicroThumbGrid li").length; - if (url == null) { - var grid_width = $("#gMicroThumbPanel").width(); - url = $("#gMicroThumbPanel").attr("ref"); - url = url.replace("__WIDTH__", grid_width); - url = url.replace("__HEIGHT__", heightMicroThumbPanel); - } - var url_data = url.replace("__OFFSET__", offset); - url_data = url_data.replace("__ITEM_ID__", item_id); - $.getJSON(url_data, getMicroThumbsCallback); -} - -function organizeToggleChildren(event) { - var id = $(this).attr("ref"); - var span_children = $("#gOrganizeChildren-" + id); - if ($(this).hasClass("ui-icon-plus")) { - $(this).removeClass("ui-icon-plus"); - $(this).addClass("ui-icon-minus"); - $("#gOrganizeChildren-" + id).removeClass("gBranchCollapsed"); - } else { - $(this).removeClass("ui-icon-minus"); - $(this).addClass("ui-icon-plus"); - $("#gOrganizeChildren-" + id).addClass("gBranchCollapsed"); - } - event.preventDefault(); -} - -function organizeOpenFolder(event) { - var selected = $(".gBranchSelected"); - if ($(selected).attr("id") != $(this).attr("id")) { - $(selected).removeClass("gBranchSelected"); - $(this).addClass("gBranchSelected"); - item_id = $(this).attr("ref"); - $("#gMicroThumbGrid").empty(); - retrieveMicroThumbs(); - } - event.preventDefault(); -} - -function get_organize_url(uri, parms) { - var url = rearrangeUrl; - url = url.replace("__URI__", uri); - url = url.replace("__ITEM_ID__", !parms.item_id ? "" : parms.item_id); - url += (parms.item_id && parms.task_id) ? "/" : ""; - url = url.replace("__TASK_ID__", !parms.task_id ? "" : parms.task_id); - return url; -} - -/** - * Set the enabled/disabled state of the buttons. The album cover is only enabled if - * there is only 1 image selected - */ -function setDrawerButtonState() { - $("#gOrganizeFormThumbStack").empty(); - $("#gOrganizeEditForm").empty(); - var selectedCount = $("#gMicroThumbGrid li.ui-selected").length; - if (selectedCount) { - $("#gOrganizeEditHandleButtonsLeft a").removeAttr("disabled"); - $("#gOrganizeEditHandleButtonsLeft a").removeClass("ui-state-disabled"); - - if (selectedCount > 1) { - $("#gOrganizeEditHandleButtonsLeft a[ref='albumCover']").attr("disabled", true); - $("#gOrganizeEditHandleButtonsLeft a[ref='albumCover']").addClass("ui-state-disabled"); - } - setSelectedThumbs(); - } else { - if ($("#gOrganizeEditDrawerPanel::visible").length) { - $("#gOrganizeEditHandleButtonsLeft a[ref='close']").trigger("click"); - } - $("#gOrganizeEditHandleButtonsLeft a").attr("disabled", true); - $("#gOrganizeEditHandleButtonsLeft a").addClass("ui-state-disabled"); - } -} + } + }, -function setSelectedThumbs() { - if (!$("#gOrganizeEditDrawerPanel::visible").length) { - return; - } - var position = $("#gOrganizeFormThumbStack").position(); - var beginLeft = position.left; - var beginTop = 50; - var zindex = 2000; - $("li.ui-selected").each(function(i) { - var clone = $(this).clone(); - $(clone).attr("id", "edit_clone_" + $(this).attr("ref")); - $("#gOrganizeFormThumbStack").append(clone); - $(clone).removeClass("ui-draggable"); - $(clone).removeClass("ui-selected"); - $(clone).css("margin-top", beginTop); - $(clone).css("left", beginLeft); - $(clone).css("z-index", zindex--); + do_drop: function(options) { + $("#gMicroThumbPanel").selectable("destroy"); + var source_ids = []; + $(options.source).each(function(i) { + source_ids.push($(this).attr("ref")); + }); - if (i < 9) { - beginTop -= 5; - beginLeft += 5; - } - }); -} + if (source_ids.length) { + $.post(options.url, + { "source_ids[]": source_ids }, + function(data) { $.organize._refresh(data); }, + "json"); + } + }, -function getEditForm() { - if ($("#gMicroThumbGrid li.ui-selected").length > 0) { - var postData = serializeItemIds("li.ui-selected"); - var url_data = get_organize_url("organize/editForm", {}) + postData; - $.get(url_data, function(data, textStatus) { - $("#gOrganizeEditForm").tabs("destroy"); - $("#gOrganizeEditForm").html(data); - if ($("#gOrganizeEditForm ul li").length) { - $("#gOrganizeEditForm").tabs(); - $("#gOrganizeEditHandleButtonsMiddle a").removeAttr("disabled"); - $("#gOrganizeEditHandleButtonsMiddle a").removeClass("ui-state-disabled"); - } else { - $("#gOrganizeEditHandleButtonsMiddle a").attr("disabled", true); - $("#gOrganizeEditHandleButtonsMiddle a").addClass("ui-state-disabled"); + _refresh: function(data) { + if (data.tree) { + $("#gOrganizeAlbumTree").html(data.tree); } - }); - } else { - $("#gOrganizeEditForm").tabs("destroy"); - $("#gOrganizeEditForm").empty(); - } -} + if (data.grid) { + $("#gMicroThumbGrid").html(data.grid); + $("#gOrganizeSortColumn").attr("value", data.sort_column); + $("#gOrganizeSortOrder").attr("value", data.sort_order); + } + $.organize.set_handlers(); + }, + + mouse_move_handler: function(event) { + if ($(".gDragHelper").length) { + $(".gMicroThumbGridCell").css("borderStyle", "hidden"); + $(".currentDropTarget").removeClass("currentDropTarget"); + var borderStyle = event.pageX < $(this).offset().left + $(this).width() / 2 ? + "borderLeftStyle" : "borderRightStyle"; + $(this).css(borderStyle, "solid"); + $(this).addClass("currentDropTarget"); + } + }, + + /** + * Dynamically initialize the organize dialog when it is displayed + */ + init: function(data) { + var self = this; + // Deal with ui.jquery bug: http://dev.jqueryui.com/ticket/4475 (target 1.8?) + $(".sf-menu li.sfHover ul").css("z-index", 68); + $("#gDialog").dialog("option", "zIndex", 70); + $("#gDialog").bind("dialogopen", function(event, ui) { + $("#gOrganize").height($("#gDialog").innerHeight() - 20); + $("#gMicroThumbPanel").height($("#gDialog").innerHeight() - 90); + $("#gOrganizeAlbumTree").height($("#gDialog").innerHeight() - 59); + }); -function serializeItemIds(selector) { - var postData = ""; - $(selector).each(function(i) { - postData += "&item[]=" + $(this).attr("ref"); - }); + $("#gDialog").bind("dialogclose", function(event, ui) { + window.location.reload(); + }); - return postData; -} + $("#gDialog #gOrganizeClose").click(function(event) { + $("#gDialog").dialog("close"); + }); -function submitCurrentForm(event) { - console.log("submitCurrentForm"); - return false; -} + $("#gOrganizeSortColumn,#gOrganizeSortOrder").change(function(event) { + $.organize.resort($("#gOrganizeSortColumn").attr("value"), $("#gOrganizeSortOrder").attr("value")); + }); -function resetCurrentForm(event) { - console.log("resetCurrentForm"); - return false; -} + $.organize.set_handlers(); + }, -function createProgressDialog(title) { - $("body").append("<div id='gOrganizeProgressDialog'>" + - "<div class='gProgressBar'></div>" + - "<button id='gOrganizeTaskPause' class='ui-state-default ui-corner-all'>" + PAUSE_BUTTON + "</button>" + - "<button id='gOrganizeTaskResume' class='ui-state-default ui-corner-all' style='display: none'>" + RESUME_BUTTON + "</button>" + - "<button id='gOrganizeTaskCancel' class='ui-state-default ui-corner-all' style='display: none'>" + CANCEL_BUTTON + "</button>" + - "</div>"); - $("#gOrganizeProgressDialog").dialog({ - autoOpen: true, - autoResize: false, - modal: true, - resizable: false, - title: title - }); + set_handlers: function() { + $("#gMicroThumbPanel").selectable({filter: ".gMicroThumbGridCell"}); + $("#gMicroThumbPanel").droppable($.organize.content_droppable); - $(".gProgressBar").progressbar(); - $("#gOrganizeTaskPause").click(function(event) { - paused = true; - $("#gOrganizeTaskPause").hide(); - $("#gOrganizeTaskResume").show(); - $("#gOrganizeTaskCancel").show(); - $("#gMessage").empty().append(task.pauseMsg); - }); - $("#gOrganizeTaskResume").click(function(event) { - $("#gOrganizeTaskPause").show(); - $("#gOrganizeTaskResume").hide(); - $("#gOrganizeTaskCancel").hide(); - $("#gMessage").empty().append(task.resumeMsg); - operationCallback(); - //startRearrangeCallback(); - }); - $("#gOrganizeTaskCancel").click(function(event) { - $("#gOrganizeTaskPause").show(); - $("#gOrganizeTaskResume").hide(); - $("#gOrganizeTaskCancel").hide(); + $(".gMicroThumbGridCell").draggable($.organize.micro_thumb_draggable); + $(".gMicroThumbGridCell").mousemove($.organize.mouse_move_handler); + $(".gOrganizeAlbum").droppable($.organize.branch_droppable); + $(".gAlbumText").click($.organize.show_album); + }, - $.ajax({async: false, - success: function(data, textStatus) { - task = null; - paused = false; - transitItems = []; - $("#gMessage").empty().append("<div class='gWarning'>" + data.task.status + "</div>"); - $("#gOrganizeProgressDialog").dialog("destroy").remove(); - }, - dataType: "json", - type: "POST", - url: get_organize_url("organize/cancelTask", {task_id: task.id}) - }); - }); -} -// ************************************************************************** -// Functions that should probably be in a gallery namespace -function getViewportSize() { - return { - width : function() { - return window.innerWidth - || document.documentElement && document.documentElement.clientWidth - || document.body.clientWidth; - }, - height : function() { - return window.innerHeight - || document.documentElement && document.documentElement.clientHeight - || document.body.clientHeight; + /** + * When the text of a selection is clicked, then show that albums contents + */ + show_album: function(event) { + event.preventDefault(); + if ($(event.currentTarget).hasClass("selected")) { + return; } + var parent = $(event.currentTarget).parents(".gOrganizeBranch"); + if ($(parent).hasClass("gViewOnly")) { + return; + } + $("#gMicroThumbPanel").selectable("destroy"); + var id = $(event.currentTarget).attr("ref"); + $("#gOrganizeAlbumTree .selected").removeClass("selected"); + $(".gAlbumText[ref=" + id + "]").addClass("selected"); + var url = $("#gMicroThumbPanel").attr("ref").replace("__ITEM_ID__", id).replace("__OFFSET__", 0); + $.get(url, {}, + function(data) { + $("#gMicroThumbGrid").html(data.grid); + $("#gOrganizeSortColumn").attr("value", data.sort_column); + $("#gOrganizeSortOrder").attr("value", data.sort_order); + $.organize.set_handlers(); + }, + "json"); + }, + + /** + * Change the sort order. + */ + resort: function(column, dir) { + var url = sort_order_url + .replace("__ALBUM_ID__", $("#gOrganizeAlbumTree .selected").attr("ref")) + .replace("__COL__", column) + .replace("__DIR__", dir); + $.get(url, {}, + function(data) { + $("#gMicroThumbGrid").html(data.grid); + $("#gOrganizeSortColumn").attr("value", data.sort_column); + $("#gOrganizeSortOrder").attr("value", data.sort_order); + $.organize.set_handlers(); + }, + "json"); + } }; -} - -function displayAjaxError(error) { - $("body").append("<div id=\"gAjaxError\" title=\"" + FATAL_ERROR + "\">" + error + "</div>"); - - $("#gAjaxError").dialog({ - autoOpen: true, - autoResize: false, - modal: true, - resizable: true, - width: 610, - height: $("#gDialog").height() - }); -} +})(jQuery); diff --git a/modules/organize/js/organize_init.js b/modules/organize/js/organize_init.js deleted file mode 100644 index ed036fdb..00000000 --- a/modules/organize/js/organize_init.js +++ /dev/null @@ -1,29 +0,0 @@ -$("document").ready(function() { - $("#gOrganizeLink").click(function(event) { - event.preventDefault(); - var href = event.target.href; - - $("body").append('<div id="gDialog"></div>'); - - $("#gDialog").dialog({ - autoOpen: false, - autoResize: false, - modal: true, - resizable: false, - close: function () { - $("#gDialog").trigger("organize_close"); - $("#gDialog").dialog("destroy").remove(); - }, - zIndex: 75 - }); - - //showLoading("#gDialog"); - - $.get(href, function(data) { - $("#gDialog").html(data); - }); - return false; - }); -}); - - diff --git a/modules/organize/views/organize.html.php b/modules/organize/views/organize.html.php deleted file mode 100644 index d2f0aa8c..00000000 --- a/modules/organize/views/organize.html.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<!-- ?= html::script("modules/organize/js/organize.js") ? --> -<script> - var FATAL_ERROR = "<?= t("Fatal Error")->for_js() ?>"; - var PAUSE_BUTTON = "<?= t("Pause")->for_js() ?>"; - var RESUME_BUTTON = "<?= t("Resume"->for_js()) ?>"; - var CANCEL_BUTTON = "<?= t("Cancel")->for_js() ?>"; - var INVALID_DROP_TARGET = "<div class=\"gError\"><?= t("Drop cancelled as it would result in a recursive move")->for_js() ?></div>"; -var CONFIRM_DELETE = "<?= t("Do you really want to delete the selected albums and/or photos")->for_js() ?>" - var item_id = <?= $item->id ?>; - - var csrf = <?= json_encode($csrf) ?>; - var rearrangeUrl = "<?= url::site("__URI__/__ITEM_ID____TASK_ID__?csrf=$csrf")->for_js() ?>"; - $("#doc3").ready(function() { - organize_dialog_init(); - }); -</script> -<fieldset style="display: none"> - <legend><?= t("Organize %name", array("name" => SafeString::purify($item->title))) ?></legend> -</fieldset> -<div id="doc3" class="yui-t7"> - <div id="bd"> - <div class="yui-gf"> - <div class="yui-u first"> - <h3><?= t("Albums") ?></h3> - </div> - <div id="gMessage" class="yui-u"> - <div class="gInfo"><?= t("Select one or more items to edit; drag and drop items to re-order or move between albums") ?></div> - </div> - </div> - <div class="yui-gf"> - <div id="gOrganizeTreeContainer" class="yui-u first"> - <?= $album_tree ?> - </div> - <div id="gMicroThumbPanel" class="yui-u" - ref="<?= url::site("organize/content/__ITEM_ID__?width=__WIDTH__&height=__HEIGHT__&offset=__OFFSET__") ?>"> - <ul id="gMicroThumbGrid"></ul> - </div> - <div id="gOrganizeEditDrawer" class="yui-u"> - <div id="gOrganizeEditDrawerPanel" class="yui-gf"> - <div id="gOrganizeFormThumbs" class="yui-u first"> - <ul id="gOrganizeFormThumbStack" /> - </div> - <div id="gOrganizeEditForm"> - </div> - </div> - <div id="gOrganizeEditDrawerHandle"> - <?= $button_pane ?> - </div> - </div> - </div> - </div> -</div> diff --git a/modules/organize/views/organize_album.html.php b/modules/organize/views/organize_album.html.php deleted file mode 100644 index 4933ed32..00000000 --- a/modules/organize/views/organize_album.html.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<ul> - <li class="gOrganizeBranch ui-icon-left" ref="<?= $album->id ?>"> - <span id="gOrganizeIcon-<?= $album->id ?>" ref="<?= $album->id ?>" - class="ui-icon <?= $album_icon ?> <?= $album_icon ? "" : "gBranchEmpty" ?>"> - </span> - - <div id="gOrganizeBranch-<?= $album->id ?>" ref="<?= $album->id ?>" - class="<?= $selected ? "gBranchSelected" : "" ?> gBranchText"> - <?= SafeString::of($album->title) ?> - </div> - <div id="gOrganizeChildren-<?= $album->id ?>" - class="<?= $album_icon == "ui-icon-plus" ? "gBranchCollapsed" : "" ?>"> - <?= $children ?> - <div> - </li> -</ul> diff --git a/modules/organize/views/organize_button_pane.html.php b/modules/organize/views/organize_button_pane.html.php deleted file mode 100644 index c5839a44..00000000 --- a/modules/organize/views/organize_button_pane.html.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<div id="gOrganizeEditHandleButtonsLeft"> - <a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="edit" - disabled="1" title="<?= t("Open Drawer") ?>"> - <span class="ui-icon ui-icon-arrowthickstop-1-n"><?= t("Open Drawer") ?></span> - </a> - - <a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="close" - disabled="1" title="<?= t("Close Drawer") ?>" style="display: none"> - <span class="ui-icon ui-icon-arrowthickstop-1-s"><?= t("Close Drawer") ?></span> - </a> - - <? if (graphics::can("rotate")): ?> - <a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="rotateCcw" - disabled="1" title="<?= t("Rotate 90 degrees counter clockwise") ?>"> - <span class="ui-icon ui-icon-rotate-ccw"><?= t("Rotate 90 degrees counter clockwise") ?></span> - </a> - - <a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="rotateCw" - disabled="1" title="<?= t("Rotate 90 degrees clockwise") ?>"> - <span class="ui-icon ui-icon-rotate-cw"> <?= t("Rotate 90 degrees clockwise") ?></span> - </a> - <? endif ?> - - <a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="albumCover" - disabled="1" title="<?= t("Choose this photo as the album cover") ?>"> - <span class="ui-icon ui-icon-star"><?= t("Choose this photo as the album cover") ?></span> - </a> - - <a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="delete" - disabled="1" title="<?= t("Delete selection") ?>"> - <span class="ui-icon ui-icon-trash"><?= t("Delete selection") ?></span> - </a> -</div> -<div id="gOrganizeEditHandleButtonsMiddle"> - <a class="gButtonLink ui-corner-all ui-state-default" href="#" ref="submit" - title="<?= t("Apply Changes") ?>" style="display: none" > - <span class="ui-icon ui-icon-check"><?= t("Apply Changes") ?></span> - </a> - - <a class="gButtonLink ui-corner-all ui-state-default" href="#" ref="reset" - title="<?= t("Reset Form") ?>" style="display: none" > - <span class="ui-icon ui-icon-closethick"><?= t("Reset Form") ?></span> - </a> -</div> -<div id="gOrganizeEditHandleButtonsRight"> - <a id="gMicroThumbSelectAll" href="#" ref="select-all" class="gButtonLink ui-corner-all ui-state-default"><?= t("Select all") ?></a> - <a id="gMicroThumbUnselectAll" href="#" ref="unselect-all" style="display: none" class="gButtonLink ui-corner-all ui-state-default"><?= t("Deselect all") ?></a> - <a id="gMicroThumbDone" href="#" ref="done" class="gButtonLink ui-corner-all ui-state-default"><?= t("Close") ?></a> -</div> diff --git a/modules/organize/views/organize_dialog.html.php b/modules/organize/views/organize_dialog.html.php new file mode 100644 index 00000000..b03c066c --- /dev/null +++ b/modules/organize/views/organize_dialog.html.php @@ -0,0 +1,47 @@ +<?php defined("SYSPATH") or die("No direct script access.") ?> +<script type="text/javascript"> + var move_url = "<?= url::site("organize/move_to/__ALBUM_ID__?csrf=$csrf") ?>"; + var rearrange_url = "<?= url::site("organize/rearrange/__TARGET_ID__/__BEFORE__?csrf=$csrf") ?>"; + var sort_order_url = "<?= url::site("organize/sort_order/__ALBUM_ID__/__COL__/__DIR__?csrf=$csrf") ?>"; +</script> +<div id="gOrganize" class="gDialogPanel"> + <h1 style="display:none"><?= t("Organize %name", array("name" => p::purify($album->title))) ?></h1> + <div id="bd"> + <div class="yui-gf"> + <div class="yui-u first"> + <h3><?= t("Albums") ?></h3> + </div> + <div id="gMessage" class="yui-u"> + <div class="gInfo"><?= t("Drag and drop photos to re-order or move between albums") ?></div> + </div> + </div> + <div id="gOrganizeContentPane" class="yui-gf"> + <div id="gOrganizeTreeContainer" class="yui-u first"> + <ul id="gOrganizeAlbumTree"> + <?= $album_tree ?> + </ul> + </div> + <div id="gOrganizeDetail" class="yui-u"> + <div id="gMicroThumbPanel" + ref="<?= url::site("organize/album/__ITEM_ID__/__OFFSET__") ?>"> + <ul id="gMicroThumbGrid"> + <?= $micro_thumb_grid ?> + </ul> + </div> + <div id="gOrganizeControls"> + <a id="gOrganizeClose" href="#" ref="done" + class="gButtonLink ui-corner-all ui-state-default"><?= t("Close") ?></a> + <form> + <?= t("Sort order") ?> + <?= form::dropdown(array("id" => "gOrganizeSortColumn"), album::get_sort_order_options(), $album->sort_column) ?> + <?= form::dropdown(array("id" => "gOrganizeSortOrder"), array("ASC" => "Ascending", "DESC" => "Descending"), $album->sort_order) ?> + </form> + </div> + </div> + </div> + </div> +</div> + +<script type="text/javascript"> + $("#gOrganize").ready($.organize.init); +</script> diff --git a/modules/organize/views/organize_edit.html.php b/modules/organize/views/organize_edit.html.php deleted file mode 100644 index 1adf290f..00000000 --- a/modules/organize/views/organize_edit.html.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<ul> -<? foreach ($panes as $idx => $pane): ?> - <li><a href="#pane-<?= $idx ?>"><?= $pane["label"] ?></a></li> -<? endforeach?> -</ul> - -<? if (count($panes) > 0): ?> - <? foreach ($panes as $idx => $pane): ?> - <div id="pane-<?= $idx ?>" class="gOrganizeEditPane ui-tabs-hide"><?= $pane["content"] ?></div> - <? endforeach?> -<? else: ?> -<div class="gWarning"><?= t("No Edit pages apply to the selected items") ?></div> -<? endif ?>
\ No newline at end of file diff --git a/modules/organize/views/organize_thumb_grid.html.php b/modules/organize/views/organize_thumb_grid.html.php index c80696ad..31dc9af5 100644 --- a/modules/organize/views/organize_thumb_grid.html.php +++ b/modules/organize/views/organize_thumb_grid.html.php @@ -1,12 +1,22 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<? foreach ($children as $i => $child): ?> -<? $item_class = "gPhoto"; ?> -<? if ($child->is_album()): ?> - <? $item_class = "gAlbum"; ?> -<? endif ?> -<li id="thumb_<?= $child->id ?>" class="gMicroThumbContainer" ref="<?= $child->id ?>"> - <div id="gMicroThumb-<?= $child->id ?>" class="gMicroThumb <?= $item_class ?>"> - <?= $child->thumb_img(array("class" => "gThumbnail"), $thumbsize, true) ?> +<? foreach ($album->children(25, $offset) as $child): ?> +<li class="gMicroThumbGridCell" ref="<?= $child->id ?>"> + <div id="gMicroThumb_<?= $child->id ?>" + class="gMicroThumb <?= $child->is_album() ? "gAlbum" : "gPhoto" ?>"> + <?= $child->thumb_img(array("class" => "gThumbnail", "ref" => $child->id), 90, true) ?> </div> </li> <? endforeach ?> + +<? if ($album->children_count() > $offset): ?> +<script> + setTimeout(function() { + $.get("<?= url::site("organize/content/$album->id/" . ($offset + 25)) ?>", + function(data) { + $("#gMicroThumbGrid").append(data); + $.organize.set_handlers(); + } + ); + }, 50); +</script> +<? endif ?> diff --git a/modules/organize/views/organize_tree.html.php b/modules/organize/views/organize_tree.html.php index d2cdd957..36f900ac 100644 --- a/modules/organize/views/organize_tree.html.php +++ b/modules/organize/views/organize_tree.html.php @@ -1,4 +1,44 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<? foreach ($children as $i => $child): ?> -<? endforeach ?> +<? foreach ($parents as $parent): ?> +<li class="gOrganizeAlbum ui-icon-left <?= access::can("edit", $parent) ? "" : "gViewOnly" ?>" + ref="<?= $parent->id ?>"> + <span class="ui-icon ui-icon-minus"> + </span> + <span class="gAlbumText" ref="<?= $parent->id ?>"> + <?= p::clean($parent->title) ?> + </span> + <ul class="ui-icon-plus"> + <? endforeach ?> + + <? foreach ($peers as $peer): ?> + <li class="gOrganizeAlbum ui-icon-left <?= access::can("edit", $peer) ? "" : "gViewOnly" ?>" + ref="<?= $peer->id ?>"> + <span class="ui-icon <?= $peer->id == $album->id ? "ui-icon-minus" : "ui-icon-plus" ?>"> + </span> + <span class="gAlbumText <?= $peer->id == $album->id ? "selected" : "" ?>" + ref="<?= $peer->id ?>"> + <?= p::clean($peer->title) ?> + </span> + <? if ($peer->id == $album->id): ?> + <ul class="ui-icon-plus"> + <? foreach ($album->children(null, 0, array("type" => "album")) as $child): ?> + <li class="gOrganizeAlbum ui-icon-left <?= access::can("edit", $child) ? "" : "gViewOnly" ?>" + ref="<?= $child->id ?>"> + <span class="ui-icon ui-icon-plus"> + </span> + <span class="gAlbumText" + ref="<?= $child->id ?>"> + <?= p::clean($child->title) ?> + </span> + </li> + <? endforeach ?> + </ul> + <? endif ?> + </li> + <? endforeach ?> + + <? foreach ($parents as $parent): ?> + </ul> +</li> +<? endforeach ?> diff --git a/modules/search/helpers/search_event.php b/modules/search/helpers/search_event.php index b65763af..836bbe15 100644 --- a/modules/search/helpers/search_event.php +++ b/modules/search/helpers/search_event.php @@ -35,9 +35,4 @@ class search_event_Core { static function item_related_update($item) { search::update($item); } - - static function item_related_update_batch($sql) { - $db = Database::instance(); - $db->query("UPDATE {search_records} SET `dirty` = 1 WHERE item_id IN ($sql)"); - } } diff --git a/modules/search/helpers/search_installer.php b/modules/search/helpers/search_installer.php index cd253be4..10d8211f 100644 --- a/modules/search/helpers/search_installer.php +++ b/modules/search/helpers/search_installer.php @@ -28,7 +28,7 @@ class search_installer { PRIMARY KEY (`id`), KEY(`item_id`), FULLTEXT INDEX (`data`)) - ENGINE=MyISAM DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("search", 1); } diff --git a/modules/server_add/controllers/server_add.php b/modules/server_add/controllers/server_add.php index f68392ce..26b3bd08 100644 --- a/modules/server_add/controllers/server_add.php +++ b/modules/server_add/controllers/server_add.php @@ -150,7 +150,8 @@ class Server_Add_Controller extends Admin_Controller { $queue[] = array($child, $entry->id); } else { $ext = strtolower(pathinfo($child, PATHINFO_EXTENSION)); - if (in_array($ext, array("gif", "jpeg", "jpg", "png", "flv", "mp4"))) { + if (in_array($ext, array("gif", "jpeg", "jpg", "png", "flv", "mp4")) && + filesize($child) > 0) { $child_entry = ORM::factory("server_add_file"); $child_entry->task_id = $task->id; $child_entry->file = $child; @@ -219,19 +220,25 @@ class Server_Add_Controller extends Admin_Controller { $album = album::create($parent, $name, $title, null, $owner_id); $entry->item_id = $album->id; } else { - $extension = strtolower(pathinfo($name, PATHINFO_EXTENSION)); - if (in_array($extension, array("gif", "png", "jpg", "jpeg"))) { - $photo = photo::create($parent, $entry->file, $name, $title, null, $owner_id); - $entry->item_id = $photo->id; - } else if (in_array($extension, array("flv", "mp4"))) { - $movie = movie::create($parent, $entry->file, $name, $title, null, $owner_id); - $entry->item_id = $movie->id; - } else { - // This should never happen, because we don't add stuff to the list that we can't - // process. But just in, case.. set this to a non-null value so that we skip this - // entry. + try { + $extension = strtolower(pathinfo($name, PATHINFO_EXTENSION)); + if (in_array($extension, array("gif", "png", "jpg", "jpeg"))) { + $photo = photo::create($parent, $entry->file, $name, $title, null, $owner_id); + $entry->item_id = $photo->id; + } else if (in_array($extension, array("flv", "mp4"))) { + $movie = movie::create($parent, $entry->file, $name, $title, null, $owner_id); + $entry->item_id = $movie->id; + } else { + // This should never happen, because we don't add stuff to the list that we can't + // process. But just in, case.. set this to a non-null value so that we skip this + // entry. + $entry->item_id = 0; + $task->log("Skipping unknown file type: $entry->file"); + } + } catch (Exception $e) { + // This can happen if a photo file is invalid, like a BMP masquerading as a .jpg $entry->item_id = 0; - $task->log("Skipping unknown file type: $entry->file"); + $task->log("Skipping invalid file: $entry->file"); } } diff --git a/modules/server_add/helpers/server_add_event.php b/modules/server_add/helpers/server_add_event.php index b53e72d1..6b21ec2e 100644 --- a/modules/server_add/helpers/server_add_event.php +++ b/modules/server_add/helpers/server_add_event.php @@ -35,30 +35,11 @@ class server_add_event_Core { // turn that into a dropdown if there are two different ways to add things. Do that in a // portable way for now. If we find ourselves duplicating this pattern, we should make an // API method for this. - $server_add = Menu::factory("dialog") - ->id("server_add") - ->label(t("Add from server")) - ->url(url::site("server_add/browse/$item->id")); - $add_photos_item = $menu->get("add_photos_item"); - $add_photos_menu = $menu->get("add_photos_menu"); - - if ($add_photos_item && !$add_photos_menu) { - // Assuming that $add_menu is unset, create add_menu and add our item - $menu->add_after( - "add_photos_item", - Menu::factory("submenu") - ->id("add_photos_menu") - ->label($add_photos_item->label) - ->append(Menu::factory("dialog") - ->id("add_photos_submenu_item") - ->label(t("Simple Uploader")) - ->url($add_photos_item->url)) - ->append($server_add)); - $menu->remove("add_photos_item"); - } else if ($add_photos_menu) { - // Append to the existing sub-menu - $add_photos_menu->append($server_add); - } + $add_menu = $menu->get("add_menu"); + $add_menu->append(Menu::factory("dialog") + ->id("server_add") + ->label(t("Server add")) + ->url(url::site("server_add/browse/$item->id"))); } } } diff --git a/modules/server_add/helpers/server_add_installer.php b/modules/server_add/helpers/server_add_installer.php index cd278eb7..c3c1572d 100644 --- a/modules/server_add/helpers/server_add_installer.php +++ b/modules/server_add/helpers/server_add_installer.php @@ -27,7 +27,7 @@ class server_add_installer { `parent_id` int(9), `task_id` int(9) NOT NULL, PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("server_add", 3); server_add::check_config(); } @@ -40,7 +40,7 @@ class server_add_installer { `task_id` int(9) NOT NULL, `file` varchar(255) NOT NULL, PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("server_add", $version = 2); } diff --git a/modules/server_add/js/server_add.js b/modules/server_add/js/server_add.js index 989555cc..fbd61dcc 100644 --- a/modules/server_add/js/server_add.js +++ b/modules/server_add/js/server_add.js @@ -4,11 +4,9 @@ function select_file(li) { $(li).toggleClass("selected"); if ($("#gServerAdd span.selected").length) { - $("#gServerAddAddButton").enable(true); - $("#gServerAddAddButton").removeClass("ui-state-disabled"); + $("#gServerAddAddButton").enable(true).removeClass("ui-state-disabled"); } else { - $("#gServerAddAddButton").enable(false); - $("#gServerAddAddButton").addClass("ui-state-disabled"); + $("#gServerAddAddButton").enable(false).addClass("ui-state-disabled"); } } @@ -54,7 +52,7 @@ function run_add(url) { $("#gStatus").html(data.status); $("#gServerAdd .gProgressBar").progressbar("value", data.percent_complete); if (data.done) { - $("#gProgress").slideUp(); + $("#gServerAddProgress").slideUp(); } else { setTimeout(function() { run_add(url); }, 0); } diff --git a/modules/server_add/views/server_add_tree_dialog.html.php b/modules/server_add/views/server_add_tree_dialog.html.php index 533cad04..912e69b6 100644 --- a/modules/server_add/views/server_add_tree_dialog.html.php +++ b/modules/server_add/views/server_add_tree_dialog.html.php @@ -23,7 +23,7 @@ <?= $tree ?> </ul> - <div id="gProgress" style="display: none"> + <div id="gServerAddProgress" style="display: none"> <div class="gProgressBar"></div> <div id="gStatus"></div> </div> @@ -34,7 +34,7 @@ <?= t("Add") ?> </button> - <button class="ui-state-default ui-corner-all" onclick="closeDialog(); window.location.reload();"> + <button id="gServerCloseButton" class="ui-state-default ui-corner-all"> <?= t("Close") ?> </button> </span> @@ -46,7 +46,10 @@ $("#gServerAdd .gProgressBar"). progressbar(). progressbar("value", 0); - $("#gProgress").slideDown("fast", function() { start_add() }); + $("#gServerAddProgress").slideDown("fast", function() { start_add() }); + }); + $("#gServerCloseButton").click(function(event) { + $("#gDialog").dialog("close"); }); }); </script> diff --git a/modules/slideshow/helpers/slideshow_event.php b/modules/slideshow/helpers/slideshow_event.php index cf79f71a..1b881de4 100644 --- a/modules/slideshow/helpers/slideshow_event.php +++ b/modules/slideshow/helpers/slideshow_event.php @@ -31,13 +31,17 @@ class slideshow_event_Core { } static function album_menu($menu, $theme) { - $menu - ->append(Menu::factory("link") - ->id("slideshow") - ->label(t("View slideshow")) - ->url("javascript:PicLensLite.start(" . - "{maxScale:0,feedUrl:PicLensLite.indexFeeds()[0].url})") - ->css_id("gSlideshowLink")); + $descendants_count = ORM::factory("item", $theme->item->id) + ->descendants_count(array("type" => "photo")); + if ($descendants_count > 1) { + $menu + ->append(Menu::factory("link") + ->id("slideshow") + ->label(t("View slideshow")) + ->url("javascript:PicLensLite.start(" . + "{maxScale:0,feedUrl:PicLensLite.indexFeeds()[0].url})") + ->css_id("gSlideshowLink")); + } } static function photo_menu($menu, $theme) { diff --git a/modules/tag/helpers/tag_installer.php b/modules/tag/helpers/tag_installer.php index 3c16e3f3..bcb830e4 100644 --- a/modules/tag/helpers/tag_installer.php +++ b/modules/tag/helpers/tag_installer.php @@ -26,7 +26,7 @@ class tag_installer { `count` int(10) unsigned NOT NULL DEFAULT 0, PRIMARY KEY (`id`), UNIQUE KEY(`name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE IF NOT EXISTS {items_tags} ( `id` int(9) NOT NULL auto_increment, @@ -35,7 +35,7 @@ class tag_installer { PRIMARY KEY (`id`), KEY(`tag_id`, `id`), KEY(`item_id`, `id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("tag", 1); } diff --git a/modules/tag/js/tag.js b/modules/tag/js/tag.js index 765c2a35..61ac73f4 100644 --- a/modules/tag/js/tag.js +++ b/modules/tag/js/tag.js @@ -23,7 +23,7 @@ function closeEditInPlaceForms() { $("#gRenameTagForm").parent().html($("#gRenameTagForm").parent().data("revert")); li.height(""); $(".gEditable", li).bind("click", editInPlace); - $(".gDialogLink", li).bind("click", handleDialogEvent); + $(".gDialogLink", li).gallery_dialog(); } } diff --git a/modules/tag/models/tag.php b/modules/tag/models/tag.php index e910a8ee..d9488e1c 100644 --- a/modules/tag/models/tag.php +++ b/modules/tag/models/tag.php @@ -54,4 +54,52 @@ class Tag_Model extends ORM { } return $model->count_all(); } + + /** + * Overload ORM::save() to trigger an item_related_update event for all items that are related + * to this tag. Since items can be added or removed as part of the save, we need to trigger an + * event for the union of all related items before and after the save. + */ + public function save() { + $db = Database::instance(); + $related_item_ids = array(); + foreach ($db->getwhere("items_tags", array("tag_id" => $this->id)) as $row) { + $related_item_ids[$row->item_id] = 1; + } + + $result = parent::save(); + + foreach ($db->getwhere("items_tags", array("tag_id" => $this->id)) as $row) { + $related_item_ids[$row->item_id] = 1; + } + + if ($related_item_ids) { + foreach (ORM::factory("item")->in("id", array_keys($related_item_ids))->find_all() as $item) { + module::event("item_related_update", $item); + } + } + + return $result; + } + + /** + * Overload ORM::delete() to trigger an item_related_update event for all items that are + * related to this tag. + */ + public function delete() { + $related_item_ids = array(); + $db = Database::Instance(); + foreach ($db->getwhere("items_tags", array("tag_id" => $this->id)) as $row) { + $related_item_ids[$row->item_id] = 1; + } + + $result = parent::delete(); + + if ($related_item_ids) { + foreach (ORM::factory("item")->in("id", array_keys($related_item_ids))->find_all() as $item) { + module::event("item_related_update", $item); + } + } + return $result; + } }
\ No newline at end of file diff --git a/modules/user/controllers/password.php b/modules/user/controllers/password.php index 066efbba..a6522369 100644 --- a/modules/user/controllers/password.php +++ b/modules/user/controllers/password.php @@ -29,8 +29,6 @@ class Password_Controller extends Controller { } public function do_reset() { - access::verify_csrf(); - if (request::method() == "post") { $this->_change_password(); } else { diff --git a/modules/user/helpers/user.php b/modules/user/helpers/user.php index 69a6ecb3..40acc2ec 100644 --- a/modules/user/helpers/user.php +++ b/modules/user/helpers/user.php @@ -159,7 +159,12 @@ class user_Core { */ static function active() { // @todo (maybe) cache this object so we're not always doing session lookups. - $user = Session::instance()->get("user", self::guest()); + $user = Session::instance()->get("user", null); + if (!isset($user)) { + // Don't do this as a fallback in the Session::get() call because it can trigger unnecessary + // work. + $user = user::guest(); + } return $user; } diff --git a/modules/user/helpers/user_installer.php b/modules/user/helpers/user_installer.php index 1959d038..8ef4f13d 100644 --- a/modules/user/helpers/user_installer.php +++ b/modules/user/helpers/user_installer.php @@ -36,7 +36,7 @@ class user_installer { PRIMARY KEY (`id`), UNIQUE KEY(`hash`), UNIQUE KEY(`name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE IF NOT EXISTS {groups} ( `id` int(9) NOT NULL auto_increment, @@ -44,14 +44,14 @@ class user_installer { `special` BOOLEAN default 0, PRIMARY KEY (`id`), UNIQUE KEY(`name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE IF NOT EXISTS {groups_users} ( `group_id` int(9) NOT NULL, `user_id` int(9) NOT NULL, PRIMARY KEY (`group_id`, `user_id`), UNIQUE KEY(`user_id`, `group_id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $everybody = group::create("Everybody"); $everybody->special = true; diff --git a/modules/user/helpers/user_theme.php b/modules/user/helpers/user_theme.php index c5351f8e..8de2d248 100644 --- a/modules/user/helpers/user_theme.php +++ b/modules/user/helpers/user_theme.php @@ -19,14 +19,10 @@ */ class user_theme_Core { static function header_top($theme) { - $view = new View("login.html"); - $view->user = user::active(); - return $view->render(); - } - - static function admin_head($theme) { - if (strpos(Router::$current_uri, "admin/users") !== false) { - $theme->script("gallery.panel.js"); + if ($theme->page_type != "login") { + $view = new View("login.html"); + $view->user = user::active(); + return $view->render(); } } } diff --git a/modules/user/models/user.php b/modules/user/models/user.php index 4b43adff..55562f34 100644 --- a/modules/user/models/user.php +++ b/modules/user/models/user.php @@ -25,6 +25,7 @@ class User_Model extends ORM { "full_name" => "length[0,255]", "email" => "valid_email|length[1,255]", "password" => "length[1,40]", + "url" => "valid_url", "locale" => "length[2,10]"); public function __set($column, $value) { diff --git a/modules/user/views/admin_users.html.php b/modules/user/views/admin_users.html.php index 54c4847d..36c4f4fd 100644 --- a/modules/user/views/admin_users.html.php +++ b/modules/user/views/admin_users.html.php @@ -28,7 +28,7 @@ {}, function(data) { $("#group-" + group_id).html(data); - $("#group-" + group_id + " .gDialogLink").bind("click", handleDialogEvent); + $("#group-" + group_id + " .gDialogLink").gallery_dialog(); }); } diff --git a/modules/watermark/helpers/watermark_installer.php b/modules/watermark/helpers/watermark_installer.php index 705b89d4..b3e91044 100644 --- a/modules/watermark/helpers/watermark_installer.php +++ b/modules/watermark/helpers/watermark_installer.php @@ -30,7 +30,7 @@ class watermark_installer { `mime_type` varchar(64) default NULL, PRIMARY KEY (`id`), UNIQUE KEY(`name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); @mkdir(VARPATH . "modules/watermark"); module::set_version("watermark", 1); |