aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB
diff options
context:
space:
mode:
authorNathan Guse <nathaniel.guse@gmail.com>2012-09-08 10:49:58 -0500
committerNathan Guse <nathaniel.guse@gmail.com>2012-09-08 10:49:58 -0500
commitb887fcc3d180860e3b7fdcb2a70e2cd8a519bea2 (patch)
tree68529c531b34b9626bbb4a79b74462efd5fc9036 /phpBB
parent7bf598954c452448c2807428f6517cd75d910f92 (diff)
downloadforums-b887fcc3d180860e3b7fdcb2a70e2cd8a519bea2.tar
forums-b887fcc3d180860e3b7fdcb2a70e2cd8a519bea2.tar.gz
forums-b887fcc3d180860e3b7fdcb2a70e2cd8a519bea2.tar.bz2
forums-b887fcc3d180860e3b7fdcb2a70e2cd8a519bea2.tar.xz
forums-b887fcc3d180860e3b7fdcb2a70e2cd8a519bea2.zip
[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
Diffstat (limited to 'phpBB')
-rw-r--r--phpBB/config/services.yml5
-rw-r--r--phpBB/includes/constants.php1
-rw-r--r--phpBB/includes/notifications/method/base.php51
-rw-r--r--phpBB/includes/notifications/method/email.php28
-rw-r--r--phpBB/includes/notifications/method/interface.php24
-rw-r--r--phpBB/includes/notifications/service.php197
-rw-r--r--phpBB/includes/notifications/type/base.php128
-rw-r--r--phpBB/includes/notifications/type/interface.php31
-rw-r--r--phpBB/includes/notifications/type/post.php65
9 files changed, 530 insertions, 0 deletions
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 @@
+<?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 class
+* @package notifications
+*/
+abstract class phpbb_notifications_method_base implements phpbb_notifications_method_interface
+{
+ protected $phpbb_container;
+ 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())
+ {
+ // 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');
+ }
+}
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 @@
+<?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
+* @package notifications
+*/
+class phpbb_notifications_method_email extends phpbb_notifications_method_base
+{
+ function notify()
+ {
+ // email the user
+ }
+}
diff --git a/phpBB/includes/notifications/method/interface.php b/phpBB/includes/notifications/method/interface.php
new file mode 100644
index 0000000000..2d8a8b605e
--- /dev/null
+++ b/phpBB/includes/notifications/method/interface.php
@@ -0,0 +1,24 @@
+<?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
+{
+}
diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php
new file mode 100644
index 0000000000..8f5d559867
--- /dev/null
+++ b/phpBB/includes/notifications/service.php
@@ -0,0 +1,197 @@
+<?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;
+}
+
+/**
+* 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;
+
+ /**
+ * 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(Symfony\Component\DependencyInjection\ContainerBuilder $phpbb_container)
+ {
+ $this->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 @@
+<?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 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;
+
+ protected $users;
+
+ /**
+ * Indentification data
+ * notification_id
+ * 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()
+ */
+ private $data = array();
+
+ public function __construct(Symfony\Component\DependencyInjection\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;
+ }
+
+ 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 @@
+<?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 function get_type();
+
+ public function get_title();
+
+ public function get_url();
+
+ public function create_insert_array($data);
+}
diff --git a/phpBB/includes/notifications/type/post.php b/phpBB/includes/notifications/type/post.php
new file mode 100644
index 0000000000..eb8d92c79c
--- /dev/null
+++ b/phpBB/includes/notifications/type/post.php
@@ -0,0 +1,65 @@
+<?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;
+}
+
+/**
+* Post notifications class
+* @package notifications
+*/
+class phpbb_notifications_type_post extends phpbb_notifications_type_base
+{
+ /**
+ * Get the type of notification this is
+ * phpbb_notifications_type_
+ */
+ public function get_type()
+ {
+ return 'post';
+ }
+
+ public function get_title()
+ {
+ return $this->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);
+ }
+}