diff --git a/installer/installer.php b/installer/installer.php index 456cffaa..50657d80 100644 --- a/installer/installer.php +++ b/installer/installer.php @@ -104,11 +104,13 @@ class installer { mysql_select_db($config["dbname"]); } - static function verify_version($config) { + static function verify_mysql_version($config) { + return version_compare(installer::mysql_version($config), "5.0.0", ">="); + } + + static function mysql_version($config) { $result = mysql_query("SHOW VARIABLES WHERE variable_name = \"version\""); - $row = mysql_fetch_object($result); - $version = substr($row->Value, 0, strpos($row->Value, "-")); - return version_compare($version, "5.0.0", ">="); + return $row->Value; } static function db_empty($config) { diff --git a/installer/views/invalid_db_version.html.php b/installer/views/invalid_db_version.html.php index 8776ac35..5b021ba2 100644 --- a/installer/views/invalid_db_version.html.php +++ b/installer/views/invalid_db_version.html.php @@ -1,5 +1,5 @@

Uh oh!

- The MySql database that you are referencing is less than the minimum version of 5.0.0. + Gallery requires at least MySQL version 5.0.0. You're using version

diff --git a/installer/web.php b/installer/web.php index aceb5368..eb0211a6 100644 --- a/installer/web.php +++ b/installer/web.php @@ -41,7 +41,7 @@ if (installer::already_installed()) { if (!installer::connect($config)) { $content = render("invalid_db_info.html.php"); - } else if (!installer::verify_version($config)) { + } else if (!installer::verify_mysql_version($config)) { $content = render("invalid_db_version.html.php"); } else if (!installer::select_db($config)) { $content = render("missing_db.html.php"); diff --git a/lib/gallery.common.css b/lib/gallery.common.css new file mode 100644 index 00000000..ca90a484 --- /dev/null +++ b/lib/gallery.common.css @@ -0,0 +1,111 @@ +/* ####### states, interactions, positioning ########### */ + +/* states */ + +.g-active, .g-enabled, .g-available, .g-editable, .g-selected, .g-highlight { + font-weight: bold; +} +.g-inactive, .g-disabled, .g-unavailable, .g-uneditable, .g-locked, .g-unselected, .g-understate { + color: #ccc; + font-weight: normal; +} + +.g-error, .g-denied { + +} +.g-success, .g-allowed { + +} +.g-info { + +} +.g-warning { + +} + +.g-open { + +} +.g-closed { + +} + +.g-installed { + +} +.g-default { + +} + +/* interactions */ + +.g-draggable, .ui-draggable { + cursor: move; +} +.g-target { + +} + + + +/* positioning */ + +.g-right { + float: right; +} +.g-left { + float: left; +} + +/* order */ + +.g-first { + +} +.g-last { + +} +.g-even-row { + +} +.g-odd-row { + +} + +/* text */ + +.g-txt-small { + font-size: .8em; +} +.g-txt-big { + font-size: 1.2em; +} +.g-txt-right { + text-align: right; +} + +/* ####### reusable containers/widgets ########### */ + +.g-dialog { + +} + +.g-button { /* a link styled like a button */ + +} + +.g-progressbar { + +} + +.g-block { + +} + +.g-message-box { + +} + +.g-list-horizontal { + +} diff --git a/lib/gallery.dialog.js b/lib/gallery.dialog.js index 67f3f02d..39c451e3 100644 --- a/lib/gallery.dialog.js +++ b/lib/gallery.dialog.js @@ -76,6 +76,7 @@ var eCancel = '' + MSG_CANCEL + ''; if ($("#gDialog .submit").length) { $("#gDialog .submit").addClass("ui-state-default ui-corner-all"); + $.fn.gallery_hover_init(); $("#gDialog .submit").parent().append(eCancel); $("#gDialog .gCancel").click(function(event) { $("#gDialog").dialog("close"); diff --git a/modules/exif/helpers/exif_task.php b/modules/exif/helpers/exif_task.php index c269b732..7c4c97c4 100644 --- a/modules/exif/helpers/exif_task.php +++ b/modules/exif/helpers/exif_task.php @@ -50,12 +50,18 @@ class exif_task_Core { ->orwhere("exif_records.dirty", 1) ->close_paren() ->find_all() as $item) { + // The query above can take a long time, so start the timer after its done + // to give ourselves a little time to actually process rows. + if (!isset($start)) { + $start = microtime(true); + } + + exif::extract($item); + $completed++; + if (microtime(true) - $start > 1.5) { break; } - - $completed++; - exif::extract($item); } list ($remaining, $total, $percent) = exif::stats(); diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php index a212ef85..40830bc0 100644 --- a/modules/gallery/helpers/gallery_installer.php +++ b/modules/gallery/helpers/gallery_installer.php @@ -223,6 +223,7 @@ class gallery_installer { module::set_var("gallery", "resize_size", 640); module::set_var("gallery", "default_locale", "en_US"); module::set_var("gallery", "image_quality", 75); + module::set_var("gallery", "image_sharpen", 15); // Add rules for generating our thumbnails and resizes graphics::add_rule( @@ -259,7 +260,7 @@ class gallery_installer { module::set_var("gallery", "show_credits", 1); // @todo this string needs to be picked up by l10n_scanner module::set_var("gallery", "credits", "Powered by Gallery %version"); - module::set_version("gallery", 10); + module::set_version("gallery", 11); } static function upgrade($version) { @@ -336,6 +337,12 @@ class gallery_installer { module::set_version("gallery", $version = 10); } + + if ($version == 10) { + module::set_var("gallery", "image_sharpen", 15); + + module::set_version("gallery", $version = 11); + } } static function uninstall() { diff --git a/modules/gallery/helpers/graphics.php b/modules/gallery/helpers/graphics.php index cc37a193..787f8dc3 100644 --- a/modules/gallery/helpers/graphics.php +++ b/modules/gallery/helpers/graphics.php @@ -209,6 +209,7 @@ class graphics_Core { Image::factory($input_file) ->resize($options["width"], $options["height"], $options["master"]) ->quality(module::get_var("gallery", "image_quality")) + ->sharpen(module::get_var("gallery", "image_sharpen")) ->save($output_file); } diff --git a/modules/gallery/js/l10n_client.js b/modules/gallery/js/l10n_client.js index 80fe166b..35986e5a 100644 --- a/modules/gallery/js/l10n_client.js +++ b/modules/gallery/js/l10n_client.js @@ -205,6 +205,19 @@ Gallery.behaviors.l10nClient = function(context) { Gallery.l10nClient.toggle(0); } }); + + // Close the l10n client using an AJAX call and refreshing the page + $('#gCloseL10n').click(function(event) { + $.ajax({ + type: "GET", + url: toggle_l10n_mode_url, + data: "csrf=" + csrf, + success: function() { + window.location.reload(true); + } + }); + event.preventDefault(); + }); // Register keybindings using jQuery hotkeys // TODO: Either remove hotkeys code or add query.hotkeys.js. diff --git a/modules/gallery/libraries/ORM_MPTT.php b/modules/gallery/libraries/ORM_MPTT.php index a7defba9..9b3e1f2b 100644 --- a/modules/gallery/libraries/ORM_MPTT.php +++ b/modules/gallery/libraries/ORM_MPTT.php @@ -212,8 +212,7 @@ class ORM_MPTT_Core extends ORM { * @return ORM_MTPP */ function move_to($target) { - if ($this->left_ptr <= $target->left_ptr && - $this->right_ptr >= $target->right_ptr) { + if ($this->is_descendant($target)) { throw new Exception("@todo INVALID_TARGET can't move item inside itself"); } diff --git a/modules/gallery/module.info b/modules/gallery/module.info index dfb1a7a2..6b9dd1ba 100644 --- a/modules/gallery/module.info +++ b/modules/gallery/module.info @@ -1,3 +1,3 @@ name = "Gallery 3" description = "Gallery core application" -version = 10 +version = 11 diff --git a/modules/gallery/views/admin_maintenance_task.html.php b/modules/gallery/views/admin_maintenance_task.html.php index 0eb0b38c..509e87b5 100644 --- a/modules/gallery/views/admin_maintenance_task.html.php +++ b/modules/gallery/views/admin_maintenance_task.html.php @@ -4,7 +4,7 @@ var animation = null; var delta = 1; animate_progress_bar = function() { - var current_value = Number($(".gProgressBar div").css("width").replace("%", "")); + var current_value = parseInt($(".gProgressBar div").css("width").replace("%", "")); if (target_value > current_value) { // speed up delta = Math.min(delta + 0.04, 3); diff --git a/modules/gallery/views/l10n_client.html.php b/modules/gallery/views/l10n_client.html.php index aca1e654..c68a63c8 100644 --- a/modules/gallery/views/l10n_client.html.php +++ b/modules/gallery/views/l10n_client.html.php @@ -3,7 +3,8 @@
_ - X + for_html_attr() ?>" + href="">X

get('show_all_l10n_messages')): ?> @@ -76,5 +77,7 @@ var MSG_CLOSE_X = for_js() ?>; var l10n_client_data = ; var plural_forms = ; + var toggle_l10n_mode_url = ; + var csrf = ;

diff --git a/modules/organize/controllers/organize.php b/modules/organize/controllers/organize.php index 2b966657..27299e85 100644 --- a/modules/organize/controllers/organize.php +++ b/modules/organize/controllers/organize.php @@ -25,7 +25,7 @@ class Organize_Controller extends Controller { $v = new View("organize_dialog.html"); $v->album = $album; - $v->album_tree = self::_tree($album); + $v->album_tree = self::_expanded_tree(ORM::factory("item", 1), $album); $v->micro_thumb_grid = self::_get_micro_thumb_grid($album, 0); print $v; } @@ -46,11 +46,14 @@ class Organize_Controller extends Controller { $album = ORM::factory("item", $album_id); foreach ($this->input->post("source_ids") as $source_id) { - item::move(ORM::factory("item", $source_id), $album); + $source = ORM::factory("item", $source_id); + if (!$album->is_descendant($source)) { + item::move($source, $album); + } } print json_encode( - array("tree" => self::_tree($album)->__toString(), + array("tree" => self::_expanded_tree(ORM::factory("item", 1), $album)->__toString(), "grid" => self::_get_micro_thumb_grid($album, 0)->__toString())); } @@ -132,17 +135,22 @@ class Organize_Controller extends Controller { return $v; } - private static function _tree($album) { + public function tree($album_id) { + $album = ORM::factory("item", $album_id); + access::required("view", $album); + + print self::_expanded_tree($album); + } + + /** + * Create an HTML representation of the tree from the root down to the selected album. We only + * include albums along the descendant hierarchy that includes the selected album, and the + * immediate child albums. + */ + private static function _expanded_tree($root, $selected_album=null) { $v = new View("organize_tree.html"); - $v->parents = $album->parents(); - $v->album = $album; - - if ($album->id == 1) { - $v->peers = array($album); - } else { - $v->peers = $album->parent()->children(null, 0, array("type" => "album")); - } - + $v->album = $root; + $v->selected = $selected_album; return $v; } } diff --git a/modules/organize/css/organize.css b/modules/organize/css/organize.css index 85168810..4a65d20e 100644 --- a/modules/organize/css/organize.css +++ b/modules/organize/css/organize.css @@ -2,10 +2,6 @@ /******************************************************************* * Dialog wide stylings */ -#gOrganizeDialog { - text-align: left; -} - #gOrganize { overflow: hidden; } @@ -51,7 +47,7 @@ padding-left: 1.2em; } -.gAlbumText:hover { +.gOrganizeAlbumText:hover { border: 1px dashed #999; padding: 1px; } @@ -67,14 +63,14 @@ cursor: pointer; } -.gAlbumText { +.gOrganizeAlbumText { cursor: pointer; width: auto; } /******************************************************************* * Album Panel Styles */ -#gMicroThumbPanel { +#gOrganizeMicroThumbPanel { margin: 0 !important; padding: 0 !important; background-color: #cfdeff; @@ -85,11 +81,11 @@ overflow-y: auto; } -#gMicroThumbGrid { +#gOrganizeMicroThumbGrid { padding: 1em; } -.gMicroThumbGridCell { +.gOrganizeMicroThumbGridCell { float: left; font-size: 0.8em; padding: .5em !important; @@ -98,14 +94,14 @@ border-right: 1px hidden #13A; } -.gMicroThumb { +.gOrganizeMicroThumb { display: block; height: 9em; text-align: center; width: 9em; } -.gMicroThumbGridCell.ui-state-selected { +.gOrganizeMicroThumbGridCell.ui-state-selected { opacity: 1; } @@ -118,11 +114,11 @@ padding: .5em; } -#gMicroThumbPanel #gMicroThumbGrid .gAlbum { +#gOrganizeMicroThumbPanel #gOrganizeMicroThumbGrid .gAlbum { background-color: #e8e8e8; } -#gMicroThumbPanel #gMicroThumbGrid :hover { +#gOrganizeMicroThumbPanel #gOrganizeMicroThumbGrid :hover { opacity: 1; } diff --git a/modules/organize/js/organize.js b/modules/organize/js/organize.js index 04e14a2f..edafae61 100644 --- a/modules/organize/js/organize.js +++ b/modules/organize/js/organize.js @@ -4,7 +4,7 @@ handle: ".ui-state-selected", distance: 10, cursorAt: { left: -10, top: -10}, - appendTo: "#gMicroThumbPanel", + appendTo: "#gOrganizeMicroThumbPanel", helper: function(event, ui) { var selected = $(".ui-draggable.ui-state-selected img"); if (selected.length) { @@ -37,16 +37,16 @@ }, start: function(event, ui) { - $("#gMicroThumbPanel .ui-state-selected").hide(); + $("#gOrganizeMicroThumbPanel .ui-state-selected").hide(); }, drag: function(event, ui) { - var top = $("#gMicroThumbPanel").offset().top; - var height = $("#gMicroThumbPanel").height(); + var top = $("#gOrganizeMicroThumbPanel").offset().top; + var height = $("#gOrganizeMicroThumbPanel").height(); if (ui.offset.top > height + top - 20) { - $("#gMicroThumbPanel").get(0).scrollTop += 100; + $("#gOrganizeMicroThumbPanel").get(0).scrollTop += 100; } else if (ui.offset.top < top + 20) { - $("#gMicroThumbPanel").get(0).scrollTop = Math.max(0, $("#gMicroThumbPanel").get(0).scrollTop - 100); + $("#gOrganizeMicroThumbPanel").get(0).scrollTop = Math.max(0, $("#gOrganizeMicroThumbPanel").get(0).scrollTop - 100); } } }, @@ -74,7 +74,7 @@ drop: function(event, ui) { if ($(event.target).hasClass("gViewOnly")) { $(".ui-state-selected").show(); - $(".gMicroThumbGridCell").css("borderStyle", "none"); + $(".gOrganizeMicroThumbGridCell").css("borderStyle", "none"); } else { $.organize.do_drop({ url: move_url.replace("__ALBUM_ID__", $(event.target).attr("ref")), @@ -85,7 +85,7 @@ }, do_drop: function(options) { - $("#gMicroThumbPanel").selectable("destroy"); + $("#gOrganizeMicroThumbPanel").selectable("destroy"); var source_ids = []; $(options.source).each(function(i) { source_ids.push($(this).attr("ref")); @@ -104,7 +104,7 @@ $("#gOrganizeAlbumTree").html(data.tree); } if (data.grid) { - $("#gMicroThumbGrid").html(data.grid); + $("#gOrganizeMicroThumbGrid").html(data.grid); $("#gOrganizeSortColumn").attr("value", data.sort_column); $("#gOrganizeSortOrder").attr("value", data.sort_order); } @@ -113,7 +113,7 @@ mouse_move_handler: function(event) { if ($(".gDragHelper").length) { - $(".gMicroThumbGridCell").css("borderStyle", "hidden"); + $(".gOrganizeMicroThumbGridCell").css("borderStyle", "hidden"); $(".currentDropTarget").removeClass("currentDropTarget"); var borderStyle = event.pageX < $(this).offset().left + $(this).width() / 2 ? "borderLeftStyle" : "borderRightStyle"; @@ -132,7 +132,7 @@ $("#gDialog").dialog("option", "zIndex", 70); $("#gDialog").bind("dialogopen", function(event, ui) { $("#gOrganize").height($("#gDialog").innerHeight() - 20); - $("#gMicroThumbPanel").height($("#gDialog").innerHeight() - 90); + $("#gOrganizeMicroThumbPanel").height($("#gDialog").innerHeight() - 90); $("#gOrganizeAlbumTree").height($("#gDialog").innerHeight() - 59); }); @@ -152,15 +152,41 @@ }, set_handlers: function() { - $("#gMicroThumbPanel").selectable({filter: ".gMicroThumbGridCell"}); - $("#gMicroThumbPanel").droppable($.organize.content_droppable); + $("#gOrganizeMicroThumbPanel").selectable({filter: ".gOrganizeMicroThumbGridCell"}); + $("#gOrganizeMicroThumbPanel").droppable($.organize.content_droppable); - $(".gMicroThumbGridCell").draggable($.organize.micro_thumb_draggable); - $(".gMicroThumbGridCell").mousemove($.organize.mouse_move_handler); + $(".gOrganizeMicroThumbGridCell").draggable($.organize.micro_thumb_draggable); + $(".gOrganizeMicroThumbGridCell").mousemove($.organize.mouse_move_handler); $(".gOrganizeAlbum").droppable($.organize.branch_droppable); - $(".gAlbumText").click($.organize.show_album); + $(".gOrganizeAlbumText").click($.organize.show_album); + $("#gOrganizeAlbumTree .ui-icon-plus,#gOrganizeAlbumTree .ui-icon-minus").click($.organize.toggle_branch); }, + toggle_branch: function(event) { + event.preventDefault(); + var target = $(event.currentTarget); + var branch = $(target).parent(); + var id = $(event.currentTarget).parent().attr("ref"); + + if ($(target).hasClass("ui-icon-plus")) { + // Expanding + if (!branch.find("ul").length) { + $.get(tree_url.replace("__ALBUM_ID__", id), { }, + function(data) { + branch.replaceWith(data); + $.organize.set_handlers(); + } + ); + } else { + branch.find("ul:eq(0)").slideDown(); + } + } else { + // Contracting + branch.find("ul:eq(0)").slideUp(); + } + $(target).toggleClass("ui-icon-plus"); + $(target).toggleClass("ui-icon-minus"); + }, /** * When the text of a selection is clicked, then show that albums contents @@ -174,14 +200,14 @@ if ($(parent).hasClass("gViewOnly")) { return; } - $("#gMicroThumbPanel").selectable("destroy"); + $("#gOrganizeMicroThumbPanel").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); + $(".gOrganizeAlbumText[ref=" + id + "]").addClass("selected"); + var url = $("#gOrganizeMicroThumbPanel").attr("ref").replace("__ITEM_ID__", id).replace("__OFFSET__", 0); $.get(url, {}, function(data) { - $("#gMicroThumbGrid").html(data.grid); + $("#gOrganizeMicroThumbGrid").html(data.grid); $("#gOrganizeSortColumn").attr("value", data.sort_column); $("#gOrganizeSortOrder").attr("value", data.sort_order); $.organize.set_handlers(); @@ -199,7 +225,7 @@ .replace("__DIR__", dir); $.get(url, {}, function(data) { - $("#gMicroThumbGrid").html(data.grid); + $("#gOrganizeMicroThumbGrid").html(data.grid); $("#gOrganizeSortColumn").attr("value", data.sort_column); $("#gOrganizeSortOrder").attr("value", data.sort_order); $.organize.set_handlers(); diff --git a/modules/organize/views/organize_dialog.html.php b/modules/organize/views/organize_dialog.html.php index 857499aa..cbc2e4f9 100644 --- a/modules/organize/views/organize_dialog.html.php +++ b/modules/organize/views/organize_dialog.html.php @@ -3,6 +3,7 @@ var move_url = ""; var rearrange_url = ""; var sort_order_url = ""; + var tree_url = "";

html::purify($album->title))) ?>

@@ -22,9 +23,9 @@
-
"> -
    +
diff --git a/modules/organize/views/organize_thumb_grid.html.php b/modules/organize/views/organize_thumb_grid.html.php index 31dc9af5..929d9ec3 100644 --- a/modules/organize/views/organize_thumb_grid.html.php +++ b/modules/organize/views/organize_thumb_grid.html.php @@ -1,8 +1,8 @@ children(25, $offset) as $child): ?> -
  • -
    "> +
  • +
    "> thumb_img(array("class" => "gThumbnail", "ref" => $child->id), 90, true) ?>
  • @@ -13,7 +13,7 @@ setTimeout(function() { $.get("id/" . ($offset + 25)) ?>", function(data) { - $("#gMicroThumbGrid").append(data); + $("#gOrganizeMicroThumbGrid").append(data); $.organize.set_handlers(); } ); diff --git a/modules/organize/views/organize_tree.html.php b/modules/organize/views/organize_tree.html.php index 5b676889..50c202b0 100644 --- a/modules/organize/views/organize_tree.html.php +++ b/modules/organize/views/organize_tree.html.php @@ -1,44 +1,29 @@ - -
  • " - ref="id ?>"> +
  • " + ref="id ?>"> - - title) ?> + + " + ref="id ?>"> + title) ?> -
      - - - -
    • " - ref="id ?>"> - "> +
        + children(null, 0, array("type" => "album")) as $child): ?> + is_descendant($selected)): ?> + $selected, "album" => $child)); ?> + +
      • " + ref="id ?>"> + - " - ref="id ?>"> - title) ?> + + title) ?> - - id == $album->id): ?> -
          - children(null, 0, array("type" => "album")) as $child): ?> -
        • " - ref="id ?>"> - - - - title) ?> - -
        • - -
        -
      • + - -
    • - + diff --git a/modules/search/helpers/search_task.php b/modules/search/helpers/search_task.php index 5643573a..9508f420 100644 --- a/modules/search/helpers/search_task.php +++ b/modules/search/helpers/search_task.php @@ -48,12 +48,18 @@ class search_task_Core { ->where("search_records.item_id", null) ->orwhere("search_records.dirty", 1) ->find_all() as $item) { - if (microtime(true) - $start > 1.5) { - break; + // The query above can take a long time, so start the timer after its done + // to give ourselves a little time to actually process rows. + if (!isset($start)) { + $start = microtime(true); } search::update($item); $completed++; + + if (microtime(true) - $start > 1.5) { + break; + } } list ($remaining, $total, $percent) = search::stats(); diff --git a/modules/server_add/helpers/server_add_event.php b/modules/server_add/helpers/server_add_event.php index b2d55153..b9dd8c28 100644 --- a/modules/server_add/helpers/server_add_event.php +++ b/modules/server_add/helpers/server_add_event.php @@ -31,15 +31,11 @@ class server_add_event_Core { $paths = unserialize(module::get_var("server_add", "authorized_paths")); if ($item && user::active()->admin && $item->is_album() && !empty($paths)) { - // This is a little tricky. Normally there's an "Add Photo" menu option, but we want to - // 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. - $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"))); + $menu->get("add_menu") + ->append(Menu::factory("dialog") + ->id("server_add") + ->label(t("Server add")) + ->url(url::site("server_add/browse/$item->id"))); } } } diff --git a/themes/default/css/screen.css b/themes/default/css/screen.css index 82cdb331..5eb30bde 100644 --- a/themes/default/css/screen.css +++ b/themes/default/css/screen.css @@ -308,7 +308,7 @@ li.gError select { .gError { background-color: #f6cbca; - color: #fc0; + color: #f00; background-image: url('../images/ico-error.png'); }