diff --git a/ext/tag_categories/main.php b/ext/tag_categories/main.php new file mode 100644 index 00000000..4a5dcffa --- /dev/null +++ b/ext/tag_categories/main.php @@ -0,0 +1,125 @@ + + * Link: http://code.shishnet.org/shimmie2/ + * Description: Let tags be split into 'categories', like Danbooru's tagging + */ + +class TagCategories extends Extension { + public function onInitExt(InitExtEvent $event) { + global $config, $database; + + // whether we split out separate categories on post view by default + // note: only takes effect if /post/view shows the image's exact tags + $config->set_default_bool("tag_categories_split_on_view", true); + + if($config->get_int("ext_tag_categories_version") < 1) { + // primary extension database, holds all our stuff! + $database->create_table('image_tag_categories', + 'category VARCHAR(60) PRIMARY KEY, + display_singular TEXT(60), + display_multiple TEXT(60), + color TEXT(7)'); + + $config->set_int("ext_tag_categories_version", 1); + + log_info("tag_categories", "extension installed"); + } + + // if empty, add our default values + $number_of_db_rows = $database->execute('SELECT COUNT(*) FROM image_tag_categories;')->fetchColumn(); + + if ($number_of_db_rows == 0) { + $database->execute('INSERT INTO image_tag_categories VALUES ("artist", "Artist", "Artists", "#BB6666");'); + $database->execute('INSERT INTO image_tag_categories VALUES ("series", "Series", "Series", "#AA00AA");'); + $database->execute('INSERT INTO image_tag_categories VALUES ("character", "Character", "Characters", "#66BB66");'); + } + } + + public function onPageRequest(PageRequestEvent $event) { + global $page, $database, $user; + + if($event->page_matches("tags/categories")) { + if($user->is_admin()) { + $this->page_update(); + $this->show_tag_categories($page); + } + } + } + + public function getDict() { + global $database; + + $tc_dict = $database->get_all('SELECT * FROM image_tag_categories;'); + + return $tc_dict; + } + + public function getKeyedDict($key_with = 'category') { + $tc_dict = $this->getDict(); + $tc_keyed_dict = array(); + + foreach ($tc_dict as $row) { + $key = $row[$key_with]; + $tc_keyed_dict[$key] = $row; + } + + return $tc_keyed_dict; + } + + public function page_update() { + global $user, $database; + + if(!$user->is_admin()) { + return false; + } + + if(!isset($_POST['tc_status']) and + !isset($_POST['tc_category']) and + !isset($_POST['tc_display_singular']) and + !isset($_POST['tc_display_multiple']) and + !isset($_POST['tc_color'])) { + return false; + } + + if($_POST['tc_status'] == 'edit') { + $is_success = $database->execute('UPDATE image_tag_categories + SET display_singular=:display_singular, + display_multiple=:display_multiple, + color=:color + WHERE category=:category', + array( + 'category' => $_POST['tc_category'], + 'display_singular' => $_POST['tc_display_singular'], + 'display_multiple' => $_POST['tc_display_multiple'], + 'color' => $_POST['tc_color'], + )); + } + else if($_POST['tc_status'] == 'new') { + $is_success = $database->execute('INSERT INTO image_tag_categories + VALUES (:category, :display_singular, :display_multiple, :color)', + array( + 'category' => $_POST['tc_category'], + 'display_singular' => $_POST['tc_display_singular'], + 'display_multiple' => $_POST['tc_display_multiple'], + 'color' => $_POST['tc_color'], + )); + } + else if($_POST['tc_status'] == 'delete') { + $is_success = $database->execute('DELETE FROM image_tag_categories + WHERE category=:category', + array( + 'category' => $_POST['tc_category'] + )); + } + + return $is_success; + } + + public function show_tag_categories($page) { + $this->theme->show_tag_categories($page, $this->getDict()); + } +} + +?> diff --git a/ext/tag_categories/theme.php b/ext/tag_categories/theme.php new file mode 100644 index 00000000..2856570c --- /dev/null +++ b/ext/tag_categories/theme.php @@ -0,0 +1,103 @@ + +
+ + + + + + + + + + + + + + + + + +
Category + '.$tag_category.' + + +
Name – Single + '.$tag_single_name.' + +
Name – Multiple + '.$tag_multiple_name.' + +
Color + '.$tag_color.' + +
+ + + + +
+ + '; + } + + // new + $tag_category = 'example'; + $tag_single_name = 'Example'; + $tag_multiple_name = 'Examples'; + $tag_color = '#EE5542'; + $html .= ' +
+
+ + + + + + + + + + + + + + + + + +
Category + +
Name – Single + +
Name – Multiple + +
Color + +
+ +
+
+ '; + + // add html to stuffs + $page->add_block(new Block("Editing", $html, "main", 10)); + } +} +?> \ No newline at end of file diff --git a/ext/tag_list/main.php b/ext/tag_list/main.php index 6dd293ab..e3990e9b 100644 --- a/ext/tag_list/main.php +++ b/ext/tag_list/main.php @@ -40,7 +40,7 @@ class TagList extends Extension { break; case 'categories': $this->theme->set_heading("Popular Categories"); - $this->theme->set_tag_list($this->build_tag_categories()); + $this->theme->set_tag_list($this->build_tag_list()); break; } $this->theme->display_page($page); @@ -81,7 +81,12 @@ class TagList extends Extension { $this->add_related_block($page, $event->image); } else { - $this->add_tags_block($page, $event->image); + if(class_exists("TagCategories") and $config->get_bool('tag_categories_split_on_view')) { + $this->add_split_tags_block($page, $event->image); + } + else { + $this->add_tags_block($page, $event->image); + } } } } @@ -290,7 +295,7 @@ class TagList extends Extension { return $html; } - private function build_tag_categories() { + private function build_tag_list() { global $database; $tags_min = $this->get_tags_min(); @@ -348,6 +353,25 @@ class TagList extends Extension { } } + private function add_split_tags_block(Page $page, Image $image) { + global $database; + global $config; + + $query = " + SELECT tags.tag, tags.count as calc_count + FROM tags, image_tags + WHERE tags.id = image_tags.tag_id + AND image_tags.image_id = :image_id + ORDER BY calc_count DESC + "; + $args = array("image_id"=>$image->id); + + $tags = $database->get_all($query, $args); + if(count($tags) > 0) { + $this->theme->display_split_related_block($page, $tags); + } + } + private function add_tags_block(Page $page, Image $image) { global $database; global $config; @@ -374,7 +398,7 @@ class TagList extends Extension { $tags = $database->cache->get("popular_tags"); if(empty($tags)) { $query = " - SELECT tag, count + SELECT tag, count as calc_count FROM tags WHERE count > 0 ORDER BY count DESC diff --git a/ext/tag_list/theme.php b/ext/tag_list/theme.php index 0d175730..23df90d7 100644 --- a/ext/tag_list/theme.php +++ b/ext/tag_list/theme.php @@ -25,6 +25,64 @@ class TagListTheme extends Themelet { // ======================================================================= + /* + * $tag_infos = array( + * array('tag' => $tag, 'count' => $number_of_uses), + * ... + * ) + */ + public function display_split_related_block(Page $page, $tag_infos) { + global $config; + + if($config->get_string('tag_list_related_sort') == 'alphabetical') asort($tag_infos); + + if(class_exists('TagCategories')) { + $this->tagcategories = new TagCategories; + $tag_category_dict = $this->tagcategories->getKeyedDict(); + } + else { + $tag_category_dict = array(); + } + $tag_categories_html = array(); + $tag_categories_count = array(); + + foreach($tag_infos as $row) { + $split = self::return_tag($row, $tag_category_dict); + $category = $split[0]; + $tag_html = $split[1]; + if(!isset($tag_categories_html[$category])) { + $tag_categories_html[$category] = ''; + } + $tag_categories_html[$category] .= $tag_html . '
'; + + if(!isset($tag_categories_count[$category])) { + $tag_categories_count[$category] = 0; + } + $tag_categories_count[$category] += 1; + } + + asort($tag_categories_html); + $main_html = $tag_categories_html[' ']; + unset($tag_categories_html[' ']); + + foreach(array_keys($tag_categories_html) as $category) { + if($tag_categories_count[$category] < 2) { + $category_display_name = html_escape($tag_category_dict[$category]['display_singular']); + } + else{ + $category_display_name = html_escape($tag_category_dict[$category]['display_multiple']); + } + $page->add_block(new Block($category_display_name, $tag_categories_html[$category], "left", 9)); + } + + if($config->get_string('tag_list_image_type')=="tags") { + $page->add_block(new Block("Tags", $main_html, "left", 10)); + } + else { + $page->add_block(new Block("Related Tags", $main_html, "left", 10)); + } + } + /* * $tag_infos = array( * array('tag' => $tag, 'count' => $number_of_uses), @@ -34,32 +92,29 @@ class TagListTheme extends Themelet { public function display_related_block(Page $page, $tag_infos) { global $config; - $html = ""; - $n = 0; if($config->get_string('tag_list_related_sort') == 'alphabetical') asort($tag_infos); - foreach($tag_infos as $row) { - $tag = $row['tag']; - $h_tag = html_escape($tag); - $h_tag_no_underscores = str_replace("_", " ", $h_tag); - $count = $row['calc_count']; - if($n++) $html .= "\n
"; - if(!is_null($config->get_string('info_link'))) { - $link = str_replace('$tag', $tag, $config->get_string('info_link')); - $html .= " ?"; - } - $link = $this->tag_link($row['tag']); - $html .= " $h_tag_no_underscores"; - if($config->get_bool("tag_list_numbers")) { - $html .= " $count"; - } - } - - if($config->get_string('tag_list_image_type')=="tags") { - $page->add_block(new Block("Tags", $html, "left", 10)); + if(class_exists('TagCategories')) { + $this->tagcategories = new TagCategories; + $tag_category_dict = $this->tagcategories->getKeyedDict(); } else { - $page->add_block(new Block("Related Tags", $html, "left", 10)); + $tag_category_dict = array(); + } + $main_html = ''; + + foreach($tag_infos as $row) { + $split = $this->return_tag($row, $tag_category_dict); + $category = $split[0]; + $tag_html = $split[1]; + $main_html .= $tag_html . '
'; + } + + if($config->get_string('tag_list_image_type')=="tags") { + $page->add_block(new Block("Tags", $main_html, "left", 10)); + } + else { + $page->add_block(new Block("Related Tags", $main_html, "left", 10)); } } @@ -72,34 +127,27 @@ class TagListTheme extends Themelet { */ public function display_popular_block(Page $page, $tag_infos) { global $config; - - // store local copies for speed. - $info_link = $config->get_string('info_link'); - $tag_list_num = $config->get_bool("tag_list_numbers"); - $html = ""; - $n = 0; if($config->get_string('tag_list_popular_sort') == 'alphabetical') asort($tag_infos); - + + if(class_exists('TagCategories')) { + $this->tagcategories = new TagCategories; + $tag_category_dict = $this->tagcategories->getKeyedDict(); + } + else { + $tag_category_dict = array(); + } + $main_html = ''; + foreach($tag_infos as $row) { - $tag = $row['tag']; - $h_tag = html_escape($tag); - $h_tag_no_underscores = str_replace("_", " ", $h_tag); - $count = $row['count']; - if($n++) $html .= "\n
"; - if(!is_null($info_link)) { - $link = str_replace('$tag', $tag, $info_link); - $html .= ' ?'; - } - $link = $this->tag_link($row['tag']); - $html .= ' '.$h_tag_no_underscores.''; - if($tag_list_num) { - $html .= ' '.$count.''; - } + $split = self::return_tag($row, $tag_category_dict); + $category = $split[0]; + $tag_html = $split[1]; + $main_html .= $tag_html . '
'; } - $html .= "
 
