diff --git a/3.0/modules/tag_albums/controllers/admin_tag_albums.php b/3.0/modules/tag_albums/controllers/admin_tag_albums.php
new file mode 100644
index 00000000..71cf8eb6
--- /dev/null
+++ b/3.0/modules/tag_albums/controllers/admin_tag_albums.php
@@ -0,0 +1,100 @@
+content = new View("admin_tag_albums.html");
+
+ // Generate a form for the admin Settings.
+ $view->content->tag_albums_form = $this->_get_admin_form();
+
+ // Display the page.
+ print $view;
+ }
+
+ private function _get_admin_form() {
+ $form = new Forge("admin/tag_albums/saveprefs", "", "post",
+ array("id" => "g-tag-albums-admin-form"));
+
+ $tag_albums_tagsort_group = $form->group("Tag_Albums_Tag_Sort")->label(t("\"All Tags\" Album Preferences"));
+ $tag_albums_tagsort_group->dropdown("tag_sort_by")
+ ->label(t("Sort \"All Tags\" Albums By:"))
+ ->options(
+ array("name" => "Name",
+ "count" => "Count",
+ "id" => "ID Number"))
+ ->selected(module::get_var("tag_albums", "tag_sort_by"));
+ $tag_albums_tagsort_group->dropdown("tag_sort_direction")
+ ->label(t("Display Albums In:"))
+ ->options(
+ array("ASC" => "Ascending Order",
+ "DESC" => "Descending"))
+ ->selected(module::get_var("tag_albums", "tag_sort_direction"));
+
+ $tag_albums_tagitemsort_group = $form->group("Tag_Albums_Tag_Item_Sort")->label(t("\"All Tags\" Sub-Album Preferences"));
+ $tag_albums_tagitemsort_group->dropdown("subalbum_sort_by")
+ ->label(t("Sort Contents of Sub-Albums By:"))
+ ->options(
+ array("title" => "Title",
+ "name" => "File name",
+ "captured" => "Date captured",
+ "created" => "Date uploaded",
+ "updated" => "Date modified",
+ "view_count" => "Number of views"))
+ ->selected(module::get_var("tag_albums", "subalbum_sort_by"));
+ $tag_albums_tagitemsort_group->dropdown("subalbum_sort_direction")
+ ->label(t("Display Contents of Sub-Albums In:"))
+ ->options(
+ array("ASC" => "Ascending Order",
+ "DESC" => "Descending"))
+ ->selected(module::get_var("tag_albums", "subalbum_sort_direction"));
+
+ // Add a save button to the form.
+ $form->submit("SaveSettings")->value(t("Save"));
+
+ // Return the newly generated form.
+ return $form;
+ }
+
+ public function saveprefs() {
+ // Prevent Cross Site Request Forgery
+ access::verify_csrf();
+
+ $form = $this->_get_admin_form();
+ if ($form->validate()) {
+ Kohana_Log::add("error",print_r($form,1));
+ module::set_var("tag_albums", "tag_sort_by", $form->Tag_Albums_Tag_Sort->tag_sort_by->value);
+ module::set_var("tag_albums", "tag_sort_direction", $form->Tag_Albums_Tag_Sort->tag_sort_direction->value);
+ module::set_var("tag_albums", "subalbum_sort_by", $form->Tag_Albums_Tag_Item_Sort->subalbum_sort_by->value);
+ module::set_var("tag_albums", "subalbum_sort_direction", $form->Tag_Albums_Tag_Item_Sort->subalbum_sort_direction->value);
+
+ message::success(t("Your settings have been saved."));
+ url::redirect("admin/tag_albums");
+ }
+
+ // Else show the page with errors
+ $view = new Admin_View("admin.html");
+ $view->content = new View("admin_tag_albums.html");
+ $view->content->tag_albums_form = $form;
+ print $view;
+ }
+}
diff --git a/3.0/modules/tag_albums/controllers/tag_albums.php b/3.0/modules/tag_albums/controllers/tag_albums.php
new file mode 100644
index 00000000..3e47f1e7
--- /dev/null
+++ b/3.0/modules/tag_albums/controllers/tag_albums.php
@@ -0,0 +1,649 @@
+where("id", "=", $id)
+ ->find_all();
+
+ // If it doesn't exist, redirect to the modules root page.
+ if (count($album_tags) == 0) {
+ url::redirect("tag_albums/");
+ }
+
+ // If it does exist, and is set to *, load a list of all tags.
+ if ($album_tags[0]->tags == "*") {
+ $this->index($id);
+ } else {
+ // Otherwise, populate this page with the specified items.
+
+ // Inherit permissions, title and description from the album that linked to this page.
+ $album = ORM::factory("item", $album_tags[0]->album_id);
+ access::required("view", $album);
+ $page_title = $album->title;
+ $page_description = $album->description;
+
+ // Determine page sort order.
+ $sort_page_field = $album->sort_column;
+ $sort_page_direction = $album->sort_order;
+
+ // Determine search type (AND/OR) and generate an array of the tag ids.
+ $tag_ids = Array();
+ foreach (explode(",", $album_tags[0]->tags) as $tag_name) {
+ $tag = ORM::factory("tag")->where("name", "=", trim($tag_name))->find();
+ if ($tag->loaded()) {
+ $tag_ids[] = $tag->id;
+ }
+ }
+ $album_tags_search_type = $album_tags[0]->search_type;
+
+ // Figure out how many items are in this "virtual album"
+ $count = $this->_count_records($tag_ids, $album_tags_search_type, true);
+
+ // Figure out how many items to display on each page.
+ $page_size = module::get_var("gallery", "page_size", 9);
+
+ // Figure out which page # the visitor is on and
+ // don't allow the visitor to go below page 1.
+ $page = Input::instance()->get("page", 1);
+ if ($page < 1) {
+ url::redirect("tag_albums/album/" . $id);
+ }
+
+ // First item to display.
+ $offset = ($page - 1) * $page_size;
+
+ // Figure out what the highest page number is.
+ $max_pages = ceil($count / $page_size);
+
+ // Don't let the visitor go past the last page.
+ if ($max_pages && $page > $max_pages) {
+ url::redirect("tag_albums/album/{$id}/?page=$max_pages");
+ }
+
+ // Figure out which items to display on this page and store their details in $children.
+ $tag_children = $this->_get_records($tag_ids, $page_size, $offset, "items." . $sort_page_field, $sort_page_direction, $album_tags_search_type, true);
+ $children = Array();
+ foreach ($tag_children as $one_child) {
+ $child_tag = new Tag_Albums_Item($one_child->name, url::site("tag_albums/show/" . $one_child->id . "/0/" . $id), $one_child->type);
+ $child_tag->id = $one_child->id;
+ if ($one_child->has_thumb()) {
+ $child_tag->set_thumb($one_child->thumb_url(), $one_child->thumb_width, $one_child->thumb_height);
+ }
+ $children[] = $child_tag;
+ }
+
+ // Set up the previous and next page buttons.
+ if ($page > 1) {
+ $previous_page = $page - 1;
+ $view->previous_page_link = url::site("tag_albums/album/{$id}/?page={$previous_page}");
+ }
+ if ($page < $max_pages) {
+ $next_page = $page + 1;
+ $view->next_page_link = url::site("tag_albums/album/{$id}/?page={$next_page}");
+ }
+
+ // Set up breadcrumbs.
+ $tag_album_breadcrumbs = Array();
+ $counter = 0;
+ $tag_album_breadcrumbs[$counter++] = new Tag_Albums_Breadcrumb($album->title, "");
+ $parent_item = ORM::factory("item", $album->parent_id);
+ while ($parent_item->id != 1) {
+ $tag_album_breadcrumbs[$counter++] = new Tag_Albums_Breadcrumb($parent_item->title, $parent_item->url());
+ $parent_item = ORM::factory("item", $parent_item->parent_id);
+ }
+ $tag_album_breadcrumbs[$counter++] = new Tag_Albums_Breadcrumb($parent_item->title, $parent_item->url());
+ $tag_album_breadcrumbs = array_reverse($tag_album_breadcrumbs, true);
+
+ // Set up and display the actual page.
+ $template = new Theme_View("page.html", "collection", "Tag Albums");
+ $template->page_title = $page_title;
+ $template->set_global("page", $page);
+ $template->set_global("page_size", $page_size);
+ $template->set_global("max_pages", $max_pages);
+ $template->set_global("children", $children);
+ $template->set_global("children_count", $count);
+ $template->content = new View("tag_albums.html");
+ $template->content->title = $page_title;
+ $template->content->description = $page_description;
+ $template->set_global("breadcrumbs", $tag_album_breadcrumbs);
+ print $template;
+ }
+ }
+
+ public function index($id) {
+ // Load a page containing sub-albums for each tag in the gallery.
+
+ // If an ID was specified, make sure it's valid.
+ $album_tags = ORM::factory("tags_album_id")
+ ->where("id", "=", $id)
+ ->find_all();
+ if (count($album_tags) == 0) {
+ $id = "";
+ }
+
+ // Inherit permissions, title and description from the album that linked to this page,
+ // if available, if not use the root album and some default values.
+ $album = "";
+ $page_title = t("All Tags");
+ $page_description = "";
+ if ($id == "") {
+ $album = ORM::factory("item", 1);
+ access::required("view", $album);
+ } else {
+ $album = ORM::factory("item", $album_tags[0]->album_id);
+ access::required("view", $album);
+ $page_title = $album->title;
+ $page_description = $album->description;
+ }
+
+ // Figure out sort order from module preferences.
+ $sort_page_field = module::get_var("tag_albums", "tag_sort_by", "name");
+ $sort_page_direction = module::get_var("tag_albums", "tag_sort_direction", "ASC");
+
+ // Figure out how many items to display on each page.
+ $page_size = module::get_var("gallery", "page_size", 9);
+
+ // Figure out which page # the visitor is on and
+ // don't allow the visitor to go below page 1.
+ $page = Input::instance()->get("page", 1);
+ if ($page < 1) {
+ url::redirect("tag_albums/");
+ }
+
+ // First item to display.
+ $offset = ($page - 1) * $page_size;
+
+ // Determine the total number of items,
+ // for page numbering purposes.
+ $all_tags_count = ORM::factory("tag")
+ ->count_all();
+
+ // Figure out what the highest page number is.
+ $max_pages = ceil($all_tags_count / $page_size);
+
+ // Don't let the visitor go past the last page.
+ if ($max_pages && $page > $max_pages) {
+ url::redirect("tag_albums/?page=$max_pages");
+ }
+
+ // Figure out which items to display on this page.
+ $display_tags = ORM::factory("tag")
+ ->order_by("tags." . $sort_page_field, $sort_page_direction)
+ ->find_all($page_size, $offset);
+
+ // Set up the previous and next page buttons.
+ if ($page > 1) {
+ $previous_page = $page - 1;
+ $view->previous_page_link = url::site("tag_albums/album/" . $id . "/?page={$previous_page}");
+ }
+ if ($page < $max_pages) {
+ $next_page = $page + 1;
+ $view->next_page_link = url::site("tag_albums/album/" . $id . "/?page={$next_page}");
+ }
+
+ // Generate an arry of "fake" items, one for each tag on the page.
+ // Grab thumbnails from the most recently uploaded item for each tag, if available.
+ $children = Array();
+ foreach ($display_tags as $one_tag) {
+ $tag_item = ORM::factory("item")
+ ->viewable()
+ ->join("items_tags", "items.id", "items_tags.item_id")
+ ->where("items_tags.tag_id", "=", $one_tag->id)
+ ->order_by("items.id", "DESC")
+ ->find_all(1, 0);
+ $child_tag = new Tag_Albums_Item($one_tag->name, url::site("tag_albums/tag/" . $one_tag->id . "/" . $id), "album");
+ if (count($tag_item) > 0) {
+ if ($tag_item[0]->has_thumb()) {
+ $child_tag->set_thumb($tag_item[0]->thumb_url(), $tag_item[0]->thumb_width, $tag_item[0]->thumb_height);
+ }
+ }
+ $children[] = $child_tag;
+ }
+
+ // Set up breadcrumbs.
+ $tag_album_breadcrumbs = Array();
+ if ($id != "") {
+ $counter = 0;
+ $tag_album_breadcrumbs[$counter++] = new Tag_Albums_Breadcrumb($album->title, "");
+ $parent_item = ORM::factory("item", $album->parent_id);
+ while ($parent_item->id != 1) {
+ $tag_album_breadcrumbs[$counter++] = new Tag_Albums_Breadcrumb($parent_item->title, $parent_item->url());
+ $parent_item = ORM::factory("item", $parent_item->parent_id);
+ }
+ $tag_album_breadcrumbs[$counter++] = new Tag_Albums_Breadcrumb($parent_item->title, $parent_item->url());
+ $tag_album_breadcrumbs = array_reverse($tag_album_breadcrumbs, true);
+ } else {
+ $tag_album_breadcrumbs[0] = new Tag_Albums_Breadcrumb(item::root()->title, item::root()->url());
+ $tag_album_breadcrumbs[1] = new Tag_Albums_Breadcrumb($page_title, "");
+ }
+
+ // Set up and display the actual page.
+ $template = new Theme_View("page.html", "collection", "Tag Albums");
+ $template->page_title = $page_title;
+ $template->set_global("page", $page);
+ $template->set_global("page_size", $page_size);
+ $template->set_global("max_pages", $max_pages);
+ $template->set_global("children", $children);
+ $template->set_global("children_count", $all_tags_count);
+ $template->content = new View("tag_albums.html");
+ $template->content->title = $page_title;
+ $template->content->description = $page_description;
+ $template->set_global("breadcrumbs", $tag_album_breadcrumbs);
+ print $template;
+ }
+
+ public function tag($id, $album_id) {
+ // Display a dynamic album containing everything tagged with a specific tag where,
+ // TAG is $id.
+ // Optionally, set the breadcrumbs to make this page look like an album where the
+ // album is $album_id.
+
+ // Make sure $album_id is valid, clear it out if it isn't.
+ $album_tags = ORM::factory("tags_album_id")
+ ->where("id", "=", $album_id)
+ ->find_all();
+ if (count($album_tags) == 0) {
+ $album_id = "";
+ }
+
+ // Figure out sort order from module preferences.
+ $sort_page_field = module::get_var("tag_albums", "subalbum_sort_by", "title");
+ $sort_page_direction = module::get_var("tag_albums", "subalbum_sort_direction", "ASC");
+
+ // Figure out how many items to display on each page.
+ $page_size = module::get_var("gallery", "page_size", 9);
+
+ // Figure out which page # the visitor is on and
+ // don't allow the visitor to go below page 1.
+ $page = Input::instance()->get("page", 1);
+ if ($page < 1) {
+ url::redirect("tag_albums/tag/" . $id . "/" . $album_id);
+ }
+
+ // First item to display.
+ $offset = ($page - 1) * $page_size;
+
+ // Determine the total number of items,
+ // for page numbering purposes.
+ $count = $this->_count_records(Array($id), "OR", true);
+
+ // Figure out what the highest page number is.
+ $max_pages = ceil($count / $page_size);
+
+ // Don't let the visitor go past the last page.
+ if ($max_pages && $page > $max_pages) {
+ url::redirect("tag_albums/tag/{$id}/" . $album_id . "/?page=$max_pages");
+ }
+
+ // Figure out which items to display on this page.
+ $tag_children = $this->_get_records(Array($id), $page_size, $offset, "items." . $sort_page_field, $sort_page_direction, "OR", true);
+
+ // Create an array of "fake" items to display on the page.
+ $children = Array();
+ foreach ($tag_children as $one_child) {
+ $child_tag = new Tag_Albums_Item($one_child->name, url::site("tag_albums/show/" . $one_child->id . "/" . $id . "/" . $album_id), $one_child->type);
+ $child_tag->id = $one_child->id;
+ if ($one_child->has_thumb()) {
+ $child_tag->set_thumb($one_child->thumb_url(), $one_child->thumb_width, $one_child->thumb_height);
+ }
+ $children[] = $child_tag;
+ }
+
+ // Set up the previous and next page buttons.
+ if ($page > 1) {
+ $previous_page = $page - 1;
+ $view->previous_page_link = url::site("tag_albums/tag/{$id}/" . $album_id . "/?page={$previous_page}");
+ }
+ if ($page < $max_pages) {
+ $next_page = $page + 1;
+ $view->next_page_link = url::site("tag_albums/tag/{$id}/" . $album_id . "/?page={$next_page}");
+ }
+
+ // Load the current tag.
+ $display_tag = ORM::factory("tag", $id);
+
+ // Set up breadcrumbs for the page.
+ $tag_album_breadcrumbs = Array();
+ if ($album_id != "") {
+ $counter = 0;
+ $tag_album_breadcrumbs[$counter++] = new Tag_Albums_Breadcrumb($display_tag->name, "");
+ $parent_item = ORM::factory("item", $album_tags[0]->album_id);
+ if ($album_tags[0]->tags != "*") {
+ $parent_item = ORM::factory("item", $parent_item->parent_id);
+ }
+ while ($parent_item->id != 1) {
+ $tag_album_breadcrumbs[$counter++] = new Tag_Albums_Breadcrumb($parent_item->title, $parent_item->url());
+ $parent_item = ORM::factory("item", $parent_item->parent_id);
+ }
+ $tag_album_breadcrumbs[$counter++] = new Tag_Albums_Breadcrumb($parent_item->title, $parent_item->url());
+ $tag_album_breadcrumbs = array_reverse($tag_album_breadcrumbs, true);
+ } else {
+ $tag_album_breadcrumbs[0] = new Tag_Albums_Breadcrumb(item::root()->title, item::root()->url());
+ $tag_album_breadcrumbs[1] = new Tag_Albums_Breadcrumb("All Tags", url::site("tag_albums/"));
+ $tag_album_breadcrumbs[2] = new Tag_Albums_Breadcrumb($display_tag->name, "");
+ }
+
+ // Set up and display the actual page.
+ $template = new Theme_View("page.html", "collection", "Tag Albums");
+ $template->page_title = $display_tag->name;
+ $template->set_global("page", $page);
+ $template->set_global("page_size", $page_size);
+ $template->set_global("max_pages", $max_pages);
+ $template->set_global("children", $children);
+ $template->set_global("children_count", $count);
+ $template->content = new View("tag_albums.html");
+ $template->content->title = $display_tag->name;
+ $template->set_global("breadcrumbs", $tag_album_breadcrumbs);
+ print $template;
+ }
+
+ public function show($item_id, $tag_id, $album_id) {
+ // Display the specified photo or video ($item_id) with breadcrumbs
+ // that point back to a virtual album ($tag_id / $album_id).
+
+ // Make sure #album_id is valid, clear it out if it isn't.
+ $album_tags = ORM::factory("tags_album_id")
+ ->where("id", "=", $album_id)
+ ->find_all();
+ if (count($album_tags) == 0) {
+ $album_id = "";
+ }
+
+ // Load the tag and item, make sure the user has access to the item.
+ $display_tag = ORM::factory("tag", $tag_id);
+ $item = ORM::factory("item", $item_id);
+ access::required("view", $item);
+
+ // Figure out sort order from module preferences.
+ $sort_page_field = "";
+ $sort_page_direction = "";
+ if (($tag_id > 0) || (count($album_tags) == 0)) {
+ $sort_page_field = module::get_var("tag_albums", "subalbum_sort_by", "title");
+ $sort_page_direction = module::get_var("tag_albums", "subalbum_sort_direction", "ASC");
+ } else {
+ $parent_album = ORM::factory("item", $album_tags[0]->album_id);
+ $sort_page_field = $parent_album->sort_column;
+ $sort_page_direction = $parent_album->sort_order;
+ }
+
+ // Load the number of items in the parent album, and determine previous and next items.
+ $sibling_count = "";
+ $tag_children = "";
+ $previous_item = "";
+ $next_item = "";
+ $position = 0;
+ if ($tag_id > 0) {
+ $sibling_count = $this->_count_records(Array($tag_id), "OR", false);
+ $position = $this->_get_position($item->$sort_page_field, $item->id, Array($tag_id), "items." . $sort_page_field, $sort_page_direction, $album_tags_search_type);
+ if ($position > 1) {
+ $previous_item_object = $this->_get_records(Array($tag_id), 1, $position-2, "items." . $sort_page_field, $sort_page_direction, $album_tags_search_type, false);
+ if (count($previous_item_object) > 0) {
+ $previous_item = new Tag_Albums_Item($previous_item_object[0]->name, url::site("tag_albums/show/" . $previous_item_object[0]->id . "/" . $tag_id . "/" . $album_id), $previous_item_object[0]->type);
+ }
+ }
+ $next_item_object = $this->_get_records(Array($tag_id), 1, $position, "items." . $sort_page_field, $sort_page_direction, $album_tags_search_type, false);
+ if (count($next_item_object) > 0) {
+ $next_item = new Tag_Albums_Item($next_item_object[0]->name, url::site("tag_albums/show/" . $next_item_object[0]->id . "/" . $tag_id . "/" . $album_id), $next_item_object[0]->type);
+ }
+ } else {
+ $tag_ids = Array();
+ foreach (explode(",", $album_tags[0]->tags) as $tag_name) {
+ $tag = ORM::factory("tag")->where("name", "=", trim($tag_name))->find();
+ if ($tag->loaded()) {
+ $tag_ids[] = $tag->id;
+ }
+ }
+ $album_tags_search_type = $album_tags[0]->search_type;
+ $sibling_count = $this->_count_records($tag_ids, $album_tags_search_type, false);
+ $position = $this->_get_position($item->$sort_page_field, $item->id, $tag_ids, "items." . $sort_page_field, $sort_page_direction, $album_tags_search_type);
+ if ($position > 1) {
+ $previous_item_object = $this->_get_records($tag_ids, 1, $position-2, "items." . $sort_page_field, $sort_page_direction, $album_tags_search_type, false);
+ if (count($previous_item_object) > 0) {
+ $previous_item = new Tag_Albums_Item($previous_item_object[0]->name, url::site("tag_albums/show/" . $previous_item_object[0]->id . "/" . $tag_id . "/" . $album_id), $previous_item_object[0]->type);
+ }
+ }
+ $next_item_object = $this->_get_records($tag_ids, 1, $position, "items." . $sort_page_field, $sort_page_direction, $album_tags_search_type, false);
+ if (count($next_item_object) > 0) {
+ $next_item = new Tag_Albums_Item($next_item_object[0]->name, url::site("tag_albums/show/" . $next_item_object[0]->id . "/" . $tag_id . "/" . $album_id), $next_item_object[0]->type);
+ }
+ }
+
+ // Set up breadcrumbs
+ $tag_album_breadcrumbs = Array();
+ if ($album_id != "") {
+ $counter = 0;
+ $tag_album_breadcrumbs[$counter++] = new Tag_Albums_Breadcrumb($item->title, "");
+ if ($album_tags[0]->tags == "*") {
+ $tag_album_breadcrumbs[$counter++] = new Tag_Albums_Breadcrumb($display_tag->name, url::site("tag_albums/tag/" . $display_tag->id . "/" . $album_id));
+ }
+ $parent_item = ORM::factory("item", $album_tags[0]->album_id);
+ while ($parent_item->id != 1) {
+ $tag_album_breadcrumbs[$counter++] = new Tag_Albums_Breadcrumb($parent_item->title, $parent_item->url());
+ $parent_item = ORM::factory("item", $parent_item->parent_id);
+ }
+ $tag_album_breadcrumbs[$counter++] = new Tag_Albums_Breadcrumb($parent_item->title, $parent_item->url());
+ $tag_album_breadcrumbs = array_reverse($tag_album_breadcrumbs, true);
+ } else {
+ $tag_album_breadcrumbs[0] = new Tag_Albums_Breadcrumb(item::root()->title, item::root()->url());
+ $tag_album_breadcrumbs[1] = new Tag_Albums_Breadcrumb("All Tags", url::site("tag_albums/"));
+ $tag_album_breadcrumbs[2] = new Tag_Albums_Breadcrumb($display_tag->name, url::site("tag_albums/tag/" . $display_tag->id));
+ $tag_album_breadcrumbs[3] = new Tag_Albums_Breadcrumb($item->title, "");
+ }
+
+ // Load the page.
+ if ($item->is_photo()) {
+ $template = new Theme_View("page.html", "item", "photo");
+ $template->page_title = $item->title;
+ $template->set_global("children", Array());
+ $template->set_global("item", $item);
+ $template->set_global("previous_item", $previous_item);
+ $template->set_global("next_item", $next_item);
+ $template->set_global("children_count", 0);
+ $template->set_global("position", $position);
+ $template->set_global("sibling_count", $sibling_count);
+ $template->content = new View("tag_albums_photo.html");
+ $template->content->title = $item->title;
+ $template->set_global("breadcrumbs", $tag_album_breadcrumbs);
+ print $template;
+ } elseif ($item->is_movie()) {
+ $template = new Theme_View("page.html", "item", "movie");
+ $template->page_title = $item->title;
+ $template->set_global("children", Array());
+ $template->set_global("item", $item);
+ $template->set_global("previous_item", $previous_item);
+ $template->set_global("next_item", $next_item);
+ $template->set_global("children_count", 0);
+ $template->set_global("position", $position);
+ $template->set_global("sibling_count", $sibling_count);
+ $template->content = new View("tag_albums_movie.html");
+ $template->content->title = $item->title;
+ $template->set_global("breadcrumbs", $tag_album_breadcrumbs);
+ print $template;
+ } else {
+ // If it's something we don't know how to deal with, just redirect to its real page.
+ url::redirect(url::abs_site("{$item->type}s/{$item->id}"));
+ }
+ }
+
+ private function _get_position($item_title, $item_id, $tag_ids, $sort_field, $sort_direction, $search_type) {
+ // Determine an item's position within a virtual album.
+
+ // Convert ASC/DESC to < or > characters.
+ if (!strcasecmp($sort_direction, "DESC")) {
+ $comp = ">";
+ } else {
+ $comp = "<";
+ }
+
+ // Figure out how many items are _before the current item.
+ $items_model = ORM::factory("item");
+ if ($search_type == "AND") {
+ $items_model->select('COUNT("*") AS result_count');
+ } else {
+ $items_model->select("items.id");
+ }
+ $items_model->viewable();
+ $items_model->join("items_tags", "items.id", "items_tags.item_id");
+ $items_model->open();
+ $items_model->where("items_tags.tag_id", "=", $tag_ids[0]);
+ $counter = 1;
+ while ($counter < count($tag_ids)) {
+ $items_model->or_where("items_tags.tag_id", "=", $tag_ids[$counter]);
+ $counter++;
+ }
+ $items_model->close();
+ $items_model->and_where("items.type", "!=", "album");
+ $items_model->and_where($sort_field, $comp, $item_title);
+ $items_model->order_by($sort_field, $sort_direction);
+ $items_model->group_by("items.id");
+ if ($search_type == "AND") {
+ $items_model->having("result_count", "=", count($tag_ids));
+ }
+ $position = count($items_model->find_all());
+
+ // In case multiple items have identical sort criteria, query for
+ // everything with the same criteria, and increment the position
+ // one at a time until we find the right item.
+ $items_model = ORM::factory("item");
+ if ($search_type == "AND") {
+ $items_model->select("items.id");
+ $items_model->select('COUNT("*") AS result_count');
+ } else {
+ $items_model->select("items.id");
+ }
+ $items_model->viewable();
+ $items_model->join("items_tags", "items.id", "items_tags.item_id");
+ $items_model->open();
+ $items_model->where("items_tags.tag_id", "=", $tag_ids[0]);
+ $counter = 1;
+ while ($counter < count($tag_ids)) {
+ $items_model->or_where("items_tags.tag_id", "=", $tag_ids[$counter]);
+ $counter++;
+ }
+ $items_model->close();
+ $items_model->and_where("items.type", "!=", "album");
+ $items_model->and_where($sort_field, "=", $item_title);
+ $items_model->order_by($sort_field, $sort_direction);
+ $items_model->group_by("items.id");
+ if ($search_type == "AND") {
+ $items_model->having("result_count", "=", count($tag_ids));
+ }
+ $match_items = $items_model->find_all();
+ foreach ($match_items as $one_item) {
+ $position++;
+ if ($one_item->id == $item_id) {
+ break;
+ }
+ }
+
+ return ($position);
+ }
+
+ private function _get_records($tag_ids, $page_size, $offset, $sort_field, $sort_direction, $search_type, $include_albums) {
+ // Returns an array of items to be displayed on the current page.
+
+ $items_model = ORM::factory("item");
+ if ($search_type == "AND") {
+ // For some reason, if I do 'select("*")' the item ids all have values that are 1000+
+ // higher then they should be. So instead, I'm manually selecting each column that I need.
+ $items_model->select("items.id");
+ $items_model->select("items.name");
+ $items_model->select("items.type");
+ $items_model->select("items.thumb_width");
+ $items_model->select("items.thumb_height");
+ $items_model->select("items.left_ptr");
+ $items_model->select("items.right_ptr");
+ $items_model->select("items.relative_path_cache");
+ $items_model->select('COUNT("*") AS result_count');
+ }
+ $items_model->viewable();
+ $items_model->join("items_tags", "items.id", "items_tags.item_id");
+ $items_model->open();
+ $items_model->where("items_tags.tag_id", "=", $tag_ids[0]);
+ $counter = 1;
+ while ($counter < count($tag_ids)) {
+ $items_model->or_where("items_tags.tag_id", "=", $tag_ids[$counter]);
+ $counter++;
+ }
+ $items_model->close();
+ if ($include_albums == false) {
+ $items_model->and_where("items.type", "!=", "album");
+ }
+ $items_model->order_by($sort_field, $sort_direction);
+ $items_model->group_by("items.id");
+ if ($search_type == "AND") {
+ $items_model->having("result_count", "=", count($tag_ids));
+ }
+ return $items_model->find_all($page_size, $offset);
+ }
+
+ private function _count_records($tag_ids, $search_type, $include_albums) {
+ // Count the number of viewable items for the designated tag(s)
+ // and return that number.
+
+ if (count($tag_ids) == 0) {
+ // If no tags were specified, return 0.
+ return 0;
+
+ } elseif (count($tag_ids) == 1) {
+ // if one tag was specified, we can use count_all to get the number.
+ $count = ORM::factory("item")
+ ->viewable()
+ ->join("items_tags", "items.id", "items_tags.item_id")
+ ->where("items_tags.tag_id", "=", $tag_ids[0]);
+ if ($include_albums == false) {
+ $count->and_where("items.type", "!=", "album");
+ }
+ return $count->count_all();
+
+ } else {
+ // If multiple tags were specified, count_all won't work,
+ // so we'll have to do count(find_all) instead.
+ $items_model = ORM::factory("item");
+ if ($search_type == "AND") {
+ $items_model->select('COUNT("*") AS result_count');
+ } else {
+ $items_model->select('items.id');
+ }
+ $items_model->viewable();
+ $items_model->join("items_tags", "items.id", "items_tags.item_id");
+ $items_model->where("items_tags.tag_id", "=", $tag_ids[0]);
+ $counter = 1;
+ while ($counter < count($tag_ids)) {
+ $items_model->or_where("items_tags.tag_id", "=", $tag_ids[$counter]);
+ $counter++;
+ }
+ if ($include_albums == false) {
+ $items_model->and_where("items.type", "!=", "album");
+ }
+ $items_model->group_by("items.id");
+ if ($search_type == "AND") {
+ $items_model->having("result_count", "=", count($tag_ids));
+ }
+
+ return count($items_model->find_all());
+ }
+ }
+}
diff --git a/3.0/modules/tag_albums/helpers/tag_albums_block.php b/3.0/modules/tag_albums/helpers/tag_albums_block.php
new file mode 100644
index 00000000..7243722c
--- /dev/null
+++ b/3.0/modules/tag_albums/helpers/tag_albums_block.php
@@ -0,0 +1,40 @@
+ t("Tag Albums"));
+ }
+
+ static function get($block_id, $theme) {
+ $block = "";
+
+ switch ($block_id) {
+ case "tag_albums":
+ // Make a new sidebar block.
+ $block = new Block();
+ $block->css_id = "g-tag-albums";
+ $block->title = t("Tag Albums");
+ $block->content = new View("tag_albums_block.html");
+
+ break;
+ }
+ return $block;
+ }
+}
diff --git a/3.0/modules/tag_albums/helpers/tag_albums_event.php b/3.0/modules/tag_albums/helpers/tag_albums_event.php
new file mode 100644
index 00000000..033293f1
--- /dev/null
+++ b/3.0/modules/tag_albums/helpers/tag_albums_event.php
@@ -0,0 +1,110 @@
+module == "tag") {
+ $data->messages["warn"][] = t("The Tag Albums module requires the Tags module.");
+ }
+ }
+
+ static function module_change($changes) {
+ // See if the Tags module is installed,
+ // tell the user to install it if it isn't.
+ if (!module::is_active("tag") || in_array("tag", $changes->deactivate)) {
+ site_status::warning(
+ t("The Tag Albums module requires the Tags module. " .
+ "Activate the Tags module now",
+ array("url" => url::site("admin/modules"))),
+ "tag_albums_needs_tag");
+ } else {
+ site_status::clear("tag_albums_needs_tag");
+ }
+ }
+
+ static function admin_menu($menu, $theme) {
+ // Add a link to the admin page to the Content menu.
+ $menu->get("settings_menu")
+ ->append(Menu::factory("link")
+ ->id("tag_albums")
+ ->label(t("Tag Albums Settings"))
+ ->url(url::site("admin/tag_albums")));
+ }
+
+ static function item_edit_form($item, $form) {
+ // Create fields on the album edit screen to allow the user to link
+ // the album to a tag_albums page.
+ if (!($item->is_album())) {
+ return;
+ }
+
+ $url = url::site("tags/autocomplete");
+ $form->script("")
+ ->text("$('form input[name=tag_albums]').ready(function() {
+ $('form input[name=tag_albums]').autocomplete(
+ '$url', {max: 30, multiple: true, multipleSeparator: ',', cacheLength: 1});
+ });");
+
+ $album_tags = ORM::factory("tags_album_id")
+ ->where("album_id", "=", $item->id)
+ ->find_all();
+
+ $tag_names = "";
+ $tag_album_type = "OR";
+ if (count($album_tags) > 0) {
+ $tag_names = $album_tags[0]->tags;
+ $tag_album_type = $album_tags[0]->search_type;
+ }
+
+ $tags_album_group = $form->edit_item->group("tags_album_group");
+ $tags_album_group->dropdown("tags_album_type")
+ ->options(
+ array("OR" => t("Display items that contain ANY of the following tags:"),
+ "AND" => t("Display items that contain ALL of the following tags:")))
+ ->selected($tag_album_type);
+ $tags_album_group->input("tag_albums")
+ ->value($tag_names);
+ }
+
+ static function item_deleted($item) {
+ // Whenever an item is deleted, delete any corresponding data.
+ db::build()->delete("tags_album_ids")->where("album_id", "=", $item->id)->execute();
+ }
+
+ static function item_edit_form_completed($item, $form) {
+ // Update the database with any changes to the tag_albums field.
+ if (!($item->is_album())) {
+ return;
+ }
+
+ $record = ORM::factory("tags_album_id")->where("album_id", "=", $item->id)->find();
+
+ if ($form->edit_item->tags_album_group->tag_albums->value != "") {
+ if (!$record->loaded()) {
+ $record->album_id = $item->id;
+ }
+ $record->tags = $form->edit_item->tags_album_group->tag_albums->value;
+ $record->search_type = $form->edit_item->tags_album_group->tags_album_type->value;
+ $record->save();
+ } else {
+ db::build()->delete("tags_album_ids")->where("album_id", "=", $item->id)->execute();
+ }
+ }
+}
diff --git a/3.0/modules/tag_albums/helpers/tag_albums_installer.php b/3.0/modules/tag_albums/helpers/tag_albums_installer.php
new file mode 100644
index 00000000..6fa9fa10
--- /dev/null
+++ b/3.0/modules/tag_albums/helpers/tag_albums_installer.php
@@ -0,0 +1,57 @@
+query("CREATE TABLE IF NOT EXISTS {tags_album_ids} (
+ `id` int(9) NOT NULL auto_increment,
+ `album_id` int(9) NOT NULL,
+ `tags` varchar(2048) default NULL,
+ `search_type` varchar(128) NOT NULL,
+ PRIMARY KEY (`id`),
+ KEY(`album_id`, `id`))
+ DEFAULT CHARSET=utf8;");
+
+ // Set up some default values.
+ module::set_var("tag_albums", "tag_sort_by", "name");
+ module::set_var("tag_albums", "tag_sort_direction", "ASC");
+ module::set_var("tag_albums", "subalbum_sort_by", "title");
+ module::set_var("tag_albums", "subalbum_sort_direction", "ASC");
+
+ // Set the module's version number.
+ module::set_version("tag_albums", 1);
+ }
+
+ static function deactivate() {
+ site_status::clear("tag_albums_needs_tag");
+ }
+
+ static function can_activate() {
+ $messages = array();
+ if (!module::is_active("tag")) {
+ $messages["warn"][] = t("The Tag Albums module requires the Tags module.");
+ }
+ return $messages;
+ }
+
+ static function uninstall() {
+ module::delete("tag_albums");
+ }
+}
diff --git a/3.0/modules/tag_albums/helpers/tag_albums_theme.php b/3.0/modules/tag_albums/helpers/tag_albums_theme.php
new file mode 100644
index 00000000..3eae0c61
--- /dev/null
+++ b/3.0/modules/tag_albums/helpers/tag_albums_theme.php
@@ -0,0 +1,34 @@
+item()) {
+ $album_tags = ORM::factory("tags_album_id")
+ ->where("album_id", "=", $theme->item->id)
+ ->find_all();
+ if (count($album_tags) > 0) {
+ url::redirect(url::abs_site("tag_albums/album/" . $album_tags[0]->id));
+ }
+ }
+ return;
+ }
+}
diff --git a/3.0/modules/tag_albums/libraries/Tag_Albums_Breadcrumb.php b/3.0/modules/tag_albums/libraries/Tag_Albums_Breadcrumb.php
new file mode 100644
index 00000000..ba576e49
--- /dev/null
+++ b/3.0/modules/tag_albums/libraries/Tag_Albums_Breadcrumb.php
@@ -0,0 +1,31 @@
+title = $new_title;
+ $this->url = $new_url;
+ }
+}
diff --git a/3.0/modules/tag_albums/libraries/Tag_Albums_Item.php b/3.0/modules/tag_albums/libraries/Tag_Albums_Item.php
new file mode 100644
index 00000000..beddc108
--- /dev/null
+++ b/3.0/modules/tag_albums/libraries/Tag_Albums_Item.php
@@ -0,0 +1,110 @@
+item_type == "album") {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function has_thumb() {
+ if ($this->thumb_url != "") {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function thumb_img($extra_attrs=array(), $max=null, $center_vertically=false) {
+ list ($height, $width) = $this->scale_dimensions($max);
+ if ($center_vertically && $max) {
+ // The constant is divide by 2 to calculate the file and 10 to convert to em
+ $margin_top = (int)(($max - $height) / 20);
+ $extra_attrs["style"] = "margin-top: {$margin_top}em";
+ $extra_attrs["title"] = $this->title;
+ }
+ $attrs = array_merge($extra_attrs,
+ array(
+ "src" => $this->thumb_url(),
+ "alt" => $this->title,
+ "width" => $width,
+ "height" => $height)
+ );
+ // html::image forces an absolute url which we don't want
+ return "";
+ }
+
+ public function scale_dimensions($max) {
+ $width = $this->thumb_width;
+ $height = $this->thumb_height;
+
+ if ($width <= $max && $height <= $max) {
+ return array($height, $width);
+ }
+
+ if ($height) {
+ if (isset($max)) {
+ if ($width > $height) {
+ $height = (int)($max * $height / $width);
+ $width = $max;
+ } else {
+ $width = (int)($max * $width / $height);
+ $height = $max;
+ }
+ }
+ } else {
+ // Missing thumbnail, can happen on albums with no photos yet.
+ // @todo we should enforce a placeholder for those albums.
+ $width = 0;
+ $height = 0;
+ }
+ return array($height, $width);
+ }
+
+ public function thumb_url() {
+ return $this->thumb_url;
+ }
+
+ public function url() {
+ return $this->url;
+ }
+
+ public function set_thumb($new_url, $new_width, $new_height) {
+ $this->thumb_url = $new_url;
+ $this->thumb_width = $new_width;
+ $this->thumb_height = $new_height;
+ }
+
+ public function __construct($new_title, $new_url, $new_type) {
+ $this->title = $new_title;
+ $this->url = $new_url;
+ $this->item_type = $new_type;
+ }
+}
diff --git a/3.0/modules/tag_albums/models/tag.php b/3.0/modules/tag_albums/models/tag.php
new file mode 100644
index 00000000..d15a36e0
--- /dev/null
+++ b/3.0/modules/tag_albums/models/tag.php
@@ -0,0 +1,141 @@
+loaded()) {
+ // Set reasonable defaults
+ $this->count = 0;
+ }
+ }
+
+ /**
+ * Return all viewable items associated with this tag.
+ * @param integer $limit number of rows to limit result to
+ * @param integer $offset offset in result to start returning rows from
+ * @param string $type the type of item (album, photo)
+ * @return ORM_Iterator
+ */
+ public function items($limit=null, $offset=null, $type=null) {
+ $model = ORM::factory("item")
+ ->viewable()
+ ->join("items_tags", "items.id", "items_tags.item_id")
+ ->where("items_tags.tag_id", "=", $this->id);
+ if ($type) {
+ $model->where("items.type", "=", $type);
+ }
+ return $model->find_all($limit, $offset);
+ }
+
+ /**
+ * Return the count of all viewable items associated with this tag.
+ * @param string $type the type of item (album, photo)
+ * @return integer
+ */
+ public function items_count($type=null) {
+ $model = ORM::factory("item")
+ ->viewable()
+ ->join("items_tags", "items.id", "items_tags.item_id")
+ ->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.
+ */
+ public function save() {
+ $related_item_ids = array();
+ foreach (db::build()
+ ->select("item_id")
+ ->from("items_tags")
+ ->where("tag_id", "=", $this->id)
+ ->execute() as $row) {
+ $related_item_ids[$row->item_id] = 1;
+ }
+
+ if (isset($this->object_relations["items"])) {
+ $added = array_diff($this->changed_relations["items"], $this->object_relations["items"]);
+ $removed = array_diff($this->object_relations["items"], $this->changed_relations["items"]);
+ if (isset($this->changed_relations["items"])) {
+ $changed = array_merge($added, $removed);
+ }
+ $this->count = count($this->object_relations["items"]) + count($added) - count($removed);
+ }
+
+ $result = parent::save();
+
+ if (!empty($changed)) {
+ foreach (ORM::factory("item")->where("id", "IN", $changed)->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, and delete all items_tags relationships.
+ */
+ public function delete($ignored_id=null) {
+ $related_item_ids = array();
+ foreach (db::build()
+ ->select("item_id")
+ ->from("items_tags")
+ ->where("tag_id", "=", $this->id)
+ ->execute() as $row) {
+ $related_item_ids[$row->item_id] = 1;
+ }
+
+ db::build()->delete("items_tags")->where("tag_id", "=", $this->id)->execute();
+ $result = parent::delete();
+
+ if ($related_item_ids) {
+ foreach (ORM::factory("item")
+ ->where("id", "IN", array_keys($related_item_ids))
+ ->find_all() as $item) {
+ module::event("item_related_update", $item);
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Return the server-relative url to this item, eg:
+ * /gallery3/index.php/tags/35
+ *
+ * @param string $query the query string (eg "page=3")
+ */
+ public function url($query=null) {
+ $url = url::site("/tag_albums/tag/{$this->id}/" . urlencode($this->name));
+ if ($query) {
+ $url .= "?$query";
+ }
+ return $url;
+ }
+}
diff --git a/3.0/modules/tag_albums/models/tags_album_id.php b/3.0/modules/tag_albums/models/tags_album_id.php
new file mode 100644
index 00000000..a9b16b4f
--- /dev/null
+++ b/3.0/modules/tag_albums/models/tags_album_id.php
@@ -0,0 +1,21 @@
+
+