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 @@
+
+
+
+ ';
+ }
+
+ // new
+ $tag_category = 'example';
+ $tag_single_name = 'Example';
+ $tag_multiple_name = 'Examples';
+ $tag_color = '#EE5542';
+ $html .= '
+
+ ';
+
+ // 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;
+}