diff --git a/adm/style/acp_mchat_globalsettings.html b/adm/style/acp_mchat_globalsettings.html index d82744c..c82ae53 100644 --- a/adm/style/acp_mchat_globalsettings.html +++ b/adm/style/acp_mchat_globalsettings.html @@ -8,7 +8,7 @@

{{ lang('MCHAT_TITLE') }}

-{{ lang('MCHAT_VERSION') ~ lang('COLON') }} {{ MCHAT_VERSION }} +{{ lang('MCHAT_VERSION') ~ lang('COLON') }} {{ MCHAT_VERSION }} | {{ lang('MCHAT_REPARSER_STATUS') ~ lang('COLON') }} {{ lang(S_REPARSER_ACTIVE ? 'MCHAT_REPARSER_ACTIVE' : 'MCHAT_REPARSER_FINISHED') }} {% if MCHAT_ERROR %}
diff --git a/composer.json b/composer.json index 12ed4ab..e6bcc4a 100644 --- a/composer.json +++ b/composer.json @@ -1,52 +1,47 @@ { - "name": "dmzx/mchat", - "type": "phpbb-extension", - "description": "mChat", - "homepage": "https://www.phpbb.com/customise/db/extension/mchat_extension/", - "version": "2.1.3", - "time": "2019-06-06", - "keywords": [ - "phpbb", - "extension", - "mchat" - ], - "license": "GPL-2.0-only", - "authors": [ - { - "name": "kasimi", - "homepage": "https://kasimi.net", - "email": "mail@kasimi.net", - "role": "Lead Developer" - }, - { - "name": "dmzx", - "homepage": "http://www.dmzx-web.net", - "email": "info@dmzx-web.net", - "role": "Former Developer" - }, - { - "name": "RMcGirr83", - "homepage": "http://rmcgirr83.org", - "role": "Original MOD author" - } - ], - "require": { - "php": ">=5.4.7", - "composer/installers": "~1.0.0", - "phpbb/phpbb": ">=3.2.0" - }, - "require-dev": { - "phpbb/epv": "dev-master" - }, - "extra": { - "display-name": "mChat", - "soft-require": { - "phpbb/phpbb": ">=3.2.0" - }, - "version-check": { - "host": "www.phpbb.com", - "directory": "/customise/db/extension/mchat_extension", - "filename": "version_check" - } - } -} \ No newline at end of file + "name": "dmzx/mchat", + "type": "phpbb-extension", + "description": "mChat", + "homepage": "https://www.phpbb.com/customise/db/extension/mchat_extension/", + "version": "2.1.4", + "time": "2020-08-08", + "keywords": ["phpbb", "extension", "mchat"], + "license": "GPL-2.0-only", + "authors": [ + { + "name": "kasimi", + "homepage": "https://kasimi.net", + "email": "mail@kasimi.net", + "role": "Lead Developer" + }, + { + "name": "dmzx", + "homepage": "http://www.dmzx-web.net", + "email": "info@dmzx-web.net", + "role": "Former Developer" + }, + { + "name": "RMcGirr83", + "homepage": "http://rmcgirr83.org", + "role": "Original MOD author" + } + ], + "require": { + "php": ">=5.4.7", + "composer/installers": "~1.0" + }, + "require-dev": { + "phpbb/epv": "dev-master" + }, + "extra": { + "display-name": "mChat", + "soft-require": { + "phpbb/phpbb": ">=3.2.0" + }, + "version-check": { + "host": "www.phpbb.com", + "directory": "/customise/db/extension/mchat_extension", + "filename": "version_check" + } + } +} diff --git a/config/routing.yml b/config/routing.yml index 10e31df..aa6a0d4 100644 --- a/config/routing.yml +++ b/config/routing.yml @@ -1,37 +1,37 @@ dmzx_mchat_page_custom_controller: - path: /mchat - methods: [GET] - defaults: { _controller: dmzx.mchat.core:page_custom } + path: '/mchat' + methods: ['GET'] + defaults: { _controller: 'dmzx.mchat.core:page_custom' } dmzx_mchat_page_archive_controller: - path: /mchat/archive - methods: [GET] - defaults: { _controller: dmzx.mchat.core:page_archive } + path: '/mchat/archive' + methods: ['GET'] + defaults: { _controller: 'dmzx.mchat.core:page_archive' } dmzx_mchat_page_rules_controller: - path: /mchat/rules - methods: [GET] - defaults: { _controller: dmzx.mchat.core:page_rules } + path: '/mchat/rules' + methods: ['GET'] + defaults: { _controller: 'dmzx.mchat.core:page_rules' } dmzx_mchat_page_whois_controller: - path: /mchat/whois/{ip} - methods: [GET] - defaults: { _controller: dmzx.mchat.core:page_whois } + path: '/mchat/whois/{ip}' + methods: ['GET'] + defaults: { _controller: 'dmzx.mchat.core:page_whois' } dmzx_mchat_action_add_controller: - path: /mchat/action/add - methods: [POST] - defaults: { _controller: dmzx.mchat.core:action_add } + path: '/mchat/action/add' + methods: ['POST'] + defaults: { _controller: 'dmzx.mchat.core:action_add' } dmzx_mchat_action_edit_controller: - path: /mchat/action/edit - methods: [POST] - defaults: { _controller: dmzx.mchat.core:action_edit } + path: '/mchat/action/edit' + methods: ['POST'] + defaults: { _controller: 'dmzx.mchat.core:action_edit' } dmzx_mchat_action_del_controller: - path: /mchat/action/del - methods: [POST] - defaults: { _controller: dmzx.mchat.core:action_del } + path: '/mchat/action/del' + methods: ['POST'] + defaults: { _controller: 'dmzx.mchat.core:action_del' } dmzx_mchat_action_refresh_controller: - path: /mchat/action/refresh - methods: [POST] - defaults: { _controller: dmzx.mchat.core:action_refresh } + path: '/mchat/action/refresh' + methods: ['POST'] + defaults: { _controller: 'dmzx.mchat.core:action_refresh' } dmzx_mchat_action_whois_controller: - path: /mchat/action/whois - methods: [POST] - defaults: { _controller: dmzx.mchat.core:action_whois } + path: '/mchat/action/whois' + methods: ['POST'] + defaults: { _controller: 'dmzx.mchat.core:action_whois' } diff --git a/config/services.yml b/config/services.yml index eae2e91..1bfe545 100644 --- a/config/services.yml +++ b/config/services.yml @@ -1,10 +1,10 @@ imports: - - { resource: tables.yml } + - { resource: 'tables.yml' } services: dmzx.mchat.acp.controller: - class: dmzx\mchat\controller\acp_controller + class: 'dmzx\mchat\controller\acp_controller' arguments: - '@dmzx.mchat.functions' - '@template' @@ -12,13 +12,14 @@ services: - '@user' - '@language' - '@dbal.conn' + - '@config_text' - '@cache.driver' - '@request' - '@dispatcher' - '@dmzx.mchat.settings' dmzx.mchat.ucp.controller: - class: dmzx\mchat\controller\ucp_controller + class: 'dmzx\mchat\controller\ucp_controller' arguments: - '@template' - '@user' @@ -30,7 +31,7 @@ services: - '@dispatcher' dmzx.mchat.notifications: - class: dmzx\mchat\core\notifications + class: 'dmzx\mchat\core\notifications' arguments: - '@dmzx.mchat.settings' - '@user' @@ -41,7 +42,7 @@ services: - '@text_formatter.parser' dmzx.mchat.log: - class: dmzx\mchat\core\log + class: 'dmzx\mchat\core\log' arguments: - '@dmzx.mchat.settings' - '@user' @@ -50,7 +51,7 @@ services: - '@dispatcher' dmzx.mchat.core: - class: dmzx\mchat\core\mchat + class: 'dmzx\mchat\core\mchat' arguments: - '@dmzx.mchat.functions' - '@dmzx.mchat.notifications' @@ -70,7 +71,7 @@ services: - '@?rmcgirr83.authorizedforurls.listener' dmzx.mchat.functions: - class: dmzx\mchat\core\functions + class: 'dmzx\mchat\core\functions' arguments: - '@dmzx.mchat.settings' - '@dmzx.mchat.notifications' @@ -85,7 +86,7 @@ services: - '@group_helper' dmzx.mchat.settings: - class: dmzx\mchat\core\settings + class: 'dmzx\mchat\core\settings' arguments: - '@user' - '@language' @@ -100,7 +101,7 @@ services: - '%dmzx.mchat.table.mchat_sessions%' dmzx.mchat.acp.listener: - class: dmzx\mchat\event\acp_listener + class: 'dmzx\mchat\event\acp_listener' arguments: - '@template' - '@request' @@ -108,10 +109,10 @@ services: - '@dmzx.mchat.settings' - '@dmzx.mchat.functions' tags: - - { name: event.listener } + - { name: 'event.listener' } dmzx.mchat.main.listener: - class: dmzx\mchat\event\main_listener + class: 'dmzx\mchat\event\main_listener' arguments: - '@dmzx.mchat.core' - '@dmzx.mchat.notifications' @@ -121,30 +122,30 @@ services: - '@request' - '%core.php_ext%' tags: - - { name: event.listener } + - { name: 'event.listener' } dmzx.mchat.cron.task.mchat_prune: - class: dmzx\mchat\cron\mchat_prune + class: 'dmzx\mchat\cron\mchat_prune' arguments: - '@dmzx.mchat.functions' - '@dmzx.mchat.settings' calls: - - [set_name, [cron.task.mchat_prune]] + - ['set_name', ['cron.task.mchat_prune']] tags: - - { name: cron.task } + - { name: 'cron.task' } dmzx.mchat.text_reparser.mchat_messages: - class: dmzx\mchat\textreparser\plugins\mchat_messages + class: 'dmzx\mchat\textreparser\plugins\mchat_messages' arguments: - '@dbal.conn' - '%dmzx.mchat.table.mchat%' calls: - - [set_name, [dmzx.mchat.text_reparser.mchat_messages]] + - ['set_name', ['dmzx.mchat.text_reparser.mchat_messages']] tags: - - { name: text_reparser.plugin } + - { name: 'text_reparser.plugin' } dmzx.mchat.text_reparser.reparser: - class: phpbb\cron\task\text_reparser\reparser + class: 'phpbb\cron\task\text_reparser\reparser' arguments: - '@config' - '@config_text' @@ -152,7 +153,7 @@ services: - '@text_reparser.manager' - '@text_reparser_collection' calls: - - [set_name, [dmzx.mchat.text_reparser.reparser]] - - [set_reparser, [dmzx.mchat.text_reparser.mchat_messages]] + - ['set_name', ['dmzx.mchat.text_reparser.reparser']] + - ['set_reparser', ['dmzx.mchat.text_reparser.mchat_messages']] tags: - - { name: cron.task } + - { name: 'cron.task' } diff --git a/config/tables.yml b/config/tables.yml index d88d30a..2a1a2f3 100644 --- a/config/tables.yml +++ b/config/tables.yml @@ -1,4 +1,4 @@ parameters: - dmzx.mchat.table.mchat: %core.table_prefix%mchat - dmzx.mchat.table.mchat_log: %core.table_prefix%mchat_log - dmzx.mchat.table.mchat_sessions: %core.table_prefix%mchat_sessions + dmzx.mchat.table.mchat: '%core.table_prefix%mchat' + dmzx.mchat.table.mchat_log: '%core.table_prefix%mchat_log' + dmzx.mchat.table.mchat_sessions: '%core.table_prefix%mchat_sessions' diff --git a/controller/acp_controller.php b/controller/acp_controller.php index 4f17992..2ca638d 100644 --- a/controller/acp_controller.php +++ b/controller/acp_controller.php @@ -14,6 +14,7 @@ namespace dmzx\mchat\controller; use dmzx\mchat\core\functions; use dmzx\mchat\core\settings; use phpbb\cache\driver\driver_interface as cache_interface; +use phpbb\config\db_text as config_text; use phpbb\db\driver\driver_interface as db_interface; use phpbb\event\dispatcher_interface; use phpbb\language\language; @@ -42,6 +43,9 @@ class acp_controller /** @var db_interface */ protected $db; + /** @var config_text */ + protected $config_text; + /** @var cache_interface */ protected $cache; @@ -63,6 +67,7 @@ class acp_controller * @param user $user * @param language $lang * @param db_interface $db + * @param config_text $config_text * @param cache_interface $cache * @param request_interface $request * @param dispatcher_interface $dispatcher @@ -75,6 +80,7 @@ class acp_controller user $user, language $lang, db_interface $db, + config_text $config_text, cache_interface $cache, request_interface $request, dispatcher_interface $dispatcher, @@ -87,6 +93,7 @@ class acp_controller $this->user = $user; $this->lang = $lang; $this->db = $db; + $this->config_text = $config_text; $this->cache = $cache; $this->request = $request; $this->dispatcher = $dispatcher; @@ -123,6 +130,10 @@ class acp_controller } } + // Enable Emojis and rich text in Rules and Static Message + $mchat_new_config['mchat_rules'] = utf8_encode_ncr($mchat_new_config['mchat_rules']); + $mchat_new_config['mchat_static_message'] = utf8_encode_ncr($mchat_new_config['mchat_static_message']); + // Remove leading & trailing | characters to not break allowed BBCodes $mchat_new_config['mchat_bbcode_disallowed'] = trim($mchat_new_config['mchat_bbcode_disallowed'], '|'); @@ -212,6 +223,7 @@ class acp_controller 'S_MCHAT_PRUNE_MODE_OPTIONS' => $this->get_prune_mode_options($this->settings->cfg('mchat_prune_mode')), 'L_MCHAT_BBCODES_DISALLOWED_EXPLAIN' => $this->lang->lang('MCHAT_BBCODES_DISALLOWED_EXPLAIN', '', ''), 'L_MCHAT_TIMEOUT_EXPLAIN' => $this->lang->lang('MCHAT_TIMEOUT_EXPLAIN','', '', $this->settings->cfg('session_length')), + 'S_REPARSER_ACTIVE' => $this->is_reparser_active('dmzx.mchat.text_reparser.mchat_messages'), 'U_ACTION' => $u_action, ]; @@ -376,4 +388,27 @@ class acp_controller return $prune_mode_options; } + + /** + * @param string $reparser_name + * @return bool + */ + protected function is_reparser_active($reparser_name) + { + $reparser_resume = $this->config_text->get('reparser_resume'); + + if (empty($reparser_resume)) + { + return false; + } + + $reparser_resume = @unserialize($reparser_resume); + + if (!isset($reparser_resume[$reparser_name]['range-min']) || !isset($reparser_resume[$reparser_name]['range-max'])) + { + return false; + } + + return $reparser_resume[$reparser_name]['range-max'] >= $reparser_resume[$reparser_name]['range-min']; + } } diff --git a/core/functions.php b/core/functions.php index 0ab786b..3f64511 100644 --- a/core/functions.php +++ b/core/functions.php @@ -212,7 +212,7 @@ class functions { if (!$row['session_viewonline']) { - if (!$can_view_hidden && $row['user_id'] !== $this->user->data['user_id']) + if (!$can_view_hidden && $row['user_id'] != $this->user->data['user_id']) { continue; } @@ -324,7 +324,7 @@ class functions $sql_array['WHERE'] = $this->db->sql_in_set('m.user_id', $user_ids); $offset = 0; } - else if ($this->mchat_settings->prune_modes[$prune_mode] === 'messages') + else if ($this->mchat_settings->prune_modes[$prune_mode] == 'messages') { // Skip fixed number of messages, delete all others $sql_array['ORDER_BY'] = 'm.message_id DESC'; @@ -499,6 +499,7 @@ class functions * @var int offset SQL offset * @var array sql_array Array containing the SQL query data * @since 2.0.0-RC6 + * @deprecated 2.1.4-RC1, to be removed in 2.1.0. */ $vars = [ 'message_ids', @@ -523,6 +524,26 @@ class functions } } + /** + * Event to modify message rows before being processed and displayed + * + * @event dmzx.mchat.get_messages_modify_rowset + * @var array message_ids IDs of specific messages to fetch, e.g. for fetching edited messages + * @var int last_id The ID of the latest message that the user has, for fetching new messages + * @var int total SQL limit + * @var int offset SQL offset + * @var array rows Array containing message data + * @since 2.1.4-RC1 + */ + $vars = [ + 'message_ids', + 'last_id', + 'total', + 'offset', + 'rows', + ]; + extract($this->dispatcher->trigger_event('dmzx.mchat.get_messages_modify_rowset', compact($vars))); + return $rows; } diff --git a/core/mchat.php b/core/mchat.php index 2c538f7..58da0ff 100644 --- a/core/mchat.php +++ b/core/mchat.php @@ -733,6 +733,27 @@ class mchat $template_data['MCHAT_TITLE'] = $active_users['users_count_title']; $template_data['MCHAT_TITLE_HINT'] = strip_tags($active_users['users_total']); } + else + { + $active_users = []; + } + + /** + * Event that is triggered before data for the navigation bar is assigned to the template + * + * @event dmzx.mchat.header_link_template_data + * @var array template_data The data that is abbout to be assigned to the template + * @var array active_users Array containing information about active users. Available array keys: + * online_userlist, users_count_title, users_total, refresh_message + * Note: This array is empty if the number of active chat sessions is not + * displayed in the navbar. + * @since 2.1.4-RC1 + */ + $vars = [ + 'template_data', + 'active_users', + ]; + extract($this->dispatcher->trigger_event('dmzx.mchat.header_link_template_data', compact($vars))); $this->template->assign_vars($template_data); } @@ -766,6 +787,8 @@ class mchat $static_message = $this->lang->lang('MCHAT_STATIC_MESSAGE') ?: $this->mchat_settings->cfg('mchat_static_message'); $whois_refresh = $this->mchat_settings->cfg('mchat_whois_index') || $this->mchat_settings->cfg('mchat_navbar_link_count'); + $total_messages = $this->mchat_functions->mchat_total_message_count(); + $template_data = [ 'MCHAT_PAGE' => $page, 'MCHAT_CURRENT_URL' => $this->mchat_settings->get_current_page(), @@ -787,6 +810,7 @@ class mchat 'MCHAT_STATIC_MESS' => htmlspecialchars_decode($static_message), 'MCHAT_MAX_INPUT_HEIGHT' => $this->mchat_settings->cfg('mchat_max_input_height'), 'MCHAT_MAX_MESSAGE_LENGTH' => $this->mchat_settings->cfg('mchat_max_message_lngth'), + 'MCHAT_TOTAL_MESSAGES' => $total_messages, 'MCHAT_JUMP_TO' => $jump_to_id, 'COOKIE_NAME' => $this->mchat_settings->cfg('cookie_name', true) . '_', ]; @@ -850,7 +874,9 @@ class mchat * @var int jump_to_id The ID of the message that is being jumped to in the archive, usually when a user clicked on a quote reference * @var array actions Array containing URLs to actions the user is allowed to perform (read only) * @var array template_data The data that is about to be assigned to the template + * @var int total_messages Total number of messages * @since 2.1.1 + * @changed 2.1.4-RC1 added total_messages */ $vars = [ 'page', @@ -861,26 +887,44 @@ class mchat 'jump_to_id', 'actions', 'template_data', + 'total_messages', ]; extract($this->dispatcher->trigger_event('dmzx.mchat.render_page_get_messages_before', compact($vars))); - $rows = $this->mchat_functions->mchat_get_messages($message_ids, $last_id, $limit, $start); - $this->assign_global_template_data(); - $this->assign_messages($rows, $page); + + // Always fetch at least one message so that we can extract the latest_message_id + $soft_limit = max(1, $limit); + + $rows = $this->mchat_functions->mchat_get_messages($message_ids, $last_id, $soft_limit, $start); + + if ($limit) + { + $this->assign_messages($rows, $page); + } + + // Pass the latest_message_id to the template so that we know later where to start looking for new messages + $latest_message_id = 0; + + if ($rows) + { + $latest_message = reset($rows); + $latest_message_id = $latest_message['message_id']; + } + + $template_data['MCHAT_LATEST_MESSAGE_ID'] = $latest_message_id; // Render pagination if ($is_archive) { $archive_url = $this->helper->route('dmzx_mchat_page_archive_controller'); - $total_messages = $this->mchat_functions->mchat_total_message_count(); /** * Event to modify mChat pagination on the archive page * * @event dmzx.mchat.render_page_pagination_before * @var string archive_url Pagination base URL - * @var int total_messages Total number of messages + * @var int total_messages Total number of messages in the mChat table * @var int limit Number of messages to display per page * @var int start The message which should be considered currently active, used to determine the page we're on * @var int jump_to_id The ID of the message that is being jumped to in the archive, usually when a user clicked on a quote reference @@ -1054,8 +1098,8 @@ class mchat $user_avatars[$row['user_id']] = !$display_avatar || !$row['user_avatar'] ? '' : phpbb_get_user_avatar([ 'avatar' => $row['user_avatar'], 'avatar_type' => $row['user_avatar_type'], - 'avatar_width' => $row['user_avatar_width'] >= $row['user_avatar_height'] ? 40 : 0, - 'avatar_height' => $row['user_avatar_width'] >= $row['user_avatar_height'] ? 0 : 40, + 'avatar_width' => $row['user_avatar_width'] >= $row['user_avatar_height'] ? 36 : 0, + 'avatar_height' => $row['user_avatar_width'] >= $row['user_avatar_height'] ? 0 : 36, ]); } } @@ -1235,8 +1279,26 @@ class mchat */ protected function assign_bbcodes_smilies() { + $display_bbcodes = $this->mchat_settings->cfg('allow_bbcode') && $this->auth->acl_get('u_mchat_bbcode'); + + $display_smilies = $this->mchat_settings->cfg('allow_smilies') && $this->auth->acl_get('u_mchat_smilies') && !$this->smilies_generated; + + /** + * Event to decide whether or to display BBCodes or smilies + * + * @event dmzx.mchat.assign_bbcodes_smilies_before + * @var bool display_bbcodes Whether or not to render BBCodes + * @var bool display_smilies Whether or not to render smilies + * @since 2.1.4-RC1 + */ + $vars = [ + 'display_bbcodes', + 'display_smilies', + ]; + extract($this->dispatcher->trigger_event('dmzx.mchat.assign_bbcodes_smilies_before', compact($vars))); + // Display BBCodes - if ($this->mchat_settings->cfg('allow_bbcode') && $this->auth->acl_get('u_mchat_bbcode')) + if ($display_bbcodes) { $bbcode_template_vars = [ 'quote' => [ @@ -1275,7 +1337,7 @@ class mchat } // Display smilies - if ($this->mchat_settings->cfg('allow_smilies') && $this->auth->acl_get('u_mchat_smilies') && !$this->smilies_generated) + if ($display_smilies) { $this->mchat_settings->include_functions('posting', 'generate_smilies'); @@ -1468,6 +1530,30 @@ class mchat } } + /** + * Event to modify the raw mChat message before it is processed + * + * @event dmzx.mchat.process_message_before + * @var string message The raw message as entered by the user + * @var string message_without_bbcode The message stripped of all BBCode tags + * @var array disallowed_bbcodes The list of disallowed BBCode tags + * @var bool mchat_img Whether or not the img BBCode is allowed + * @var bool mchat_flash Whether or not the flash BBCode is allowed + * @var bool mchat_quote Whether or not the quote BBCode is allowed + * @var bool mchat_url Whether or not the url BBCode is allowed + * @since 2.1.4-RC1 + */ + $vars = [ + 'message', + 'message_without_bbcode', + 'disallowed_bbcodes', + 'mchat_img', + 'mchat_flash', + 'mchat_quote', + 'mchat_url', + ]; + extract($this->dispatcher->trigger_event('dmzx.mchat.process_message_before', compact($vars))); + $uid = $bitfield = $options = ''; generate_text_for_storage($message, $uid, $bitfield, $options, $mchat_bbcode, $mchat_magic_urls, $mchat_smilies, $mchat_img, $mchat_flash, $mchat_quote, $mchat_url, 'mchat'); diff --git a/core/notifications.php b/core/notifications.php index 89c8d57..e0a9894 100644 --- a/core/notifications.php +++ b/core/notifications.php @@ -119,9 +119,8 @@ class notifications */ public function process($rows) { - // All language keys of valid notifications for which we need to fetch post information - // from the database. We need to check for them here because notifications in < 2.0.0-RC6 - // are plain text and don't need to be processed. + // All language keys of valid notifications. We need to check for them here because + // notifications in < 2.0.0-RC6 are plain text and don't need to be processed. $notification_lang = [ 'MCHAT_NEW_POST', 'MCHAT_NEW_QUOTE', @@ -130,6 +129,20 @@ class notifications 'MCHAT_NEW_LOGIN', ]; + /** + * Event that allows to modify rows and language keys before checking for notifications + * + * @event dmzx.mchat.process_notifications_before + * @var array rows Message rows about to be checked for notifications + * @var array notification_lang Unprocessed language keys of valid/known notifications + * @since 2.1.4-RC1 + */ + $vars = [ + 'rows', + 'notification_lang', + ]; + extract($this->dispatcher->trigger_event('dmzx.mchat.process_notifications_before', compact($vars))); + $notification_langs = array_merge( // Raw notification messages in phpBB < 3.2 array_combine($notification_lang, $notification_lang), @@ -164,6 +177,24 @@ class notifications $rows[$i] = $this->process_notification($rows[$i], $type, $lang_key, $post_data); } + /** + * Event that allows to modify rows after processing their notifications + * + * @event dmzx.mchat.process_notifications_after + * @var array rows Message rows about to be checked for notifications + * @var array notification_lang Unprocessed language keys of valid/known notifications + * @var array notification_langs Processed language keys of valid/known notifications + * @var array notification_post_data Post data of notifications found in the rows array + * @since 2.1.4-RC1 + */ + $vars = [ + 'rows', + 'notification_lang', + 'notification_langs', + 'notification_post_data', + ]; + extract($this->dispatcher->trigger_event('dmzx.mchat.process_notifications_after', compact($vars))); + return $rows; } @@ -191,24 +222,15 @@ class notifications $rows = $this->db->sql_fetchrowset($result); $this->db->sql_freeresult($result); - $post_subjects = []; - - foreach ($rows as $row) - { - $post_subjects[$row['post_id']] = [ - 'post_subject' => $row['post_subject'], - 'forum_id' => $row['forum_id'], - 'forum_name' => $row['forum_name'], - ]; - } + $existing_post_ids = array_column($rows, 'post_id'); + $existing_posts = array_combine($existing_post_ids, $rows); // Map IDs of missing posts to null - $missing_post_subjects = array_fill_keys(array_diff($post_ids, array_keys($post_subjects)), null); + $missing_posts = array_fill_keys(array_diff($post_ids, $existing_post_ids), null); - return $post_subjects + $missing_post_subjects; + return $existing_posts + $missing_posts; } - /** * Converts the message field of the post row so that it can be passed to generate_text_for_display() * @@ -399,4 +421,33 @@ class notifications return ''; } + + /** + * Delete post notification messages, for example when disapproving posts + * + * @param array $post_ids + */ + public function delete_post_notifications($post_ids) + { + if ($post_ids) + { + $sql = 'DELETE FROM ' . $this->mchat_settings->get_table_mchat() . ' + WHERE forum_id <> 0 AND ' . $this->db->sql_in_set('post_id', $post_ids); + $this->db->sql_query($sql); + } + } + + /** + * Change the user to which a post notification belongs + * + * @param int $post_id + * @param int $user_id + */ + public function update_post_notification_user($post_id, $user_id) + { + $sql = 'UPDATE ' . $this->mchat_settings->get_table_mchat() . ' + SET user_id = ' . (int) $user_id . ' + WHERE forum_id <> 0 AND post_id = ' . (int) $post_id; + $this->db->sql_query($sql); + } } diff --git a/core/settings.php b/core/settings.php index f3c341b..494b5a7 100644 --- a/core/settings.php +++ b/core/settings.php @@ -15,6 +15,7 @@ use phpbb\auth\auth; use phpbb\config\config; use phpbb\config\db_text; use phpbb\event\dispatcher_interface; +use phpbb\exception\runtime_exception; use phpbb\language\language; use phpbb\user; @@ -361,6 +362,11 @@ class settings } } + if (isset($this->config[$config])) + { + return $this->config[$config]; + } + $global_text_settings = $this->global_text_settings(); if (isset($global_text_settings[$config])) @@ -369,7 +375,7 @@ class settings return $global_text_values[$config]; } - return $this->config[$config]; + throw new runtime_exception(); } /** diff --git a/event/main_listener.php b/event/main_listener.php index 1bfb50a..99debce 100644 --- a/event/main_listener.php +++ b/event/main_listener.php @@ -84,9 +84,11 @@ class main_listener implements EventSubscriberInterface 'core.page_header' => 'add_page_header_link', 'core.index_modify_page_title' => 'display_mchat_on_index', 'core.submit_post_end' => 'insert_posting', + 'core.delete_posts_after' => 'delete_posts_after', 'core.display_custom_bbcodes_modify_sql' => [['remove_disallowed_bbcodes'], ['pm_compose_add_quote']], 'core.generate_smilies_after' => 'generate_smilies_after', 'core.user_add_modify_data' => 'user_registration_set_default_values', + 'core.mcp_change_poster_after' => 'mcp_change_poster_after', 'core.login_box_redirect' => 'user_login_success', 'core.session_gc_after' => 'session_gc', ]; @@ -141,6 +143,14 @@ class main_listener implements EventSubscriberInterface $this->mchat_notifications->insert_post($event['mode'], $event['data']['forum_id'], $event['data']['post_id']); } + /** + * @param data $event + */ + public function delete_posts_after(data $event) + { + $this->mchat_notifications->delete_post_notifications($event['post_ids']); + } + /** * @param data $event */ @@ -167,6 +177,14 @@ class main_listener implements EventSubscriberInterface $event['sql_ary'] = $this->mchat->set_user_default_values($event['sql_ary']); } + /** + * @param data $event + */ + public function mcp_change_poster_after(data $event) + { + $this->mchat_notifications->update_post_notification_user($event['post_info']['post_id'], $event['userdata']['user_id']); + } + /** * @param data $event */ diff --git a/language/en/mchat_acp.php b/language/en/mchat_acp.php index 4b16bad..4d6d588 100644 --- a/language/en/mchat_acp.php +++ b/language/en/mchat_acp.php @@ -64,7 +64,7 @@ $lang = array_merge($lang, [ 'MCHAT_VERSION' => 'Version', 'MCHAT_RULES' => 'Rules', 'MCHAT_RULES_EXPLAIN' => 'Enter the rules here. HTML code is allowed. Set to empty to disable the display.
This message can be translated: edit the MCHAT_RULES_MESSAGE language key in /ext/dmzx/mchat/language/XX/mchat.php.', - 'MCHAT_CONFIG_SAVED' => 'mChat configuration has been updated', + 'MCHAT_CONFIG_SAVED' => 'mChat configuration has been updated.', 'MCHAT_AVATARS' => 'Display avatars', 'MCHAT_AVATARS_EXPLAIN' => 'If set to yes, resized user avatars will be displayed.', 'MCHAT_INDEX' => 'Display mChat on the index page', @@ -129,7 +129,11 @@ $lang = array_merge($lang, [ 'MCHAT_SOUND' => 'Play sounds for new, edited and deleted messages', 'MCHAT_PURGE' => 'Delete all messages now', 'MCHAT_PURGE_CONFIRM' => 'Confirm deleting all messages', - 'MCHAT_PURGED' => 'All mChat messages have been successfully deleted', + 'MCHAT_PURGED' => 'All mChat messages have been successfully deleted.', + + 'MCHAT_REPARSER_STATUS' => 'Message reparser status', + 'MCHAT_REPARSER_ACTIVE' => 'active', + 'MCHAT_REPARSER_FINISHED' => 'finished', // '%1$s' contains 'Retain posts' and 'Delete posts' respectively 'MCHAT_RETAIN_MESSAGES' => '%1$s and retain mChat messages', diff --git a/migrations/mchat_2_1_4.php b/migrations/mchat_2_1_4.php new file mode 100644 index 0000000..709d42d --- /dev/null +++ b/migrations/mchat_2_1_4.php @@ -0,0 +1,30 @@ += container.get(0).scrollHeight - container.height() - scrollLeeway) { - var animateOptions = { - duration: dataAddMessageBefore.delay - 10, - easing: 'swing' - }; - this.message.slideDown(animateOptions); - if (mChat.messageTop) { - container.animate({scrollTop: 0}, animateOptions); - } else { - animateOptions.complete = function() { - var scrollHeight = container.get(0).scrollHeight; - if (container.scrollTop() + container.innerHeight() < scrollHeight) { - container.animate({scrollTop: scrollHeight}, animateOptions); - } - }; - animateOptions.complete(); - } - } else { - this.message.show(); - if (mChat.messageTop) { - this.container.scrollTop(scrollTop + this.message.outerHeight()); - } - } - this.message.addClass('mchat-message-flash'); + $messages.reverse(mChat.messageTop).hide().each(this.addMessage); + }, + addMessage: function(index) { + var $message = $(this); + var dataAddMessageBefore = { + message: $message, + delay: mChat.refreshInterval ? 400 : 0, + abort: $.inArray($message.data('mchat-id'), mChat.messageIds) !== -1, + playSound: index === 0, + titleAlert: index === 0 + }; + $(mChat).trigger('mchat_add_message_before', [dataAddMessageBefore]); + if (dataAddMessageBefore.abort) { + return; + } + if (dataAddMessageBefore.playSound) { + mChat.sound('add'); + } + if (dataAddMessageBefore.titleAlert) { + mChat.titleAlert(); + } + mChat.messageIds.push($message.data('mchat-id')); + mChat.fixJumpToUrl.call($message); + var dataAddMessageAnimateBefore = { + container: mChat.cached('messages'), + message: $message, + add: function() { + if (mChat.messageTop) { + this.container.prepend(this.message); + } else { + this.container.append(this.message); + } + }, + show: function() { + var scrollLeeway = 20; + var scrollTop = this.container.scrollTop(); + var scrollHeight = this.container[0].scrollHeight; + this.message.show(); + this.message.addClass('mchat-message-flash'); + if (mChat.messageTop) { + if (scrollTop <= scrollLeeway) { + this.container.scrollTop(0); } - }; - $(mChat).trigger('mchat_add_message_animate_before', [dataAddMessageAnimateBefore]); - dataAddMessageAnimateBefore.add(); - dataAddMessageAnimateBefore.show(); - }, i * dataAddMessageBefore.delay); - if (mChat.editDeleteLimit && $message.data('mchat-edit-delete-limit') && $message.find('[data-mchat-action="edit"], [data-mchat-action="del"]').length > 0) { - var id = $message.prop('id'); - setTimeout(function() { - $('#' + id).find('[data-mchat-action="edit"], [data-mchat-action="del"]').fadeOut(function() { - $(this).closest('li').remove(); - }); - }, mChat.editDeleteLimit); + } else { + var height = this.container.height(); + if (scrollHeight - height - scrollTop <= scrollLeeway) { + this.container.scrollTop(scrollHeight); + } + } } - mChat.startRelativeTimeUpdate.call($message); - }); + }; + $(mChat).trigger('mchat_add_message_animate_before', [dataAddMessageAnimateBefore]); + dataAddMessageAnimateBefore.add(); + dataAddMessageAnimateBefore.show(); + if (mChat.editDeleteLimit && $message.data('mchat-edit-delete-limit') && $message.find('[data-mchat-action="edit"], [data-mchat-action="del"]').length > 0) { + var id = $message.prop('id'); + setTimeout(function() { + $('#' + id).find('[data-mchat-action="edit"], [data-mchat-action="del"]').fadeOut(function() { + $(this).closest('li').remove(); + }); + }, mChat.editDeleteLimit); + } + mChat.startRelativeTimeUpdate.call($message); }, updateMessages: function($messages) { var playSound = true; @@ -729,7 +717,22 @@ jQuery(function($) { mChat.cache[name] = $('#mchat-' + name); } return mChat.cache[name]; - } + }, + onKeyPress: function(e, callbacks) { + var isEnter = e.which === 10 || e.which === 13; + if (isEnter && $(e.target).is('textarea')) { + var callback; + var isCtrl = e.ctrlKey || e.metaKey; + if (!mChat.maxInputHeight || !isCtrl === !mChat.storage.get('no_enter')) { + callback = 'submit'; + } else if (mChat.maxInputHeight && isCtrl) { + callback = 'newline'; + } + if (typeof callbacks[callback] === 'function') { + callbacks[callback].call(this, e); + } + } + }, }); mChat.messageIds = mChat.cached('messages').children() @@ -737,6 +740,10 @@ jQuery(function($) { .each(mChat.fixJumpToUrl) .map(function() { return $(this).data('mchat-id'); }).get(); + if (!mChat.messageIds.length) { + mChat.messageIds.push(mChat.latestMessageId); + } + mChat.hiddenFields = {}; mChat.cached('form').find('input[type=hidden]').each(function() { mChat.hiddenFields[this.name] = this.value; @@ -772,10 +779,9 @@ jQuery(function($) { }); $.each(['userlist', 'smilies', 'bbcodes', 'colour'], function(i, elem) { - if (mChat.storage.get('show_' + elem)) { - $('.mchat-button-' + elem).addClass('mchat-button-is-down'); - mChat.cached(elem).toggle(); - } + var isVisible = mChat.storage.get('show_' + elem) === 'yes'; + $('.mchat-button-' + elem).toggleClass('mchat-button-is-down', isVisible); + mChat.cached(elem).toggle(isVisible); }); var toggleRememberColor = function() { @@ -827,19 +833,18 @@ jQuery(function($) { }); } - mChat.cached('form').submit(function(e) { + mChat.cached('form').on('submit', function(e) { e.preventDefault(); - }).keypress(function(e) { - var isEnter = e.which === 10 || e.which === 13; - if (isEnter && mChat.cached('input').is(e.target)) { - var isCtrl = e.ctrlKey || e.metaKey; - if (!mChat.maxInputHeight || !isCtrl === !mChat.storage.get('no_enter')) { + }).on('keypress', function(e) { + mChat.onKeyPress(e, { + 'submit': function(e) { e.preventDefault(); mChat.add(); - } else if (mChat.maxInputHeight && isCtrl) { + }, + 'newline': function() { mChat.appendText('\n'); } - } + }); }); if (mChat.showCharCount || mChat.mssgLngth) { @@ -870,9 +875,19 @@ jQuery(function($) { e.preventDefault(); mChat.jumpToMessage.call(this); }).on('click', '.mchat-panel-buttons button', function() { - var $this = $(this).blur(); + var $this = $(this).trigger('blur'); if ($this.hasClass('mchat-button-down')) { $this.toggleClass('mchat-button-is-down'); } + }).on('keydown.phpbb.alert', mChat.cached('confirm'), function(e) { + mChat.onKeyPress(e, { + 'newline': function(e) { + e.stopImmediatePropagation(); + var $target = $(e.target); + $target.val(function(i, text) { + return text + '\n'; + }); + } + }); }); }); diff --git a/styles/all/template/mchat_script_data.html b/styles/all/template/mchat_script_data.html index b1ce974..457409f 100644 --- a/styles/all/template/mchat_script_data.html +++ b/styles/all/template/mchat_script_data.html @@ -35,6 +35,7 @@ maxInputHeight : {{ MCHAT_MAX_INPUT_HEIGHT }}, editDeleteLimit : {{ MCHAT_EDIT_DELETE_LIMIT }}, logId : {{ MCHAT_LOG_ID }}, + latestMessageId : {{ MCHAT_LATEST_MESSAGE_ID | default(0) }}, removeBBCodes : '{{ MCHAT_DISALLOWED_BBCODES | escape('js') }}', // Language diff --git a/styles/prosilver/template/mchat_body.html b/styles/prosilver/template/mchat_body.html index 381a568..3f1fc68 100644 --- a/styles/prosilver/template/mchat_body.html +++ b/styles/prosilver/template/mchat_body.html @@ -84,13 +84,13 @@ {% EVENT dmzx_mchat_static_container_after %} {% endif %} -
+
{% EVENT dmzx_mchat_messages_container_before %}
    {% if loops.mchatrow|length %} {% INCLUDE '@dmzx_mchat/mchat_messages.html' %} - {% else %} + {% elseif not MCHAT_TOTAL_MESSAGES %}
  • {{ lang('MCHAT_NOMESSAGE') }}
  • {% endif %}
