diff options
| author | root <root@sleepydogs.net> | 2009-09-13 09:01:55 -0700 |
|---|---|---|
| committer | root <root@sleepydogs.net> | 2009-09-13 09:01:55 -0700 |
| commit | c62d1f440f077ba806b7ff0c6b90ef89c79b2fd3 (patch) | |
| tree | b64f05e2a7bd8db7200e3c407904e255826b4cf2 /modules/tag | |
| parent | b96ac1eb81b7ccd5bd050ffab0ca9ce1feec8f4f (diff) | |
| parent | caa2002d7777e0ceb884d4c628650804620ca2b6 (diff) | |
Merge branch 'master' of git://github.com/gallery/gallery3
Diffstat (limited to 'modules/tag')
| -rw-r--r-- | modules/tag/controllers/admin_tags.php | 8 | ||||
| -rw-r--r-- | modules/tag/controllers/tags.php | 19 | ||||
| -rw-r--r-- | modules/tag/helpers/tag.php | 40 | ||||
| -rw-r--r-- | modules/tag/helpers/tag_event.php | 48 | ||||
| -rw-r--r-- | modules/tag/helpers/tag_installer.php | 4 | ||||
| -rw-r--r-- | modules/tag/helpers/tag_menu.php | 28 | ||||
| -rw-r--r-- | modules/tag/helpers/tag_rss.php | 3 | ||||
| -rw-r--r-- | modules/tag/helpers/tag_theme.php | 6 | ||||
| -rw-r--r-- | modules/tag/js/tag.js | 15 | ||||
| -rw-r--r-- | modules/tag/models/tag.php | 58 | ||||
| -rw-r--r-- | modules/tag/views/admin_tags.html.php | 14 | ||||
| -rw-r--r-- | modules/tag/views/tag_block.html.php | 14 | ||||
| -rw-r--r-- | modules/tag/views/tag_cloud.html.php | 2 |
13 files changed, 194 insertions, 65 deletions
diff --git a/modules/tag/controllers/admin_tags.php b/modules/tag/controllers/admin_tags.php index dcdc16b9..8b8dde21 100644 --- a/modules/tag/controllers/admin_tags.php +++ b/modules/tag/controllers/admin_tags.php @@ -53,8 +53,8 @@ class Admin_Tags_Controller extends Admin_Controller { $name = $tag->name; Database::instance()->delete("items_tags", array("tag_id" => "$tag->id")); $tag->delete(); - message::success(t("Deleted tag %tag_name", array("tag_name" => p::clean($name)))); - log::success("tags", t("Deleted tag %tag_name", array("tag_name" => p::clean($name)))); + message::success(t("Deleted tag %tag_name", array("tag_name" => $name))); + log::success("tags", t("Deleted tag %tag_name", array("tag_name" => $name))); print json_encode( array("result" => "success", @@ -98,7 +98,7 @@ class Admin_Tags_Controller extends Admin_Controller { $tag->save(); $message = t("Renamed tag %old_name to %new_name", - array("old_name" => p::clean($old_name), "new_name" => p::clean($tag->name))); + array("old_name" => $old_name, "new_name" => $tag->name)); message::success($message); log::success("tags", $message); @@ -106,7 +106,7 @@ class Admin_Tags_Controller extends Admin_Controller { array("result" => "success", "location" => url::site("admin/tags"), "tag_id" => $tag->id, - "new_tagname" => p::clean($tag->name))); + "new_tagname" => html::clean($tag->name))); } else { print json_encode( array("result" => "error", diff --git a/modules/tag/controllers/tags.php b/modules/tag/controllers/tags.php index 85f6d16e..c993e374 100644 --- a/modules/tag/controllers/tags.php +++ b/modules/tag/controllers/tags.php @@ -53,7 +53,7 @@ class Tags_Controller extends REST_Controller { $form = tag::get_add_form($item); if ($form->validate()) { - foreach (split("[\,\ \;]", $form->add_tag->inputs["name"]->value) as $tag_name) { + foreach (split(",", $form->add_tag->inputs["name"]->value) as $tag_name) { $tag_name = trim($tag_name); if ($tag_name) { $tag = tag::add($item, $tag_name); @@ -78,4 +78,21 @@ class Tags_Controller extends REST_Controller { return tag::get_add_form($item); } + + public function autocomplete() { + $tags = array(); + $tag_parts = preg_split("#,#", $this->input->get("q")); + $limit = $this->input->get("limit"); + $tag_part = end($tag_parts); + $tag_list = ORM::factory("tag") + ->like("name", "{$tag_part}%", false) + ->orderby("name", "ASC") + ->limit($limit) + ->find_all(); + foreach ($tag_list as $tag) { + $tags[] = $tag->name; + } + + print implode("\n", $tags); + } } diff --git a/modules/tag/helpers/tag.php b/modules/tag/helpers/tag.php index 7c4b56ba..be5461a4 100644 --- a/modules/tag/helpers/tag.php +++ b/modules/tag/helpers/tag.php @@ -79,6 +79,24 @@ class tag_Core { } } + + /** + * Return all the tags for a given item. + * @return array + */ + static function item_tags($item) { + $tags = array(); + foreach (Database::instance() + ->select("name") + ->from("tags") + ->join("items_tags", "tags.id", "items_tags.tag_id", "left") + ->where("items_tags.item_id", $item->id) + ->get() as $row) { + $tags[] = $row->name; + } + return $tags; + } + static function get_add_form($item) { $form = new Forge("tags", "", "post", array("id" => "gAddTagForm")); $label = $item->is_album() ? @@ -86,7 +104,7 @@ class tag_Core { ($item->is_photo() ? t("Add tag to photo") : t("Add tag to movie")); $group = $form->group("add_tag")->label("Add Tag"); - $group->input("name")->label($label)->rules("required|length[1,64]"); + $group->input("name")->label($label)->rules("required"); $group->hidden("item_id")->value($item->id); $group->submit("")->value(t("Add Tag")); return $form; @@ -108,4 +126,24 @@ class tag_Core { $group->submit("")->value(t("Delete Tag")); return $form; } + + /** + * Delete all tags associated with an item + */ + static function clear_all($item) { + $db = Database::instance(); + $db->query("UPDATE {tags} SET `count` = `count` - 1 WHERE `count` > 0 " . + "AND `id` IN (SELECT `tag_id` from {items_tags} WHERE `item_id` = $item->id)"); + $db->delete("items_tags", array("item_id" => "$item->id")); + } + + /** + * Get rid of any tags that have no associated items. + */ + static function compact() { + // @todo There's a potential race condition here which we can solve by adding a lock around + // this and all the cases where we create/update tags. I'm loathe to do that since it's an + // extremely rare case. + Database::instance() ->delete("tags", array("count" => 0)); + } }
\ No newline at end of file diff --git a/modules/tag/helpers/tag_event.php b/modules/tag/helpers/tag_event.php index 7a170bf8..57986e40 100644 --- a/modules/tag/helpers/tag_event.php +++ b/modules/tag/helpers/tag_event.php @@ -34,8 +34,8 @@ class tag_event_Core { if (!empty($iptc["2#025"])) { foreach($iptc["2#025"] as $tag) { $tag = str_replace("\0", "", $tag); - foreach (preg_split("/[,;]/", $tag) as $word) { - $word = preg_replace('/\s+/', '.', trim($word)); + foreach (preg_split("/,/", $tag) as $word) { + $word = trim($word); if (function_exists("mb_detect_encoding") && mb_detect_encoding($word) != "UTF-8") { $word = utf8_encode($word); } @@ -59,12 +59,42 @@ class tag_event_Core { return; } - static function item_before_delete($item) { - $db = Database::instance(); - $db->query("UPDATE {tags} SET `count` = `count` - 1 WHERE `count` > 0 " . - "AND `id` IN (SELECT `tag_id` from {items_tags} WHERE `item_id` = $item->id)"); - $db->query("DELETE FROM {tags} WHERE `count` = 0 AND `id` IN (" . - "SELECT `tag_id` from {items_tags} WHERE `item_id` = $item->id)"); - $db->delete("items_tags", array("item_id" => "$item->id")); + static function item_deleted($item) { + tag::clear_all($item); + tag::compact(); + } + + static function item_edit_form($item, $form) { + $url = url::site("tags/autocomplete"); + $form->script("") + ->text("$('form input[id=tags]').ready(function() { + $('form input[id=tags]').autocomplete( + '$url', {max: 30, multiple: true, multipleSeparator: ',', cacheLength: 1}); + });"); + $tag_value = implode(", ", tag::item_tags($item)); + $form->edit_item->input("tags")->label(t("Tags (comma separated)")) + ->value($tag_value); + } + + static function item_edit_form_completed($item, $form) { + tag::clear_all($item); + foreach (preg_split("/,/", $form->edit_item->tags->value) as $tag_name) { + if ($tag_name) { + tag::add($item, trim($tag_name)); + } + } + tag::compact(); + } + + static function admin_menu($menu, $theme) { + $menu->get("content_menu") + ->append(Menu::factory("link") + ->id("tags") + ->label(t("Tags")) + ->url(url::site("admin/tags"))); + } + + static function item_index_data($item, $data) { + $data[] = join(" ", tag::item_tags($item)); } } 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/helpers/tag_menu.php b/modules/tag/helpers/tag_menu.php deleted file mode 100644 index e1b61a93..00000000 --- a/modules/tag/helpers/tag_menu.php +++ /dev/null @@ -1,28 +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 tag_menu_Core { - static function admin($menu, $theme) { - $menu->get("content_menu") - ->append(Menu::factory("link") - ->id("tags") - ->label(t("Tags")) - ->url(url::site("admin/tags"))); - } -} diff --git a/modules/tag/helpers/tag_rss.php b/modules/tag/helpers/tag_rss.php index f94508cf..de5d6c72 100644 --- a/modules/tag/helpers/tag_rss.php +++ b/modules/tag/helpers/tag_rss.php @@ -22,7 +22,7 @@ class tag_rss_Core { static function available_feeds($item, $tag) { if ($tag) { $feeds["tag/tag/{$tag->id}"] = - t("Tag feed for %tag_name", array("tag_name" => p::clean($tag->name))); + t("Tag feed for %tag_name", array("tag_name" => $tag->name)); return $feeds; } return array(); @@ -37,7 +37,6 @@ class tag_rss_Core { $feed->children = $tag->items($limit, $offset, "photo"); $feed->max_pages = ceil($tag->count / $limit); $feed->title = $tag->name; - $feed->link = url::abs_site("tags/{$tag->id}"); $feed->description = t("Photos related to %tag_name", array("tag_name" => $tag->name)); return $feed; diff --git a/modules/tag/helpers/tag_theme.php b/modules/tag/helpers/tag_theme.php index fe30354f..1bce9bd8 100644 --- a/modules/tag/helpers/tag_theme.php +++ b/modules/tag/helpers/tag_theme.php @@ -19,11 +19,13 @@ */ class tag_theme_Core { static function head($theme) { - $theme->script("modules/tag/js/tag.js"); + $theme->css("jquery.autocomplete.css"); + $theme->script("jquery.autocomplete.js"); + $theme->script("tag.js"); } static function admin_head($theme) { - $theme->script("modules/tag/js/tag.js"); + $theme->script("tag.js"); } static function sidebar_blocks($theme) { diff --git a/modules/tag/js/tag.js b/modules/tag/js/tag.js index a1eaeecd..aaae9e72 100644 --- a/modules/tag/js/tag.js +++ b/modules/tag/js/tag.js @@ -7,7 +7,7 @@ function ajaxify_tag_form() { dataType: "json", success: function(data) { if (data.result == "success") { - $.get($("#gTagCloud").attr("src"), function(data, textStatus) { + $.get($("#gTagCloud").attr("title"), function(data, textStatus) { $("#gTagCloud").html(data); }); } @@ -23,22 +23,28 @@ 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(); } } +function str_replace(search_term, replacement, string) { + var temp = string.split(search_term); + return temp.join(replacement); +} + function editInPlace(element) { closeEditInPlaceForms(); // create edit form var tag_id = $(this).attr('id').substr(5); - var tag_name = $(this).text(); + var tag_name = $(this).html(); var tag_width = $(this).width(); $(this).parent().data("revert", $(this).parent().html()); var form = '<form id="gRenameTagForm" method="post" class="ui-helper-clearfix" '; form += 'action="' + TAG_RENAME_URL.replace('__ID__', tag_id) + '">'; form += '<input name="csrf" type="hidden" value="' + csrf_token + '" />'; - form += '<input id="name" name="name" type="text" class="textbox" value="' + tag_name + '" />'; + form += '<input id="name" name="name" type="text" class="textbox" value="' + + str_replace('"', """, tag_name) + '" />'; form += '<input type="submit" class="submit ui-state-default ui-corner-all" value="' + save_i18n + '" i/>'; form += '<a href="#">' + cancel_i18n + '</a>'; form += '</form>'; @@ -66,3 +72,4 @@ function editInPlace(element) { }; ajaxify_editInPlaceForm(); } + diff --git a/modules/tag/models/tag.php b/modules/tag/models/tag.php index 7a85dbab..d9488e1c 100644 --- a/modules/tag/models/tag.php +++ b/modules/tag/models/tag.php @@ -44,10 +44,62 @@ class Tag_Model extends ORM { * @return integer */ public function items_count($type=null) { - return ORM::factory("item") + $model = ORM::factory("item") ->viewable() ->join("items_tags", "items.id", "items_tags.item_id") - ->where("items_tags.tag_id", $this->id) - ->count_all(); + ->where("items_tags.tag_id", $this->id); + + if ($type) { + $model->where("items.type", $type); + } + 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/tag/views/admin_tags.html.php b/modules/tag/views/admin_tags.html.php index 7d201da7..8f3693aa 100644 --- a/modules/tag/views/admin_tags.html.php +++ b/modules/tag/views/admin_tags.html.php @@ -1,9 +1,9 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <script> - var TAG_RENAME_URL = "<?= url::site("admin/tags/rename/__ID__") ?>"; + var TAG_RENAME_URL = <?= html::js_string(url::site("admin/tags/rename/__ID__")) ?>; $("document").ready(function() { // using JS for adding link titles to avoid running t() for each tag - $("#gTagAdmin .tag-name").attr("title", "<?= t("Click to edit this tag") ?>"); + $("#gTagAdmin .tag-name").attr("title", <?= t("Click to edit this tag")->for_js() ?>); $("#gTagAdmin .delete-link").attr("title", $(".delete-link:first span").html()); // In-place editing for tag admin @@ -11,8 +11,8 @@ }); // make some values available within tag.js var csrf_token = "<?= $csrf ?>"; - var save_i18n = '<?= t("save") ?>'; - var cancel_i18n = '<?= t("cancel") ?>'; + var save_i18n = <?= html::js_string(t("save")->for_html_attr()) ?>; + var cancel_i18n = <?= html::js_string(t("cancel")->for_html_attr()) ?>; </script> <div class="gBlock"> <h2> @@ -32,7 +32,7 @@ <? $current_letter = strtoupper(mb_substr($tag->name, 0, 1)) ?> <? if ($i == 0): /* first letter */ ?> - <strong><?= $current_letter ?></strong> + <strong><?= html::clean($current_letter) ?></strong> <ul> <? elseif ($last_letter != $current_letter): /* new letter */ ?> <? if ($column_tag_count > $tags_per_column): /* new column */ ?> @@ -42,12 +42,12 @@ <? endif ?> </ul> - <strong><?= $current_letter ?></strong> + <strong><?= html::clean($current_letter) ?></strong> <ul> <? endif ?> <li> - <span id="gTag-<?= $tag->id ?>" class="gEditable tag-name"><?= p::clean($tag->name) ?></span> + <span id="gTag-<?= $tag->id ?>" class="gEditable tag-name"><?= html::clean($tag->name) ?></span> <span class="understate">(<?= $tag->count ?>)</span> <a href="<?= url::site("admin/tags/form_delete/$tag->id") ?>" class="gDialogLink delete-link gButtonLink"> diff --git a/modules/tag/views/tag_block.html.php b/modules/tag/views/tag_block.html.php index 9c8f3de5..59a4ef88 100644 --- a/modules/tag/views/tag_block.html.php +++ b/modules/tag/views/tag_block.html.php @@ -1,5 +1,17 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<div id="gTagCloud" src="<?= url::site("tags") ?>"> +<script> + $("#gAddTagForm").ready(function() { + var url = $("#gTagCloud").attr("title") + "/autocomplete"; + $("#gAddTagForm input:text").autocomplete( + url, { + max: 30, + multiple: true, + multipleSeparator: ',', + cacheLength: 1} + ); + }); +</script> +<div id="gTagCloud" title="<?= url::site("tags") ?>"> <?= $cloud ?> </div> <?= $form ?>
\ No newline at end of file diff --git a/modules/tag/views/tag_cloud.html.php b/modules/tag/views/tag_cloud.html.php index eba615fc..d6a0b5f8 100644 --- a/modules/tag/views/tag_cloud.html.php +++ b/modules/tag/views/tag_cloud.html.php @@ -3,7 +3,7 @@ <? foreach ($tags as $tag): ?> <li class="size<?=(int)(($tag->count / $max_count) * 7) ?>"> <span><?= $tag->count ?> photos are tagged with </span> - <a href="<?= url::site("tags/$tag->id") ?>"><?= p::clean($tag->name) ?></a> + <a href="<?= url::site("tags/$tag->id") ?>"><?= html::clean($tag->name) ?></a> </li> <? endforeach ?> </ul> |
