From b887fcc3d180860e3b7fdcb2a70e2cd8a519bea2 Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sat, 8 Sep 2012 10:49:58 -0500 Subject: [PATCH 001/308] [ticket/11103] The start of an all-encompassing notifications system This system will take input from various systems to store notifications and send notifications to users all in one nice extendable system. This system should act something like the notifications system on other social networking sites (in that, there is a single location where a user can see all of their notifications for various events). PHPBB3-11103 --- phpBB/config/services.yml | 5 + phpBB/includes/constants.php | 1 + phpBB/includes/notifications/method/base.php | 51 +++++ phpBB/includes/notifications/method/email.php | 28 +++ .../notifications/method/interface.php | 24 +++ phpBB/includes/notifications/service.php | 197 ++++++++++++++++++ phpBB/includes/notifications/type/base.php | 128 ++++++++++++ .../includes/notifications/type/interface.php | 31 +++ phpBB/includes/notifications/type/post.php | 65 ++++++ 9 files changed, 530 insertions(+) create mode 100644 phpBB/includes/notifications/method/base.php create mode 100644 phpBB/includes/notifications/method/email.php create mode 100644 phpBB/includes/notifications/method/interface.php create mode 100644 phpBB/includes/notifications/service.php create mode 100644 phpBB/includes/notifications/type/base.php create mode 100644 phpBB/includes/notifications/type/interface.php create mode 100644 phpBB/includes/notifications/type/post.php diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml index 133a43b77e..b9c697b481 100644 --- a/phpBB/config/services.yml +++ b/phpBB/config/services.yml @@ -89,6 +89,11 @@ services: - .%core.php_ext% - @cache.driver + notifications: + class: phpbb_notifications_service + arguments: + - @container + processor.config: class: phpbb_di_processor_ext arguments: diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 68af41ab20..de289c73dc 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -239,6 +239,7 @@ define('LOG_TABLE', $table_prefix . 'log'); define('LOGIN_ATTEMPT_TABLE', $table_prefix . 'login_attempts'); define('MODERATOR_CACHE_TABLE', $table_prefix . 'moderator_cache'); define('MODULES_TABLE', $table_prefix . 'modules'); +define('NOTIFICATIONS_TABLE', $table_prefix . 'notifications'); define('POLL_OPTIONS_TABLE', $table_prefix . 'poll_options'); define('POLL_VOTES_TABLE', $table_prefix . 'poll_votes'); define('POSTS_TABLE', $table_prefix . 'posts'); diff --git a/phpBB/includes/notifications/method/base.php b/phpBB/includes/notifications/method/base.php new file mode 100644 index 0000000000..a70f37db95 --- /dev/null +++ b/phpBB/includes/notifications/method/base.php @@ -0,0 +1,51 @@ +phpbb_container = $phpbb_container; + + // Some common things we're going to use + $this->db = $phpbb_container->get('dbal.conn'); + $this->user = $phpbb_container->get('user'); + } +} diff --git a/phpBB/includes/notifications/method/email.php b/phpBB/includes/notifications/method/email.php new file mode 100644 index 0000000000..b06e2c018e --- /dev/null +++ b/phpBB/includes/notifications/method/email.php @@ -0,0 +1,28 @@ +phpbb_container = $phpbb_container; + + // Some common things we're going to use + $this->db = $phpbb_container->get('dbal.conn'); + } + + private function get_type_class_name(&$type, $safe = false) + { + if (!$safe) + { + $type = preg_replace('#[^a-z]#', '', $type); + } + + return 'phpbb_notifications_type_' . $type; + } + + /** + * Load the user's notifications + * + * @param array $options Optional options to control what notifications are loaded + * user_id User id to load notifications for (Default: $user->data['user_id']) + * limit Number of notifications to load (Default: 5) + * start Notifications offset (Default: 0) + */ + public function load_notifications($options = array()) + { + $user = $this->phpbb_container->get('user'); + + // Merge default options + $options = array_merge(array( + 'user_id' => $user->data['user_id'], + 'limit' => 5, + 'start' => 0, + ), $options); + + $notifications = $user_ids = array(); + + $sql = 'SELECT * FROM ' . NOTIFICATIONS_TABLE . ' + WHERE user_id = ' . (int) $options['user_id']; + $result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']); + + while ($row = $this->db->sql_fetchrow($result)) + { + $type_class_name = $this->get_type_class_name($row['type'], true); + + $notification = new $type_class_name($this->phpbb_container, $row); + $notification->users($this->users); + + $user_ids = array_merge($user_ids, $notification->users_to_query()); + + $notifications[] = $notification(); + } + $this->db->sql_freeresult($result); + + // Load the users + $user_ids = array_unique($user_ids); + + // @todo do not load users we already have in $this->users + + if (sizeof($user_ids)) + { + // @todo do not select everything + $sql = 'SELECT * FROM ' . USERS_TABLE . ' + WHERE ' . $this->db->sql_in_set('user_id', $user_ids); + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $this->users[$row['user_id']] = $row; + } + $this->db->sql_freeresult($result); + } + + return $notifications; + } + + public function add_notifications($type, $data) + { + $type_class_name = $this->get_type_class_name($type); + + $notification_objects = array(); // 'user_id' => object + $methods = $new_rows = array(); + + // find out which users want to receive this type of notification + $sql = 'SELECT user_id FROM ' . USERS_TABLE . ' + WHERE ' . $this->db->sql_in_set('user_id', array(2)); + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $row['method'] = ''; + + $notification = new $type_class_name($this->phpbb_container); + + $notification->user_id = $row['user_id']; + + $new_rows[] = $notification->create_insert_array($data); + + // setup the notification methods and add the notification to the queue + if ($row['method']) + { + if (!isset($methods[$row['method']])) + { + $method_class_name = 'phpbb_notifications_method_' . $row['method']; + $methods[$row['method']] = new $$method_class_name(); + } + + $methods[$row['method']]->add_to_queue($notification); + } + } + + // insert into the db + $this->db->sql_multi_insert(NOTIFICATIONS_TABLE, $new_rows); + + // run the queue for each method to send notifications + foreach ($methods as $method) + { + $method->run_queue(); + } + } + + public function update_notifications($type, $type_id, $data) + { + $type_class_name = $this->get_type_class_name($type); + + $object = new $$type_class($this->phpbb_container); + $update = $object->update($data); + + $sql = 'UPDATE ' . NOTIFICATIONS_TABLE . ' + SET ' . $this->db->sql_build_array('UPDATE', $update) . " + WHERE type = '" . $this->db->sql_escape($type) . "' + AND type_id = " . (int) $type_id; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $object = new $type_class_name($this->phpbb_container, $row); + $object->update($data); + + $update_rows[] = $object->getForUpdate(); + } + } +} diff --git a/phpBB/includes/notifications/type/base.php b/phpBB/includes/notifications/type/base.php new file mode 100644 index 0000000000..959516fd19 --- /dev/null +++ b/phpBB/includes/notifications/type/base.php @@ -0,0 +1,128 @@ +phpbb_container = $phpbb_container; + + // Some common things we're going to use + $this->db = $phpbb_container->get('dbal.conn'); + $this->phpbb_root_path = $phpbb_container->getParameter('core.root_path'); + $this->php_ext = $phpbb_container->getParameter('core.php_ext'); + + // The row from the database (unless this is a new notification we're going to add) + $this->data = $data; + $this->data['data'] = (isset($this->data['data'])) ? unserialize($this->data['data']) : array(); + } + + public function __get($name) + { + return $this->data[$name]; + } + + public function __set($name, $value) + { + $this->data[$name] = $value; + } + + public function get_data($name) + { + return $this->data['data'][$name]; + } + + public function set_data($name, $value) + { + $this->data['data'][$name] = $value; + } + + public function users(&$users) + { + $this->users = $users; + } + + /** + * Output the notification to the template + * + * @param array $options Array of options + * template_block Template block name to output to (Default: notifications) + */ + public function display($options = array()) + { + $template = $this->phpbb_container->get('template'); + $user = $this->phpbb_container->get('user'); + + // Merge default options + $options = array_merge(array( + 'template_block' => 'notifications', + ), $options); + + $template->assign_block_vars($options['template_block'], array( + 'TITLE' => $this->get_title(), + 'URL' => $this->get_url(), + 'TIME' => $user->format_date($this->time), + + 'ID' => $this->notification_id, + 'UNREAD' => $this->unread, + )); + } + + public function create_insert_array($data) + { + // Defaults + $data = array_merge(array( + 'item_type' => $this->get_type(), + 'time' => time(), + 'unread' => true, + + 'data' => array(), + ), $this->data); + + $data['data'] = serialize($data['data']); + + return $data; + } +} diff --git a/phpBB/includes/notifications/type/interface.php b/phpBB/includes/notifications/type/interface.php new file mode 100644 index 0000000000..ace5ca67da --- /dev/null +++ b/phpBB/includes/notifications/type/interface.php @@ -0,0 +1,31 @@ +data['post_username'] . ' posted in the topic ' . censor_text($this->data['topic_title']); + } + + public function get_url() + { + return append_sid($this->phpbb_root_path . 'viewtopic.' . $this->php_ext, "p={$this->item_id}#p{$this->item_id}"); + } + + /** + * Users needed to query before this notification can be displayed + * + * @return array Array of user_ids + */ + public function users_to_query() + { + return array($this->data['poster_id']); + } + + public function create_insert_array($post) + { + $this->item_id = $post['post_id']; + + $this->set_data('poster_id', $post['poster_id']); + + $this->set_data('topic_title', $post['topic_title']); + + $this->set_data('post_username', $post['post_username']); + + return parent::create_insert_array($post); + } +} From 44f07df96fbf933bc20166a516bf0eecee00df4c Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sat, 8 Sep 2012 11:40:02 -0500 Subject: [PATCH 002/308] [ticket/11103] Working on the add/update notifications functions Some cleanup and additional commenting as well PHPBB3-11103 --- phpBB/includes/notifications/method/base.php | 18 +--- phpBB/includes/notifications/service.php | 100 +++++++++++------- phpBB/includes/notifications/type/base.php | 66 ++++++++++-- .../includes/notifications/type/interface.php | 2 +- phpBB/includes/notifications/type/post.php | 20 ++++ 5 files changed, 146 insertions(+), 60 deletions(-) diff --git a/phpBB/includes/notifications/method/base.php b/phpBB/includes/notifications/method/base.php index a70f37db95..1c223df045 100644 --- a/phpBB/includes/notifications/method/base.php +++ b/phpBB/includes/notifications/method/base.php @@ -7,6 +7,8 @@ * */ +use Symfony\Component\DependencyInjection\ContainerBuilder; + /** * @ignore */ @@ -25,21 +27,7 @@ abstract class phpbb_notifications_method_base implements phpbb_notifications_me protected $db; protected $user; - /** - * notification_id - * item_type - * item_id - * - * by_user_id (one who caused the notification) - * user_id - * time - * unread - * - * data (special serialized field that each notification type can use to store stuff) - */ - protected $data = array(); - - public function __construct(Symfony\Component\DependencyInjection\ContainerBuilder $phpbb_container, $data = array()) + public function __construct(ContainerBuilder $phpbb_container, $data = array()) { // phpBB Container $this->phpbb_container = $phpbb_container; diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php index 8f5d559867..fd2c51a330 100644 --- a/phpBB/includes/notifications/service.php +++ b/phpBB/includes/notifications/service.php @@ -7,6 +7,8 @@ * */ +use Symfony\Component\DependencyInjection\ContainerBuilder; + /** * @ignore */ @@ -50,7 +52,7 @@ class phpbb_notifications_service * sms? */ - public function __construct(Symfony\Component\DependencyInjection\ContainerBuilder $phpbb_container) + public function __construct(ContainerBuilder $phpbb_container) { $this->phpbb_container = $phpbb_container; @@ -58,23 +60,13 @@ class phpbb_notifications_service $this->db = $phpbb_container->get('dbal.conn'); } - private function get_type_class_name(&$type, $safe = false) - { - if (!$safe) - { - $type = preg_replace('#[^a-z]#', '', $type); - } - - return 'phpbb_notifications_type_' . $type; - } - /** * Load the user's notifications * * @param array $options Optional options to control what notifications are loaded - * user_id User id to load notifications for (Default: $user->data['user_id']) - * limit Number of notifications to load (Default: 5) - * start Notifications offset (Default: 0) + * user_id User id to load notifications for (Default: $user->data['user_id']) + * limit Number of notifications to load (Default: 5) + * start Notifications offset (Default: 0) */ public function load_notifications($options = array()) { @@ -128,38 +120,58 @@ class phpbb_notifications_service return $notifications; } + /** + * Add a notification + * + * @param string $type Type identifier + * @param int $type_id Identifier within the type + * @param array $data Data specific for this type that will be inserted + */ public function add_notifications($type, $data) { $type_class_name = $this->get_type_class_name($type); - $notification_objects = array(); // 'user_id' => object - $methods = $new_rows = array(); + $notify_users = array(); + $notification_objects = $notification_methods = array(); + $new_rows = array(); // find out which users want to receive this type of notification $sql = 'SELECT user_id FROM ' . USERS_TABLE . ' WHERE ' . $this->db->sql_in_set('user_id', array(2)); $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) { - $row['method'] = ''; + if (!isset($notify_users[$row['user_id']])) + { + $notify_users[$row['user_id']] = array(); + } + $notify_users[$row['user_id']][] = ''; + } + $this->db->sql_freeresult($result); + + // Go through each user so we can insert a row in the DB and then notify them by their desired means + foreach ($notify_users as $user => $methods) + { $notification = new $type_class_name($this->phpbb_container); - $notification->user_id = $row['user_id']; + $notification->user_id = (int) $user; $new_rows[] = $notification->create_insert_array($data); - // setup the notification methods and add the notification to the queue - if ($row['method']) + foreach ($methods as $method) { - if (!isset($methods[$row['method']])) + // setup the notification methods and add the notification to the queue + if ($row['method']) { - $method_class_name = 'phpbb_notifications_method_' . $row['method']; - $methods[$row['method']] = new $$method_class_name(); - } + if (!isset($notification_methods[$row['method']])) + { + $method_class_name = 'phpbb_notifications_method_' . $row['method']; + $notification_methods[$row['method']] = new $method_class_name(); + } - $methods[$row['method']]->add_to_queue($notification); + $notification_methods[$row['method']]->add_to_queue($notification); + } } } @@ -167,31 +179,43 @@ class phpbb_notifications_service $this->db->sql_multi_insert(NOTIFICATIONS_TABLE, $new_rows); // run the queue for each method to send notifications - foreach ($methods as $method) + foreach ($notification_methods as $method) { $method->run_queue(); } } + /** + * Update a notification + * + * @param string $type Type identifier + * @param int $type_id Identifier within the type + * @param array $data Data specific for this type that will be updated + */ public function update_notifications($type, $type_id, $data) { $type_class_name = $this->get_type_class_name($type); - $object = new $$type_class($this->phpbb_container); - $update = $object->update($data); + $notification = new $type_class_name($this->phpbb_container); + $update_array = $notification->create_update_array($data); $sql = 'UPDATE ' . NOTIFICATIONS_TABLE . ' - SET ' . $this->db->sql_build_array('UPDATE', $update) . " - WHERE type = '" . $this->db->sql_escape($type) . "' - AND type_id = " . (int) $type_id; - $result = $this->db->sql_query($sql); + SET ' . $this->db->sql_build_array('UPDATE', $update_array) . " + WHERE item_type = '" . $this->db->sql_escape($type) . "' + AND item_id = " . (int) $type_id; + $this->db->sql_query($sql); + } - while ($row = $this->db->sql_fetchrow($result)) + /** + * Helper to get the notifications type class name and clean it if unsafe + */ + private function get_type_class_name(&$type, $safe = false) + { + if (!$safe) { - $object = new $type_class_name($this->phpbb_container, $row); - $object->update($data); - - $update_rows[] = $object->getForUpdate(); + $type = preg_replace('#[^a-z]#', '', $type); } + + return 'phpbb_notifications_type_' . $type; } } diff --git a/phpBB/includes/notifications/type/base.php b/phpBB/includes/notifications/type/base.php index 959516fd19..2b194557e3 100644 --- a/phpBB/includes/notifications/type/base.php +++ b/phpBB/includes/notifications/type/base.php @@ -7,6 +7,8 @@ * */ +use Symfony\Component\DependencyInjection\ContainerBuilder; + /** * @ignore */ @@ -26,7 +28,12 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type protected $phpbb_root_path; protected $php_ext; - protected $users; + /** + * Array of user data containing information needed to output the notifications to the template + * + * @var array + */ + protected $users = array(); /** * Indentification data @@ -40,11 +47,11 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type * data (special serialized field that each notification type can use to store stuff) * * @var array $data Notification row from the database - * This must be private, all interaction should use __get(), __set() + * This must be private, all interaction should use __get(), __set(), get_data(), set_data() */ private $data = array(); - public function __construct(Symfony\Component\DependencyInjection\ContainerBuilder $phpbb_container, $data = array()) + public function __construct(ContainerBuilder $phpbb_container, $data = array()) { // phpBB Container $this->phpbb_container = $phpbb_container; @@ -69,16 +76,33 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type $this->data[$name] = $value; } - public function get_data($name) + /** + * Get special data (only important for the classes that extend this) + * + * @param string $name Name of the variable to get + * + * @return mixed + */ + protected function get_data($name) { return $this->data['data'][$name]; } - public function set_data($name, $value) + /** + * Set special data (only important for the classes that extend this) + * + * @param string $name Name of the variable to set + * @param mixed $value Value to set to the variable + */ + protected function set_data($name, $value) { $this->data['data'][$name] = $value; } + /** + * Function to store the users loaded from the database (for output to the template) + * (The service handles this) + */ public function users(&$users) { $this->users = $users; @@ -110,7 +134,15 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type )); } - public function create_insert_array($data) + /** + * Function for preparing the data for insertion in an SQL query + * (The service handles insertion) + * + * @param array $special_data Data unique to this notification type + * + * @return array Array of data ready to be inserted into the database + */ + public function create_insert_array($special_data) { // Defaults $data = array_merge(array( @@ -125,4 +157,26 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type return $data; } + + /** + * Function for preparing the data for update in an SQL query + * (The service handles insertion) + * + * @param array $special_data Data unique to this notification type + * + * @return array Array of data ready to be updated in the database + */ + public function create_update_array($special_data) + { + $data = $this->create_insert_array($special_data); + + // Unset data unique to each row + unset( + $data['notification_id'], + $data['unread'], + $data['user_id'] + ); + + return $data; + } } diff --git a/phpBB/includes/notifications/type/interface.php b/phpBB/includes/notifications/type/interface.php index ace5ca67da..57de755c82 100644 --- a/phpBB/includes/notifications/type/interface.php +++ b/phpBB/includes/notifications/type/interface.php @@ -27,5 +27,5 @@ interface phpbb_notifications_type_interface public function get_url(); - public function create_insert_array($data); + public function create_insert_array($special_data); } diff --git a/phpBB/includes/notifications/type/post.php b/phpBB/includes/notifications/type/post.php index eb8d92c79c..08da7a77cb 100644 --- a/phpBB/includes/notifications/type/post.php +++ b/phpBB/includes/notifications/type/post.php @@ -30,11 +30,21 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base return 'post'; } + /** + * Get the title of this notification + * + * @return string + */ public function get_title() { return $this->data['post_username'] . ' posted in the topic ' . censor_text($this->data['topic_title']); } + /** + * Get the url to this item + * + * @return string URL + */ public function get_url() { return append_sid($this->phpbb_root_path . 'viewtopic.' . $this->php_ext, "p={$this->item_id}#p{$this->item_id}"); @@ -50,6 +60,14 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base return array($this->data['poster_id']); } + /** + * Function for preparing the data for insertion in an SQL query + * (The service handles insertion) + * + * @param array $post Data from submit_post + * + * @return array Array of data ready to be inserted into the database + */ public function create_insert_array($post) { $this->item_id = $post['post_id']; @@ -60,6 +78,8 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base $this->set_data('post_username', $post['post_username']); + $this->time = $post['post_time']; + return parent::create_insert_array($post); } } From e45fb0025ec8c27147caee7e3c14902f2e3f02c5 Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sat, 8 Sep 2012 12:05:55 -0500 Subject: [PATCH 003/308] [ticket/11103] Output the notifications to the template For now, just dumping the notifications in the header. PHPBB3-11103 --- phpBB/common.php | 3 +++ phpBB/includes/functions.php | 9 ++++++++- phpBB/includes/notifications/service.php | 4 ++-- phpBB/includes/notifications/type/base.php | 15 +++++++++++++-- phpBB/includes/notifications/type/post.php | 13 ++++++++++++- .../styles/prosilver/template/overall_header.html | 7 +++++++ 6 files changed, 45 insertions(+), 6 deletions(-) diff --git a/phpBB/common.php b/phpBB/common.php index 281eb88c4d..52879deb9c 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -146,6 +146,9 @@ if (!$config['use_system_cron']) $cron = $phpbb_container->get('cron.manager'); } +// Load notifications +$phpbb_notifications = $phpbb_container->get('notifications'); + /** * Main event which is triggered on every page * diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 834f57a38b..7632ea1fcb 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -4778,7 +4778,7 @@ function phpbb_http_login($param) function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum') { global $db, $config, $template, $SID, $_SID, $_EXTRA_URL, $user, $auth, $phpEx, $phpbb_root_path; - global $phpbb_dispatcher; + global $phpbb_dispatcher, $phpbb_container; if (defined('HEADER_INC')) { @@ -5092,6 +5092,13 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 'A_COOKIE_SETTINGS' => addslashes('; path=' . $config['cookie_path'] . ((!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . $config['cookie_domain']) . ((!$config['cookie_secure']) ? '' : '; secure')), )); + // Output the notifications + $phpbb_notifications = $phpbb_container->get('notifications'); + foreach ($phpbb_notifications->load_notifications() as $notification) + { + $notification->display(); + } + // application/xhtml+xml not used because of IE header('Content-type: text/html; charset=UTF-8'); diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php index fd2c51a330..8db414cb16 100644 --- a/phpBB/includes/notifications/service.php +++ b/phpBB/includes/notifications/service.php @@ -87,14 +87,14 @@ class phpbb_notifications_service while ($row = $this->db->sql_fetchrow($result)) { - $type_class_name = $this->get_type_class_name($row['type'], true); + $type_class_name = $this->get_type_class_name($row['item_type'], true); $notification = new $type_class_name($this->phpbb_container, $row); $notification->users($this->users); $user_ids = array_merge($user_ids, $notification->users_to_query()); - $notifications[] = $notification(); + $notifications[] = $notification; } $this->db->sql_freeresult($result); diff --git a/phpBB/includes/notifications/type/base.php b/phpBB/includes/notifications/type/base.php index 2b194557e3..1b01e1d46c 100644 --- a/phpBB/includes/notifications/type/base.php +++ b/phpBB/includes/notifications/type/base.php @@ -85,7 +85,7 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type */ protected function get_data($name) { - return $this->data['data'][$name]; + return (isset($this->data['data'][$name])) ? $this->data['data'][$name] : null; } /** @@ -105,7 +105,18 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type */ public function users(&$users) { - $this->users = $users; + $this->users = &$users; + } + + /** + * Get a user row from our users cache + * + * @param int $user_id + * @return array + */ + protected function get_user($user_id) + { + return $this->users[$user_id]; } /** diff --git a/phpBB/includes/notifications/type/post.php b/phpBB/includes/notifications/type/post.php index 08da7a77cb..4b343650a1 100644 --- a/phpBB/includes/notifications/type/post.php +++ b/phpBB/includes/notifications/type/post.php @@ -37,7 +37,18 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base */ public function get_title() { - return $this->data['post_username'] . ' posted in the topic ' . censor_text($this->data['topic_title']); + if ($this->get_data('post_username')) + { + $username = $this->get_data('post_username'); + } + else + { + $user_data = $this->get_user($this->get_data('poster_id')); + + $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']); + } + + return $username . ' posted in the topic ' . censor_text($this->get_data('topic_title')); } /** diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html index 43ae83767d..77fdb230ad 100644 --- a/phpBB/styles/prosilver/template/overall_header.html +++ b/phpBB/styles/prosilver/template/overall_header.html @@ -166,3 +166,10 @@ + + +

