diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index ff0a59a4e3..26d9b81896 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -2256,7 +2256,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $notifications->update_notifications('post', array_merge($data, array( 'post_username' => $username, ))); - $notifications->add_notifications('quote', array_merge($data, array( + $notifications->update_notifications('quote', array_merge($data, array( 'post_username' => $username, ))); break; diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php index 0f7752446a..10af5b349b 100644 --- a/phpBB/includes/notifications/service.php +++ b/phpBB/includes/notifications/service.php @@ -110,7 +110,6 @@ class phpbb_notifications_service * Add a notification * * @param string $item_type Type identifier - * @param int $item_id Identifier within the type * @param array $data Data specific for this type that will be inserted */ public function add_notifications($item_type, $data) @@ -120,20 +119,38 @@ class phpbb_notifications_service $item_id = $item_type_class_name::get_item_id($data); // Update any existing notifications for this item - $this->update_notifications($item_type, $item_id, $data); - - $notify_users = $user_ids = array(); - $notification_objects = $notification_methods = array(); - $new_rows = array(); + $this->update_notifications($item_type, $data); // find out which users want to receive this type of notification $notify_users = $item_type_class_name::find_users_for_notification($this->phpbb_container, $data); + $this->add_notifications_for_users($item_type, $data, $notify_users); + } + + /** + * Add a notification for specific users + * + * @param string $item_type Type identifier + * @param array $data Data specific for this type that will be inserted + * @param array $notify_users User list to notify + */ + public function add_notifications_for_users($item_type, $data, $notify_users) + { + $item_type_class_name = $this->get_item_type_class_name($item_type); + + $item_id = $item_type_class_name::get_item_id($data); + + $user_ids = array(); + $notification_objects = $notification_methods = array(); + $new_rows = array(); + // Never send notifications to the anonymous user or the current user! unset($notify_users[ANONYMOUS], $notify_users[$this->phpbb_container->get('user')->data['user_id']]); // Make sure not to send new notifications to users who've already been notified about this item // This may happen when an item was added, but now new users are able to see the item + // todo Users should not receive notifications from multiple events from the same item (ex: for a topic reply with a quote including your username) + // Probably should be handled within each type? $sql = 'SELECT user_id FROM ' . NOTIFICATIONS_TABLE . " WHERE item_type = '" . $this->db->sql_escape($item_type) . "' @@ -202,6 +219,16 @@ class phpbb_notifications_service { $item_type_class_name = $this->get_item_type_class_name($item_type); + // Allow the notifications class to over-ride the update_notifications functionality + if (method_exists($item_type_class_name, 'update_notifications')) + { + // Return False to over-ride the rest of the update + if ($item_type_class_name::update_notifications($this->phpbb_container, $data) === false) + { + return; + } + } + $item_id = $item_type_class_name::get_item_id($data); $notification = new $item_type_class_name($this->phpbb_container); diff --git a/phpBB/includes/notifications/type/pm.php b/phpBB/includes/notifications/type/pm.php index c78efcdd55..8ea1045641 100644 --- a/phpBB/includes/notifications/type/pm.php +++ b/phpBB/includes/notifications/type/pm.php @@ -41,7 +41,7 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base */ public static function get_item_id($pm) { - return $pm['msg_id']; + return (int) $pm['msg_id']; } /** diff --git a/phpBB/includes/notifications/type/post.php b/phpBB/includes/notifications/type/post.php index 4fd4128168..d5759111cf 100644 --- a/phpBB/includes/notifications/type/post.php +++ b/phpBB/includes/notifications/type/post.php @@ -41,7 +41,7 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base */ public static function get_item_id($post) { - return $post['post_id']; + return (int) $post['post_id']; } /** diff --git a/phpBB/includes/notifications/type/quote.php b/phpBB/includes/notifications/type/quote.php index 8f93c67de1..e17769acea 100644 --- a/phpBB/includes/notifications/type/quote.php +++ b/phpBB/includes/notifications/type/quote.php @@ -146,4 +146,59 @@ class phpbb_notifications_type_quote extends phpbb_notifications_type_post censor_text($this->get_data('topic_title')) ); } + + /** + * Update a notification + * + * @param ContainerBuilder $phpbb_container + * @param array $data Data specific for this type that will be updated + */ + public static function update_notifications(ContainerBuilder $phpbb_container, $post) + { + $service = $phpbb_container->get('notifications'); + $db = $phpbb_container->get('dbal.conn'); + + $old_notifications = array(); + $sql = 'SELECT user_id + FROM ' . NOTIFICATIONS_TABLE . " + WHERE item_type = '" . self::get_item_type() . "' + AND item_id = " . self::get_item_id($post); + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $old_notifications[] = $row['user_id']; + } + $db->sql_freeresult($result); + + // Find the new users to notify + $notifications = self::find_users_for_notification($phpbb_container, $post); + + // Find the notifications we must delete + $remove_notifications = array_diff($old_notifications, array_keys($notifications)); + + // Find the notifications we must add + $add_notifications = array(); + foreach (array_diff(array_keys($notifications), $old_notifications) as $user_id) + { + $add_notifications[$user_id] = $notifications[$user_id]; + } + + var_dump($old_notifications, $notifications, $remove_notifications, $add_notifications); + + // Add the necessary notifications + $service->add_notifications_for_users(self::get_item_type(), $post, $add_notifications); + + // Remove the necessary notifications + if (!empty($remove_notifications)) + { + $sql = 'DELETE FROM ' . NOTIFICATIONS_TABLE . " + WHERE item_type = '" . self::get_item_type() . "' + AND item_id = " . self::get_item_id($post) . ' + AND ' . $db->sql_in_set('user_id', $remove_notifications); + $db->sql_query($sql); + } + + // return true to continue with the update code in the notifications service (this will update the rest of the notifications) + return true; + } } diff --git a/phpBB/includes/notifications/type/topic.php b/phpBB/includes/notifications/type/topic.php index 209d23b823..cb7bfdbb8f 100644 --- a/phpBB/includes/notifications/type/topic.php +++ b/phpBB/includes/notifications/type/topic.php @@ -41,7 +41,7 @@ class phpbb_notifications_type_topic extends phpbb_notifications_type_base */ public static function get_item_id($post) { - return $post['topic_id']; + return (int) $post['topic_id']; } /**