summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorAndy Staudacher <andy.st@gmail.com>2009-08-29 14:17:48 -0700
committerAndy Staudacher <andy.st@gmail.com>2009-08-29 14:17:48 -0700
commita5dfc81a8f7bef0305b62254252de6df23684199 (patch)
tree4851cb68abede6920208871449dedd2e939c1a16 /modules
parentd5660d2d3ea6e8172272f1eb27e8071a1a42d87b (diff)
parenta9fcec755a835e284465bafcc9aba9ec9c2f0f62 (diff)
Merge commit 'upstream/master'
Conflicts: modules/akismet/views/admin_akismet.html.php modules/comment/helpers/comment_rss.php modules/gallery/helpers/gallery_rss.php modules/gallery/libraries/I18n.php modules/gallery/views/permissions_browse.html.php modules/gallery/views/simple_uploader.html.php modules/info/views/info_block.html.php modules/organize/controllers/organize.php modules/organize/views/organize.html.php modules/organize/views/organize_album.html.php themes/default/views/album.html.php themes/default/views/movie.html.php themes/default/views/photo.html.php
Diffstat (limited to 'modules')
-rw-r--r--modules/akismet/views/admin_akismet.html.php6
-rw-r--r--modules/comment/helpers/comment.php2
-rw-r--r--modules/comment/helpers/comment_installer.php15
-rw-r--r--modules/comment/helpers/comment_rss.php51
-rw-r--r--modules/comment/helpers/comment_theme.php2
-rw-r--r--modules/comment/js/comment.js10
-rw-r--r--modules/comment/models/comment.php10
-rw-r--r--modules/comment/tests/Comment_Model_Test.php40
-rw-r--r--modules/comment/views/admin_comments.html.php2
-rw-r--r--modules/comment/views/comments.html.php10
-rw-r--r--modules/digibug/helpers/digibug_event.php26
-rw-r--r--modules/digibug/helpers/digibug_installer.php2
-rw-r--r--modules/exif/helpers/exif_installer.php2
-rw-r--r--modules/g2_import/helpers/g2_import_installer.php2
-rw-r--r--modules/gallery/controllers/admin_graphics.php39
-rw-r--r--modules/gallery/controllers/admin_languages.php52
-rw-r--r--modules/gallery/controllers/combined.php9
-rw-r--r--modules/gallery/controllers/file_proxy.php2
-rw-r--r--modules/gallery/controllers/l10n_client.php13
-rw-r--r--modules/gallery/controllers/packager.php4
-rw-r--r--modules/gallery/controllers/quick.php14
-rw-r--r--modules/gallery/controllers/simple_uploader.php2
-rw-r--r--modules/gallery/css/l10n_client.css12
-rw-r--r--modules/gallery/css/quick.css52
-rw-r--r--modules/gallery/helpers/album.php23
-rw-r--r--modules/gallery/helpers/gallery.php179
-rw-r--r--modules/gallery/helpers/gallery_installer.php32
-rw-r--r--modules/gallery/helpers/gallery_quick.php152
-rw-r--r--modules/gallery/helpers/gallery_rss.php5
-rw-r--r--modules/gallery/helpers/gallery_theme.php32
-rw-r--r--modules/gallery/helpers/graphics.php92
-rw-r--r--modules/gallery/helpers/item.php53
-rw-r--r--modules/gallery/helpers/module.php8
-rw-r--r--modules/gallery/helpers/photo.php8
-rw-r--r--modules/gallery/helpers/task.php1
-rw-r--r--modules/gallery/js/l10n_client.js7
-rw-r--r--modules/gallery/js/quick.js78
-rw-r--r--modules/gallery/libraries/I18n.php9
-rw-r--r--modules/gallery/libraries/Menu.php38
-rw-r--r--modules/gallery/libraries/ORM_MPTT.php65
-rw-r--r--modules/gallery/libraries/Sendmail.php4
-rw-r--r--modules/gallery/libraries/Theme_View.php9
-rw-r--r--modules/gallery/models/item.php71
-rw-r--r--modules/gallery/tests/Item_Helper_Test.php49
-rw-r--r--modules/gallery/tests/Item_Model_Test.php14
-rw-r--r--modules/gallery/tests/ORM_MPTT_Test.php8
-rw-r--r--modules/gallery/views/admin_graphics.html.php14
-rw-r--r--modules/gallery/views/admin_graphics_gd.html.php23
-rw-r--r--modules/gallery/views/admin_graphics_graphicsmagick.html.php18
-rw-r--r--modules/gallery/views/admin_graphics_imagemagick.html.php20
-rw-r--r--modules/gallery/views/admin_graphics_none.html.php7
-rw-r--r--modules/gallery/views/admin_languages.html.php103
-rw-r--r--modules/gallery/views/admin_maintenance.html.php16
-rw-r--r--modules/gallery/views/admin_modules.html.php2
-rw-r--r--modules/gallery/views/after_install.html.php2
-rw-r--r--modules/gallery/views/after_install_loader.html.php2
-rw-r--r--modules/gallery/views/l10n_client.html.php5
-rw-r--r--modules/gallery/views/permissions_browse.html.php42
-rw-r--r--modules/gallery/views/quick_pane.html.php26
-rw-r--r--modules/gallery/views/simple_uploader.html.php2
-rw-r--r--modules/info/views/info_block.html.php4
-rw-r--r--modules/notification/helpers/notification.php2
-rw-r--r--modules/notification/helpers/notification_event.php72
-rw-r--r--modules/notification/helpers/notification_installer.php4
-rw-r--r--modules/organize/controllers/organize.php560
-rw-r--r--modules/organize/css/organize.css268
-rw-r--r--modules/organize/helpers/organize.php94
-rw-r--r--modules/organize/helpers/organize_event.php4
-rw-r--r--modules/organize/helpers/organize_task.php131
-rw-r--r--modules/organize/helpers/organize_theme.php13
-rw-r--r--modules/organize/js/organize.js789
-rw-r--r--modules/organize/js/organize_init.js29
-rw-r--r--modules/organize/views/organize.html.php53
-rw-r--r--modules/organize/views/organize_album.html.php17
-rw-r--r--modules/organize/views/organize_button_pane.html.php50
-rw-r--r--modules/organize/views/organize_dialog.html.php47
-rw-r--r--modules/organize/views/organize_edit.html.php14
-rw-r--r--modules/organize/views/organize_thumb_grid.html.php26
-rw-r--r--modules/organize/views/organize_tree.html.php44
-rw-r--r--modules/search/helpers/search_event.php5
-rw-r--r--modules/search/helpers/search_installer.php2
-rw-r--r--modules/server_add/controllers/server_add.php33
-rw-r--r--modules/server_add/helpers/server_add_event.php29
-rw-r--r--modules/server_add/helpers/server_add_installer.php4
-rw-r--r--modules/server_add/js/server_add.js8
-rw-r--r--modules/server_add/views/server_add_tree_dialog.html.php9
-rw-r--r--modules/slideshow/helpers/slideshow_event.php18
-rw-r--r--modules/tag/helpers/tag_installer.php4
-rw-r--r--modules/tag/js/tag.js2
-rw-r--r--modules/tag/models/tag.php48
-rw-r--r--modules/user/controllers/password.php2
-rw-r--r--modules/user/helpers/user.php7
-rw-r--r--modules/user/helpers/user_installer.php6
-rw-r--r--modules/user/helpers/user_theme.php12
-rw-r--r--modules/user/models/user.php1
-rw-r--r--modules/user/views/admin_users.html.php2
-rw-r--r--modules/watermark/helpers/watermark_installer.php2
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&deg; 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&deg; 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__&amp;height=__HEIGHT__&amp;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);