From 3a568602dab0587d9b2561d2065d54f408494167 Mon Sep 17 00:00:00 2001 From: ebassi Date: Thu, 1 Jan 1970 00:00:00 +0000 Subject: [PATCH] First commit --- README.md | 1 + acp/main_info.php | 21 ++ acp/main_module.php | 223 ++++++++++++++++++ adm/style/acp_tagging_body.html | 13 + adm/style/acp_tagging_delete.html | 19 ++ adm/style/acp_tagging_edit.html | 50 ++++ adm/style/acp_tagging_main.html | 128 ++++++++++ composer.json | 22 ++ config/services.yml | 66 ++++++ core/request_helper.php | 40 ++++ core/search_helper.php | 99 ++++++++ core/tag_helper.php | 84 +++++++ event/permissions.php | 24 ++ event/posting_listener.php | 190 +++++++++++++++ event/search_tag_listener.php | 166 +++++++++++++ event/viewforum_listener.php | 59 +++++ event/viewtopic_listener.php | 59 +++++ language/en/info_acp_tagging.php | 48 ++++ language/en/permissions_tagging.php | 15 ++ language/en/tagging_post.php | 19 ++ language/en/tagging_search.php | 20 ++ migrations/dev_1.php | 40 ++++ migrations/dev_2.php | 23 ++ migrations/dev_3.php | 24 ++ migrations/dev_4.php | 38 +++ migrations/dev_5.php | 23 ++ .../event/overall_header_head_append.html | 1 + .../event/posting_editor_subject_after.html | 18 ++ .../event/posting_preview_poll_after.html | 1 + .../search_body_search_options_append.html | 13 + .../search_body_search_query_append.html | 18 ++ .../search_results_post_subject_before.html | 1 + .../template/event/topiclist_row_prepend.html | 2 + .../viewtopic_body_post_buttons_before.html | 1 + styles/all/theme/pedodev_tagging_main.css | 14 ++ taglist.json | 1 + 36 files changed, 1584 insertions(+) create mode 100644 README.md create mode 100755 acp/main_info.php create mode 100755 acp/main_module.php create mode 100755 adm/style/acp_tagging_body.html create mode 100755 adm/style/acp_tagging_delete.html create mode 100755 adm/style/acp_tagging_edit.html create mode 100755 adm/style/acp_tagging_main.html create mode 100755 composer.json create mode 100755 config/services.yml create mode 100755 core/request_helper.php create mode 100755 core/search_helper.php create mode 100755 core/tag_helper.php create mode 100755 event/permissions.php create mode 100755 event/posting_listener.php create mode 100755 event/search_tag_listener.php create mode 100755 event/viewforum_listener.php create mode 100755 event/viewtopic_listener.php create mode 100755 language/en/info_acp_tagging.php create mode 100755 language/en/permissions_tagging.php create mode 100755 language/en/tagging_post.php create mode 100755 language/en/tagging_search.php create mode 100755 migrations/dev_1.php create mode 100755 migrations/dev_2.php create mode 100755 migrations/dev_3.php create mode 100755 migrations/dev_4.php create mode 100755 migrations/dev_5.php create mode 100755 styles/all/template/event/overall_header_head_append.html create mode 100755 styles/all/template/event/posting_editor_subject_after.html create mode 100755 styles/all/template/event/posting_preview_poll_after.html create mode 100755 styles/all/template/event/search_body_search_options_append.html create mode 100755 styles/all/template/event/search_body_search_query_append.html create mode 100755 styles/all/template/event/search_results_post_subject_before.html create mode 100755 styles/all/template/event/topiclist_row_prepend.html create mode 100755 styles/all/template/event/viewtopic_body_post_buttons_before.html create mode 100755 styles/all/theme/pedodev_tagging_main.css create mode 100755 taglist.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..f16edb7 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +Content tagging extension for phpBB. Work in progress diff --git a/acp/main_info.php b/acp/main_info.php new file mode 100755 index 0000000..0ed343b --- /dev/null +++ b/acp/main_info.php @@ -0,0 +1,21 @@ + '\pedodev\tagging\acp\main_module', + 'title' => 'ACP_TAGGING_TITLE', + 'modes' => [ + 'settings' => [ + 'title' => 'ACP_TAGGING_SETTINGS', + 'auth' => 'ext_pedodev/tagging && acl_a_board', + 'cat' => ['ACP_TAGGING_TITLE'], + ], + ], + ]; + } +} diff --git a/acp/main_module.php b/acp/main_module.php new file mode 100755 index 0000000..5016144 --- /dev/null +++ b/acp/main_module.php @@ -0,0 +1,223 @@ +config = $phpbb_container->get('config'); + $this->request = $phpbb_container->get('request'); + $this->template = $phpbb_container->get('template'); + $this->user = $phpbb_container->get('user'); + $this->language = $phpbb_container->get('language'); + $this->tag_helper = $phpbb_container->get('pedodev.tagging.tag_helper'); + + $this->page_title = $this->language->lang('ACP_TAGGING_TITLE'); + $this->tpl_name = 'acp_tagging_body'; + $this->tag_list = $this->tag_helper->get_tag_list(); + + $action = $this->request->variable('action', '', $super_global = request_interface::GET); + + switch($action) + { + case 'edit': + $this->load_edit_page(); + break; + case 'delete': + $this->load_delete_page(); + break; + case 'add': + $this->load_add_page(); + break; + default: + $this->load_main_page(); + break; + } + } + + private function load_edit_page() + { + $form_key = 'pedodev_tagging_edit_tag'; + + add_form_key($form_key); + + $tag_id = $this->request->variable('tag', -1, request_interface::GET); + + if (!isset($this->tag_list[$tag_id])) + { + trigger_error($this->language->lang('ACP_TAGGING_INVALID_TAG') . adm_back_link($this->u_action)); + } + + if ($this->request->is_set_post('submit')) + { + $this->check_form_key($form_key); + + $tag_data = array( + 'title' => $this->request->variable('tagging_tagtitle', ''), + 'color' => $this->request->variable('tagging_tagcolor', ''), + 'active' => $this->request->variable('tagging_tagactive', false), + 'searchable' => $this->request->variable('tagging_tagsearchable', false), + ); + + if (empty($tag_data['title']) || empty($tag_data['color'])) + { + trigger_error($this->language->lang('ACP_TAGGING_TAG_EMPTY') . adm_back_link($this->u_action)); + } + + $this->tag_list[$tag_id] = $tag_data; + $this->tag_helper->update_tag_list($this->tag_list); + + trigger_error($this->language->lang('ACP_TAGGING_TAG_EDITED', $tag_data['title']) . adm_back_link($this->u_action)); + } + + $tag = $this->tag_list[$tag_id]; + + $this->template->assign_vars([ + 'EDIT' => 1, + 'TAGGING_PAGE_TITLE' => $this->language->lang('ACP_TAGGING_SETTINGS_EDIT'), + 'EDIT_TAG_NAME' => $tag['title'], + 'TAG_COLOR' => $tag['color'], + 'TAG_ACTIVE' => $tag['active'], + 'TAG_SEARCHABLE' => $tag['searchable'], + ]); + } + + private function load_delete_page() + { + $form_key = 'pedodev_tagging_delete_tag'; + + add_form_key($form_key); + + $tag_id = $this->request->variable('tag', -1, request_interface::GET); + + if (!isset($this->tag_list[$tag_id])) + { + trigger_error($this->language->lang('ACP_TAGGING_INVALID_TAG') . adm_back_link($this->u_action)); + } + + $tag = $this->tag_list[$tag_id]; + + if ($this->request->is_set_post('submit')) + { + $this->check_form_key($form_key); + + unset($this->tag_list[$tag_id]); + $this->tag_helper->update_tag_list($this->tag_list); + + trigger_error($this->language->lang('ACP_TAGGING_TAG_DELETED', $tag['title']) . adm_back_link($this->u_action)); + } + + $this->template->assign_vars([ + 'DELETE' => 1, + 'TAGGING_PAGE_TITLE' => $this->language->lang('ACP_TAGGING_SETTINGS_DELETE'), + 'DELETE_CONFIRMATION' => $this->language->lang('ACP_TAGGING_DELETE_CONFIRMATION', $tag['title']), + ]); + } + + private function load_add_page() + { + $form_key = 'pedodev_tagging_add_tag'; + + add_form_key($form_key); + + if ($this->request->is_set_post('submit')) + { + $this->check_form_key($form_key); + + $new_tag = $this->request->variable('tagging_tagtitle', ''); + + if (empty($new_tag)) + { + trigger_error($this->language->lang('ACP_TAGGING_TAG_EMPTY') . adm_back_link($this->u_action)); + } + + $this->tag_list[] = array( + 'title' => $new_tag, + 'color' => $this->request->variable('tagging_tagcolor', ''), + 'active' => $this->request->variable('tagging_tagactive', false), + 'searchable' => $this->request->variable('tagging_tagsearchable', false), + ); + + $this->tag_helper->update_tag_list($this->tag_list); + + trigger_error($this->language->lang('ACP_TAGGING_TAG_ADDED', $new_tag) . adm_back_link($this->u_action)); + } + + $random_color = '#' . substr(md5(rand()), 0, 6); + + $this->template->assign_vars([ + 'EDIT' => 1, + 'TAGGING_PAGE_TITLE' => $this->language->lang('ACP_TAGGING_SETTINGS_ADD',), + 'TAG_COLOR' => $random_color, + 'TAG_ACTIVE' => true, + 'TAG_SEARCHABLE' => true, + ]); + } + + private function load_main_page() + { + $form_key = 'pedodev_tagging_main'; + add_form_key($form_key); + + $id = 0; + + if ($this->request->is_set_post('submit')) + { + $this->check_form_key($form_key); + $this->config->set('pedodev_tagging_tagthreads', $this->request->variable('tagging_tagthreads', false)); + $this->config->set('pedodev_tagging_tagposts', $this->request->variable('tagging_tagposts', false)); + $this->config->set('pedodev_tagging_maxtags', $this->request->variable('tagging_maxtags', 0)); + $this->config->set('pedodev_tagging_tagsearch', $this->request->variable('tagging_tagsearch', false)); + $this->config->set('pedodev_tagging_viewtopic', $this->request->variable('tagging_viewtopic', false)); + $this->config->set('pedodev_tagging_viewforum', $this->request->variable('tagging_viewforum', false)); + $this->config->set('pedodev_tagging_results', $this->request->variable('tagging_results', false)); + + trigger_error($this->language->lang('ACP_TAGGING_SETTING_SAVED') . adm_back_link($this->u_action)); + } + + foreach ($this->tag_list as $id => $tag) + { + $this->template->assign_block_vars('tag_list', [ + 'TITLE' => $tag['title'], + 'COLOR' => $tag['color'], + 'ACTIVE' => $tag['active'], + 'SEARCHABLE' => $tag['searchable'], + 'EDIT_LINK' => $this->u_action . "&tag={$id}&action=edit", + 'DELETE_LINK' => $this->u_action . "&tag={$id}&action=delete", + ]); + } + + $id++; + + $this->template->assign_vars([ + 'TAGGING_PAGE_TITLE' => $this->language->lang('ACP_TAGGING_SETTINGS'), + 'U_ACTION' => $this->u_action, + 'TAGGING_ADD_TAG' => $this->u_action . "&tag={$id}&action=add", + 'TAG_THREADS' => $this->config['pedodev_tagging_tagthreads'], + 'TAG_POSTS' => $this->config['pedodev_tagging_tagposts'], + 'MAX_TAGS' => (int)$this->config['pedodev_tagging_maxtags'], + 'TAG_SEARCH' => $this->config['pedodev_tagging_tagsearch'], + 'TAG_VIEWTOPIC' => $this->config['pedodev_tagging_viewtopic'], + 'TAG_VIEWFORUM' => $this->config['pedodev_tagging_viewforum'], + 'TAG_RESULTS' => $this->config['pedodev_tagging_results'], + ]); + } + + private function check_form_key($form_key) + { + if (!check_form_key($form_key)) + { + trigger_error('FORM_INVALID'); + } + } +} diff --git a/adm/style/acp_tagging_body.html b/adm/style/acp_tagging_body.html new file mode 100755 index 0000000..b8cbb0e --- /dev/null +++ b/adm/style/acp_tagging_body.html @@ -0,0 +1,13 @@ +{% INCLUDE 'overall_header.html' %} + +