Full List\n"; - $page->add_block(new Block("Popular Tags", $html, "left", 60)); + $main_html .= " 
Full List\n"; + $page->add_block(new Block("Popular Tags", $main_html, "left", 60)); } /* @@ -112,27 +160,63 @@ class TagListTheme extends Themelet { public function display_refine_block(Page $page, $tag_infos, $search) { global $config; - // store local copy for speed. - $info_link = $config->get_string('info_link'); - - $html = ""; - $n = 0; - + if($config->get_string('tag_list_popular_sort') == 'alphabetical') asort($tag_infos); + + if(class_exists('TagCategories')) { + $this->tagcategories = new TagCategories; + $tag_category_dict = $this->tagcategories->getKeyedDict(); + } + else { + $tag_category_dict = array(); + } + $main_html = ''; + foreach($tag_infos as $row) { - $tag = $row['tag']; - $h_tag = html_escape($tag); - $h_tag_no_underscores = str_replace("_", " ", $h_tag); - if($n++) $html .= "\n
"; - if(!is_null($info_link)) { - $link = str_replace('$tag', $tag, $info_link); - $html .= ' ?'; - } - $link = $this->tag_link($row['tag']); - $html .= ' '.$h_tag_no_underscores.''; - $html .= $this->ars($tag, $search); + $split = self::return_tag($row, $tag_category_dict); + $category = $split[0]; + $tag_html = $split[1]; + $main_html .= $tag_html . '
'; } - $page->add_block(new Block("Refine Search", $html, "left", 60)); + $main_html .= " 
Full List\n"; + $page->add_block(new Block("refine Search", $main_html, "left", 60)); + } + + public function return_tag($row, $tag_category_dict) { + global $config; + + $display_html = ''; + $tag = $row['tag']; + $h_tag = html_escape($tag); + + $tag_category_css = ''; + $tag_category_style = ''; + $h_tag_split = explode(':', html_escape($tag), 2); + $category = ' '; + + // we found a tag, see if it's valid! + if((count($h_tag_split) > 1) and array_key_exists($h_tag_split[0], $tag_category_dict)) { + $category = $h_tag_split[0]; + $h_tag = $h_tag_split[1]; + $tag_category_css .= ' tag_category_'.$category; + $tag_category_style .= 'style="color:'.html_escape($tag_category_dict[$category]['color']).';" '; + } + + $h_tag_no_underscores = str_replace("_", " ", $h_tag); + $count = $row['calc_count']; + // if($n++) $display_html .= "\n
"; + if(!is_null($config->get_string('info_link'))) { + $link = str_replace('$tag', $tag, $config->get_string('info_link')); + $display_html .= ' ?'; + } + $link = $this->tag_link($row['tag']); + $display_html .= ' '.$h_tag_no_underscores.''; + + if($config->get_bool("tag_list_numbers")) { + $display_html .= " $count"; + } + + return [$category, $display_html]; } protected function ars(/*string*/ $tag, /*array(string)*/ $tags) { diff --git a/themes/default/style.css b/themes/default/style.css index 284119b8..3056deac 100644 --- a/themes/default/style.css +++ b/themes/default/style.css @@ -163,3 +163,36 @@ ARTICLE TABLE { -webkit-box-shadow: 2px 2px 6px rgba(0,0,0,0.6); /* webkit haven't committed yet */ -moz-box-shadow: 2px 2px 6px rgba(0,0,0,0.6); /* mozilla haven't committed yet */ } +.tagcategoryblock { +margin:0.6rem 1rem 0.6rem 0; +padding:0.5rem 0.6rem 0.7rem; +width:18rem; +border:1px solid #AAAAAA; +border-radius:0.25rem; +display:inline-block; +} +.tagcategoryblock table { +width:100%; +border-spacing:0; +} +.tagcategoryblock input, .tagcategoryblock span { +width:100%; +height:100%; +} +.tagcategoryblock td:first-child { +padding:0.3rem 0.7rem 0.4rem 0; +text-align:right; +width:40%; +} +.tagcategoryblock td:last-child { +width:60%; +} +.tagcategoryblock td:last-child span { +padding:0.24rem 0.7rem 0.5rem 0; +display:block; +} +.tagcategoryblock button { +width:100%; +margin-top:0.4rem; +padding:0.2rem 0.6rem; +}