From f3664b07d289d34c9181620ded665845cf61d282 Mon Sep 17 00:00:00 2001 From: Jakub Senko Date: Thu, 18 Oct 2018 09:35:16 +0200 Subject: [PATCH] [ticket/14754] Use dedicated table to stop receiving notifications PHPBB3-14754 --- .../container/services_notification.yml | 6 +- phpBB/config/default/container/tables.yml | 1 + .../v32x/add_email_notifications_table.php | 50 +++++++ phpBB/phpbb/notification/method/email.php | 125 ++++++++++-------- tests/notification/base.php | 6 +- tests/notification/submit_post_base.php | 6 +- 6 files changed, 121 insertions(+), 73 deletions(-) create mode 100644 phpBB/phpbb/db/migration/data/v32x/add_email_notifications_table.php diff --git a/phpBB/config/default/container/services_notification.yml b/phpBB/config/default/container/services_notification.yml index a9db2bdd38..a10330143f 100644 --- a/phpBB/config/default/container/services_notification.yml +++ b/phpBB/config/default/container/services_notification.yml @@ -209,11 +209,7 @@ services: - '@dbal.conn' - '%core.root_path%' - '%core.php_ext%' - - '%tables.topics_watch%' - - '%tables.topics_track%' - - '%tables.posts%' - - '%tables.forums_watch%' - - '%tables.forums_track%' + - '%tables.email_notifications%' tags: - { name: notification.method } diff --git a/phpBB/config/default/container/tables.yml b/phpBB/config/default/container/tables.yml index 4aed35710b..de082043fd 100644 --- a/phpBB/config/default/container/tables.yml +++ b/phpBB/config/default/container/tables.yml @@ -20,6 +20,7 @@ parameters: tables.confirm: '%core.table_prefix%confirm' tables.disallow: '%core.table_prefix%disallow' tables.drafts: '%core.table_prefix%drafts' + tables.email_notifications: '%core.table_prefix%email_notifications' tables.ext: '%core.table_prefix%ext' tables.extensions: '%core.table_prefix%extensions' tables.extension_groups: '%core.table_prefix%extension_groups' diff --git a/phpBB/phpbb/db/migration/data/v32x/add_email_notifications_table.php b/phpBB/phpbb/db/migration/data/v32x/add_email_notifications_table.php new file mode 100644 index 0000000000..46a9e45f67 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/add_email_notifications_table.php @@ -0,0 +1,50 @@ + + * @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\db\migration\data\v32x; + +class add_email_notifications_table extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v323', + ); + } + + public function update_schema() + { + return array( + 'add_tables' => array( + $this->table_prefix . 'email_notifications' => array( + 'COLUMNS' => array( + 'notification_type_id' => array('USINT', 0), + 'item_id' => array('UINT', 0), + 'item_parent_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + ), + 'PRIMARY_KEY' => array('notification_type_id', 'item_id', 'item_parent_id', 'user_id'), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_tables' => array( + $this->table_prefix . 'email_notifications', + ), + ); + } +} diff --git a/phpBB/phpbb/notification/method/email.php b/phpBB/phpbb/notification/method/email.php index 66182f2d78..10318ea215 100644 --- a/phpBB/phpbb/notification/method/email.php +++ b/phpBB/phpbb/notification/method/email.php @@ -32,19 +32,7 @@ class email extends \phpbb\notification\method\messenger_base protected $db; /** @var string */ - protected $topics_watch_table; - - /** @var string */ - protected $topics_track_table; - - /** @var string */ - protected $posts_table; - - /** @var string */ - protected $forums_watch_table; - - /** @var string */ - protected $forums_track_table; + protected $email_notifications_table; /** * Notification Method email Constructor @@ -55,24 +43,16 @@ class email extends \phpbb\notification\method\messenger_base * @param \phpbb\db\driver\driver_interface $db * @param string $phpbb_root_path * @param string $php_ext - * @param string $topics_watch_table - * @param string $topics_track_table - * @param string $posts_table - * @param string $forums_watch_table - * @param string $forums_track_table + * @param string $email_notifications_table */ - public function __construct(\phpbb\user_loader $user_loader, \phpbb\user $user, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, $phpbb_root_path, $php_ext, $topics_watch_table, $topics_track_table, $posts_table, $forums_watch_table, $forums_track_table) + public function __construct(\phpbb\user_loader $user_loader, \phpbb\user $user, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, $phpbb_root_path, $php_ext, $email_notifications_table) { parent::__construct($user_loader, $phpbb_root_path, $php_ext); $this->user = $user; $this->config = $config; $this->db = $db; - $this->topics_watch_table = $topics_watch_table; - $this->topics_track_table = $topics_track_table; - $this->posts_table = $posts_table; - $this->forums_watch_table = $forums_watch_table; - $this->forums_track_table = $forums_track_table; + $this->email_notifications_table = $email_notifications_table; } /** @@ -105,42 +85,18 @@ class email extends \phpbb\notification\method\messenger_base { $notified_users = array(); - if ($notification_type_id == 'notification.type.post' && !empty($options['item_parent_id'])) + $sql = 'SELECT user_id + FROM ' . $this->email_notifications_table . ' + WHERE notification_type_id = ' . (int) $notification_type_id . + (isset($options['item_id']) ? ' AND item_id = ' . (int) $options['item_id'] : '') . + (isset($options['item_parent_id']) ? ' AND item_parent_id = ' . (int) $options['item_parent_id'] : '') . + (isset($options['user_id']) ? ' AND user_id = ' . (int) $options['user_id'] : ''); + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) { - // Topics watch - $sql = 'SELECT tw.user_id - FROM ' . $this->topics_watch_table . ' tw - LEFT JOIN ' . $this->topics_track_table . ' tt - ON (tt.user_id = tw.user_id AND tt.topic_id = tw.topic_id) - LEFT JOIN ' . $this->posts_table . ' p - ON (p.topic_id = tw.topic_id) - WHERE tw.topic_id = ' . (int) $options['item_parent_id'] . ' - AND p.post_time > tt.mark_time - HAVING COUNT(p.post_id) > 1'; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - $notified_users[$row['user_id']] = $row; - } - $this->db->sql_freeresult($result); - - // Forums watch - $sql = 'SELECT fw.user_id - FROM ' . $this->forums_watch_table . ' fw - LEFT JOIN ' . $this->forums_track_table . ' ft - ON (ft.user_id = fw.user_id AND ft.forum_id = fw.forum_id) - LEFT JOIN ' . $this->posts_table . ' p - ON (p.forum_id = fw.forum_id) - WHERE p.topic_id = ' . (int) $options['item_parent_id'] . ' - AND p.post_time > ft.mark_time - HAVING COUNT(p.post_id) > 1'; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - $notified_users[$row['user_id']] = $row; - } - $this->db->sql_freeresult($result); + $notified_users[$row['user_id']] = $row; } + $this->db->sql_freeresult($result); return $notified_users; } @@ -150,6 +106,59 @@ class email extends \phpbb\notification\method\messenger_base */ public function notify() { + $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->email_notifications_table); + + /** @var \phpbb\notification\type\type_interface $notification */ + foreach ($this->queue as $notification) + { + $data = $this->clean_data($notification->get_insert_array()); + $insert_buffer->insert($data); + } + + $insert_buffer->flush(); + return $this->notify_using_messenger(NOTIFY_EMAIL); } + + /** + * {@inheritdoc} + */ + public function mark_notifications($notification_type_id, $item_id, $user_id, $time = false, $mark_read = true) + { + $sql = 'DELETE FROM ' . $this->email_notifications_table . ' + WHERE ' . (($notification_type_id !== false) ? (is_array($notification_type_id) ? $this->db->sql_in_set('notification_type_id', $notification_type_id) : 'notification_type_id = ' . $notification_type_id) : '') . + (($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : '') . + (($item_id !== false) ? ' AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) : ''); + $this->db->sql_query($sql); + } + + /** + * {@inheritdoc} + */ + public function mark_notifications_by_parent($notification_type_id, $item_parent_id, $user_id, $time = false, $mark_read = true) + { + $sql = 'DELETE FROM ' . $this->email_notifications_table . ' + WHERE ' . (($notification_type_id !== false) ? (is_array($notification_type_id) ? $this->db->sql_in_set('notification_type_id', $notification_type_id) : 'notification_type_id = ' . $notification_type_id) : '') . + (($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : '') . + (($item_parent_id !== false) ? ' AND ' . (is_array($item_parent_id) ? $this->db->sql_in_set('item_parent_id', $item_parent_id, false, true) : 'item_parent_id = ' . (int) $item_parent_id) : ''); + $this->db->sql_query($sql); + } + + /** + * Clean data to contain only what we need for email notifications table + * + * @param array $data Notification data + * @return array Cleaned notification data + */ + protected function clean_data(array $data) + { + $model = array( + 'notification_type_id' => null, + 'item_id' => null, + 'item_parent_id' => null, + 'user_id' => null, + ); + + return array_intersect_key($data, $model); + } } diff --git a/tests/notification/base.php b/tests/notification/base.php index 0e254a66fd..5990da011f 100644 --- a/tests/notification/base.php +++ b/tests/notification/base.php @@ -103,11 +103,7 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case $phpbb_container->setParameter('tables.notifications', 'phpbb_notifications'); $phpbb_container->setParameter('tables.user_notifications', 'phpbb_user_notifications'); $phpbb_container->setParameter('tables.notification_types', 'phpbb_notification_types'); - $phpbb_container->setParameter('tables.topics_watch', 'phpbb_topics_watch'); - $phpbb_container->setParameter('tables.topics_track', 'phpbb_topics_track'); - $phpbb_container->setParameter('tables.posts', 'phpbb_posts'); - $phpbb_container->setParameter('tables.forums_watch', 'phpbb_forums_watch'); - $phpbb_container->setParameter('tables.forums_track', 'phpbb_forums_track'); + $phpbb_container->setParameter('tables.email_notifications', 'phpbb_email_notifications'); $this->notifications = new phpbb_notification_manager_helper( array(), diff --git a/tests/notification/submit_post_base.php b/tests/notification/submit_post_base.php index 6f8e10f357..edcbef76e2 100644 --- a/tests/notification/submit_post_base.php +++ b/tests/notification/submit_post_base.php @@ -130,11 +130,7 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c $phpbb_container->setParameter('tables.notifications', 'phpbb_notifications'); $phpbb_container->setParameter('tables.user_notifications', 'phpbb_user_notifications'); $phpbb_container->setParameter('tables.notification_types', 'phpbb_notification_types'); - $phpbb_container->setParameter('tables.topics_watch', 'phpbb_topics_watch'); - $phpbb_container->setParameter('tables.topics_track', 'phpbb_topics_track'); - $phpbb_container->setParameter('tables.posts', 'phpbb_posts'); - $phpbb_container->setParameter('tables.forums_watch', 'phpbb_forums_watch'); - $phpbb_container->setParameter('tables.forums_track', 'phpbb_forums_track'); + $phpbb_container->setParameter('tables.email_notifications', 'phpbb_email_notifications'); $phpbb_container->set('content.visibility', new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE)); $phpbb_container->compile();