aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--phpBB/common.php3
-rw-r--r--phpBB/config/services.yml5
-rw-r--r--phpBB/develop/create_schema_files.php41
-rw-r--r--phpBB/includes/constants.php2
-rw-r--r--phpBB/includes/functions.php9
-rw-r--r--phpBB/includes/functions_privmsgs.php12
-rw-r--r--phpBB/includes/notifications/method/base.php80
-rw-r--r--phpBB/includes/notifications/method/email.php97
-rw-r--r--phpBB/includes/notifications/method/interface.php25
-rw-r--r--phpBB/includes/notifications/method/jabber.php36
-rw-r--r--phpBB/includes/notifications/service.php245
-rw-r--r--phpBB/includes/notifications/type/base.php192
-rw-r--r--phpBB/includes/notifications/type/interface.php35
-rw-r--r--phpBB/includes/notifications/type/pm.php159
-rw-r--r--phpBB/includes/notifications/type/post.php110
-rw-r--r--phpBB/install/database_update.php51
-rw-r--r--phpBB/styles/prosilver/template/overall_header.html7
17 files changed, 1105 insertions, 4 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/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/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php
index 6eb4a80199..a2f7463dd4 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('VCHAR:25', ''),
+ '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('VCHAR:25', ''),
+ '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/constants.php b/phpBB/includes/constants.php
index 68af41ab20..7a3c73e987 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');
@@ -272,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/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/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php
index 9e055a319f..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'];
diff --git a/phpBB/includes/notifications/method/base.php b/phpBB/includes/notifications/method/base.php
new file mode 100644
index 0000000000..98c06509c6
--- /dev/null
+++ b/phpBB/includes/notifications/method/base.php
@@ -0,0 +1,80 @@
+<?php
+/**
+*
+* @package notifications
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Base notifications method class
+* @package notifications
+*/
+abstract class phpbb_notifications_method_base implements phpbb_notifications_method_interface
+{
+ protected $phpbb_container;
+ protected $db;
+ protected $user;
+ protected $phpbb_root_path;
+ protected $php_ext;
+
+ /**
+ * Queue of messages to be sent
+ *
+ * @var array
+ */
+ protected $queue = array();
+
+ public function __construct(ContainerBuilder $phpbb_container, $data = array())
+ {
+ // phpBB Container
+ $this->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');
+
+ $this->phpbb_root_path = $phpbb_container->getParameter('core.root_path');
+ $this->php_ext = $phpbb_container->getParameter('core.php_ext');
+ }
+
+ /**
+ * 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);
+ }
+
+ $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
new file mode 100644
index 0000000000..0120485cff
--- /dev/null
+++ b/phpBB/includes/notifications/method/email.php
@@ -0,0 +1,97 @@
+<?php
+/**
+*
+* @package notifications
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Email notification method class
+* This class handles sending emails for notifications
+*
+* @package notifications
+*/
+class phpbb_notifications_method_email extends phpbb_notifications_method_base
+{
+ public static function is_available()
+ {
+ // Email is always available
+ return true;
+ }
+
+ public function notify($notification)
+ {
+ // 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($notification->user_id);
+
+ $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->item_id}",
+ ));
+
+ $messenger->send('email');
+ }
+
+ // 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/method/interface.php b/phpBB/includes/notifications/method/interface.php
new file mode 100644
index 0000000000..f18d005b8b
--- /dev/null
+++ b/phpBB/includes/notifications/method/interface.php
@@ -0,0 +1,25 @@
+<?php
+/**
+*
+* @package notifications
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Base notifications method interface
+* @package notifications
+*/
+interface phpbb_notifications_method_interface
+{
+ public function notify($notification);
+}
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 @@
+<?php
+/**
+*
+* @package notifications
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Jabber notification method class
+* This class handles sending Jabber notifications for notifications
+*
+* @package notifications
+*/
+class phpbb_notifications_method_jabber extends phpbb_notifications_method_base
+{
+ public static function is_available()
+ {
+ // Is jabber enabled & can this user receive jabber messages?
+ return false; // for now
+ }
+
+ public function notify()
+ {
+ // message the user
+ }
+}
diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php
new file mode 100644
index 0000000000..74e2e29e1a
--- /dev/null
+++ b/phpBB/includes/notifications/service.php
@@ -0,0 +1,245 @@
+<?php
+/**
+*
+* @package notifications
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Notifications service class
+* @package notifications
+*/
+class phpbb_notifications_service
+{
+ protected $phpbb_container;
+ protected $db;
+
+ /**
+ * Users loaded from the DB
+ *
+ * @var array Array of user data that we've loaded from the DB
+ */
+ protected $users;
+
+ public function __construct(ContainerBuilder $phpbb_container)
+ {
+ $this->phpbb_container = $phpbb_container;
+
+ // Some common things we're going to use
+ $this->db = $phpbb_container->get('dbal.conn');
+ }
+
+ /**
+ * 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))
+ {
+ $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());
+
+ $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;
+ }
+
+ /**
+ * Add a notification
+ *
+ * @param string $item_type Type identifier
+ * @param int $item_id Identifier within the type
+ * @param array $data Data specific for this type that will be inserted
+ */
+ public function add_notifications($item_type, $data)
+ {
+ $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();
+ $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);
+
+ // 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);
+
+ 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)
+ {
+ $notification = new $item_type_class_name($this->phpbb_container);
+
+ $notification->user_id = (int) $user;
+
+ $new_rows[] = $notification->create_insert_array($data);
+
+ foreach ($methods as $method)
+ {
+ // setup the notification methods and add the notification to the queue
+ if ($method)
+ {
+ if (!isset($notification_methods[$method]))
+ {
+ $method_class_name = 'phpbb_notifications_method_' . $method;
+ $notification_methods[$method] = new $method_class_name($this->phpbb_container);
+ }
+ $notification_methods[$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 ($notification_methods as $method)
+ {
+ $method->run_queue();
+ }
+ }
+
+ /**
+ * 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)
+ {
+ $item_type_class_name = $this->get_item_type_class_name($item_type);
+
+ $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($item_type) . "'
+ AND item_id = " . (int) $item_id;
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * 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
+ */
+ 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)
+ {
+ $item_type = preg_replace('#[^a-z]#', '', $item_type);
+ }
+
+ return 'phpbb_notifications_type_' . $item_type;
+ }
+}
diff --git a/phpBB/includes/notifications/type/base.php b/phpBB/includes/notifications/type/base.php
new file mode 100644
index 0000000000..32d8f58ff3
--- /dev/null
+++ b/phpBB/includes/notifications/type/base.php
@@ -0,0 +1,192 @@
+<?php
+/**
+*
+* @package notifications
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Base notifications class
+* @package notifications
+*/
+abstract class phpbb_notifications_type_base implements phpbb_notifications_type_interface
+{
+ protected $phpbb_container;
+ protected $db;
+ protected $phpbb_root_path;
+ protected $php_ext;
+
+ /**
+ * Array of user data containing information needed to output the notifications to the template
+ *
+ * @var array
+ */
+ protected $users = array();
+
+ /**
+ * Indentification data
+ * item_type
+ * item_id
+ * user_id
+ * unread
+ *
+ * time
+ * 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(), get_data(), set_data()
+ */
+ private $data = array();
+
+ public function __construct(ContainerBuilder $phpbb_container, $data = array())
+ {
+ // phpBB Container
+ $this->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;
+ }
+
+ /**
+ * 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 (isset($this->data['data'][$name])) ? $this->data['data'][$name] : null;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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
+ *
+ * @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),
+
+ 'UNREAD' => $this->unread,
+ ));
+ }
+
+ /**
+ * Function for preparing the data for insertion in an SQL query
+ * (The service handles insertion)
+ *
+ * @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($type_data)
+ {
+ // Defaults
+ $data = array_merge(array(
+ 'item_type' => $this->get_item_type(),
+ 'time' => time(),
+ 'unread' => true,
+
+ 'data' => array(),
+ ), $this->data);
+
+ $data['data'] = serialize($data['data']);
+
+ return $data;
+ }
+
+ /**
+ * Function for preparing the data for update in an SQL query
+ * (The service handles insertion)
+ *
+ * @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($type_data)
+ {
+ $data = $this->create_insert_array($type_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
new file mode 100644
index 0000000000..ccd963ba06
--- /dev/null
+++ b/phpBB/includes/notifications/type/interface.php
@@ -0,0 +1,35 @@
+<?php
+/**
+*
+* @package notifications
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Base notifications interface
+* @package notifications
+*/
+interface phpbb_notifications_type_interface
+{
+ public static function get_item_type();
+
+ public static function get_item_id($type_data);
+
+ public function get_title();
+
+ public function get_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
new file mode 100644
index 0000000000..2b2a835470
--- /dev/null
+++ b/phpBB/includes/notifications/type/pm.php
@@ -0,0 +1,159 @@
+<?php
+/**
+*
+* @package notifications
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Private message notifications class
+* This class handles notifications for private messages
+*
+* @package notifications
+*/
+class phpbb_notifications_type_pm extends phpbb_notifications_type_base
+{
+ /**
+ * Get the type of notification this is
+ * phpbb_notifications_type_
+ */
+ public static function get_item_type()
+ {
+ return 'pm';
+ }
+
+ /**
+ * Get the id of the
+ *
+ * @param array $pm The data from the private message
+ */
+ public static function get_item_id($pm)
+ {
+ return $pm['msg_id'];
+ }
+
+ /**
+ * Get the title of this notification
+ *
+ * @return string
+ */
+ public function get_title()
+ {
+ $user_data = $this->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&amp;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($pm)
+ {
+ $this->item_id = $pm['msg_id'];
+
+ $this->set_data('author_id', $pm['author_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, 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);
+
+ 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'];
+ }
+}
diff --git a/phpBB/includes/notifications/type/post.php b/phpBB/includes/notifications/type/post.php
new file mode 100644
index 0000000000..920a53bcf2
--- /dev/null
+++ b/phpBB/includes/notifications/type/post.php
@@ -0,0 +1,110 @@
+<?php
+/**
+*
+* @package notifications
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Post notifications class
+* This class handles notifications for replies to a topic
+*
+* @package notifications
+*/
+class phpbb_notifications_type_post extends phpbb_notifications_type_base
+{
+ /**
+ * Get the type of notification this is
+ * phpbb_notifications_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
+ *
+ * @return string
+ */
+ public function get_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'));
+ }
+
+ /**
+ * 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}");
+ }
+
+ /**
+ * 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->time = $post['post_time'];
+
+ return parent::create_insert_array($post);
+ }
+}
diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php
index 0b470ced26..c3c2da4451 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('VCHAR:25', ''),
+ '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('VCHAR:25', ''),
+ '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(
@@ -2629,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']))
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 @@
</div>
</div>
<!-- ENDIF -->
+
+<!-- BEGIN notifications -->
+ <p>
+ <a href="{notifications.URL}">{notifications.TITLE}</a><br />
+ {notifications.TIME}
+ </p>
+<!-- END notifications --> \ No newline at end of file