{{ TAGGING_PAGE_TITLE }}

+ +{% if EDIT %} + {% INCLUDE 'acp_tagging_edit.html' %} +{% elseif DELETE %} + {% INCLUDE 'acp_tagging_delete.html' %} +{% else %} + {% INCLUDE 'acp_tagging_main.html' %} +{% endif %} + +{% INCLUDE 'overall_footer.html' %} \ No newline at end of file diff --git a/adm/style/acp_tagging_delete.html b/adm/style/acp_tagging_delete.html new file mode 100755 index 0000000..169f76a --- /dev/null +++ b/adm/style/acp_tagging_delete.html @@ -0,0 +1,19 @@ +
+
+ +
+
+ {{ DELETE_CONFIRMATION }} +
+ {{ lang('ACP_TAGGING_DELETE_EXPLANATION') }} +
+
+ +

+ +

+ + {{ S_FORM_TOKEN }} + +
+
\ No newline at end of file diff --git a/adm/style/acp_tagging_edit.html b/adm/style/acp_tagging_edit.html new file mode 100755 index 0000000..69b2795 --- /dev/null +++ b/adm/style/acp_tagging_edit.html @@ -0,0 +1,50 @@ +
+
+ +
+
+
{{ lang('ACP_TAGGING_TITLE_EXPLANATION') }} +
+
+ +
+
+ +
+
+
{{ lang('ACP_TAGGING_TAGCOLOR_EXPLANATION') }} +
+
+ +
+
+ +
+
+
{{ lang('ACP_TAGGING_TAGACTIVE_EXPLANATION') }} +
+
+ + +
+
+ +
+
+
{{ lang('ACP_TAGGING_TAGSEARCHABLE_EXPLANATION') }} +
+
+ + +
+
+ +

