diff --git a/phpBB/config/default/container/services_notification.yml b/phpBB/config/default/container/services_notification.yml index c18e358114..65552b1e13 100644 --- a/phpBB/config/default/container/services_notification.yml +++ b/phpBB/config/default/container/services_notification.yml @@ -95,6 +95,15 @@ services: tags: - { name: notification.type } + notification.type.mention: + class: phpbb\notification\type\mention + shared: false + parent: notification.type.post + calls: + - [set_helper, ['@text_formatter.s9e.mention_helper']] + tags: + - { name: notification.type } + notification.type.pm: class: phpbb\notification\type\pm shared: false diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index adc09b9382..c7c6375b06 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -575,6 +575,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ // Mark all topic notifications read for this user $phpbb_notifications->mark_notifications(array( 'notification.type.topic', + 'notification.type.mention', 'notification.type.quote', 'notification.type.bookmark', 'notification.type.post', @@ -660,6 +661,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ $db->sql_freeresult($result); $phpbb_notifications->mark_notifications_by_parent(array( + 'notification.type.mention', 'notification.type.quote', 'notification.type.bookmark', 'notification.type.post', @@ -771,6 +773,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ ), $topic_id, $user->data['user_id'], $post_time); $phpbb_notifications->mark_notifications_by_parent(array( + 'notification.type.mention', 'notification.type.quote', 'notification.type.bookmark', 'notification.type.post', diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index dc76a2eb80..f0813708c3 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -908,6 +908,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = // Notifications types to delete $delete_notifications_types = array( + 'notification.type.mention', 'notification.type.quote', 'notification.type.approve_post', 'notification.type.post_in_queue', diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 817a98f836..14b50a4a31 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -2405,6 +2405,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data { case 'post': $phpbb_notifications->add_notifications(array( + 'notification.type.mention', 'notification.type.quote', 'notification.type.topic', ), $notification_data); @@ -2413,6 +2414,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data case 'reply': case 'quote': $phpbb_notifications->add_notifications(array( + 'notification.type.mention', 'notification.type.quote', 'notification.type.bookmark', 'notification.type.post', @@ -2432,6 +2434,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data } $phpbb_notifications->update_notifications(array( + 'notification.type.mention', 'notification.type.bookmark', 'notification.type.topic', 'notification.type.post', diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index fe54a01de7..eebb8e4fc4 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -810,10 +810,14 @@ class mcp_queue ), $post_data); } } - $phpbb_notifications->add_notifications(array('notification.type.quote'), $post_data); + $phpbb_notifications->add_notifications(array( + 'notification.type.mention', + 'notification.type.quote', + ), $post_data); $phpbb_notifications->delete_notifications('notification.type.post_in_queue', $post_id); $phpbb_notifications->mark_notifications(array( + 'notification.type.mention', 'notification.type.quote', 'notification.type.bookmark', 'notification.type.post', @@ -1045,12 +1049,13 @@ class mcp_queue if ($topic_data['topic_visibility'] == ITEM_UNAPPROVED) { $phpbb_notifications->add_notifications(array( + 'notification.type.mention', 'notification.type.quote', 'notification.type.topic', ), $topic_data); } - $phpbb_notifications->mark_notifications('quote', $topic_data['post_id'], $user->data['user_id']); + $phpbb_notifications->mark_notifications(array('mention', 'quote'), $topic_data['post_id'], $user->data['user_id']); $phpbb_notifications->mark_notifications('topic', $topic_id, $user->data['user_id']); if ($notify_poster) diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index 24fd293326..f04a0e891b 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -475,6 +475,9 @@ $lang = array_merge($lang, array( 'NOTIFICATION_FORUM' => 'Forum: %1$s', 'NOTIFICATION_GROUP_REQUEST' => 'Group request from %1$s to join the group %2$s.', 'NOTIFICATION_GROUP_REQUEST_APPROVED' => 'Group request approved to join the group %1$s.', + 'NOTIFICATION_MENTION' => array( + 1 => 'Mentioned by %1$s in:', + ), 'NOTIFICATION_METHOD_INVALID' => 'The method "%s" does not refer to a valid notification method.', 'NOTIFICATION_PM' => 'Private Message from %1$s:', 'NOTIFICATION_POST' => array( diff --git a/phpBB/language/en/email/mention.txt b/phpBB/language/en/email/mention.txt new file mode 100644 index 0000000000..51c161453e --- /dev/null +++ b/phpBB/language/en/email/mention.txt @@ -0,0 +1,20 @@ +Subject: Topic reply notification - "{TOPIC_TITLE}" + +Hello {USERNAME}, + +You are receiving this notification because "{AUTHOR_NAME}" mentioned you in the topic "{TOPIC_TITLE}" at "{SITENAME}". You can use the following link to view the reply made. + +If you want to view the post where you have been mentioned, click the following link: +{U_VIEW_POST} + +If you want to view the topic, click the following link: +{U_TOPIC} + +If you want to view the forum, click the following link: +{U_FORUM} + +If you no longer wish to receive updates about replies mentioning you, please update your notification settings here: + +{U_NOTIFICATION_SETTINGS} + +{EMAIL_SIG} diff --git a/phpBB/language/en/ucp.php b/phpBB/language/en/ucp.php index 446f357f5d..8c4e59904c 100644 --- a/phpBB/language/en/ucp.php +++ b/phpBB/language/en/ucp.php @@ -332,6 +332,7 @@ $lang = array_merge($lang, array( 'NOTIFICATION_TYPE_GROUP_REQUEST' => 'Someone requests to join a group you lead', 'NOTIFICATION_TYPE_FORUM' => 'Someone replies to a topic in a forum to which you are subscribed', 'NOTIFICATION_TYPE_IN_MODERATION_QUEUE' => 'A post or topic needs approval', + 'NOTIFICATION_TYPE_MENTION' => 'Someone mentiones you in a post', 'NOTIFICATION_TYPE_MODERATION_QUEUE' => 'Your topics/posts are approved or disapproved by a moderator', 'NOTIFICATION_TYPE_PM' => 'Someone sends you a private message', 'NOTIFICATION_TYPE_POST' => 'Someone replies to a topic to which you are subscribed', diff --git a/phpBB/phpbb/notification/type/mention.php b/phpBB/phpbb/notification/type/mention.php new file mode 100644 index 0000000000..54c180ad2c --- /dev/null +++ b/phpBB/phpbb/notification/type/mention.php @@ -0,0 +1,172 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\notification\type; + +/** +* Post mentioning notifications class +* This class handles notifying users when they have been mentioned in a post +*/ + +class mention extends \phpbb\notification\type\post +{ + /** + * @var \phpbb\textformatter\s9e\mention_helper + */ + protected $helper; + + /** + * Get notification type name + * + * @return string + */ + public function get_type() + { + return 'notification.type.mention'; + } + + /** + * Language key used to output the text + * + * @var string + */ + protected $language_key = 'NOTIFICATION_MENTION'; + + /** + * Notification option data (for outputting to the user) + * + * @var bool|array False if the service should use it's default data + * Array of data (including keys 'id', 'lang', and 'group') + */ + static public $notification_option = array( + 'lang' => 'NOTIFICATION_TYPE_MENTION', + 'group' => 'NOTIFICATION_GROUP_POSTING', + ); + + /** + * Is available + */ + public function is_available() + { + return true; + } + + /** + * Find the users who want to receive notifications + * + * @param array $post Data from submit_post + * @param array $options Options for finding users for notification + * + * @return array + */ + public function find_users_for_notification($post, $options = array()) + { + $options = array_merge(array( + 'ignore_users' => array(), + ), $options); + + $user_ids = $this->helper->get_mentioned_users($post['post_text']); + + $user_ids = array_unique($user_ids); + + $user_ids = array_diff($user_ids, [(int) $post['poster_id']]); + + if (empty($user_ids)) + { + return array(); + } + + return $this->get_authorised_recipients($user_ids, $post['forum_id'], $options, true); + } + + /** + * Update a notification + * TODO: decide what to do with this stuff + * + * @param array $post Data specific for this type that will be updated + * @return true + */ + public function update_notifications($post) + { + $old_notifications = $this->notification_manager->get_notified_users($this->get_type(), array( + 'item_id' => static::get_item_id($post), + )); + + // Find the new users to notify + $notifications = $this->find_users_for_notification($post); + + // Find the notifications we must delete + $remove_notifications = array_diff(array_keys($old_notifications), array_keys($notifications)); + + // Find the notifications we must add + $add_notifications = array(); + foreach (array_diff(array_keys($notifications), array_keys($old_notifications)) as $user_id) + { + $add_notifications[$user_id] = $notifications[$user_id]; + } + + // Add the necessary notifications + $this->notification_manager->add_notifications_for_users($this->get_type(), $post, $add_notifications); + + // Remove the necessary notifications + if (!empty($remove_notifications)) + { + $this->notification_manager->delete_notifications($this->get_type(), static::get_item_id($post), false, $remove_notifications); + } + + // return true to continue with the update code in the notifications service (this will update the rest of the notifications) + return true; + } + + /** + * {inheritDoc} + */ + public function get_redirect_url() + { + return $this->get_url(); + } + + /** + * Get email template + * + * @return string|bool + */ + public function get_email_template() + { + return 'mention'; + } + + /** + * Get email template variables + * + * @return array + */ + public function get_email_template_variables() + { + $user_data = $this->user_loader->get_user($this->get_data('poster_id')); + + return array_merge(parent::get_email_template_variables(), array( + 'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']), + )); + } + + /** + * Set the helper service used to retrieve mentioned used + * + * @param \phpbb\textformatter\s9e\mention_helper $helper + */ + public function set_helper(\phpbb\textformatter\s9e\mention_helper $helper) + { + $this->helper = $helper; + } +} diff --git a/phpBB/phpbb/textformatter/s9e/mention_helper.php b/phpBB/phpbb/textformatter/s9e/mention_helper.php index b383dc46f7..66092dbbc5 100644 --- a/phpBB/phpbb/textformatter/s9e/mention_helper.php +++ b/phpBB/phpbb/textformatter/s9e/mention_helper.php @@ -149,4 +149,30 @@ class mention_helper } ); } + + /** + * Get a list of mentioned users + * TODO: decide what to do with groups + * + * @param string $xml Parsed text + * @return int[] List of user IDs + */ + public function get_mentioned_users($xml) + { + $user_ids = array(); + if (strpos($xml, 'loadXML($xml); + $xpath = new \DOMXPath($dom); + foreach ($xpath->query('//MENTION/@user_id') as $user_id) + { + $user_ids[] = (int) $user_id->textContent; + } + + return $user_ids; + } }