id}") */ static function add($item, $tag_name) { if (empty($tag_name)) { throw new exception("@todo MISSING_TAG_NAME"); } $tag = ORM::factory("tag")->where("name", "=", $tag_name)->find(); if (!$tag->loaded()) { $tag->name = $tag_name; } $tag->add($item); return $tag->save(); } /** * Return the N most popular tags. * * @return ORM_Iterator of Tag_Model in descending tag count order */ static function popular_tags($count) { $count = max($count, 1); return ORM::factory("tag") ->order_by("count", "DESC") ->limit($count) ->find_all(); } /** * Return a rendering of the cloud for the N most popular tags. * * @param integer $count the number of tags * @return View */ static function cloud($count) { $tags = tag::popular_tags($count)->as_array(); if ($tags) { $cloud = new View("tag_cloud.html"); $cloud->max_count = $tags[0]->count; if (!$cloud->max_count) { return; } usort($tags, array("tag", "sort_by_name")); $cloud->tags = $tags; return $cloud; } } static function sort_by_name($tag1, $tag2) { return strcasecmp($tag1->name, $tag2->name); } /** * Return all the tags for a given item. * @return array */ static function item_tags($item) { return ORM::factory("tag") ->join("items_tags", "tags.id", "items_tags.tag_id", "left") ->where("items_tags.item_id", "=", $item->id) ->find_all(); } static function get_add_form($item) { $form = new Forge("tags/create/{$item->id}", "", "post", array("id" => "g-add-tag-form", "class" => "g-short-form")); $label = $item->is_album() ? t("Add tag to album") : ($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")->id("name"); $group->hidden("item_id")->value($item->id); $group->submit("")->value(t("Add Tag")); return $form; } static function get_delete_form($tag) { $form = new Forge("admin/tags/delete/$tag->id", "", "post", array("id" => "g-delete-tag-form")); $group = $form->group("delete_tag") ->label(t("Really delete tag %tag_name?", array("tag_name" => $tag->name))); $group->submit("")->value(t("Delete Tag")); return $form; } /** * Delete all tags associated with an item */ static function clear_all($item) { db::build() ->update("tags") ->set("count", db::expr("`count` - 1")) ->where("count", ">", 0) ->where("id", "IN", db::build()->select("tag_id")->from("items_tags")->where("item_id", "=", $item->id)) ->execute(); db::build() ->delete("items_tags") ->where("item_id", "=", $item->id) ->execute(); } /** * 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. db::build()->delete("tags")->where("count", "=", 0)->execute(); } /** * Find the position of the given item in the tag collection. The resulting * value is 1-indexed, so the first child in the album is at position 1. * * @param Tag_Model $tag * @param Item_Model $item * @param array $where an array of arrays, each compatible with ORM::where() */ static function get_position($tag, $item, $where=array()) { return ORM::factory("item") ->viewable() ->join("items_tags", "items.id", "items_tags.item_id") ->where("items_tags.tag_id", "=", $tag->id) ->where("items.id", "<=", $item->id) ->merge_where($where) ->order_by("items.id") ->count_all(); } }