diff --git a/styles/prosilver/template/mchat_messages_icons.html b/styles/prosilver/template/mchat_messages_icons.html index 513f833..f4c1c0e 100644 --- a/styles/prosilver/template/mchat_messages_icons.html +++ b/styles/prosilver/template/mchat_messages_icons.html @@ -12,14 +12,14 @@ {% if definition.MCHAT_ALLOW_MENTION or definition.MCHAT_ALLOW_QUOTE or definition.MCHAT_ALLOW_LIKE or definition.MCHAT_ALLOW_PM or MCHAT_ALLOW_IP or MCHAT_ALLOW_PERMISSIONS or definition.MCHAT_ALLOW_EDIT or definition.MCHAT_ALLOW_DEL or definition.MCHAT_ADD_CUSTOM_BUTTON %} {% endif %} diff --git a/styles/prosilver/theme/mchat.css b/styles/prosilver/theme/mchat.css index 5640c2d..346a06e 100644 --- a/styles/prosilver/theme/mchat.css +++ b/styles/prosilver/theme/mchat.css @@ -26,11 +26,11 @@ display: -ms-flexbox; display: flex; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: left; - -ms-flex-pack: left; - justify-content: left; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: start; } .mchat-wrapper li.header dd { @@ -118,7 +118,7 @@ .mchat-avatar { float: left; - width: 40px; + width: 36px; margin-right: 5px; } @@ -149,7 +149,7 @@ margin: 0 3px; } -.mchat-wrapper .mchat-buttons .fa { +.mchat-wrapper .mchat-buttons .icon { font-size: 12pt; } @@ -164,7 +164,7 @@ .mchat-text { clear: both; overflow: hidden; - padding: 2px 5px; + padding: 0 5px 1px; font-size: 1.2em; }