+   + +

+ + {{ S_FORM_TOKEN }} + +
+
\ No newline at end of file diff --git a/adm/style/acp_tagging_main.html b/adm/style/acp_tagging_main.html new file mode 100755 index 0000000..83a65be --- /dev/null +++ b/adm/style/acp_tagging_main.html @@ -0,0 +1,128 @@ +
+
+
+
+
{{ lang('ACP_TAGGING_TAGLIST_EXPLANATION') }} +
+ +
+ + + + + + + + + + + + + {% if loops.tag_list|length %} + {% for TAG in loops.tag_list %} + + + + + + + + + {% endfor %} + {% endif %} + +
{{ lang('ACP_TAGGING_TAGTITLE') }}{{ lang('ACP_TAGGING_COLOR') }}{{ lang('ACP_TAGGING_ACTIVE') }}{{ lang('ACP_TAGGING_SEARCHABLE') }}{{ lang('ACP_TAGGING_EDIT') }}{{ lang('ACP_TAGGING_DELETE') }}
{{ TAG.TITLE }}{% if TAG.ACTIVE %}{{ lang('YES') }}{% else %}{{ lang('NO') }}{% endif %}{% if TAG.SEARCHABLE %}{{ lang('YES') }}{% else %}{{ lang('NO') }}{% endif %}{{ lang('ACP_TAGGING_EDIT') }}{{ lang('ACP_TAGGING_DELETE') }}
+ +
+ {{ lang('ACP_TAGGING_ADDTAG') }} +
+
+
+ +
+ {{ lang('ACP_TAGGING_POSTING') }} +
+
+
{{ lang('ACP_TAGGING_TITLE_MAXTAGS') }} +
+
+ +
+
+ +
+
+
{{ lang('ACP_TAGGING_TAGTHREADS_EXPLANATION') }} +
+
+ + +
+
+ +
+
+
{{ lang('ACP_TAGGING_TAGPOSTS_EXPLANATION') }} +
+
+ + +
+
+
+ +
+ {{ lang('ACP_TAGGING_SEARCH') }} +
+
+
{{ lang('ACP_TAGGING_TAGSEARCH_EXPLANATION') }} +
+
+ + +
+
+
+ +
+ {{ lang('ACP_TAGGING_DISPLAY') }} +
+
+
{{ lang('ACP_TAGGING_TAGVIEWFORUM_EXPLANATION') }} +
+
+ + +
+
+ +
+
+
{{ lang('ACP_TAGGING_TAGVIEWTOPIC_EXPLANATION') }} +
+
+ + +
+
+ +
+
+
{{ lang('ACP_TAGGING_TAGRESULTS_EXPLANATION') }} +
+
+ + +
+
+
+ +
+

+   + +