+ {notifications.TITLE}
+ {notifications.TIME} +

+ \ No newline at end of file From 32a966b21da7051def3bd2ae608f3f2457d22476 Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sat, 8 Sep 2012 12:28:58 -0500 Subject: [PATCH 004/308] [ticket/11103] Private Message type notification Also cleanup PHPBB3-11103 --- phpBB/includes/notifications/service.php | 68 +++++++++---- phpBB/includes/notifications/type/base.php | 2 +- .../includes/notifications/type/interface.php | 4 +- phpBB/includes/notifications/type/pm.php | 97 +++++++++++++++++++ phpBB/includes/notifications/type/post.php | 12 ++- 5 files changed, 162 insertions(+), 21 deletions(-) create mode 100644 phpBB/includes/notifications/type/pm.php diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php index 8db414cb16..059c2b420d 100644 --- a/phpBB/includes/notifications/service.php +++ b/phpBB/includes/notifications/service.php @@ -87,9 +87,9 @@ class phpbb_notifications_service while ($row = $this->db->sql_fetchrow($result)) { - $type_class_name = $this->get_type_class_name($row['item_type'], true); + $item_type_class_name = $this->get_item_type_class_name($row['item_type'], true); - $notification = new $type_class_name($this->phpbb_container, $row); + $notification = new $item_type_class_name($this->phpbb_container, $row); $notification->users($this->users); $user_ids = array_merge($user_ids, $notification->users_to_query()); @@ -123,13 +123,18 @@ class phpbb_notifications_service /** * Add a notification * - * @param string $type Type identifier - * @param int $type_id Identifier within the type + * @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($type, $data) + public function add_notifications($item_type, $data) { - $type_class_name = $this->get_type_class_name($type); + $item_type_class_name = $this->get_item_type_class_name($item_type); + + $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 = array(); $notification_objects = $notification_methods = array(); @@ -150,10 +155,22 @@ class phpbb_notifications_service } $this->db->sql_freeresult($result); + // 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 + $sql = 'SELECT user_id FROM ' . NOTIFICATIONS_TABLE . " + WHERE item_type = '" . $this->db->sql_escape($item_type) . "' + AND item_id = " . (int) $item_id; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + unset($notify_users[$row['user_id']]); + } + $this->db->sql_freeresult($result); + // Go through each user so we can insert a row in the DB and then notify them by their desired means foreach ($notify_users as $user => $methods) { - $notification = new $type_class_name($this->phpbb_container); + $notification = new $item_type_class_name($this->phpbb_container); $notification->user_id = (int) $user; @@ -188,34 +205,49 @@ class phpbb_notifications_service /** * Update a notification * - * @param string $type Type identifier - * @param int $type_id Identifier within the type + * @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 updated */ - public function update_notifications($type, $type_id, $data) + public function update_notifications($item_type, $item_id, $data) { - $type_class_name = $this->get_type_class_name($type); + $item_type_class_name = $this->get_item_type_class_name($item_type); - $notification = new $type_class_name($this->phpbb_container); + $notification = new $item_type_class_name($this->phpbb_container); $update_array = $notification->create_update_array($data); $sql = 'UPDATE ' . NOTIFICATIONS_TABLE . ' SET ' . $this->db->sql_build_array('UPDATE', $update_array) . " - WHERE item_type = '" . $this->db->sql_escape($type) . "' - AND item_id = " . (int) $type_id; + WHERE item_type = '" . $this->db->sql_escape($item_type) . "' + AND item_id = " . (int) $item_id; $this->db->sql_query($sql); } /** - * Helper to get the notifications type class name and clean it if unsafe + * Delete 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 updated */ - private function get_type_class_name(&$type, $safe = false) + public function delete_notifications($item_type, $item_id) + { + $sql = 'DELETE FROM ' . NOTIFICATIONS_TABLE . " + WHERE item_type = '" . $this->db->sql_escape($item_type) . "' + AND item_id = " . (int) $item_id; + $this->db->sql_query($sql); + } + + /** + * Helper to get the notifications item type class name and clean it if unsafe + */ + private function get_item_type_class_name(&$item_type, $safe = false) { if (!$safe) { - $type = preg_replace('#[^a-z]#', '', $type); + $item_type = preg_replace('#[^a-z]#', '', $item_type); } - return 'phpbb_notifications_type_' . $type; + return 'phpbb_notifications_type_' . $item_type; } } diff --git a/phpBB/includes/notifications/type/base.php b/phpBB/includes/notifications/type/base.php index 1b01e1d46c..89143873a8 100644 --- a/phpBB/includes/notifications/type/base.php +++ b/phpBB/includes/notifications/type/base.php @@ -157,7 +157,7 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type { // Defaults $data = array_merge(array( - 'item_type' => $this->get_type(), + 'item_type' => $this->get_item_type(), 'time' => time(), 'unread' => true, diff --git a/phpBB/includes/notifications/type/interface.php b/phpBB/includes/notifications/type/interface.php index 57de755c82..b1ee9ae0b6 100644 --- a/phpBB/includes/notifications/type/interface.php +++ b/phpBB/includes/notifications/type/interface.php @@ -21,7 +21,9 @@ if (!defined('IN_PHPBB')) */ interface phpbb_notifications_type_interface { - public function get_type(); + public static function get_item_type(); + + public static function get_item_id($post); public function get_title(); diff --git a/phpBB/includes/notifications/type/pm.php b/phpBB/includes/notifications/type/pm.php new file mode 100644 index 0000000000..f86050486e --- /dev/null +++ b/phpBB/includes/notifications/type/pm.php @@ -0,0 +1,97 @@ +get_user($this->get_data('author_id')); + + $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']); + + return $username . ' sent you a private message titled: ' . $this->get_data('message_subject'); + } + + /** + * Get the url to this item + * + * @return string URL + */ + public function get_url() + { + return append_sid($this->phpbb_root_path . 'ucp.' . $this->php_ext, "i=pm&mode=view&p={$this->item_id}"); + } + + /** + * Users needed to query before this notification can be displayed + * + * @return array Array of user_ids + */ + public function users_to_query() + { + return array($this->data['author_id']); + } + + /** + * Function for preparing the data for insertion in an SQL query + * (The service handles insertion) + * + * @param array $post Data from submit_post + * + * @return array Array of data ready to be inserted into the database + */ + public function create_insert_array($post) + { + $this->item_id = $post['msg_id']; + + $this->set_data('author_id', $post['author_id']); + + $this->set_data('message_subject', $post['message_subject']); + + $this->time = $post['message_time']; + + return parent::create_insert_array($post); + } +} diff --git a/phpBB/includes/notifications/type/post.php b/phpBB/includes/notifications/type/post.php index 4b343650a1..9bd343d288 100644 --- a/phpBB/includes/notifications/type/post.php +++ b/phpBB/includes/notifications/type/post.php @@ -25,11 +25,21 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base * Get the type of notification this is * phpbb_notifications_type_ */ - public function get_type() + public static function get_item_type() { return 'post'; } + /** + * Get the id of the + * + * @param array $post The data from the post + */ + public static function get_item_id($post) + { + return $post['post_id']; + } + /** * Get the title of this notification * From b59463552644ca4afd9e8ca7edd761ae382fc8ed Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sat, 8 Sep 2012 13:09:34 -0500 Subject: [PATCH 005/308] [ticket/11103] Add tables to the database updater and installer PHPBB3-11103 --- phpBB/develop/create_schema_files.php | 41 ++++++++++++++++ phpBB/includes/notifications/method/base.php | 32 +++++++++++++ .../notifications/method/interface.php | 1 + phpBB/includes/notifications/service.php | 38 +++++++-------- phpBB/install/database_update.php | 47 +++++++++++++++++++ 5 files changed, 140 insertions(+), 19 deletions(-) diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index 6eb4a80199..88aa9b70dd 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -1295,6 +1295,28 @@ function get_schema_struct() ), ); + $schema_data['phpbb_notifications'] = array( + 'COLUMNS' => array( + 'item_type' => array('UINT', 0), + 'item_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'unread' => array('BOOL', 1), + 'time' => array('TIMESTAMP', 1), + 'data' => array('TEXT_UNI', ''), + ), + 'PRIMARY_KEY' => array( + 'item_type', + 'item_id', + 'user_id', + ), + 'KEYS' => array( + 'item_type' => array('INDEX', 'item_type'), + 'item_id' => array('INDEX', 'item_id'), + 'user_id' => array('INDEX', 'user_id'), + 'time' => array('INDEX', 'time'), + ), + ); + $schema_data['phpbb_poll_options'] = array( 'COLUMNS' => array( 'poll_option_id' => array('TINT:4', 0), @@ -1751,6 +1773,25 @@ function get_schema_struct() ), ); + $schema_data['phpbb_user_notifications'] = array( + 'COLUMNS' => array( + 'item_type' => array('UINT', 0), + 'item_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'method' => array('VCHAR:25', ''), + ), + 'PRIMARY_KEY' => array( + 'item_type', + 'item_id', + 'user_id', + 'method', + ), + 'KEYS' => array( + 'it' => array('INDEX', 'item_type'), + 'uid' => array('INDEX', 'user_id'), + ), + ); + $schema_data['phpbb_user_group'] = array( 'COLUMNS' => array( 'group_id' => array('UINT', 0), diff --git a/phpBB/includes/notifications/method/base.php b/phpBB/includes/notifications/method/base.php index 1c223df045..dbf851a059 100644 --- a/phpBB/includes/notifications/method/base.php +++ b/phpBB/includes/notifications/method/base.php @@ -27,6 +27,13 @@ abstract class phpbb_notifications_method_base implements phpbb_notifications_me protected $db; protected $user; + /** + * Queue of messages to be sent + * + * @var array + */ + protected $queue = array(); + public function __construct(ContainerBuilder $phpbb_container, $data = array()) { // phpBB Container @@ -36,4 +43,29 @@ abstract class phpbb_notifications_method_base implements phpbb_notifications_me $this->db = $phpbb_container->get('dbal.conn'); $this->user = $phpbb_container->get('user'); } + + /** + * Add a notification to the queue + * + * @param phpbb_notifications_type_interface $notification + */ + public function add_to_queue(phpbb_notifications_type_interface $notification) + { + $this->queue[] = $notification; + } + + /** + * Basic run queue function. + * Child methods should override this function if there are more efficient methods to mass-notification + */ + public function run_queue() + { + foreach ($this->queue as $notification) + { + $this->notify($notification); + } + + // Empty queue + $this->queue = array(); + } } diff --git a/phpBB/includes/notifications/method/interface.php b/phpBB/includes/notifications/method/interface.php index 2d8a8b605e..f18d005b8b 100644 --- a/phpBB/includes/notifications/method/interface.php +++ b/phpBB/includes/notifications/method/interface.php @@ -21,4 +21,5 @@ if (!defined('IN_PHPBB')) */ interface phpbb_notifications_method_interface { + public function notify($notification); } diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php index 059c2b420d..32211b26cf 100644 --- a/phpBB/includes/notifications/service.php +++ b/phpBB/includes/notifications/service.php @@ -33,25 +33,6 @@ class phpbb_notifications_service */ protected $users; - /** - * Desired notifications - * unique by (type, type_id, user_id, method) - * if multiple methods are desired, multiple rows will exist. - * - * method of "none" will over-ride any other options - * - * type - * type_id - * user_id - * method - * none (will never receive notifications) - * standard (listed in notifications window - * popup? - * email - * jabber - * sms? - */ - public function __construct(ContainerBuilder $phpbb_container) { $this->phpbb_container = $phpbb_container; @@ -140,6 +121,25 @@ class phpbb_notifications_service $notification_objects = $notification_methods = array(); $new_rows = array(); + /** + * Desired notifications + * unique by (type, type_id, user_id, method) + * if multiple methods are desired, multiple rows will exist. + * + * method of "none" will over-ride any other options + * + * item_type + * item_id + * user_id + * method + * none (will never receive notifications) + * standard (listed in notifications window + * popup? + * email + * jabber + * sms? + */ + // find out which users want to receive this type of notification $sql = 'SELECT user_id FROM ' . USERS_TABLE . ' WHERE ' . $this->db->sql_in_set('user_id', array(2)); diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 0b470ced26..99e40ddee9 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -106,6 +106,14 @@ if (!defined('EXT_TABLE')) { define('EXT_TABLE', $table_prefix . 'ext'); } +if (!defined('NOTIFICATIONS_TABLE')) +{ + define('NOTIFICATIONS_TABLE', $table_prefix . 'notifications'); +} +if (!defined('USER_NOTIFICATIONS_TABLE')) +{ + define('USER_NOTIFICATIONS_TABLE', $table_prefix . 'user_notifications'); +} $phpbb_class_loader_ext = new phpbb_class_loader('phpbb_ext_', $phpbb_root_path . 'ext/', ".$phpEx"); $phpbb_class_loader_ext->register(); @@ -1097,6 +1105,45 @@ function database_update_info() 'ext_name' => array('UNIQUE', 'ext_name'), ), ), + NOTIFICATIONS_TABLE => array( + 'COLUMNS' => array( + 'item_type' => array('UINT', 0), + 'item_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'unread' => array('BOOL', 1), + 'time' => array('TIMESTAMP', 1), + 'data' => array('TEXT_UNI', ''), + ), + 'PRIMARY_KEY' => array( + 'item_type', + 'item_id', + 'user_id', + ), + 'KEYS' => array( + 'item_type' => array('INDEX', 'item_type'), + 'item_id' => array('INDEX', 'item_id'), + 'user_id' => array('INDEX', 'user_id'), + 'time' => array('INDEX', 'time'), + ), + ), + USER_NOTIFICATIONS_TABLE => array( + 'COLUMNS' => array( + 'item_type' => array('UINT', 0), + 'item_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'method' => array('VCHAR:25', ''), + ), + 'PRIMARY_KEY' => array( + 'item_type', + 'item_id', + 'user_id', + 'method', + ), + 'KEYS' => array( + 'it' => array('INDEX', 'item_type'), + 'uid' => array('INDEX', 'user_id'), + ), + ), ), 'add_columns' => array( GROUPS_TABLE => array( From 7b0b6fc63c2593cafaa84cc38a9b3029af1ed369 Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sat, 8 Sep 2012 13:40:05 -0500 Subject: [PATCH 006/308] [ticket/11103] Forgot a constant PHPBB3-11103 --- phpBB/includes/constants.php | 1 + phpBB/includes/notifications/method/email.php | 10 +++++++++- phpBB/includes/notifications/type/pm.php | 2 ++ phpBB/includes/notifications/type/post.php | 2 ++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index de289c73dc..7a3c73e987 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -273,6 +273,7 @@ define('TOPICS_POSTED_TABLE', $table_prefix . 'topics_posted'); define('TOPICS_TRACK_TABLE', $table_prefix . 'topics_track'); define('TOPICS_WATCH_TABLE', $table_prefix . 'topics_watch'); define('USER_GROUP_TABLE', $table_prefix . 'user_group'); +define('USER_NOTIFICATIONS_TABLE', $table_prefix . 'user_notifications'); define('USERS_TABLE', $table_prefix . 'users'); define('WARNINGS_TABLE', $table_prefix . 'warnings'); define('WORDS_TABLE', $table_prefix . 'words'); diff --git a/phpBB/includes/notifications/method/email.php b/phpBB/includes/notifications/method/email.php index b06e2c018e..0c3cb4bd85 100644 --- a/phpBB/includes/notifications/method/email.php +++ b/phpBB/includes/notifications/method/email.php @@ -17,11 +17,19 @@ if (!defined('IN_PHPBB')) /** * Email notification method class +* This class handles sending emails for notifications +* * @package notifications */ class phpbb_notifications_method_email extends phpbb_notifications_method_base { - function notify() + public static function is_available() + { + // Email is always available + return true; + } + + public function notify() { // email the user } diff --git a/phpBB/includes/notifications/type/pm.php b/phpBB/includes/notifications/type/pm.php index f86050486e..191c0b7e7f 100644 --- a/phpBB/includes/notifications/type/pm.php +++ b/phpBB/includes/notifications/type/pm.php @@ -17,6 +17,8 @@ if (!defined('IN_PHPBB')) /** * Private message notifications class +* This class handles notifications for private messages +* * @package notifications */ class phpbb_notifications_type_pm extends phpbb_notifications_type_base diff --git a/phpBB/includes/notifications/type/post.php b/phpBB/includes/notifications/type/post.php index 9bd343d288..addaa30ea6 100644 --- a/phpBB/includes/notifications/type/post.php +++ b/phpBB/includes/notifications/type/post.php @@ -17,6 +17,8 @@ if (!defined('IN_PHPBB')) /** * Post notifications class +* This class handles notifications for replies to a topic +* * @package notifications */ class phpbb_notifications_type_post extends phpbb_notifications_type_base From 7fee0cfdf60c9aeebcd498d2f41696bb7fed2dd0 Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sat, 8 Sep 2012 15:48:46 -0500 Subject: [PATCH 007/308] [ticket/11103] Work on the pm type and email method PHPBB3-11103 --- phpBB/includes/functions_privmsgs.php | 13 ++++ phpBB/includes/notifications/method/base.php | 11 ++- phpBB/includes/notifications/method/email.php | 61 ++++++++++++++++ phpBB/includes/notifications/service.php | 14 +--- phpBB/includes/notifications/type/base.php | 13 ++-- .../includes/notifications/type/interface.php | 6 +- phpBB/includes/notifications/type/pm.php | 69 +++++++++++++++++-- 7 files changed, 159 insertions(+), 28 deletions(-) diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 9e055a319f..99ad2ad791 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -1855,6 +1855,19 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) */ function pm_notification($mode, $author, $recipients, $subject, $message, $msg_id) { + global $phpbb_container; + + $phpbb_notifications = $phpbb_container->get('notifications'); + + $phpbb_notifications->add_notifications('pm', array( + 'author_id' => $author, + 'recipients' => $recipients, + 'message_subject' => $subject, + 'msg_id' => $msg_id, + )); + + return; + global $db, $user, $config, $phpbb_root_path, $phpEx, $auth; $subject = censor_text($subject); diff --git a/phpBB/includes/notifications/method/base.php b/phpBB/includes/notifications/method/base.php index dbf851a059..98c06509c6 100644 --- a/phpBB/includes/notifications/method/base.php +++ b/phpBB/includes/notifications/method/base.php @@ -26,6 +26,8 @@ abstract class phpbb_notifications_method_base implements phpbb_notifications_me protected $phpbb_container; protected $db; protected $user; + protected $phpbb_root_path; + protected $php_ext; /** * Queue of messages to be sent @@ -42,6 +44,9 @@ abstract class phpbb_notifications_method_base implements phpbb_notifications_me // Some common things we're going to use $this->db = $phpbb_container->get('dbal.conn'); $this->user = $phpbb_container->get('user'); + + $this->phpbb_root_path = $phpbb_container->getParameter('core.root_path'); + $this->php_ext = $phpbb_container->getParameter('core.php_ext'); } /** @@ -65,7 +70,11 @@ abstract class phpbb_notifications_method_base implements phpbb_notifications_me $this->notify($notification); } - // Empty queue + $this->empty_queue(); + } + + protected function empty_queue() + { $this->queue = array(); } } diff --git a/phpBB/includes/notifications/method/email.php b/phpBB/includes/notifications/method/email.php index 0c3cb4bd85..725ede7913 100644 --- a/phpBB/includes/notifications/method/email.php +++ b/phpBB/includes/notifications/method/email.php @@ -33,4 +33,65 @@ class phpbb_notifications_method_email extends phpbb_notifications_method_base { // email the user } + + public function run_queue() + { + if (!sizeof($this->queue)) + { + return; + } + + // Load all users we want to notify (we need their email address) + $user_ids = $users = array(); + foreach ($this->queue as $notification) + { + $user_ids[] = $notification->user_id; + } + + $sql = 'SELECT * FROM ' . USERS_TABLE . ' + WHERE ' . $this->db->sql_in_set('user_id', $user_ids); + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + $users[$row['user_id']] = $row; + } + $this->db->sql_freeresult($result); + + // Load the messenger + if (!class_exists('messenger')) + { + include($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext); + } + $messenger = new messenger(); + $board_url = generate_board_url(); + + // Time to go through the queue and send emails + foreach ($this->queue as $notification) + { + $notification->users($users); + + $user = $notification->get_user(); + + $messenger->template('privmsg_notify', $user['user_lang']); + + $messenger->to($user['user_email'], $user['username']); + + $messenger->assign_vars(array( + 'SUBJECT' => htmlspecialchars_decode($notification->get_title()), + 'AUTHOR_NAME' => '', + 'USERNAME' => htmlspecialchars_decode($user['username']), + + 'U_INBOX' => $board_url . "/ucp.{$this->php_ext}?i=pm&folder=inbox", + 'U_VIEW_MESSAGE' => $board_url . "/ucp.{$this->php_ext}?i=pm&mode=view&p={$notification->get_item_id()}", + )); + + $messenger->send($addr['method']); + } + + // Save the queue in the messenger class (has to be called or these emails could be lost?) + $messenger->save_queue(); + + // We're done, empty the queue + $this->empty_queue(); + } } diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php index 32211b26cf..ba57fe9f72 100644 --- a/phpBB/includes/notifications/service.php +++ b/phpBB/includes/notifications/service.php @@ -141,19 +141,7 @@ class phpbb_notifications_service */ // find out which users want to receive this type of notification - $sql = 'SELECT user_id FROM ' . USERS_TABLE . ' - WHERE ' . $this->db->sql_in_set('user_id', array(2)); - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - if (!isset($notify_users[$row['user_id']])) - { - $notify_users[$row['user_id']] = array(); - } - - $notify_users[$row['user_id']][] = ''; - } - $this->db->sql_freeresult($result); + $notify_users = $item_type_class_name::find_users_for_notification($data); // 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 diff --git a/phpBB/includes/notifications/type/base.php b/phpBB/includes/notifications/type/base.php index 89143873a8..f031abae77 100644 --- a/phpBB/includes/notifications/type/base.php +++ b/phpBB/includes/notifications/type/base.php @@ -58,6 +58,7 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type // Some common things we're going to use $this->db = $phpbb_container->get('dbal.conn'); + $this->phpbb_root_path = $phpbb_container->getParameter('core.root_path'); $this->php_ext = $phpbb_container->getParameter('core.php_ext'); @@ -114,7 +115,7 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type * @param int $user_id * @return array */ - protected function get_user($user_id) + public function get_user($user_id) { return $this->users[$user_id]; } @@ -149,11 +150,11 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type * Function for preparing the data for insertion in an SQL query * (The service handles insertion) * - * @param array $special_data Data unique to this notification type + * @param array $type_data Data unique to this notification type * * @return array Array of data ready to be inserted into the database */ - public function create_insert_array($special_data) + public function create_insert_array($type_data) { // Defaults $data = array_merge(array( @@ -173,13 +174,13 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type * Function for preparing the data for update in an SQL query * (The service handles insertion) * - * @param array $special_data Data unique to this notification type + * @param array $type_data Data unique to this notification type * * @return array Array of data ready to be updated in the database */ - public function create_update_array($special_data) + public function create_update_array($type_data) { - $data = $this->create_insert_array($special_data); + $data = $this->create_insert_array($type_data); // Unset data unique to each row unset( diff --git a/phpBB/includes/notifications/type/interface.php b/phpBB/includes/notifications/type/interface.php index b1ee9ae0b6..b710a75606 100644 --- a/phpBB/includes/notifications/type/interface.php +++ b/phpBB/includes/notifications/type/interface.php @@ -23,11 +23,13 @@ interface phpbb_notifications_type_interface { public static function get_item_type(); - public static function get_item_id($post); + public static function get_item_id($type_data); public function get_title(); public function get_url(); - public function create_insert_array($special_data); + public function create_insert_array($type_data); + + public function find_users_for_notification($type_data); } diff --git a/phpBB/includes/notifications/type/pm.php b/phpBB/includes/notifications/type/pm.php index 191c0b7e7f..7685a49614 100644 --- a/phpBB/includes/notifications/type/pm.php +++ b/phpBB/includes/notifications/type/pm.php @@ -84,16 +84,73 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base * * @return array Array of data ready to be inserted into the database */ - public function create_insert_array($post) + public function create_insert_array($pm) { - $this->item_id = $post['msg_id']; + $this->item_id = $pm['msg_id']; - $this->set_data('author_id', $post['author_id']); + $this->set_data('author_id', $pm['author_id']); - $this->set_data('message_subject', $post['message_subject']); + $this->set_data('message_subject', $pm['message_subject']); - $this->time = $post['message_time']; + return parent::create_insert_array($pm); + } - return parent::create_insert_array($post); + /** + * Find the users who want to receive notifications + * + * @param array $pm Data from + * @return array + */ + public function find_users_for_notification($pm) + { + $user = $this->phpbb_container->get('user'); + + // Exclude guests, current user and banned users from notifications + unset($pm['recipients'][ANONYMOUS], $pm['recipients'][$user->data['user_id']]); + + if (!sizeof($pm['recipients'])) + { + return; + } + + if (!function_exists('phpbb_get_banned_user_ids')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } + $banned_users = phpbb_get_banned_user_ids(array_keys($pm['recipients'])); + $pm['recipients'] = array_diff(array_keys($pm['recipients']), $banned_users); + + if (!sizeof($pm['recipients'])) + { + return; + } + + $sql = 'SELECT user_id, user_notify_pm, user_notify_type + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $pm['recipients']); + $result = $db->sql_query($sql); + + $pm['recipients'] = array(); + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['user_notify_pm']) + { + $pm['recipients'][$row['user_id']] = array(); + + if ($row['user_notify_type'] == NOTIFY_EMAIL || $row['user_notify_type'] == NOTIFY_BOTH) + { + $pm['recipients'][$row['user_id']][] = 'email'; + } + + if ($row['user_notify_type'] == NOTIFY_IM || $row['user_notify_type'] == NOTIFY_BOTH) + { + $pm['recipients'][$row['user_id']][] = 'jabber'; + } + } + } + $db->sql_freeresult($result); + + return $pm['recipients']; } } From a4eb8bf47a77cb2637bfad5db20ab9f0dc236059 Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sat, 8 Sep 2012 15:49:22 -0500 Subject: [PATCH 008/308] [ticket/11103] Jabber notification method base PHPBB3-11103 --- .../includes/notifications/method/jabber.php | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 phpBB/includes/notifications/method/jabber.php diff --git a/phpBB/includes/notifications/method/jabber.php b/phpBB/includes/notifications/method/jabber.php new file mode 100644 index 0000000000..15614db96c --- /dev/null +++ b/phpBB/includes/notifications/method/jabber.php @@ -0,0 +1,36 @@ + Date: Sat, 8 Sep 2012 16:02:32 -0500 Subject: [PATCH 009/308] [ticket/11103] Fixing some db columns that were of the incorrect type PHPBB3-11103 --- phpBB/develop/create_schema_files.php | 4 ++-- phpBB/includes/notifications/service.php | 7 ++++++- phpBB/includes/notifications/type/interface.php | 2 +- phpBB/includes/notifications/type/pm.php | 11 +++++++---- phpBB/includes/notifications/type/post.php | 2 ++ phpBB/install/database_update.php | 8 ++++---- 6 files changed, 22 insertions(+), 12 deletions(-) diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index 88aa9b70dd..a2f7463dd4 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -1297,7 +1297,7 @@ function get_schema_struct() $schema_data['phpbb_notifications'] = array( 'COLUMNS' => array( - 'item_type' => array('UINT', 0), + 'item_type' => array('VCHAR:25', ''), 'item_id' => array('UINT', 0), 'user_id' => array('UINT', 0), 'unread' => array('BOOL', 1), @@ -1775,7 +1775,7 @@ function get_schema_struct() $schema_data['phpbb_user_notifications'] = array( 'COLUMNS' => array( - 'item_type' => array('UINT', 0), + 'item_type' => array('VCHAR:25', ''), 'item_id' => array('UINT', 0), 'user_id' => array('UINT', 0), 'method' => array('VCHAR:25', ''), diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php index ba57fe9f72..a689e1c68a 100644 --- a/phpBB/includes/notifications/service.php +++ b/phpBB/includes/notifications/service.php @@ -141,7 +141,7 @@ class phpbb_notifications_service */ // find out which users want to receive this type of notification - $notify_users = $item_type_class_name::find_users_for_notification($data); + $notify_users = $item_type_class_name::find_users_for_notification($this->phpbb_container, $data); // 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 @@ -155,6 +155,11 @@ class phpbb_notifications_service } $this->db->sql_freeresult($result); + if (!sizeof($notify_users)) + { + return; + } + // Go through each user so we can insert a row in the DB and then notify them by their desired means foreach ($notify_users as $user => $methods) { diff --git a/phpBB/includes/notifications/type/interface.php b/phpBB/includes/notifications/type/interface.php index b710a75606..ccd963ba06 100644 --- a/phpBB/includes/notifications/type/interface.php +++ b/phpBB/includes/notifications/type/interface.php @@ -31,5 +31,5 @@ interface phpbb_notifications_type_interface public function create_insert_array($type_data); - public function find_users_for_notification($type_data); + public static function find_users_for_notification(ContainerBuilder $phpbb_container, $type_data); } diff --git a/phpBB/includes/notifications/type/pm.php b/phpBB/includes/notifications/type/pm.php index 7685a49614..2b2a835470 100644 --- a/phpBB/includes/notifications/type/pm.php +++ b/phpBB/includes/notifications/type/pm.php @@ -7,6 +7,8 @@ * */ +use Symfony\Component\DependencyInjection\ContainerBuilder; + /** * @ignore */ @@ -101,12 +103,13 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base * @param array $pm Data from * @return array */ - public function find_users_for_notification($pm) + public static function find_users_for_notification(ContainerBuilder $phpbb_container, $pm) { - $user = $this->phpbb_container->get('user'); + $db = $phpbb_container->get('dbal.conn'); + $user = $phpbb_container->get('user'); // Exclude guests, current user and banned users from notifications - unset($pm['recipients'][ANONYMOUS], $pm['recipients'][$user->data['user_id']]); + unset($pm['recipients'][ANONYMOUS]);//, $pm['recipients'][$user->data['user_id']]); if (!sizeof($pm['recipients'])) { @@ -115,7 +118,7 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base if (!function_exists('phpbb_get_banned_user_ids')) { - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + include($phpbb_container->getParameter('core.root_path') . 'includes/functions_user.' . $phpbb_container->getParameter('core.php_ext')); } $banned_users = phpbb_get_banned_user_ids(array_keys($pm['recipients'])); $pm['recipients'] = array_diff(array_keys($pm['recipients']), $banned_users); diff --git a/phpBB/includes/notifications/type/post.php b/phpBB/includes/notifications/type/post.php index addaa30ea6..920a53bcf2 100644 --- a/phpBB/includes/notifications/type/post.php +++ b/phpBB/includes/notifications/type/post.php @@ -7,6 +7,8 @@ * */ +use Symfony\Component\DependencyInjection\ContainerBuilder; + /** * @ignore */ diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 99e40ddee9..c3c2da4451 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -1107,7 +1107,7 @@ function database_update_info() ), NOTIFICATIONS_TABLE => array( 'COLUMNS' => array( - 'item_type' => array('UINT', 0), + 'item_type' => array('VCHAR:25', ''), 'item_id' => array('UINT', 0), 'user_id' => array('UINT', 0), 'unread' => array('BOOL', 1), @@ -1128,7 +1128,7 @@ function database_update_info() ), USER_NOTIFICATIONS_TABLE => array( 'COLUMNS' => array( - 'item_type' => array('UINT', 0), + 'item_type' => array('VCHAR:25', ''), 'item_id' => array('UINT', 0), 'user_id' => array('UINT', 0), 'method' => array('VCHAR:25', ''), @@ -2676,10 +2676,10 @@ function change_database_data(&$no_updates, $version) // Create config value for displaying last subject on forum list if (!isset($config['display_last_subject'])) - { + { $config->set('display_last_subject', '1'); } - + $no_updates = false; if (!isset($config['assets_version'])) From 86b801df7304d43f117bea762710149c25385260 Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sat, 8 Sep 2012 16:12:20 -0500 Subject: [PATCH 010/308] [ticket/11103] Some fixes for the email method PHPBB3-11103 --- phpBB/includes/functions_privmsgs.php | 25 ++++++++----------- phpBB/includes/notifications/method/email.php | 8 +++--- phpBB/includes/notifications/service.php | 11 ++++---- phpBB/includes/notifications/type/base.php | 2 -- 4 files changed, 20 insertions(+), 26 deletions(-) diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 99ad2ad791..8002765ee2 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -1543,6 +1543,7 @@ function get_folder_status($folder_id, $folder) function submit_pm($mode, $subject, &$data, $put_in_outbox = true) { global $db, $auth, $config, $phpEx, $template, $user, $phpbb_root_path; + global $phpbb_container; // We do not handle erasing pms here if ($mode == 'delete') @@ -1844,7 +1845,16 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) // Send Notifications if ($mode != 'edit') { - pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message'], $data['msg_id']); + $phpbb_notifications = $phpbb_container->get('notifications'); + + $phpbb_notifications->add_notifications('pm', array( + 'author_id' => $data['from_user_id'], + 'recipients' => $recipients, + 'message_subject' => $subject, + 'msg_id' => $data['msg_id'], + )); + + //pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message'], $data['msg_id']); } return $data['msg_id']; @@ -1855,19 +1865,6 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) */ function pm_notification($mode, $author, $recipients, $subject, $message, $msg_id) { - global $phpbb_container; - - $phpbb_notifications = $phpbb_container->get('notifications'); - - $phpbb_notifications->add_notifications('pm', array( - 'author_id' => $author, - 'recipients' => $recipients, - 'message_subject' => $subject, - 'msg_id' => $msg_id, - )); - - return; - global $db, $user, $config, $phpbb_root_path, $phpEx, $auth; $subject = censor_text($subject); diff --git a/phpBB/includes/notifications/method/email.php b/phpBB/includes/notifications/method/email.php index 725ede7913..0120485cff 100644 --- a/phpBB/includes/notifications/method/email.php +++ b/phpBB/includes/notifications/method/email.php @@ -29,7 +29,7 @@ class phpbb_notifications_method_email extends phpbb_notifications_method_base return true; } - public function notify() + public function notify($notification) { // email the user } @@ -70,7 +70,7 @@ class phpbb_notifications_method_email extends phpbb_notifications_method_base { $notification->users($users); - $user = $notification->get_user(); + $user = $notification->get_user($notification->user_id); $messenger->template('privmsg_notify', $user['user_lang']); @@ -82,10 +82,10 @@ class phpbb_notifications_method_email extends phpbb_notifications_method_base 'USERNAME' => htmlspecialchars_decode($user['username']), 'U_INBOX' => $board_url . "/ucp.{$this->php_ext}?i=pm&folder=inbox", - 'U_VIEW_MESSAGE' => $board_url . "/ucp.{$this->php_ext}?i=pm&mode=view&p={$notification->get_item_id()}", + 'U_VIEW_MESSAGE' => $board_url . "/ucp.{$this->php_ext}?i=pm&mode=view&p={$notification->item_id}", )); - $messenger->send($addr['method']); + $messenger->send('email'); } // Save the queue in the messenger class (has to be called or these emails could be lost?) diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php index a689e1c68a..74e2e29e1a 100644 --- a/phpBB/includes/notifications/service.php +++ b/phpBB/includes/notifications/service.php @@ -172,15 +172,14 @@ class phpbb_notifications_service foreach ($methods as $method) { // setup the notification methods and add the notification to the queue - if ($row['method']) + if ($method) { - if (!isset($notification_methods[$row['method']])) + if (!isset($notification_methods[$method])) { - $method_class_name = 'phpbb_notifications_method_' . $row['method']; - $notification_methods[$row['method']] = new $method_class_name(); + $method_class_name = 'phpbb_notifications_method_' . $method; + $notification_methods[$method] = new $method_class_name($this->phpbb_container); } - - $notification_methods[$row['method']]->add_to_queue($notification); + $notification_methods[$method]->add_to_queue($notification); } } } diff --git a/phpBB/includes/notifications/type/base.php b/phpBB/includes/notifications/type/base.php index f031abae77..32d8f58ff3 100644 --- a/phpBB/includes/notifications/type/base.php +++ b/phpBB/includes/notifications/type/base.php @@ -37,7 +37,6 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type /** * Indentification data - * notification_id * item_type * item_id * user_id @@ -141,7 +140,6 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type 'URL' => $this->get_url(), 'TIME' => $user->format_date($this->time), - 'ID' => $this->notification_id, 'UNREAD' => $this->unread, )); } From 16a0757f2a21ad2ca36a9463c822539c9ea14d30 Mon Sep 17 00:00:00 2001 From: Nathaniel Guse Date: Sat, 8 Sep 2012 17:28:13 -0500 Subject: [PATCH 011/308] [ticket/11103] Order notifications properly PHPBB3-11103 --- phpBB/includes/notifications/service.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php index 74e2e29e1a..4794472883 100644 --- a/phpBB/includes/notifications/service.php +++ b/phpBB/includes/notifications/service.php @@ -46,6 +46,8 @@ class phpbb_notifications_service * * @param array $options Optional options to control what notifications are loaded * user_id User id to load notifications for (Default: $user->data['user_id']) + * order_by Order by (Default: time) + * order_dir Order direction (Default: DESC) * limit Number of notifications to load (Default: 5) * start Notifications offset (Default: 0) */ @@ -58,12 +60,15 @@ class phpbb_notifications_service 'user_id' => $user->data['user_id'], 'limit' => 5, 'start' => 0, + 'order_by' => 'time', + 'order_dir' => 'DESC', ), $options); $notifications = $user_ids = array(); $sql = 'SELECT * FROM ' . NOTIFICATIONS_TABLE . ' - WHERE user_id = ' . (int) $options['user_id']; + WHERE user_id = ' . (int) $options['user_id'] . ' + ORDER BY ' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']); $result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']); while ($row = $this->db->sql_fetchrow($result)) From 6983f380c55779054b545e4760bf250e8ecace2e Mon Sep 17 00:00:00 2001 From: Nathaniel Guse Date: Sat, 8 Sep 2012 17:48:13 -0500 Subject: [PATCH 012/308] [ticket/11103] Full url function PHPBB3-11103 --- phpBB/includes/notifications/method/email.php | 11 ++++++----- phpBB/includes/notifications/type/interface.php | 2 ++ phpBB/includes/notifications/type/pm.php | 12 +++++++++++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/phpBB/includes/notifications/method/email.php b/phpBB/includes/notifications/method/email.php index 0120485cff..b1979296b9 100644 --- a/phpBB/includes/notifications/method/email.php +++ b/phpBB/includes/notifications/method/email.php @@ -23,6 +23,10 @@ if (!defined('IN_PHPBB')) */ class phpbb_notifications_method_email extends phpbb_notifications_method_base { + /** + * Is this method available for the user? + * This is checked on the notifications options + */ public static function is_available() { // Email is always available @@ -77,12 +81,9 @@ class phpbb_notifications_method_email extends phpbb_notifications_method_base $messenger->to($user['user_email'], $user['username']); $messenger->assign_vars(array( - 'SUBJECT' => htmlspecialchars_decode($notification->get_title()), - 'AUTHOR_NAME' => '', - 'USERNAME' => htmlspecialchars_decode($user['username']), + 'SUBJECT' => htmlspecialchars_decode($notification->get_title()), - 'U_INBOX' => $board_url . "/ucp.{$this->php_ext}?i=pm&folder=inbox", - 'U_VIEW_MESSAGE' => $board_url . "/ucp.{$this->php_ext}?i=pm&mode=view&p={$notification->item_id}", + 'U_VIEW_MESSAGE' => $notification->get_full_url(), )); $messenger->send('email'); diff --git a/phpBB/includes/notifications/type/interface.php b/phpBB/includes/notifications/type/interface.php index ccd963ba06..03e24358a9 100644 --- a/phpBB/includes/notifications/type/interface.php +++ b/phpBB/includes/notifications/type/interface.php @@ -29,6 +29,8 @@ interface phpbb_notifications_type_interface public function get_url(); + public function get_full_url(); + public function create_insert_array($type_data); public static function find_users_for_notification(ContainerBuilder $phpbb_container, $type_data); diff --git a/phpBB/includes/notifications/type/pm.php b/phpBB/includes/notifications/type/pm.php index 2b2a835470..50c67de21a 100644 --- a/phpBB/includes/notifications/type/pm.php +++ b/phpBB/includes/notifications/type/pm.php @@ -65,7 +65,17 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base */ public function get_url() { - return append_sid($this->phpbb_root_path . 'ucp.' . $this->php_ext, "i=pm&mode=view&p={$this->item_id}"); + return append_sid($this->phpbb_root_path . 'ucp.' . $this->php_ext, "i=pm&mode=view&p={$this->item_id}"); + } + + /** + * Get the full url to this item + * + * @return string URL + */ + public function get_full_url() + { + return generate_board_url() . "/ucp.{$this->php_ext}?i=pm&mode=view&p={$this->item_id}"; } /** From 98a03090a05b1d7651c05ad23802973cf20dcf6b Mon Sep 17 00:00:00 2001 From: Nathaniel Guse Date: Sat, 8 Sep 2012 21:05:49 -0500 Subject: [PATCH 013/308] [ticket/11103] Move banned user checking to email method This will make sure banned users are never sent notification emails PHPBB3-11103 --- phpBB/includes/notifications/method/email.php | 12 ++++++++++++ phpBB/includes/notifications/type/pm.php | 16 ++-------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/phpBB/includes/notifications/method/email.php b/phpBB/includes/notifications/method/email.php index b1979296b9..2b80b5bf3a 100644 --- a/phpBB/includes/notifications/method/email.php +++ b/phpBB/includes/notifications/method/email.php @@ -52,6 +52,13 @@ class phpbb_notifications_method_email extends phpbb_notifications_method_base $user_ids[] = $notification->user_id; } + // We do not send emails to banned users + if (!function_exists('phpbb_get_banned_user_ids')) + { + include($phpbb_container->getParameter('core.root_path') . 'includes/functions_user.' . $phpbb_container->getParameter('core.php_ext')); + } + $banned_users = phpbb_get_banned_user_ids($user_ids); + $sql = 'SELECT * FROM ' . USERS_TABLE . ' WHERE ' . $this->db->sql_in_set('user_id', $user_ids); $result = $this->db->sql_query($sql); @@ -72,6 +79,11 @@ class phpbb_notifications_method_email extends phpbb_notifications_method_base // Time to go through the queue and send emails foreach ($this->queue as $notification) { + if (in_array($notification->user_id, $banned_users)) + { + continue; + } + $notification->users($users); $user = $notification->get_user($notification->user_id); diff --git a/phpBB/includes/notifications/type/pm.php b/phpBB/includes/notifications/type/pm.php index 50c67de21a..92026c08d7 100644 --- a/phpBB/includes/notifications/type/pm.php +++ b/phpBB/includes/notifications/type/pm.php @@ -118,20 +118,8 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base $db = $phpbb_container->get('dbal.conn'); $user = $phpbb_container->get('user'); - // Exclude guests, current user and banned users from notifications - unset($pm['recipients'][ANONYMOUS]);//, $pm['recipients'][$user->data['user_id']]); - - if (!sizeof($pm['recipients'])) - { - return; - } - - if (!function_exists('phpbb_get_banned_user_ids')) - { - include($phpbb_container->getParameter('core.root_path') . 'includes/functions_user.' . $phpbb_container->getParameter('core.php_ext')); - } - $banned_users = phpbb_get_banned_user_ids(array_keys($pm['recipients'])); - $pm['recipients'] = array_diff(array_keys($pm['recipients']), $banned_users); + // Exclude guests and current user from notifications + unset($pm['recipients'][ANONYMOUS], $pm['recipients'][$user->data['user_id']]); if (!sizeof($pm['recipients'])) { From 4b4ea7c5cde7c9f3684ca325c110f81eda593d67 Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sun, 9 Sep 2012 10:19:46 -0500 Subject: [PATCH 014/308] [ticket/11103] The service now handles all user loading itself Delete pm notifications when pms are deleted PHPBB3-11103 --- phpBB/includes/functions_privmsgs.php | 112 +++--------------- phpBB/includes/notifications/method/base.php | 25 +++- phpBB/includes/notifications/method/email.php | 14 +-- phpBB/includes/notifications/service.php | 101 +++++++++------- phpBB/includes/notifications/type/base.php | 24 +--- .../includes/notifications/type/interface.php | 4 +- phpBB/includes/notifications/type/pm.php | 98 ++++++++------- 7 files changed, 155 insertions(+), 223 deletions(-) diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 8002765ee2..88c5bd8e2a 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -982,6 +982,7 @@ function handle_mark_actions($user_id, $mark_action) function delete_pm($user_id, $msg_ids, $folder_id) { global $db, $user, $phpbb_root_path, $phpEx; + global $phpbb_container; $user_id = (int) $user_id; $folder_id = (int) $folder_id; @@ -1093,6 +1094,10 @@ function delete_pm($user_id, $msg_ids, $folder_id) $user->data['user_unread_privmsg'] -= $num_unread; } + // Delete Notifications + $phpbb_notifications = $phpbb_container->get('notifications'); + $phpbb_notifications->delete_notifications('pm', array_keys($delete_rows)); + // Now we have to check which messages we can delete completely $sql = 'SELECT msg_id FROM ' . PRIVMSGS_TO_TABLE . ' @@ -1843,106 +1848,25 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) $db->sql_transaction('commit'); // Send Notifications - if ($mode != 'edit') + $phpbb_notifications = $phpbb_container->get('notifications'); + + $pm_data = array_merge($data, array( + 'message_subject' => $subject, + 'recipients' => $recipients, + )); + + if ($mode == 'edit') { - $phpbb_notifications = $phpbb_container->get('notifications'); - - $phpbb_notifications->add_notifications('pm', array( - 'author_id' => $data['from_user_id'], - 'recipients' => $recipients, - 'message_subject' => $subject, - 'msg_id' => $data['msg_id'], - )); - - //pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message'], $data['msg_id']); + $phpbb_notifications->update_notifications('pm', $pm_data); + } + else + { + $phpbb_notifications->add_notifications('pm', $pm_data); } return $data['msg_id']; } -/** -* PM Notification -*/ -function pm_notification($mode, $author, $recipients, $subject, $message, $msg_id) -{ - global $db, $user, $config, $phpbb_root_path, $phpEx, $auth; - - $subject = censor_text($subject); - - // Exclude guests, current user and banned users from notifications - unset($recipients[ANONYMOUS], $recipients[$user->data['user_id']]); - - if (!sizeof($recipients)) - { - return; - } - - if (!function_exists('phpbb_get_banned_user_ids')) - { - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); - } - $banned_users = phpbb_get_banned_user_ids(array_keys($recipients)); - $recipients = array_diff(array_keys($recipients), $banned_users); - - if (!sizeof($recipients)) - { - return; - } - - $sql = 'SELECT user_id, username, user_email, user_lang, user_notify_pm, user_notify_type, user_jabber - FROM ' . USERS_TABLE . ' - WHERE ' . $db->sql_in_set('user_id', $recipients); - $result = $db->sql_query($sql); - - $msg_list_ary = array(); - while ($row = $db->sql_fetchrow($result)) - { - if ($row['user_notify_pm'] == 1 && trim($row['user_email'])) - { - $msg_list_ary[] = array( - 'method' => $row['user_notify_type'], - 'email' => $row['user_email'], - 'jabber' => $row['user_jabber'], - 'name' => $row['username'], - 'lang' => $row['user_lang'] - ); - } - } - $db->sql_freeresult($result); - - if (!sizeof($msg_list_ary)) - { - return; - } - - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - $messenger = new messenger(); - - foreach ($msg_list_ary as $pos => $addr) - { - $messenger->template('privmsg_notify', $addr['lang']); - - $messenger->to($addr['email'], $addr['name']); - $messenger->im($addr['jabber'], $addr['name']); - - $messenger->assign_vars(array( - 'SUBJECT' => htmlspecialchars_decode($subject), - 'AUTHOR_NAME' => htmlspecialchars_decode($author), - 'USERNAME' => htmlspecialchars_decode($addr['name']), - - 'U_INBOX' => generate_board_url() . "/ucp.$phpEx?i=pm&folder=inbox", - 'U_VIEW_MESSAGE' => generate_board_url() . "/ucp.$phpEx?i=pm&mode=view&p=$msg_id", - )); - - $messenger->send($addr['method']); - } - unset($msg_list_ary); - - $messenger->save_queue(); - - unset($messenger); -} - /** * Display Message History */ diff --git a/phpBB/includes/notifications/method/base.php b/phpBB/includes/notifications/method/base.php index 98c06509c6..3ed9d3f33c 100644 --- a/phpBB/includes/notifications/method/base.php +++ b/phpBB/includes/notifications/method/base.php @@ -24,11 +24,31 @@ if (!defined('IN_PHPBB')) abstract class phpbb_notifications_method_base implements phpbb_notifications_method_interface { protected $phpbb_container; + protected $service; protected $db; protected $user; protected $phpbb_root_path; protected $php_ext; + /** + * Desired notifications + * unique by (type, type_id, user_id, method) + * if multiple methods are desired, multiple rows will exist. + * + * method of "none" will over-ride any other options + * + * item_type + * item_id + * user_id + * method + * none (will never receive notifications) + * standard (listed in notifications window + * popup? + * email + * jabber + * sms? + */ + /** * Queue of messages to be sent * @@ -36,11 +56,14 @@ abstract class phpbb_notifications_method_base implements phpbb_notifications_me */ protected $queue = array(); - public function __construct(ContainerBuilder $phpbb_container, $data = array()) + public function __construct(ContainerBuilder $phpbb_container) { // phpBB Container $this->phpbb_container = $phpbb_container; + // Service + $this->service = $phpbb_container->get('notifications'); + // Some common things we're going to use $this->db = $phpbb_container->get('dbal.conn'); $this->user = $phpbb_container->get('user'); diff --git a/phpBB/includes/notifications/method/email.php b/phpBB/includes/notifications/method/email.php index 2b80b5bf3a..50df9a6c56 100644 --- a/phpBB/includes/notifications/method/email.php +++ b/phpBB/includes/notifications/method/email.php @@ -59,14 +59,8 @@ class phpbb_notifications_method_email extends phpbb_notifications_method_base } $banned_users = phpbb_get_banned_user_ids($user_ids); - $sql = 'SELECT * FROM ' . USERS_TABLE . ' - WHERE ' . $this->db->sql_in_set('user_id', $user_ids); - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - $users[$row['user_id']] = $row; - } - $this->db->sql_freeresult($result); + // Load all the users we need + $this->service->load_users($user_ids); // Load the messenger if (!class_exists('messenger')) @@ -84,9 +78,7 @@ class phpbb_notifications_method_email extends phpbb_notifications_method_base continue; } - $notification->users($users); - - $user = $notification->get_user($notification->user_id); + $user = $this->service->get_user($notification->user_id); $messenger->template('privmsg_notify', $user['user_lang']); diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php index 4794472883..50ceb1584a 100644 --- a/phpBB/includes/notifications/service.php +++ b/phpBB/includes/notifications/service.php @@ -31,7 +31,7 @@ class phpbb_notifications_service * * @var array Array of user data that we've loaded from the DB */ - protected $users; + protected $users = array(); public function __construct(ContainerBuilder $phpbb_container) { @@ -76,7 +76,6 @@ class phpbb_notifications_service $item_type_class_name = $this->get_item_type_class_name($row['item_type'], true); $notification = new $item_type_class_name($this->phpbb_container, $row); - $notification->users($this->users); $user_ids = array_merge($user_ids, $notification->users_to_query()); @@ -84,24 +83,7 @@ class phpbb_notifications_service } $this->db->sql_freeresult($result); - // Load the users - $user_ids = array_unique($user_ids); - - // @todo do not load users we already have in $this->users - - if (sizeof($user_ids)) - { - // @todo do not select everything - $sql = 'SELECT * FROM ' . USERS_TABLE . ' - WHERE ' . $this->db->sql_in_set('user_id', $user_ids); - $result = $this->db->sql_query($sql); - - while ($row = $this->db->sql_fetchrow($result)) - { - $this->users[$row['user_id']] = $row; - } - $this->db->sql_freeresult($result); - } + $this->load_users($user_ids); return $notifications; } @@ -122,32 +104,16 @@ class phpbb_notifications_service // Update any existing notifications for this item $this->update_notifications($item_type, $item_id, $data); - $notify_users = array(); + $notify_users = $user_ids = array(); $notification_objects = $notification_methods = array(); $new_rows = array(); - /** - * Desired notifications - * unique by (type, type_id, user_id, method) - * if multiple methods are desired, multiple rows will exist. - * - * method of "none" will over-ride any other options - * - * item_type - * item_id - * user_id - * method - * none (will never receive notifications) - * standard (listed in notifications window - * popup? - * email - * jabber - * sms? - */ - // 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); + // Never send notifications to the anonymous user or the current user! + $notify_users = array_diff($notify_users, array(ANONYMOUS, $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 $sql = 'SELECT user_id FROM ' . NOTIFICATIONS_TABLE . " @@ -172,8 +138,12 @@ class phpbb_notifications_service $notification->user_id = (int) $user; + // Store the creation array in our new rows that will be inserted later $new_rows[] = $notification->create_insert_array($data); + // Users are needed to send notifications + $user_ids = array_merge($user_ids, $notification->users_to_query()); + foreach ($methods as $method) { // setup the notification methods and add the notification to the queue @@ -184,6 +154,7 @@ class phpbb_notifications_service $method_class_name = 'phpbb_notifications_method_' . $method; $notification_methods[$method] = new $method_class_name($this->phpbb_container); } + $notification_methods[$method]->add_to_queue($notification); } } @@ -192,6 +163,9 @@ class phpbb_notifications_service // insert into the db $this->db->sql_multi_insert(NOTIFICATIONS_TABLE, $new_rows); + // We need to load all of the users to send notifications + $this->load_users($user_ids); + // run the queue for each method to send notifications foreach ($notification_methods as $method) { @@ -203,13 +177,14 @@ class phpbb_notifications_service * Update 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 updated */ - public function update_notifications($item_type, $item_id, $data) + public function update_notifications($item_type, $data) { $item_type_class_name = $this->get_item_type_class_name($item_type); + $item_id = $item_type_class_name::get_item_id($data); + $notification = new $item_type_class_name($this->phpbb_container); $update_array = $notification->create_update_array($data); @@ -224,17 +199,55 @@ class phpbb_notifications_service * Delete a notification * * @param string $item_type Type identifier - * @param int $item_id Identifier within the type + * @param int|array $item_id Identifier within the type (or array of ids) * @param array $data Data specific for this type that will be updated */ public function delete_notifications($item_type, $item_id) { $sql = 'DELETE FROM ' . NOTIFICATIONS_TABLE . " WHERE item_type = '" . $this->db->sql_escape($item_type) . "' - AND item_id = " . (int) $item_id; + AND " . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id); $this->db->sql_query($sql); } + /** + * Load user helper + * + * @param array $user_ids + */ + public function load_users($user_ids) + { + // Load the users + $user_ids = array_unique($user_ids); + + // Do not load users we already have in $this->users + $user_ids = array_diff($user_ids, array_keys($this->users)); + + if (sizeof($user_ids)) + { + $sql = 'SELECT * FROM ' . USERS_TABLE . ' + WHERE ' . $this->db->sql_in_set('user_id', $user_ids); + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $this->users[$row['user_id']] = $row; + } + $this->db->sql_freeresult($result); + } + } + + /** + * Get a user row from our users cache + * + * @param int $user_id + * @return array + */ + public function get_user($user_id) + { + return $this->users[$user_id]; + } + /** * Helper to get the notifications item type class name and clean it if unsafe */ diff --git a/phpBB/includes/notifications/type/base.php b/phpBB/includes/notifications/type/base.php index 32d8f58ff3..b0b8801a7e 100644 --- a/phpBB/includes/notifications/type/base.php +++ b/phpBB/includes/notifications/type/base.php @@ -24,6 +24,7 @@ if (!defined('IN_PHPBB')) abstract class phpbb_notifications_type_base implements phpbb_notifications_type_interface { protected $phpbb_container; + protected $service; protected $db; protected $phpbb_root_path; protected $php_ext; @@ -55,6 +56,9 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type // phpBB Container $this->phpbb_container = $phpbb_container; + // Service + $this->service = $phpbb_container->get('notifications'); + // Some common things we're going to use $this->db = $phpbb_container->get('dbal.conn'); @@ -99,26 +103,6 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type $this->data['data'][$name] = $value; } - /** - * Function to store the users loaded from the database (for output to the template) - * (The service handles this) - */ - public function users(&$users) - { - $this->users = &$users; - } - - /** - * Get a user row from our users cache - * - * @param int $user_id - * @return array - */ - public function get_user($user_id) - { - return $this->users[$user_id]; - } - /** * Output the notification to the template * diff --git a/phpBB/includes/notifications/type/interface.php b/phpBB/includes/notifications/type/interface.php index 03e24358a9..85fe41f6ef 100644 --- a/phpBB/includes/notifications/type/interface.php +++ b/phpBB/includes/notifications/type/interface.php @@ -25,6 +25,8 @@ interface phpbb_notifications_type_interface public static function get_item_id($type_data); + public static function find_users_for_notification(ContainerBuilder $phpbb_container, $type_data); + public function get_title(); public function get_url(); @@ -32,6 +34,4 @@ interface phpbb_notifications_type_interface public function get_full_url(); public function create_insert_array($type_data); - - public static function find_users_for_notification(ContainerBuilder $phpbb_container, $type_data); } diff --git a/phpBB/includes/notifications/type/pm.php b/phpBB/includes/notifications/type/pm.php index 92026c08d7..8b8f41d1c2 100644 --- a/phpBB/includes/notifications/type/pm.php +++ b/phpBB/includes/notifications/type/pm.php @@ -44,6 +44,50 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base return $pm['msg_id']; } + /** + * Find the users who want to receive notifications + * + * @param array $pm Data from + * @return array + */ + public static function find_users_for_notification(ContainerBuilder $phpbb_container, $pm) + { + $service = $phpbb_container->get('notifications'); + $db = $phpbb_container->get('dbal.conn'); + $user = $phpbb_container->get('user'); + + if (!sizeof($pm['recipients'])) + { + return array(); + } + + $service->load_users(array_keys($pm['recipients'])); + + $notify_users = array(); + + foreach (array_keys($pm['recipients']) as $user_id) + { + $recipient = $service->get_user($user_id); + + if ($recipient['user_notify_pm']) + { + $notify_users[$recipient['user_id']] = array(); + + if ($recipient['user_notify_type'] == NOTIFY_EMAIL || $recipient['user_notify_type'] == NOTIFY_BOTH) + { + $notify_users[$recipient['user_id']][] = 'email'; + } + + if ($recipient['user_notify_type'] == NOTIFY_IM || $recipient['user_notify_type'] == NOTIFY_BOTH) + { + $notify_users[$recipient['user_id']][] = 'jabber'; + } + } + } + + return $notify_users; + } + /** * Get the title of this notification * @@ -51,7 +95,7 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base */ public function get_title() { - $user_data = $this->get_user($this->get_data('author_id')); + $user_data = $this->service->get_user($this->get_data('from_user_id')); $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']); @@ -85,7 +129,7 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base */ public function users_to_query() { - return array($this->data['author_id']); + return array($this->data['from_user_id']); } /** @@ -100,58 +144,10 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base { $this->item_id = $pm['msg_id']; - $this->set_data('author_id', $pm['author_id']); + $this->set_data('from_user_id', $pm['from_user_id']); $this->set_data('message_subject', $pm['message_subject']); return parent::create_insert_array($pm); } - - /** - * Find the users who want to receive notifications - * - * @param array $pm Data from - * @return array - */ - public static function find_users_for_notification(ContainerBuilder $phpbb_container, $pm) - { - $db = $phpbb_container->get('dbal.conn'); - $user = $phpbb_container->get('user'); - - // Exclude guests and current user from notifications - unset($pm['recipients'][ANONYMOUS], $pm['recipients'][$user->data['user_id']]); - - if (!sizeof($pm['recipients'])) - { - return; - } - - $sql = 'SELECT user_id, user_notify_pm, user_notify_type - FROM ' . USERS_TABLE . ' - WHERE ' . $db->sql_in_set('user_id', $pm['recipients']); - $result = $db->sql_query($sql); - - $pm['recipients'] = array(); - - while ($row = $db->sql_fetchrow($result)) - { - if ($row['user_notify_pm']) - { - $pm['recipients'][$row['user_id']] = array(); - - if ($row['user_notify_type'] == NOTIFY_EMAIL || $row['user_notify_type'] == NOTIFY_BOTH) - { - $pm['recipients'][$row['user_id']][] = 'email'; - } - - if ($row['user_notify_type'] == NOTIFY_IM || $row['user_notify_type'] == NOTIFY_BOTH) - { - $pm['recipients'][$row['user_id']][] = 'jabber'; - } - } - } - $db->sql_freeresult($result); - - return $pm['recipients']; - } } From ff45c9aa7c077fc0a03c64764917d1efcccf48f4 Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sun, 9 Sep 2012 10:36:22 -0500 Subject: [PATCH 015/308] [ticket/11103] General notification email template. PHPBB3-11103 --- phpBB/includes/notifications/method/base.php | 13 +---------- phpBB/includes/notifications/method/email.php | 15 ++++++------- .../notifications/method/interface.php | 2 +- phpBB/includes/notifications/service.php | 2 +- phpBB/includes/notifications/type/base.php | 22 ++++++++++++++++++- .../includes/notifications/type/interface.php | 4 ++++ phpBB/includes/notifications/type/pm.php | 20 +++++++++++++---- phpBB/language/en/email/notification.txt | 16 ++++++++++++++ 8 files changed, 67 insertions(+), 27 deletions(-) create mode 100644 phpBB/language/en/email/notification.txt diff --git a/phpBB/includes/notifications/method/base.php b/phpBB/includes/notifications/method/base.php index 3ed9d3f33c..b860fcffda 100644 --- a/phpBB/includes/notifications/method/base.php +++ b/phpBB/includes/notifications/method/base.php @@ -83,19 +83,8 @@ abstract class phpbb_notifications_method_base implements phpbb_notifications_me } /** - * Basic run queue function. - * Child methods should override this function if there are more efficient methods to mass-notification + * Empty the queue */ - public function run_queue() - { - foreach ($this->queue as $notification) - { - $this->notify($notification); - } - - $this->empty_queue(); - } - protected function empty_queue() { $this->queue = array(); diff --git a/phpBB/includes/notifications/method/email.php b/phpBB/includes/notifications/method/email.php index 50df9a6c56..69546be73f 100644 --- a/phpBB/includes/notifications/method/email.php +++ b/phpBB/includes/notifications/method/email.php @@ -33,12 +33,7 @@ class phpbb_notifications_method_email extends phpbb_notifications_method_base return true; } - public function notify($notification) - { - // email the user - } - - public function run_queue() + public function notify() { if (!sizeof($this->queue)) { @@ -80,14 +75,18 @@ class phpbb_notifications_method_email extends phpbb_notifications_method_base $user = $this->service->get_user($notification->user_id); - $messenger->template('privmsg_notify', $user['user_lang']); + $messenger->template('notification', $user['user_lang']); $messenger->to($user['user_email'], $user['username']); $messenger->assign_vars(array( - 'SUBJECT' => htmlspecialchars_decode($notification->get_title()), + 'USERNAME' => $user['username'], + + 'MESSAGE' => htmlspecialchars_decode($notification->get_title()), 'U_VIEW_MESSAGE' => $notification->get_full_url(), + + 'U_UNSUBSCRIBE' => $notification->get_unsubscribe_url(), )); $messenger->send('email'); diff --git a/phpBB/includes/notifications/method/interface.php b/phpBB/includes/notifications/method/interface.php index f18d005b8b..7d7f3abcd0 100644 --- a/phpBB/includes/notifications/method/interface.php +++ b/phpBB/includes/notifications/method/interface.php @@ -21,5 +21,5 @@ if (!defined('IN_PHPBB')) */ interface phpbb_notifications_method_interface { - public function notify($notification); + public function notify(); } diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php index 50ceb1584a..463798fa07 100644 --- a/phpBB/includes/notifications/service.php +++ b/phpBB/includes/notifications/service.php @@ -169,7 +169,7 @@ class phpbb_notifications_service // run the queue for each method to send notifications foreach ($notification_methods as $method) { - $method->run_queue(); + $method->notify(); } } diff --git a/phpBB/includes/notifications/type/base.php b/phpBB/includes/notifications/type/base.php index b0b8801a7e..91cc9f175a 100644 --- a/phpBB/includes/notifications/type/base.php +++ b/phpBB/includes/notifications/type/base.php @@ -120,7 +120,7 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type ), $options); $template->assign_block_vars($options['template_block'], array( - 'TITLE' => $this->get_title(), + 'TITLE' => $this->get_formatted_title(), 'URL' => $this->get_url(), 'TIME' => $user->format_date($this->time), @@ -173,4 +173,24 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type return $data; } + + /** + * Get the formatted title of this notification (fall-back) + * + * @return string + */ + public function get_formatted_title() + { + return $this->get_title(); + } + + /** + * URL to unsubscribe to this notification + * + * @param string|bool $method Method name to unsubscribe from (email|jabber|etc), False to unsubscribe from all notifications for this item + */ + public function get_unsubscribe_url($method = false) + { + return false; + } } diff --git a/phpBB/includes/notifications/type/interface.php b/phpBB/includes/notifications/type/interface.php index 85fe41f6ef..c165815835 100644 --- a/phpBB/includes/notifications/type/interface.php +++ b/phpBB/includes/notifications/type/interface.php @@ -29,9 +29,13 @@ interface phpbb_notifications_type_interface public function get_title(); + public function get_formatted_title(); + public function get_url(); public function get_full_url(); + public function get_unsubscribe_url($method); + public function create_insert_array($type_data); } diff --git a/phpBB/includes/notifications/type/pm.php b/phpBB/includes/notifications/type/pm.php index 8b8f41d1c2..702ec39c16 100644 --- a/phpBB/includes/notifications/type/pm.php +++ b/phpBB/includes/notifications/type/pm.php @@ -89,7 +89,21 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base } /** - * Get the title of this notification + * Get the HTML formatted title of this notification + * + * @return string + */ + public function get_formatted_title() + { + $user_data = $this->service->get_user($this->get_data('from_user_id')); + + $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']); + + return $username . ' sent you a private message titled: ' . $this->get_data('message_subject'); + } + + /** + * Get the plain text title of this notification * * @return string */ @@ -97,9 +111,7 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base { $user_data = $this->service->get_user($this->get_data('from_user_id')); - $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']); - - return $username . ' sent you a private message titled: ' . $this->get_data('message_subject'); + return $user_data['username'] . ' sent you a private message titled: ' . $this->get_data('message_subject'); } /** diff --git a/phpBB/language/en/email/notification.txt b/phpBB/language/en/email/notification.txt new file mode 100644 index 0000000000..ed35e96c85 --- /dev/null +++ b/phpBB/language/en/email/notification.txt @@ -0,0 +1,16 @@ +Subject: Notification from {SITENAME} + +Hello {USERNAME}, + +{MESSAGE} + +You can view this by clicking on the following link: + +{U_VIEW_MESSAGE} + + +You may unsubscribe by clicking on the following link: +{U_UNSUBSCRIBE} + + +{EMAIL_SIG} \ No newline at end of file From 570fe6cee87da807f0917cdc0c84aee604b50510 Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sun, 9 Sep 2012 12:27:37 -0500 Subject: [PATCH 016/308] [ticket/11103] Do not initialize the notifications in common.php DIC initializes it when it is needed. PHPBB3-11103 --- phpBB/common.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/phpBB/common.php b/phpBB/common.php index 52879deb9c..281eb88c4d 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -146,9 +146,6 @@ if (!$config['use_system_cron']) $cron = $phpbb_container->get('cron.manager'); } -// Load notifications -$phpbb_notifications = $phpbb_container->get('notifications'); - /** * Main event which is triggered on every page * From 74e2a8f893a2e7a69ba129a74dd0b3c31e742e79 Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sun, 9 Sep 2012 13:29:47 -0500 Subject: [PATCH 017/308] [ticket/11103] Post notifications PHPBB3-11103 --- phpBB/includes/functions_posting.php | 252 ++------------------- phpBB/includes/mcp/mcp_queue.php | 6 +- phpBB/includes/notifications/type/base.php | 32 +++ phpBB/includes/notifications/type/pm.php | 2 + phpBB/includes/notifications/type/post.php | 71 +++++- 5 files changed, 122 insertions(+), 241 deletions(-) diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index c50395a5df..6c5c4535a3 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -61,7 +61,7 @@ function generate_smilies($mode, $forum_id) 'body' => 'posting_smilies.html') ); - generate_pagination(append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id), $smiley_count, $config['smilies_per_page'], $start); + generate_pagination(append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id), $smiley_count, $config['smilies_per_page'], $start); } $display_link = false; @@ -1173,237 +1173,6 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id return true; } -/** -* User Notification -*/ -function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id, $topic_id, $post_id) -{ - global $db, $user, $config, $phpbb_root_path, $phpEx, $auth; - - $topic_notification = ($mode == 'reply' || $mode == 'quote') ? true : false; - $forum_notification = ($mode == 'post') ? true : false; - - if (!$topic_notification && !$forum_notification) - { - trigger_error('NO_MODE'); - } - - if (($topic_notification && !$config['allow_topic_notify']) || ($forum_notification && !$config['allow_forum_notify'])) - { - return; - } - - $topic_title = ($topic_notification) ? $topic_title : $subject; - $topic_title = censor_text($topic_title); - - // Exclude guests, current user and banned users from notifications - if (!function_exists('phpbb_get_banned_user_ids')) - { - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); - } - $sql_ignore_users = phpbb_get_banned_user_ids(); - $sql_ignore_users[ANONYMOUS] = ANONYMOUS; - $sql_ignore_users[$user->data['user_id']] = $user->data['user_id']; - - $notify_rows = array(); - - // -- get forum_userids || topic_userids - $sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber - FROM ' . (($topic_notification) ? TOPICS_WATCH_TABLE : FORUMS_WATCH_TABLE) . ' w, ' . USERS_TABLE . ' u - WHERE w.' . (($topic_notification) ? 'topic_id' : 'forum_id') . ' = ' . (($topic_notification) ? $topic_id : $forum_id) . ' - AND ' . $db->sql_in_set('w.user_id', $sql_ignore_users, true) . ' - AND w.notify_status = ' . NOTIFY_YES . ' - AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') - AND u.user_id = w.user_id'; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $notify_user_id = (int) $row['user_id']; - $notify_rows[$notify_user_id] = array( - 'user_id' => $notify_user_id, - 'username' => $row['username'], - 'user_email' => $row['user_email'], - 'user_jabber' => $row['user_jabber'], - 'user_lang' => $row['user_lang'], - 'notify_type' => ($topic_notification) ? 'topic' : 'forum', - 'template' => ($topic_notification) ? 'topic_notify' : 'newtopic_notify', - 'method' => $row['user_notify_type'], - 'allowed' => false - ); - - // Add users who have been already notified to ignore list - $sql_ignore_users[$notify_user_id] = $notify_user_id; - } - $db->sql_freeresult($result); - - // forum notification is sent to those not already receiving topic notifications - if ($topic_notification) - { - $sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber - FROM ' . FORUMS_WATCH_TABLE . ' fw, ' . USERS_TABLE . " u - WHERE fw.forum_id = $forum_id - AND " . $db->sql_in_set('fw.user_id', $sql_ignore_users, true) . ' - AND fw.notify_status = ' . NOTIFY_YES . ' - AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') - AND u.user_id = fw.user_id'; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $notify_user_id = (int) $row['user_id']; - $notify_rows[$notify_user_id] = array( - 'user_id' => $notify_user_id, - 'username' => $row['username'], - 'user_email' => $row['user_email'], - 'user_jabber' => $row['user_jabber'], - 'user_lang' => $row['user_lang'], - 'notify_type' => 'forum', - 'template' => 'forum_notify', - 'method' => $row['user_notify_type'], - 'allowed' => false - ); - } - $db->sql_freeresult($result); - } - - if (!sizeof($notify_rows)) - { - return; - } - - // Make sure users are allowed to read the forum - foreach ($auth->acl_get_list(array_keys($notify_rows), 'f_read', $forum_id) as $forum_id => $forum_ary) - { - foreach ($forum_ary as $auth_option => $user_ary) - { - foreach ($user_ary as $user_id) - { - $notify_rows[$user_id]['allowed'] = true; - } - } - } - - // Now, we have to do a little step before really sending, we need to distinguish our users a little bit. ;) - $msg_users = $delete_ids = $update_notification = array(); - foreach ($notify_rows as $user_id => $row) - { - if (!$row['allowed'] || !trim($row['user_email'])) - { - $delete_ids[$row['notify_type']][] = $row['user_id']; - } - else - { - $msg_users[] = $row; - $update_notification[$row['notify_type']][] = $row['user_id']; - - /* - * We also update the forums watch table for this user when we are - * sending out a topic notification to prevent sending out another - * notification in case this user is also subscribed to the forum - * this topic was posted in. - * Since an UPDATE query is used, this has no effect on users only - * subscribed to the topic (i.e. no row is created) and should not - * be a performance issue. - */ - if ($row['notify_type'] === 'topic') - { - $update_notification['forum'][] = $row['user_id']; - } - } - } - unset($notify_rows); - - // Now, we are able to really send out notifications - if (sizeof($msg_users)) - { - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - $messenger = new messenger(); - - $msg_list_ary = array(); - foreach ($msg_users as $row) - { - $pos = (!isset($msg_list_ary[$row['template']])) ? 0 : sizeof($msg_list_ary[$row['template']]); - - $msg_list_ary[$row['template']][$pos]['method'] = $row['method']; - $msg_list_ary[$row['template']][$pos]['email'] = $row['user_email']; - $msg_list_ary[$row['template']][$pos]['jabber'] = $row['user_jabber']; - $msg_list_ary[$row['template']][$pos]['name'] = $row['username']; - $msg_list_ary[$row['template']][$pos]['lang'] = $row['user_lang']; - $msg_list_ary[$row['template']][$pos]['user_id']= $row['user_id']; - } - unset($msg_users); - - foreach ($msg_list_ary as $email_template => $email_list) - { - foreach ($email_list as $addr) - { - $messenger->template($email_template, $addr['lang']); - - $messenger->to($addr['email'], $addr['name']); - $messenger->im($addr['jabber'], $addr['name']); - - $messenger->assign_vars(array( - 'USERNAME' => htmlspecialchars_decode($addr['name']), - 'TOPIC_TITLE' => htmlspecialchars_decode($topic_title), - 'FORUM_NAME' => htmlspecialchars_decode($forum_name), - - 'U_FORUM' => generate_board_url() . "/viewforum.$phpEx?f=$forum_id", - 'U_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id", - 'U_NEWEST_POST' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id&p=$post_id&e=$post_id", - 'U_STOP_WATCHING_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?uid={$addr['user_id']}&f=$forum_id&t=$topic_id&unwatch=topic", - 'U_STOP_WATCHING_FORUM' => generate_board_url() . "/viewforum.$phpEx?uid={$addr['user_id']}&f=$forum_id&unwatch=forum", - )); - - $messenger->send($addr['method']); - } - } - unset($msg_list_ary); - - $messenger->save_queue(); - } - - // Handle the DB updates - $db->sql_transaction('begin'); - - if (!empty($update_notification['topic'])) - { - $sql = 'UPDATE ' . TOPICS_WATCH_TABLE . ' - SET notify_status = ' . NOTIFY_NO . " - WHERE topic_id = $topic_id - AND " . $db->sql_in_set('user_id', $update_notification['topic']); - $db->sql_query($sql); - } - - if (!empty($update_notification['forum'])) - { - $sql = 'UPDATE ' . FORUMS_WATCH_TABLE . ' - SET notify_status = ' . NOTIFY_NO . " - WHERE forum_id = $forum_id - AND " . $db->sql_in_set('user_id', $update_notification['forum']); - $db->sql_query($sql); - } - - // Now delete the user_ids not authorised to receive notifications on this topic/forum - if (!empty($delete_ids['topic'])) - { - $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . " - WHERE topic_id = $topic_id - AND " . $db->sql_in_set('user_id', $delete_ids['topic']); - $db->sql_query($sql); - } - - if (!empty($delete_ids['forum'])) - { - $sql = 'DELETE FROM ' . FORUMS_WATCH_TABLE . " - WHERE forum_id = $forum_id - AND " . $db->sql_in_set('user_id', $delete_ids['forum']); - $db->sql_query($sql); - } - - $db->sql_transaction('commit'); -} - // // Post handling functions // @@ -1640,6 +1409,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data) function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true) { global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path; + global $phpbb_container; // We do not handle erasing posts here if ($mode == 'delete') @@ -2452,7 +2222,23 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u // Send Notifications if (($mode == 'reply' || $mode == 'quote' || $mode == 'post') && $post_approval) { - user_notification($mode, $subject, $data['topic_title'], $data['forum_name'], $data['forum_id'], $data['topic_id'], $data['post_id']); + $notifications = $phpbb_container->get('notifications'); + + switch ($mode) + { + case 'reply' : + case 'quote' : + $notifications->add_notifications('post', array_merge($data, array( + 'post_username' => $username, + ))); + break; + + case 'post' : + $notifications->add_notifications('topic', array_merge($data, array( + 'post_username' => $username, + ))); + break; + } } $params = $add_anchor = ''; diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index b44685b8a3..d5c431e478 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -421,7 +421,7 @@ class mcp_queue $base_url = $this->u_action . "&f=$forum_id&st=$sort_days&sk=$sort_key&sd=$sort_dir"; phpbb_generate_template_pagination($template, $base_url, 'pagination', 'start', $total, $config['topics_per_page'], $start); - + // Now display the page $template->assign_vars(array( 'L_DISPLAY_ITEMS' => ($mode == 'unapproved_posts') ? $user->lang['DISPLAY_POSTS'] : $user->lang['DISPLAY_TOPICS'], @@ -639,12 +639,12 @@ function approve_post($post_id_list, $id, $mode) if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id']) { // Forum Notifications - user_notification('post', $post_data['topic_title'], $post_data['topic_title'], $post_data['forum_name'], $post_data['forum_id'], $post_data['topic_id'], $post_id); + $notifications->add_notifications('topic', $post_data); } else { // Topic Notifications - user_notification('reply', $post_data['post_subject'], $post_data['topic_title'], $post_data['forum_name'], $post_data['forum_id'], $post_data['topic_id'], $post_id); + $notifications->add_notifications('post', $post_data); } } diff --git a/phpBB/includes/notifications/type/base.php b/phpBB/includes/notifications/type/base.php index 91cc9f175a..df273f9e81 100644 --- a/phpBB/includes/notifications/type/base.php +++ b/phpBB/includes/notifications/type/base.php @@ -174,6 +174,38 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type return $data; } + /** + * Find the users who want to receive notifications (helper) + * + * @param ContainerBuilder $phpbb_container + * @param array $item_id The item_id to search for + * + * @return array + */ + protected static function _find_users_for_notification(ContainerBuilder $phpbb_container, $item_id) + { + $db = $phpbb_container->get('dbal.conn'); + + $rowset = array(); + + $sql = 'SELECT * FROM ' . USER_NOTIFICATIONS_TABLE . " + WHERE item_type = '" . static::get_item_type() . "' + AND item_id = " . (int) $item_id; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + if (!isset($rowset[$row['user_id']])) + { + $rowset[$row['user_id']] = array(); + } + + $rowset[$row['user_id']][] = $row['method']; + } + $db->sql_freeresult($result); + + return $rowset; + } + /** * Get the formatted title of this notification (fall-back) * diff --git a/phpBB/includes/notifications/type/pm.php b/phpBB/includes/notifications/type/pm.php index 702ec39c16..e060b5d658 100644 --- a/phpBB/includes/notifications/type/pm.php +++ b/phpBB/includes/notifications/type/pm.php @@ -47,7 +47,9 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base /** * Find the users who want to receive notifications * + * @param ContainerBuilder $phpbb_container * @param array $pm Data from + * * @return array */ public static function find_users_for_notification(ContainerBuilder $phpbb_container, $pm) diff --git a/phpBB/includes/notifications/type/post.php b/phpBB/includes/notifications/type/post.php index 920a53bcf2..96faa0131c 100644 --- a/phpBB/includes/notifications/type/post.php +++ b/phpBB/includes/notifications/type/post.php @@ -44,6 +44,61 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base return $post['post_id']; } + /** + * Find the users who want to receive notifications + * + * @param ContainerBuilder $phpbb_container + * @param array $post Data from + * + * @return array + */ + public static function find_users_for_notification(ContainerBuilder $phpbb_container, $post) + { + $users = parent::_find_users_for_notification($phpbb_container, $post['topic_id']); + + if (!sizeof($users)) + { + return array(); + } + + $auth_read = $phpbb_container->get('auth')->acl_get_list(array_keys($users), 'f_read', $post['forum_id']); + + if (empty($auth_read)) + { + return array(); + } + + $notify_users = array(); + + foreach ($auth_read[$post['forum_id']]['f_read'] as $user_id) + { + $notify_users[$user_id] = $users[$user_id]; + } + + return $notify_users; + } + + /** + * Get the HTML formatted title of this notification + * + * @return string + */ + public function get_formatted_title() + { + if ($this->get_data('post_username')) + { + $username = $this->get_data('post_username'); + } + else + { + $user_data = $this->service->get_user($this->get_data('poster_id')); + + $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']); + } + + return $username . ' posted in the topic ' . censor_text($this->get_data('topic_title')); + } + /** * Get the title of this notification * @@ -57,9 +112,7 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base } else { - $user_data = $this->get_user($this->get_data('poster_id')); - - $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']); + $username = $user_data['username']; } return $username . ' posted in the topic ' . censor_text($this->get_data('topic_title')); @@ -75,6 +128,16 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base return append_sid($this->phpbb_root_path . 'viewtopic.' . $this->php_ext, "p={$this->item_id}#p{$this->item_id}"); } + /** + * Get the full url to this item + * + * @return string URL + */ + public function get_full_url() + { + return generate_board_url() . "/viewtopic.{$this->php_ext}?p={$this->item_id}#p{$this->item_id}"; + } + /** * Users needed to query before this notification can be displayed * @@ -103,8 +166,6 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base $this->set_data('post_username', $post['post_username']); - $this->time = $post['post_time']; - return parent::create_insert_array($post); } } From 3624d2c50ac1acca767c5642767102b97fd6b832 Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sun, 9 Sep 2012 14:20:14 -0500 Subject: [PATCH 018/308] [ticket/11103] Use the language system, topic notifications PHPBB3-11103 --- phpBB/includes/notifications/method/email.php | 8 +- phpBB/includes/notifications/type/pm.php | 4 +- phpBB/includes/notifications/type/post.php | 8 +- phpBB/includes/notifications/type/topic.php | 185 ++++++++++++++++++ phpBB/language/en/common.php | 3 + 5 files changed, 200 insertions(+), 8 deletions(-) create mode 100644 phpBB/includes/notifications/type/topic.php diff --git a/phpBB/includes/notifications/method/email.php b/phpBB/includes/notifications/method/email.php index 69546be73f..d6468c9dc3 100644 --- a/phpBB/includes/notifications/method/email.php +++ b/phpBB/includes/notifications/method/email.php @@ -50,7 +50,7 @@ class phpbb_notifications_method_email extends phpbb_notifications_method_base // We do not send emails to banned users if (!function_exists('phpbb_get_banned_user_ids')) { - include($phpbb_container->getParameter('core.root_path') . 'includes/functions_user.' . $phpbb_container->getParameter('core.php_ext')); + include($this->phpbb_container->getParameter('core.root_path') . 'includes/functions_user.' . $this->phpbb_container->getParameter('core.php_ext')); } $banned_users = phpbb_get_banned_user_ids($user_ids); @@ -68,13 +68,13 @@ class phpbb_notifications_method_email extends phpbb_notifications_method_base // Time to go through the queue and send emails foreach ($this->queue as $notification) { - if (in_array($notification->user_id, $banned_users)) + $user = $this->service->get_user($notification->user_id); + + if ($user['user_type'] == USER_IGNORE || in_array($notification->user_id, $banned_users)) { continue; } - $user = $this->service->get_user($notification->user_id); - $messenger->template('notification', $user['user_lang']); $messenger->to($user['user_email'], $user['username']); diff --git a/phpBB/includes/notifications/type/pm.php b/phpBB/includes/notifications/type/pm.php index e060b5d658..3368b171df 100644 --- a/phpBB/includes/notifications/type/pm.php +++ b/phpBB/includes/notifications/type/pm.php @@ -101,7 +101,7 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']); - return $username . ' sent you a private message titled: ' . $this->get_data('message_subject'); + return $this->phpbb_container->get('user')->lang('NOTIFICATION_PM', $username, $this->get_data('message_subject')); } /** @@ -113,7 +113,7 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base { $user_data = $this->service->get_user($this->get_data('from_user_id')); - return $user_data['username'] . ' sent you a private message titled: ' . $this->get_data('message_subject'); + return $this->phpbb_container->get('user')->lang('NOTIFICATION_PM', $user_data['username'], $this->get_data('message_subject')); } /** diff --git a/phpBB/includes/notifications/type/post.php b/phpBB/includes/notifications/type/post.php index 96faa0131c..04e269737e 100644 --- a/phpBB/includes/notifications/type/post.php +++ b/phpBB/includes/notifications/type/post.php @@ -96,7 +96,7 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']); } - return $username . ' posted in the topic ' . censor_text($this->get_data('topic_title')); + return $this->phpbb_container->get('user')->lang('NOTIFICATION_POST', $username, censor_text($this->get_data('topic_title'))); } /** @@ -112,10 +112,12 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base } else { + $user_data = $this->service->get_user($this->get_data('poster_id')); + $username = $user_data['username']; } - return $username . ' posted in the topic ' . censor_text($this->get_data('topic_title')); + return $this->phpbb_container->get('user')->lang('NOTIFICATION_POST', $username, censor_text($this->get_data('topic_title'))); } /** @@ -166,6 +168,8 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base $this->set_data('post_username', $post['post_username']); + $this->set_data('forum_name', $post['forum_name']); + return parent::create_insert_array($post); } } diff --git a/phpBB/includes/notifications/type/topic.php b/phpBB/includes/notifications/type/topic.php new file mode 100644 index 0000000000..f58419a633 --- /dev/null +++ b/phpBB/includes/notifications/type/topic.php @@ -0,0 +1,185 @@ +get('auth')->acl_get_list(array_keys($users), 'f_read', $topic['forum_id']); + + if (empty($auth_read)) + { + return array(); + } + + $notify_users = array(); + + foreach ($auth_read[$topic['forum_id']]['f_read'] as $user_id) + { + $notify_users[$user_id] = $users[$user_id]; + } + + return $notify_users; + } + + /** + * Get the HTML formatted title of this notification + * + * @return string + */ + public function get_formatted_title() + { + if ($this->get_data('post_username')) + { + $username = $this->get_data('post_username'); + } + else + { + $user_data = $this->service->get_user($this->get_data('poster_id')); + + $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']); + } + + return $this->phpbb_container->get('user')->lang( + 'NOTIFICATION_TOPIC', + $username, + censor_text($this->get_data('topic_title')), + $this->get_data('forum_name') + ); + } + + /** + * Get the title of this notification + * + * @return string + */ + public function get_title() + { + if ($this->get_data('post_username')) + { + $username = $this->get_data('post_username'); + } + else + { + $user_data = $this->service->get_user($this->get_data('poster_id')); + + $username = $user_data['username']; + } + + return $this->phpbb_container->get('user')->lang( + 'NOTIFICATION_TOPIC', + $username, + censor_text($this->get_data('topic_title')), + $this->get_data('forum_name') + ); + } + + /** + * Get the url to this item + * + * @return string URL + */ + public function get_url() + { + return append_sid($this->phpbb_root_path . 'viewtopic.' . $this->php_ext, "t{$this->item_id}"); + } + + /** + * Get the full url to this item + * + * @return string URL + */ + public function get_full_url() + { + return generate_board_url() . "/viewtopic.{$this->php_ext}?t{$this->item_id}"; + } + + /** + * Users needed to query before this notification can be displayed + * + * @return array Array of user_ids + */ + public function users_to_query() + { + return array($this->data['poster_id']); + } + + /** + * Function for preparing the data for insertion in an SQL query + * (The service handles insertion) + * + * @param array $post Data from submit_post + * + * @return array Array of data ready to be inserted into the database + */ + public function create_insert_array($post) + { + $this->item_id = $post['post_id']; + + $this->set_data('poster_id', $post['poster_id']); + + $this->set_data('topic_title', $post['topic_title']); + + $this->set_data('post_username', $post['post_username']); + + $this->set_data('forum_name', $post['forum_name']); + + return parent::create_insert_array($post); + } +} diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index e6022e3b79..23f205dcc7 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -385,6 +385,9 @@ $lang = array_merge($lang, array( 'NOT_AUTHORISED' => 'You are not authorised to access this area.', 'NOT_WATCHING_FORUM' => 'You are no longer subscribed to updates on this forum.', 'NOT_WATCHING_TOPIC' => 'You are no longer subscribed to this topic.', + 'NOTIFICATION_PM' => '%1$s sent you a Private Message titled: %2$s.', + 'NOTIFICATION_POST' => '%1$s replied to the topic "%2$s".', + 'NOTIFICATION_TOPIC' => '%1$s posted a new topic "%2$s" in the forum "%3$s".', 'NOTIFY_ADMIN' => 'Please notify the board administrator or webmaster.', 'NOTIFY_ADMIN_EMAIL' => 'Please notify the board administrator or webmaster: %1$s', 'NO_ACCESS_ATTACHMENT' => 'You are not allowed to access this file.', From e09f25d59707fc842b073fa2909cefc3d16ecbf3 Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sun, 9 Sep 2012 14:55:40 -0500 Subject: [PATCH 019/308] [ticket/11103] Update notifications on post/topic edit PHPBB3-11103 --- phpBB/includes/functions_posting.php | 19 ++++++++++++++++--- phpBB/includes/notifications/service.php | 6 +++--- phpBB/includes/notifications/type/post.php | 14 +++++++++++--- phpBB/includes/notifications/type/topic.php | 8 ++++---- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 6c5c4535a3..64840bfa51 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -2220,12 +2220,18 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u } // Send Notifications - if (($mode == 'reply' || $mode == 'quote' || $mode == 'post') && $post_approval) + if ($post_approval) { $notifications = $phpbb_container->get('notifications'); switch ($mode) { + case 'post' : + $notifications->add_notifications('topic', array_merge($data, array( + 'post_username' => $username, + ))); + break; + case 'reply' : case 'quote' : $notifications->add_notifications('post', array_merge($data, array( @@ -2233,8 +2239,15 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u ))); break; - case 'post' : - $notifications->add_notifications('topic', array_merge($data, array( + case 'edit_topic' : + case 'edit_first_post' : + case 'edit' : + case 'edit_last_post' : + $notifications->update_notifications('topic', array_merge($data, array( + 'post_username' => $username, + 'topic_title' => $subject, + ))); + $notifications->update_notifications('post', array_merge($data, array( 'post_username' => $username, ))); break; diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php index 463798fa07..112cbae3fd 100644 --- a/phpBB/includes/notifications/service.php +++ b/phpBB/includes/notifications/service.php @@ -58,10 +58,10 @@ class phpbb_notifications_service // Merge default options $options = array_merge(array( 'user_id' => $user->data['user_id'], - 'limit' => 5, - 'start' => 0, 'order_by' => 'time', 'order_dir' => 'DESC', + 'limit' => 5, + 'start' => 0, ), $options); $notifications = $user_ids = array(); @@ -147,7 +147,7 @@ class phpbb_notifications_service foreach ($methods as $method) { // setup the notification methods and add the notification to the queue - if ($method) + if ($method) // blank means we just insert it as a notification, but do not notify them by any other means { if (!isset($notification_methods[$method])) { diff --git a/phpBB/includes/notifications/type/post.php b/phpBB/includes/notifications/type/post.php index 04e269737e..efada4220e 100644 --- a/phpBB/includes/notifications/type/post.php +++ b/phpBB/includes/notifications/type/post.php @@ -96,7 +96,11 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']); } - return $this->phpbb_container->get('user')->lang('NOTIFICATION_POST', $username, censor_text($this->get_data('topic_title'))); + return $this->phpbb_container->get('user')->lang( + 'NOTIFICATION_POST', + $username, + censor_text($this->get_data('topic_title')) + ); } /** @@ -117,7 +121,11 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base $username = $user_data['username']; } - return $this->phpbb_container->get('user')->lang('NOTIFICATION_POST', $username, censor_text($this->get_data('topic_title'))); + return $this->phpbb_container->get('user')->lang( + 'NOTIFICATION_POST', + $username, + censor_text($this->get_data('topic_title')) + ); } /** @@ -166,7 +174,7 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base $this->set_data('topic_title', $post['topic_title']); - $this->set_data('post_username', $post['post_username']); + $this->set_data('post_username', (($post['post_username'] != $this->phpbb_container->get('user')->data['username']) ? $post['post_username'] : '')); $this->set_data('forum_name', $post['forum_name']); diff --git a/phpBB/includes/notifications/type/topic.php b/phpBB/includes/notifications/type/topic.php index f58419a633..ee8c21fd9c 100644 --- a/phpBB/includes/notifications/type/topic.php +++ b/phpBB/includes/notifications/type/topic.php @@ -137,7 +137,7 @@ class phpbb_notifications_type_topic extends phpbb_notifications_type_base */ public function get_url() { - return append_sid($this->phpbb_root_path . 'viewtopic.' . $this->php_ext, "t{$this->item_id}"); + return append_sid($this->phpbb_root_path . 'viewtopic.' . $this->php_ext, "t={$this->item_id}"); } /** @@ -147,7 +147,7 @@ class phpbb_notifications_type_topic extends phpbb_notifications_type_base */ public function get_full_url() { - return generate_board_url() . "/viewtopic.{$this->php_ext}?t{$this->item_id}"; + return generate_board_url() . "/viewtopic.{$this->php_ext}?t={$this->item_id}"; } /** @@ -170,13 +170,13 @@ class phpbb_notifications_type_topic extends phpbb_notifications_type_base */ public function create_insert_array($post) { - $this->item_id = $post['post_id']; + $this->item_id = $post['topic_id']; $this->set_data('poster_id', $post['poster_id']); $this->set_data('topic_title', $post['topic_title']); - $this->set_data('post_username', $post['post_username']); + $this->set_data('post_username', (($post['post_username'] != $this->phpbb_container->get('user')->data['username']) ? $post['post_username'] : '')); $this->set_data('forum_name', $post['forum_name']); From 5502f3c4aa30ce72131f2a55bcfa3db7a4059427 Mon Sep 17 00:00:00 2001 From: Nathan Guse Date: Sun, 9 Sep 2012 17:20:39 -0500 Subject: [PATCH 020/308] [ticket/11103] Restyle the notification list Very rough (lots of inline CSS, very ugly) PHPBB3-11103 --- phpBB/includes/functions.php | 2 +- phpBB/includes/functions_display.php | 7 +-- phpBB/includes/mcp/mcp_queue.php | 4 +- phpBB/includes/notifications/service.php | 14 ++++++ phpBB/includes/notifications/type/base.php | 44 ++++++++++++------- phpBB/includes/notifications/type/pm.php | 8 ++++ phpBB/includes/notifications/type/post.php | 8 ++++ phpBB/includes/notifications/type/topic.php | 8 ++++ .../prosilver/template/overall_header.html | 25 +++++++---- phpBB/styles/prosilver/theme/common.css | 8 ++++ 10 files changed, 98 insertions(+), 30 deletions(-) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 7632ea1fcb..e5c7839894 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -5096,7 +5096,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 $phpbb_notifications = $phpbb_container->get('notifications'); foreach ($phpbb_notifications->load_notifications() as $notification) { - $notification->display(); + $template->assign_block_vars('notifications', $notification->prepare_for_display()); } // application/xhtml+xml not used because of IE diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 8328b9ee7a..84cb47867e 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -1319,10 +1319,11 @@ function get_user_rank($user_rank, $user_posts, &$rank_title, &$rank_img, &$rank * @param string $avatar_height Height of users avatar * @param string $alt Optional language string for alt tag within image, can be a language key or text * @param bool $ignore_config Ignores the config-setting, to be still able to view the avatar in the UCP +* @param string $custom_css Custom CSS class to apply to the image * * @return string Avatar image */ -function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $alt = 'USER_AVATAR', $ignore_config = false) +function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $alt = 'USER_AVATAR', $ignore_config = false, $custom_css = '') { global $user, $config, $phpbb_root_path, $phpEx; global $phpbb_dispatcher; @@ -1343,7 +1344,7 @@ function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $ * @var string overwrite_avatar If set, this string will be the avatar * @since 3.1-A1 */ - $vars = array('avatar', 'avatar_type', 'avatar_width', 'avatar_height', 'alt', 'ignore_config', 'overwrite_avatar'); + $vars = array('avatar', 'avatar_type', 'avatar_width', 'avatar_height', 'alt', 'ignore_config', 'overwrite_avatar', 'custom_css'); extract($phpbb_dispatcher->trigger_event('core.user_get_avatar', compact($vars))); if ($overwrite_avatar) @@ -1385,7 +1386,7 @@ function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $ } $avatar_img .= $avatar; - return '' . ((!empty($user->lang[$alt])) ? $user->lang[$alt] : $alt) . ''; + return '' . ((!empty($user->lang[$alt])) ? $user->lang[$alt] : $alt) . ''; } /** diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index d5c431e478..1d9a2dfedc 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -451,7 +451,7 @@ function approve_post($post_id_list, $id, $mode) { global $db, $template, $user, $config; global $phpEx, $phpbb_root_path; - global $request; + global $request, $phpbb_container; if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) { @@ -634,6 +634,8 @@ function approve_post($post_id_list, $id, $mode) // Send out normal user notifications $email_sig = str_replace('
', "\n", "-- \n" . $config['board_email_sig']); + $notifications = $phpbb_container->get('notifications'); + foreach ($post_info as $post_id => $post_data) { if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id']) diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php index 112cbae3fd..5dcfeb127b 100644 --- a/phpBB/includes/notifications/service.php +++ b/phpBB/includes/notifications/service.php @@ -210,6 +210,20 @@ class phpbb_notifications_service $this->db->sql_query($sql); } + public function add_subscription($item_type, $item_id, $method = '') + { + $this->get_item_type_class_name($item_type); + + $sql = 'INSERT INTO ' . USER_NOTIFICATIONS_TABLE . ' ' . + $this->db->sql_build_array('INSERT', array( + 'item_type' => $item_type, + 'item_id' => (int) $item_id, + 'user_id' => $this->phpbb_container->get('user')->data['user_id'], + 'method' => $method, + )); + $this->db->sql_query($sql); + } + /** * Load user helper * diff --git a/phpBB/includes/notifications/type/base.php b/phpBB/includes/notifications/type/base.php index df273f9e81..e60b20c449 100644 --- a/phpBB/includes/notifications/type/base.php +++ b/phpBB/includes/notifications/type/base.php @@ -104,28 +104,23 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type } /** - * Output the notification to the template - * - * @param array $options Array of options - * template_block Template block name to output to (Default: notifications) + * Prepare to output the notification to the template */ - public function display($options = array()) + public function prepare_for_display() { - $template = $this->phpbb_container->get('template'); $user = $this->phpbb_container->get('user'); - // Merge default options - $options = array_merge(array( - 'template_block' => 'notifications', - ), $options); + return array( + 'AVATAR' => $this->get_avatar(), - $template->assign_block_vars($options['template_block'], array( - 'TITLE' => $this->get_formatted_title(), - 'URL' => $this->get_url(), - 'TIME' => $user->format_date($this->time), + 'FORMATTED_TITLE' => $this->get_formatted_title(), + 'TITLE' => $this->get_title(), - 'UNREAD' => $this->unread, - )); + 'URL' => $this->get_url(), + 'TIME' => $user->format_date($this->time), + + 'UNREAD' => $this->unread, + ); } /** @@ -206,6 +201,13 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type return $rowset; } + protected function _get_avatar($user_id) + { + $user = $this->service->get_user($user_id); + + return get_user_avatar($user['user_avatar'], $user['user_avatar_type'], $user['user_avatar_width'], $user['user_avatar_height'], $user['username'], false, 'notifications-avatar'); + } + /** * Get the formatted title of this notification (fall-back) * @@ -217,7 +219,7 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type } /** - * URL to unsubscribe to this notification + * URL to unsubscribe to this notification (fall-back) * * @param string|bool $method Method name to unsubscribe from (email|jabber|etc), False to unsubscribe from all notifications for this item */ @@ -225,4 +227,12 @@ abstract class phpbb_notifications_type_base implements phpbb_notifications_type { return false; } + + /** + * Get the user's avatar (fall-back) + */ + public function get_avatar() + { + return ''; + } } diff --git a/phpBB/includes/notifications/type/pm.php b/phpBB/includes/notifications/type/pm.php index 3368b171df..c78efcdd55 100644 --- a/phpBB/includes/notifications/type/pm.php +++ b/phpBB/includes/notifications/type/pm.php @@ -90,6 +90,14 @@ class phpbb_notifications_type_pm extends phpbb_notifications_type_base return $notify_users; } + /** + * Get the user's avatar + */ + public function get_avatar() + { + return $this->_get_avatar($this->get_data('from_user_id')); + } + /** * Get the HTML formatted title of this notification * diff --git a/phpBB/includes/notifications/type/post.php b/phpBB/includes/notifications/type/post.php index efada4220e..f374114890 100644 --- a/phpBB/includes/notifications/type/post.php +++ b/phpBB/includes/notifications/type/post.php @@ -78,6 +78,14 @@ class phpbb_notifications_type_post extends phpbb_notifications_type_base return $notify_users; } + /** + * Get the user's avatar + */ + public function get_avatar() + { + return $this->_get_avatar($this->get_data('poster_id')); + } + /** * Get the HTML formatted title of this notification * diff --git a/phpBB/includes/notifications/type/topic.php b/phpBB/includes/notifications/type/topic.php index ee8c21fd9c..51a95d5e19 100644 --- a/phpBB/includes/notifications/type/topic.php +++ b/phpBB/includes/notifications/type/topic.php @@ -78,6 +78,14 @@ class phpbb_notifications_type_topic extends phpbb_notifications_type_base return $notify_users; } + /** + * Get the user's avatar + */ + public function get_avatar() + { + return $this->_get_avatar($this->get_data('poster_id')); + } + /** * Get the HTML formatted title of this notification * diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html index 77fdb230ad..1695f8d03a 100644 --- a/phpBB/styles/prosilver/template/overall_header.html +++ b/phpBB/styles/prosilver/template/overall_header.html @@ -132,6 +132,22 @@