+ + {{ S_FORM_TOKEN }} +
+
\ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100755 index 0000000..340a76d --- /dev/null +++ b/composer.json @@ -0,0 +1,22 @@ +{ + "name": "pedodev/tagging", + "type": "phpbb-extension", + "description": "Content Tagging system for phpBB 3.3. Allows users to tag posts with a selection of pre-configured tags, and allows users to search by tag", + "version": "1.0.0", + "license": "None", + "authors": [ + { + "name": "PedoDeveloper" + } + ], + "require": { + "php": ">=8.0", + "composer/installers": "~1.0" + }, + "extra": { + "display-name": "Content Tagging", + "soft-require": { + "phpbb/phpbb": ">=3.3" + } + } +} \ No newline at end of file diff --git a/config/services.yml b/config/services.yml new file mode 100755 index 0000000..f076634 --- /dev/null +++ b/config/services.yml @@ -0,0 +1,66 @@ +services: + pedodev.tagging.tag_helper: + class: pedodev\tagging\core\tag_helper + arguments: + - '@dbal.conn' + + pedodev.tagging.search_helper: + class: pedodev\tagging\core\search_helper + arguments: + - '@dbal.conn' + - '@pedodev.tagging.tag_helper' + + pedodev.tagging.request_helper: + class: pedodev\tagging\core\request_helper + arguments: + - '@request' + - '@pedodev.tagging.tag_helper' + + pedodev.tagging.permissions_listener: + class: pedodev\tagging\event\permissions + tags: + - { name: event.listener } + + pedodev.tagging.posting_listener: + class: pedodev\tagging\event\posting_listener + tags: + - { name: event.listener } + arguments: + - '@config' + - '@template' + - '@dbal.conn' + - '@language' + - '@auth' + - '@pedodev.tagging.tag_helper' + - '@pedodev.tagging.search_helper' + - '@pedodev.tagging.request_helper' + + pedodev.tagging.search_tag_listener: + class: pedodev\tagging\event\search_tag_listener + tags: + - { name: event.listener } + arguments: + - '@config' + - '@template' + - '@language' + - '@pedodev.tagging.tag_helper' + - '@pedodev.tagging.search_helper' + - '@pedodev.tagging.request_helper' + + pedodev.tagging.viewtopic_listener: + class: pedodev\tagging\event\viewtopic_listener + tags: + - { name: event.listener } + arguments: + - '@config' + - '@pedodev.tagging.tag_helper' + - '@pedodev.tagging.search_helper' + + pedodev.tagging.viewforum_listener: + class: pedodev\tagging\event\viewforum_listener + tags: + - { name: event.listener } + arguments: + - '@config' + - '@pedodev.tagging.tag_helper' + - '@pedodev.tagging.search_helper' diff --git a/core/request_helper.php b/core/request_helper.php new file mode 100755 index 0000000..49ff745 --- /dev/null +++ b/core/request_helper.php @@ -0,0 +1,40 @@ +request->variable('tag_' . $tag_id, '', request_interface::GET); + } + + public function get_selected_tags(): array + { + $tag_list = $this->tag_helper->get_tag_list(); + + $select_tags = array_filter($tag_list, [$this, 'tag_is_selected'], ARRAY_FILTER_USE_KEY); + + return array_keys($select_tags); + } + + public function get_tag_filter(): string + { + return $this->request->variable('tag_filter', '', request_interface::GET); + } + + public function is_keyword_search(): bool + { + return (bool)$this->request->variable('keywords', '', request_interface::GET); + } +} diff --git a/core/search_helper.php b/core/search_helper.php new file mode 100755 index 0000000..309d0fc --- /dev/null +++ b/core/search_helper.php @@ -0,0 +1,99 @@ +tag_helper->get_tag_table() . ' t + WHERE t.' . $this->db->sql_in_set('post_id', $post_list); + + $result = $this->db->sql_query($sql); + + $post_tags = array(); + + while ($row = $this->db->sql_fetchrow($result)) + { + $post_tags[$row['post_id']][] = $row['tag_id']; + } + + return $post_tags; + } + + public function search_topic_tags(array $topic_list): array + { + if (empty($topic_list)) + { + return array(); + } + + $sql = 'SELECT t.topic_id, c.tag_id + FROM ' . $this->tag_helper->get_tag_table() . ' c, ' . TOPICS_TABLE . ' t + WHERE t.topic_first_post_id = c.post_id AND t.' . $this->db->sql_in_set('topic_id', $topic_list); + + $result = $this->db->sql_query($sql); + + $topic_tags = array(); + + while ($row = $this->db->sql_fetchrow($result)) + { + $topic_tags[$row['topic_id']][] = $row['tag_id']; + } + + return $topic_tags; + } + + public function search_posts_by_tag(array $tag_list, string $filter_mode, string $mode): array + { + if (empty($tag_list)) + { + return array(); + } + + if ($mode === 'posts') + { + $sql = 'SELECT post_id, count(*) + FROM ' . $this->tag_helper->get_tag_table() . ' + WHERE ' . $this->db->sql_in_set('tag_id', $tag_list) . ' + GROUP BY post_id'; + } + else if ($mode === 'topics') + { + $sql = 'SELECT t.topic_id, count(*) + FROM ' . $this->tag_helper->get_tag_table() . ' c, ' . TOPICS_TABLE . ' t + WHERE t.topic_first_post_id = c.post_id AND c.' . $this->db->sql_in_set('tag_id', $tag_list) . ' + GROUP BY t.topic_id'; + } + + $result = $this->db->sql_query($sql); + + $count = count($tag_list); + $post_list = array(); + + while ($row = $this->db->sql_fetchrow($result)) + { + if ($filter_mode === 'union' || ($filter_mode === 'intersect' && $row['count(*)'] == $count)) + { + $post_list[] = (isset($row['post_id'])) ? (int)$row['post_id'] : (int)$row['topic_id']; + } + } + + return $post_list; + } +} \ No newline at end of file diff --git a/core/tag_helper.php b/core/tag_helper.php new file mode 100755 index 0000000..a7f1eb5 --- /dev/null +++ b/core/tag_helper.php @@ -0,0 +1,84 @@ +tag_list_filepath = __DIR__ . '/../taglist.json'; + $this->tag_table = $this->db->sql_escape($table_prefix . 'content_tags'); + $this->load_tag_list(); + } + + private function load_tag_list(): void + { + $tag_list_json = ''; + + if (file_exists($this->tag_list_filepath)) + { + $tag_list_json = file_get_contents($this->tag_list_filepath); + } + + $tag_list = json_decode($tag_list_json, $associative = true); + $this->tag_list = isset($tag_list) ? $tag_list : array(); + + $this->active_tag_list = array_filter($this->tag_list, function($v) { + return (bool)$v['active']; + }); + + $this->searchable_tag_list = array_filter($this->tag_list, function($v) { + return (bool)$v['searchable']; + }); + } + + public function update_tag_list(array $tag_list): bool + { + $tag_list_json = json_encode($tag_list); + return (bool)file_put_contents($this->tag_list_filepath, $tag_list_json); + } + + public function get_tag_list(): array + { + return $this->tag_list; + } + + public function get_active_tag_list(): array + { + return $this->active_tag_list; + } + + public function get_searchable_tag_list(): array + { + return $this->searchable_tag_list; + } + + public function get_tag_table(): string + { + return $this->tag_table; + } + + public function get_colored_title(int $tag_id): string + { + if (!array_key_exists($tag_id, $this->tag_list)) + { + return ''; + } + + $tag = $this->tag_list[$tag_id]; + return '' . $tag['title'] . ''; + } +} diff --git a/event/permissions.php b/event/permissions.php new file mode 100755 index 0000000..1f7f7e2 --- /dev/null +++ b/event/permissions.php @@ -0,0 +1,24 @@ + 'load_permissions', + ]; + } + + public function load_permissions(object $event): void + { + $event->update_subarray('permissions', 'u_pedodev_tagging_cantagposts', ['lang' => 'ACL_U_PEDODEV_TAGGING_CANTAGPOSTS', 'cat' => 'post']); + } +} diff --git a/event/posting_listener.php b/event/posting_listener.php new file mode 100755 index 0000000..1f4b4a6 --- /dev/null +++ b/event/posting_listener.php @@ -0,0 +1,190 @@ + 'load_language', + 'core.posting_modify_template_vars' => 'template_add_tags', + 'core.posting_modify_submission_errors' => 'check_errors', + 'core.submit_post_end' => 'posting_add_tags', + ]; + } + + public function load_language(object $event): void + { + $this->language->add_lang('tagging_post', 'pedodev/tagging'); + } + + public function check_errors(object $event): void + { + $error = $event['error']; + + $this->selected_tag_list = $this->request_helper->get_selected_tags(); + $tag_count = count($this->selected_tag_list); + + if (!isset($event['post_data']['topic_first_post_id']) || $event['post_id'] == $event['post_data']['topic_first_post_id']) + { + $allowed = $this->config['pedodev_tagging_tagthreads']; + $error_msg = $this->language->lang('TAGGING_THREAD_ERROR'); + } + else + { + $allowed = $this->config['pedodev_tagging_tagposts']; + $error_msg = $this->language->lang('TAGGING_POST_ERROR'); + } + + if (!$this->auth->acl_get('u_pedodev_tagging_cantagposts') && $tag_count > 0) + { + $error[] = $this->language->lang('TAGGING_PERMISSION_ERROR'); + } + else if (!$allowed && $tag_count > 0) + { + $error[] = $error_msg; + } + else if ($tag_count > $this->config['pedodev_tagging_maxtags']) + { + $error[] = $this->language->lang('TAGGING_LIMIT_ERROR', $this->config['pedodev_tagging_maxtags'], count($this->selected_tag_list)); + } + + $event['error'] = $error; + } + + public function template_add_tags(object $event): void + { + if (!isset($event['post_data']['topic_first_post_id']) || $event['post_id'] == $event['post_data']['topic_first_post_id']) + { + $allowed = $this->config['pedodev_tagging_tagthreads']; + } + else + { + $allowed = $this->config['pedodev_tagging_tagposts']; + } + + if (!$allowed || !$this->auth->acl_get('u_pedodev_tagging_cantagposts')) + { + return; + } + + $post_id = (int)$event['post_id']; + + if (isset($this->selected_tag_list)) + { + $post_tags = $this->selected_tag_list; + } + else if ($post_id != 0) + { + $post_tags = $this->search_helper->search_post_tags(array($post_id)); + $post_tags = empty($post_tags) ? array() : current($post_tags); + } + else + { + $post_tags = array(); + } + + $active_tag_list = $this->tag_helper->get_active_tag_list(); + + $this->template->assign_var('TAGGING_ALLOWED', 1); + + if ($event['preview']) + { + $this->template->assign_var('POST_TAGS', implode(' ', array_map([$this->tag_helper, 'get_colored_title'], $post_tags))); + } + + foreach ($active_tag_list as $id => $tag) + { + $this->template->assign_block_vars('tags', [ + 'ID' => $id, + 'TITLE' => $tag['title'], + 'COLOR' => $tag['color'], + 'SELECTED' => in_array($id, $post_tags), + ]); + } + } + + public function posting_add_tags(object $event): void + { + $post_id = $event['data']['post_id']; + + switch ($event['mode']) + { + case 'post': + $this->insert_post_tags($post_id); + break; + case 'reply': + $this->insert_post_tags($post_id); + break; + case 'edit': + $this->delete_post_tags($post_id); + $this->insert_post_tags($post_id); + break; + } + } + + private function insert_post_tags(int $post_id): void + { + if ($post_id <= 0) + { + return; + } + + $sql_ary = array(); + $active_tag_list = $this->tag_helper->get_active_tag_list(); + + foreach ($active_tag_list as $id => $tag) + { + if (in_array($id, $this->selected_tag_list)) + { + $sql_ary[] = [ + 'post_id' => (int)$post_id, + 'tag_id' => (int)$id, + ]; + } + } + + $this->db->sql_multi_insert($this->tag_helper->get_tag_table(), $sql_ary); + } + + private function delete_post_tags(int $post_id): void + { + if ($post_id <= 0) + { + return; + } + + $sql = 'DELETE FROM ' . $this->tag_helper->get_tag_table() . ' + WHERE post_id = ' . (int)$post_id; + + $this->db->sql_query($sql); + } +} diff --git a/event/search_tag_listener.php b/event/search_tag_listener.php new file mode 100755 index 0000000..c2f3a77 --- /dev/null +++ b/event/search_tag_listener.php @@ -0,0 +1,166 @@ + 'assign_presearch_tags', +// 'core.search_backend_search_after' => [['fetch_results_tags', 0], ['search_by_tag', 1]], + 'core.search_modify_url_parameters' => 'add_tags_url', +// 'core.search_modify_tpl_ary' => 'assign_results_tags', + 'core.search_modify_submit_parameters' => 'load_language', + 'core.search_native_keywords_count_query_before' => 'test_func', + ]; + } + + public function load_language(object $event): void + { + $this->language->add_lang('tagging_search', 'pedodev/tagging'); + } + + public function assign_presearch_tags(object $event): void + { + if (!$this->config['pedodev_tagging_tagsearch']) + { + return; + } + + $active_tag_list = $this->tag_helper->get_searchable_tag_list(); + + $this->template->assign_var('TAGGING_ALLOWED', 1); + + foreach ($active_tag_list as $id => $tag) + { + $this->template->assign_block_vars('tags', [ + 'ID' => $id, + 'TITLE' => $tag['title'], + 'COLOR' => $tag['color'], + ]); + } + } + + public function fetch_results_tags(object $event): void + { + if (!$this->config['pedodev_tagging_results']) + { + return; + } + + $this->mode = $event['show_results']; + + if ($this->mode === 'posts') + { + $this->post_tags = $this->search_helper->search_post_tags($event['id_ary']); + } + else if ($this->mode === 'topics') + { + $this->post_tags = $this->search_helper->search_topic_tags($event['id_ary']); + } + } + + public function add_tags_url(object $event): void + { + $tag_ids = $this->request_helper->get_selected_tags(); + + if (empty($tag_ids)) + { + return; + } + + $u_search = $event['u_search']; + $u_search .= '&tag_' . implode('=1&tag_', $tag_ids) . '=1'; + $u_search .= '&tag_filter=' . $this->request_helper->get_tag_filter(); + $event['u_search'] = $u_search; + } + + public function assign_results_tags(object $event): void + { + if (!$this->config['pedodev_tagging_results']) + { + return; + } + + $post_row = $event['tpl_ary']; + $post_id = $post_row['POST_ID'] ? (int)$post_row['POST_ID'] : (int)$post_row['TOPIC_ID']; + + if (array_key_exists($post_id, $this->post_tags)) + { + $post_tags = $this->post_tags[$post_id]; + $tags = implode(' ', array_map([$this->tag_helper, 'get_colored_title'], $post_tags)); + $post_row['POST_TAGS'] = $tags; + } + + $event['tpl_ary'] = $post_row; + } + + public function search_by_tag(object $event): void + { + if (!$this->config['pedodev_tagging_tagsearch']) + { + return; + } + + $id_ary = $event['id_ary']; + + if (empty($id_ary) && $this->request_helper->is_keyword_search()) + { + var_dump("Empty search"); + return; + } + + $tag_ids = $this->request_helper->get_selected_tags(); + + if (empty($tag_ids)) + { + return; + } + + $mode = $event['show_results']; + $tag_filter = $this->request_helper->get_tag_filter(); + + $post_ary = $this->search_helper->search_posts_by_tag($tag_ids, $tag_filter, $mode); + + if (empty($id_ary)) + { + $id_ary = $post_ary; + } + else + { + $id_ary = array_intersect($id_ary, $post_ary); + } + + $event['id_ary'] = $id_ary; + $event['total_match_count'] = count($id_ary); + } + + public function test_func(object $event): void + { + // var_dump($event); + } +} diff --git a/event/viewforum_listener.php b/event/viewforum_listener.php new file mode 100755 index 0000000..abb541a --- /dev/null +++ b/event/viewforum_listener.php @@ -0,0 +1,59 @@ + 'fetch_topic_tags', + 'core.viewforum_modify_topicrow' => 'assign_topic_tags', + ]; + } + + public function fetch_topic_tags(object $event): void + { + if (!$this->config['pedodev_tagging_viewforum']) + { + return; + } + + $this->topic_tags = $this->search_helper->search_topic_tags($event['topic_list']); + } + + public function assign_topic_tags(object $event): void + { + if (!$this->config['pedodev_tagging_viewforum']) + { + return; + } + + $topic_row = $event['topic_row']; + $topic_id = (int)$topic_row['TOPIC_ID']; + + if (array_key_exists($topic_id, $this->topic_tags)) + { + $topic_tags = $this->topic_tags[$topic_id]; + $tags = implode(' ', array_map([$this->tag_helper, 'get_colored_title'], $topic_tags)); + $topic_row['TOPIC_TAGS'] = $tags; + } + + $event['topic_row'] = $topic_row; + } +} diff --git a/event/viewtopic_listener.php b/event/viewtopic_listener.php new file mode 100755 index 0000000..2a2cef0 --- /dev/null +++ b/event/viewtopic_listener.php @@ -0,0 +1,59 @@ + 'fetch_post_tags', + 'core.viewtopic_modify_post_row' => 'assign_post_tags', + ]; + } + + public function fetch_post_tags(object $event): void + { + if (!$this->config['pedodev_tagging_viewtopic']) + { + return; + } + + $this->post_tags = $this->search_helper->search_post_tags($event['post_list']); + } + + public function assign_post_tags(object $event): void + { + if (!$this->config['pedodev_tagging_viewtopic']) + { + return; + } + + $post_row = $event['post_row']; + $post_id = (int)$post_row['POST_ID']; + + if (array_key_exists($post_id, $this->post_tags)) + { + $post_tags = $this->post_tags[$post_id]; + $tags = implode(' ', array_map([$this->tag_helper, 'get_colored_title'], $post_tags)); + $post_row['POST_TAGS'] = $tags; + } + + $event['post_row'] = $post_row; + } +} diff --git a/language/en/info_acp_tagging.php b/language/en/info_acp_tagging.php new file mode 100755 index 0000000..b342cbc --- /dev/null +++ b/language/en/info_acp_tagging.php @@ -0,0 +1,48 @@ + 'Content Tagging', + 'ACP_TAGGING_SETTINGS' => 'Settings', + 'ACP_TAGGING_SETTING_SAVED' => 'Settings have been saved', + 'ACP_TAGGING_ADDTAG' => 'Add New Tag', + 'ACP_TAGGING_EDIT' => 'Edit', + 'ACP_TAGGING_DELETE' => 'Delete', + 'ACP_TAGGING_ACTIVE' => 'Active', + 'ACP_TAGGING_SEARCHABLE' => 'Searchable', + 'ACP_TAGGING_COLOR' => 'Color', + 'ACP_TAGGING_TAGTITLE' => 'Name', + 'ACP_TAGGING_SETTINGS_EDIT' => 'Edit A Tag', + 'ACP_TAGGING_SETTINGS_ADD' => 'Add New Tag', + 'ACP_TAGGING_SETTINGS_DELETE' => 'Delete Tag', + 'ACP_TAGGING_TAGACTIVE' => 'Active', + 'ACP_TAGGING_TAG_ADDED' => 'New tag \'%s\' added successfully', + 'ACP_TAGGING_TAG_EDITED' => 'Tag \'%s\' successfully edited', + 'ACP_TAGGING_TAG_DELETED' => 'Tag \'%s\' has been deleted', + 'ACP_TAGGING_INVALID_TAG' => 'Invalid tag id', + 'ACP_TAGGING_TAG_EMPTY' => 'Tag cannot be empty', + 'ACP_TAGGING_DELETE_CONFIRMATION' => 'Confirm Deletion of Tag \'%s\'', + 'ACP_TAGGING_DELETE_EXPLANATION' => 'Once this tag is deleted, all data associated with it will be lost and the tag will be removed from all existing posts. This cannot be undone', + 'ACP_TAGGING_TAGCOLOR' => 'Color', + 'ACP_TAGGING_TAGSEARCHABLE' => 'Searchable', + 'ACP_TAGGING_MAXTAGS' => 'Maximum Tags Per Post', + 'ACP_TAGGING_TAGTHREADS' => 'Allow Tagging Threads', + 'ACP_TAGGING_TAGPOSTS' => 'Allow Tagging Posts', + 'ACP_TAGGING_TAGLIST' => 'Tag List', + 'ACP_TAGGING_TAGSEARCH' => 'Allow Searching by Tag', + 'ACP_TAGGING_VIEWFORUM' => 'Show Tags in Forum View', + 'ACP_TAGGING_VIEWTOPIC' => 'Show Tags in Topic View', + 'ACP_TAGGING_RESULTS' => 'Show Tags in Search Results', + 'ACP_TAGGING_POSTING' => 'Posting Options', + 'ACP_TAGGING_SEARCH' => 'Search Options', + 'ACP_TAGGING_DISPLAY' => 'Display Options', +)); diff --git a/language/en/permissions_tagging.php b/language/en/permissions_tagging.php new file mode 100755 index 0000000..6868bfe --- /dev/null +++ b/language/en/permissions_tagging.php @@ -0,0 +1,15 @@ + 'Can tag posts', +)); diff --git a/language/en/tagging_post.php b/language/en/tagging_post.php new file mode 100755 index 0000000..023284e --- /dev/null +++ b/language/en/tagging_post.php @@ -0,0 +1,19 @@ + 'Tags', + 'TAGGING_LIMIT_ERROR' => 'Error: you are trying to select too many tags. Maximum tags: %d. You have selected: %d', + 'TAGGING_PERMISSION_ERROR' => 'Error: you do not have permission to tag posts', + 'TAGGING_THREAD_ERROR' => 'Error: tagging threads is not allowed', + 'TAGGING_POST_ERROR' => 'Error: tagging posts is not allowed', +)); diff --git a/language/en/tagging_search.php b/language/en/tagging_search.php new file mode 100755 index 0000000..e3047a1 --- /dev/null +++ b/language/en/tagging_search.php @@ -0,0 +1,20 @@ + 'Tags', + 'TAGGING_TAGS_EXPLANATION' => 'Show results containing these tags. Can be used as a standalone search method or combined with the methods above', + 'TAGGING_TAGFILTER' => 'Tag Filter Method', + 'TAGGING_TAGFILTER_EXPLANATION' => 'When multiple tags are selected, this controls the tag filter method. Intersect will show results containing ALL matching tags, while union will show results containing ANY matching tags', + 'TAGGING_INTERSECT' => 'Intersect', + 'TAGGING_UNION' => 'Union', +)); diff --git a/migrations/dev_1.php b/migrations/dev_1.php new file mode 100755 index 0000000..a67a678 --- /dev/null +++ b/migrations/dev_1.php @@ -0,0 +1,40 @@ +config['pedodev_tagging']); + } + + static public function depends_on() + { + return ['\phpbb\db\migration\data\v330\v330']; + } + + public function update_data() + { + return [ + + ['config.add', ['pedodev_tagging', 1]], + + ['module.add', [ + 'acp', + 'ACP_CAT_DOT_MODS', + 'ACP_TAGGING_TITLE' + ]], + + ['module.add', [ + 'acp', + 'ACP_TAGGING_TITLE', + [ + 'module_basename' => '\pedodev\tagging\acp\main_module', + 'modes' => ['settings'], + ], + ]], + + ]; + } +} diff --git a/migrations/dev_2.php b/migrations/dev_2.php new file mode 100755 index 0000000..62bb58c --- /dev/null +++ b/migrations/dev_2.php @@ -0,0 +1,23 @@ + [ + $this->table_prefix . 'content_tags' => [ + 'COLUMNS' => [ + 'id' => ['ULINT', NULL, 'auto_increment'], + 'post_id' => ['ULINT', 0, 'NON-NULL'], + 'tag_id' => ['USINT', 0, 'NON-NULL'], + ], + 'PRIMARY_KEY' => 'id', + ], + ], + + ]; + } + + public function revert_schema() + { + return [ + 'drop_tables' => [ + $this->table_prefix . 'content_tags', + ], + ]; + } +} diff --git a/migrations/dev_5.php b/migrations/dev_5.php new file mode 100755 index 0000000..96c151f --- /dev/null +++ b/migrations/dev_5.php @@ -0,0 +1,23 @@ + +
+ +
+ +
+ {% if loops.tags|length %} + {% for TAG in loops.tags %} + + {% endfor %} + {% endif %} +
+ +{% endif %} diff --git a/styles/all/template/event/posting_preview_poll_after.html b/styles/all/template/event/posting_preview_poll_after.html new file mode 100755 index 0000000..8d5a874 --- /dev/null +++ b/styles/all/template/event/posting_preview_poll_after.html @@ -0,0 +1 @@ +{{ POST_TAGS }} \ No newline at end of file diff --git a/styles/all/template/event/search_body_search_options_append.html b/styles/all/template/event/search_body_search_options_append.html new file mode 100755 index 0000000..6315431 --- /dev/null +++ b/styles/all/template/event/search_body_search_options_append.html @@ -0,0 +1,13 @@ +{% if TAGGING_ALLOWED %} +
+
+
+
{{ lang('TAGGING_TAGFILTER_EXPLANATION') }} +
+ +
+ + +
+
+{% endif %} diff --git a/styles/all/template/event/search_body_search_query_append.html b/styles/all/template/event/search_body_search_query_append.html new file mode 100755 index 0000000..5b32445 --- /dev/null +++ b/styles/all/template/event/search_body_search_query_append.html @@ -0,0 +1,18 @@ +{% if TAGGING_ALLOWED %} +
+
+
{{ lang('TAGGING_TAGS_EXPLANATION') }} +
+ +
+ {% if loops.tags|length %} + {% for TAG in loops.tags %} +   + {% endfor %} + {% endif %} +
+
+{% endif %} diff --git a/styles/all/template/event/search_results_post_subject_before.html b/styles/all/template/event/search_results_post_subject_before.html new file mode 100755 index 0000000..43a982d --- /dev/null +++ b/styles/all/template/event/search_results_post_subject_before.html @@ -0,0 +1 @@ +{{ searchresults.POST_TAGS }} \ No newline at end of file diff --git a/styles/all/template/event/topiclist_row_prepend.html b/styles/all/template/event/topiclist_row_prepend.html new file mode 100755 index 0000000..6c02dee --- /dev/null +++ b/styles/all/template/event/topiclist_row_prepend.html @@ -0,0 +1,2 @@ +{% if topicrow.TOPIC_TAGS %}{{ topicrow.TOPIC_TAGS }}{% endif %} +{% if searchresults.POST_TAGS %}{{ searchresults.POST_TAGS }}{% endif %} \ No newline at end of file diff --git a/styles/all/template/event/viewtopic_body_post_buttons_before.html b/styles/all/template/event/viewtopic_body_post_buttons_before.html new file mode 100755 index 0000000..3fbea53 --- /dev/null +++ b/styles/all/template/event/viewtopic_body_post_buttons_before.html @@ -0,0 +1 @@ +
  • {{ postrow.POST_TAGS }}
  • \ No newline at end of file diff --git a/styles/all/theme/pedodev_tagging_main.css b/styles/all/theme/pedodev_tagging_main.css new file mode 100755 index 0000000..28206f2 --- /dev/null +++ b/styles/all/theme/pedodev_tagging_main.css @@ -0,0 +1,14 @@ +.content_tag { + padding: 2px 4px 2px 4px; + color: white; + border-radius: 10px; + font-size: 80%; + font-weight: bold; + display: inline-block; +} + +.content_tag_checkbox { +} + +.content_tag_list { +} \ No newline at end of file diff --git a/taglist.json b/taglist.json new file mode 100755 index 0000000..2276bba --- /dev/null +++ b/taglist.json @@ -0,0 +1 @@ +[{"title":"Lesbian","color":"#dc8add","active":true,"searchable":true},{"title":"Hardcore","color":"#cfd11c","active":true,"searchable":true},{"title":"Softcore","color":"#ffbe6f","active":true,"searchable":true},{"title":"White","color":"#deddda","active":true,"searchable":true},{"title":"Ebony","color":"#77767b","active":true,"searchable":true},{"title":"Hispanic","color":"#cdab8f","active":true,"searchable":true},{"title":"Indian","color":"#986a44","active":true,"searchable":true},{"title":"Studio","color":"#4a87da","active":true,"searchable":true},{"title":"Non-nude","color":"#bcc28f","active":true,"searchable":true},{"title":"Gay","color":"#61c4c7","active":true,"searchable":true},{"title":"Pedomom","color":"#e73e61","active":true,"searchable":true},{"title":"Pedowoman","color":"#a9559b","active":true,"searchable":true},{"title":"Pedofamily","color":"#b02cd4","active":true,"searchable":true}] \ No newline at end of file