aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB')
-rw-r--r--phpBB/common.php3
-rw-r--r--phpBB/config/services.yml13
-rw-r--r--phpBB/develop/create_schema_files.php43
-rw-r--r--phpBB/includes/acp/acp_board.php1
-rw-r--r--phpBB/includes/constants.php2
-rw-r--r--phpBB/includes/functions.php49
-rw-r--r--phpBB/includes/functions_admin.php8
-rw-r--r--phpBB/includes/functions_posting.php292
-rw-r--r--phpBB/includes/functions_privmsgs.php132
-rw-r--r--phpBB/includes/mcp/mcp_pm_reports.php4
-rw-r--r--phpBB/includes/mcp/mcp_queue.php127
-rw-r--r--phpBB/includes/mcp/mcp_reports.php40
-rw-r--r--phpBB/includes/notification/manager.php752
-rw-r--r--phpBB/includes/notification/method/base.php83
-rw-r--r--phpBB/includes/notification/method/email.php104
-rw-r--r--phpBB/includes/notification/method/interface.php27
-rw-r--r--phpBB/includes/notification/method/jabber.php60
-rw-r--r--phpBB/includes/notification/type/approve_post.php169
-rw-r--r--phpBB/includes/notification/type/approve_topic.php165
-rw-r--r--phpBB/includes/notification/type/base.php382
-rw-r--r--phpBB/includes/notification/type/bookmark.php134
-rw-r--r--phpBB/includes/notification/type/disapprove_post.php116
-rw-r--r--phpBB/includes/notification/type/disapprove_topic.php116
-rw-r--r--phpBB/includes/notification/type/interface.php53
-rw-r--r--phpBB/includes/notification/type/pm.php186
-rw-r--r--phpBB/includes/notification/type/post.php385
-rw-r--r--phpBB/includes/notification/type/post_in_queue.php154
-rw-r--r--phpBB/includes/notification/type/quote.php217
-rw-r--r--phpBB/includes/notification/type/report_pm.php242
-rw-r--r--phpBB/includes/notification/type/report_pm_closed.php146
-rw-r--r--phpBB/includes/notification/type/report_post.php194
-rw-r--r--phpBB/includes/notification/type/report_post_closed.php146
-rw-r--r--phpBB/includes/notification/type/topic.php293
-rw-r--r--phpBB/includes/notification/type/topic_in_queue.php147
-rw-r--r--phpBB/includes/ucp/info/ucp_notifications.php35
-rw-r--r--phpBB/includes/ucp/ucp_notifications.php229
-rw-r--r--phpBB/includes/ucp/ucp_prefs.php18
-rw-r--r--phpBB/index.php24
-rw-r--r--phpBB/install/database_update.php74
-rw-r--r--phpBB/install/schemas/firebird_schema.sql47
-rw-r--r--phpBB/install/schemas/mssql_schema.sql75
-rw-r--r--phpBB/install/schemas/mysql_40_schema.sql34
-rw-r--r--phpBB/install/schemas/mysql_41_schema.sql34
-rw-r--r--phpBB/install/schemas/oracle_schema.sql65
-rw-r--r--phpBB/install/schemas/postgres_schema.sql40
-rw-r--r--phpBB/install/schemas/schema_data.sql1
-rw-r--r--phpBB/install/schemas/sqlite_schema.sql33
-rw-r--r--phpBB/language/en/acp/common.php2
-rw-r--r--phpBB/language/en/common.php21
-rw-r--r--phpBB/language/en/email/forum_notify.txt2
-rw-r--r--phpBB/language/en/email/newtopic_notify.txt2
-rw-r--r--phpBB/language/en/email/notifications/bookmark.txt20
-rw-r--r--phpBB/language/en/email/notifications/post_in_queue.txt17
-rw-r--r--phpBB/language/en/email/notifications/quote.txt20
-rw-r--r--phpBB/language/en/email/notifications/report_pm.txt14
-rw-r--r--phpBB/language/en/email/notifications/report_post.txt17
-rw-r--r--phpBB/language/en/email/notifications/topic_in_queue.txt17
-rw-r--r--phpBB/language/en/email/topic_notify.txt2
-rw-r--r--phpBB/language/en/ucp.php24
-rw-r--r--phpBB/report.php14
-rw-r--r--phpBB/styles/prosilver/template/ajax.js11
-rw-r--r--phpBB/styles/prosilver/template/overall_header.html36
-rw-r--r--phpBB/styles/prosilver/template/ucp_notifications.html124
-rw-r--r--phpBB/styles/prosilver/template/ucp_prefs_personal.html24
-rw-r--r--phpBB/styles/prosilver/theme/colours.css31
-rw-r--r--phpBB/styles/prosilver/theme/common.css80
-rw-r--r--phpBB/styles/subsilver2/template/overall_footer.html14
-rw-r--r--phpBB/styles/subsilver2/template/overall_header.html45
-rw-r--r--phpBB/styles/subsilver2/template/ucp_notifications.html146
-rw-r--r--phpBB/styles/subsilver2/template/ucp_prefs_personal.html14
-rw-r--r--phpBB/styles/subsilver2/theme/stylesheet.css46
71 files changed, 5930 insertions, 507 deletions
diff --git a/phpBB/common.php b/phpBB/common.php
index 6943b02fa0..c1787f6773 100644
--- a/phpBB/common.php
+++ b/phpBB/common.php
@@ -130,6 +130,9 @@ $phpbb_subscriber_loader = $phpbb_container->get('event.subscriber_loader');
$template = $phpbb_container->get('template');
$phpbb_style = $phpbb_container->get('style');
+// Notifications manager
+$phpbb_notifications = $phpbb_container->get('notification_manager');
+
$ids = array_keys($phpbb_container->findTaggedServiceIds('container.processor'));
foreach ($ids as $id)
{
diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml
index c3d2494952..4ae519091b 100644
--- a/phpBB/config/services.yml
+++ b/phpBB/config/services.yml
@@ -89,6 +89,19 @@ services:
- .%core.php_ext%
- @cache.driver
+ notification_manager:
+ class: phpbb_notification_manager
+ arguments:
+ - @dbal.conn
+ - @cache.driver
+ - @template
+ - @ext.manager
+ - @user
+ - @auth
+ - @config
+ - %core.root_path%
+ - %core.php_ext%
+
processor.ext:
class: phpbb_di_processor_ext
arguments:
diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php
index 6eb4a80199..69aca10e6c 100644
--- a/phpBB/develop/create_schema_files.php
+++ b/phpBB/develop/create_schema_files.php
@@ -1295,6 +1295,30 @@ function get_schema_struct()
),
);
+ $schema_data['phpbb_notifications'] = array(
+ 'COLUMNS' => array(
+ 'notification_id' => array('UINT', NULL, 'auto_increment'),
+ 'item_type' => array('VCHAR:25', ''),
+ 'item_id' => array('UINT', 0),
+ 'item_parent_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ 'unread' => array('BOOL', 1),
+ 'is_disabled' => array('BOOL', 0),
+ 'time' => array('TIMESTAMP', 1),
+ 'data' => array('TEXT_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => 'notification_id',
+ 'KEYS' => array(
+ 'item_type' => array('INDEX', 'item_type'),
+ 'item_id' => array('INDEX', 'item_id'),
+ 'item_pid' => array('INDEX', 'item_parent_id'),
+ 'user_id' => array('INDEX', 'user_id'),
+ 'time' => array('INDEX', 'time'),
+ 'unread' => array('INDEX', 'unread'),
+ 'is_disabled' => array('INDEX', 'is_disabled'),
+ ),
+ );
+
$schema_data['phpbb_poll_options'] = array(
'COLUMNS' => array(
'poll_option_id' => array('TINT:4', 0),
@@ -1751,6 +1775,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/acp/acp_board.php b/phpBB/includes/acp/acp_board.php
index 322e1c55d8..aed27d7122 100644
--- a/phpBB/includes/acp/acp_board.php
+++ b/phpBB/includes/acp/acp_board.php
@@ -314,6 +314,7 @@ class acp_board
'load_online_time' => array('lang' => 'ONLINE_LENGTH', 'validate' => 'int:0', 'type' => 'text:4:3', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
'legend2' => 'GENERAL_OPTIONS',
+ 'load_notifications' => array('lang' => 'LOAD_NOTIFICATIONS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'load_db_track' => array('lang' => 'YES_POST_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'load_db_lastread' => array('lang' => 'YES_READ_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'load_anon_lastread' => array('lang' => 'YES_ANON_READ_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
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 b255d41241..0af8e824c8 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -1319,7 +1319,7 @@ function phpbb_timezone_select($user, $default = '', $truncate = false)
function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $user_id = 0)
{
global $db, $user, $config;
- global $request;
+ global $request, $phpbb_notifications;
$post_time = ($post_time === 0 || $post_time > time()) ? time() : (int) $post_time;
@@ -1327,6 +1327,11 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
{
if ($forum_id === false || !sizeof($forum_id))
{
+ // Mark all forums read (index page)
+
+ // Mark all topic notifications read for this user
+ $phpbb_notifications->mark_notifications_read(array('topic', 'quote', 'bookmark', 'post', 'approve_topic', 'approve_post'), false, $user->data['user_id'], $post_time);
+
if ($config['load_db_lastread'] && $user->data['is_registered'])
{
// Mark all forums read (index page)
@@ -1381,6 +1386,23 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
$forum_id = array($forum_id);
}
+ // Mark topic notifications read for this user in this forum
+ $phpbb_notifications->mark_notifications_read_by_parent(array('topic', 'approve_topic'), $forum_id, $user->data['user_id'], $post_time);
+
+ // Mark all post/quote notifications read for this user in this forum
+ $topic_ids = array();
+ $sql = 'SELECT topic_id
+ FROM ' . TOPICS_TABLE . '
+ WHERE ' . $db->sql_in_set('forum_id', $forum_id);
+ $result = $db->sql_query($sql);
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $topic_ids[] = $row['topic_id'];
+ }
+ $db->sql_freeresult($result);
+
+ $phpbb_notifications->mark_notifications_read_by_parent(array('quote', 'bookmark', 'post', 'approve_post'), $topic_ids, $user->data['user_id'], $post_time);
+
// Add 0 to forums array to mark global announcements correctly
// $forum_id[] = 0;
@@ -1478,6 +1500,10 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
return;
}
+ // Mark post notifications read for this user in this topic
+ $phpbb_notifications->mark_notifications_read(array('topic', 'approve_topic'), $topic_id, $user->data['user_id'], $post_time);
+ $phpbb_notifications->mark_notifications_read_by_parent(array('quote', 'bookmark', 'post', 'approve_post'), $topic_id, $user->data['user_id'], $post_time);
+
if ($config['load_db_lastread'] && $user->data['is_registered'])
{
$sql = 'UPDATE ' . TOPICS_TRACK_TABLE . "
@@ -4837,7 +4863,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_notifications;
if (defined('HEADER_INC'))
{
@@ -5026,6 +5052,20 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
$timezone_name = $user->lang['timezones'][$timezone_name];
}
+ // Output the notifications
+ if ($config['load_notifications'])
+ {
+ $notifications = $phpbb_notifications->load_notifications(array(
+ 'all_unread' => true,
+ 'limit' => 5,
+ ));
+
+ foreach ($notifications['notifications'] as $notification)
+ {
+ $template->assign_block_vars('notifications', $notification->prepare_for_display());
+ }
+ }
+
// The following assigns all _common_ variables that may be used at any point in a template.
$template->assign_vars(array(
'SITENAME' => $config['sitename'],
@@ -5041,6 +5081,11 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'PRIVATE_MESSAGE_INFO' => $l_privmsgs_text,
'PRIVATE_MESSAGE_INFO_UNREAD' => $l_privmsgs_text_unread,
+ 'UNREAD_NOTIFICATIONS_COUNT' => ($config['load_notifications']) ? $notifications['unread_count'] : '',
+ 'NOTIFICATIONS_COUNT' => ($config['load_notifications']) ? $user->lang('NOTIFICATIONS_COUNT', $notifications['unread_count']) : '',
+ 'U_VIEW_ALL_NOTIFICATIONS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications'),
+ 'S_NOTIFICATIONS_DISPLAY' => $config['load_notifications'],
+
'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'],
'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'],
'S_USER_NEW' => $user->data['user_new'],
diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php
index 5e2ee8c8f6..3deb2e9c59 100644
--- a/phpBB/includes/functions_admin.php
+++ b/phpBB/includes/functions_admin.php
@@ -619,6 +619,7 @@ function move_posts($post_ids, $topic_id, $auto_sync = true)
function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_sync = true, $call_delete_posts = true)
{
global $db, $config;
+ global $phpbb_notifications;
$approved_topics = 0;
$forum_ids = $topic_ids = array();
@@ -715,6 +716,9 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s
set_config_count('num_topics', $approved_topics * (-1), true);
}
+ // Delete notifications
+ $phpbb_notifications->delete_notifications(array('topic', 'approve_topic', 'topic_in_queue'), $topic_ids);
+
return $return;
}
@@ -724,6 +728,7 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s
function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = true, $post_count_sync = true, $call_delete_topics = true)
{
global $db, $config, $phpbb_root_path, $phpEx, $auth, $user;
+ global $phpbb_notifications;
if ($where_type === 'range')
{
@@ -892,6 +897,9 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =
delete_topics('topic_id', $remove_topics, $auto_sync, $post_count_sync, false);
}
+ // Delete notifications
+ $phpbb_notifications->delete_notifications(array('quote', 'bookmark', 'post', 'approve_post', 'post_in_queue'), $post_ids);
+
return sizeof($post_ids);
}
diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php
index 171cf988ce..4deffe653b 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;
@@ -296,15 +296,13 @@ function posting_gen_topic_icons($mode, $icon_id)
if (sizeof($icons))
{
- $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path;
-
foreach ($icons as $id => $data)
{
if ($data['display'])
{
$template->assign_block_vars('topic_icon', array(
'ICON_ID' => $id,
- 'ICON_IMG' => $root_path . $config['icons_path'] . '/' . $data['img'],
+ 'ICON_IMG' => $phpbb_root_path . $config['icons_path'] . '/' . $data['img'],
'ICON_WIDTH' => $data['width'],
'ICON_HEIGHT' => $data['height'],
@@ -1175,238 +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, $author_name = '')
-{
- 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),
- 'AUTHOR_NAME' => htmlspecialchars_decode($author_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
//
@@ -1643,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_notifications;
// We do not handle erasing posts here
if ($mode == 'delete')
@@ -2453,10 +2220,57 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
// Send Notifications
- if (($mode == 'reply' || $mode == 'quote' || $mode == 'post') && $post_approval)
+ $notification_data = array_merge($data, array(
+ 'topic_title' => (isset($data['topic_title'])) ? $data['topic_title'] : $subject,
+ 'post_username' => $username,
+ 'poster_id' => $poster_id,
+ 'post_text' => $data['message'],
+ 'post_time' => $current_time,
+ 'post_subject' => $subject,
+ ));
+
+ if ($post_approval)
{
- $username = ($username) ? $username : $user->data['username'];
- user_notification($mode, $subject, $data['topic_title'], $data['forum_name'], $data['forum_id'], $data['topic_id'], $data['post_id'], $username);
+ switch ($mode)
+ {
+ case 'post':
+ $phpbb_notifications->add_notifications(array('quote', 'topic'), $notification_data);
+ break;
+
+ case 'reply':
+ case 'quote':
+ $phpbb_notifications->add_notifications(array('quote', 'bookmark', 'post'), $notification_data);
+ break;
+
+ case 'edit_topic':
+ case 'edit_first_post':
+ case 'edit':
+ case 'edit_last_post':
+ $phpbb_notifications->update_notifications(array('quote', 'bookmark', 'topic', 'post'), $notification_data);
+ break;
+ }
+ }
+ else
+ {
+ switch ($mode)
+ {
+ case 'post':
+ $phpbb_notifications->add_notifications(array('topic_in_queue'), $notification_data);
+ break;
+
+ case 'reply':
+ case 'quote':
+ $phpbb_notifications->add_notifications(array('post_in_queue'), $notification_data);
+ break;
+
+ case 'edit_topic':
+ case 'edit_first_post':
+ case 'edit':
+ case 'edit_last_post':
+ $phpbb_notifications->delete_notifications('topic', $data['topic_id']);
+ $phpbb_notifications->delete_notifications(array('quote', 'bookmark', 'post'), $data['post_id']);
+ break;
+ }
}
$params = $add_anchor = '';
diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php
index 9e055a319f..6c31c6d6c3 100644
--- a/phpBB/includes/functions_privmsgs.php
+++ b/phpBB/includes/functions_privmsgs.php
@@ -269,46 +269,46 @@ function check_rule(&$rules, &$rule_row, &$message_row, $user_id)
case RULE_IS_LIKE:
$result = preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0);
break;
-
+
case RULE_IS_NOT_LIKE:
$result = !preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0);
break;
-
+
case RULE_IS:
$result = ($check0 == $rule_row['rule_string']);
break;
-
+
case RULE_IS_NOT:
$result = ($check0 != $rule_row['rule_string']);
break;
-
+
case RULE_BEGINS_WITH:
$result = preg_match("/^" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0);
break;
-
+
case RULE_ENDS_WITH:
$result = preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '$/i', $check0);
break;
-
+
case RULE_IS_FRIEND:
case RULE_IS_FOE:
case RULE_ANSWERED:
case RULE_FORWARDED:
$result = ($check0 == 1);
break;
-
+
case RULE_IS_USER:
$result = ($check0 == $rule_row['rule_user_id']);
break;
-
+
case RULE_IS_GROUP:
$result = in_array($rule_row['rule_group_id'], $check0);
break;
-
+
case RULE_TO_GROUP:
$result = (in_array('g_' . $message_row[$check_ary['check2']], $check0) || in_array('g_' . $message_row[$check_ary['check2']], $message_row[$check_ary['check1']]));
break;
-
+
case RULE_TO_ME:
$result = (in_array('u_' . $user_id, $check0) || in_array('u_' . $user_id, $message_row[$check_ary['check1']]));
break;
@@ -876,7 +876,10 @@ function update_unread_status($unread, $msg_id, $user_id, $folder_id)
return;
}
- global $db, $user;
+ global $db, $user, $phpbb_notifications;
+
+ // Mark the PM as read
+ $phpbb_notifications->mark_notifications_read('pm', $msg_id, $user_id);
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
SET pm_unread = 0
@@ -982,6 +985,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_notifications;
$user_id = (int) $user_id;
$folder_id = (int) $folder_id;
@@ -1093,6 +1097,9 @@ function delete_pm($user_id, $msg_ids, $folder_id)
$user->data['user_unread_privmsg'] -= $num_unread;
}
+ // Delete 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 . '
@@ -1137,6 +1144,7 @@ function delete_pm($user_id, $msg_ids, $folder_id)
function phpbb_delete_user_pms($user_id)
{
global $db, $user, $phpbb_root_path, $phpEx;
+ global $phpbb_notifications;
$user_id = (int) $user_id;
@@ -1253,6 +1261,9 @@ function phpbb_delete_user_pms($user_id)
WHERE folder_id = ' . PRIVMSGS_NO_BOX . '
AND ' . $db->sql_in_set('msg_id', $delivered_msg);
$db->sql_query($sql);
+
+ // Delete Notifications
+ $phpbb_notifications->delete_notifications('pm', $delivered_msg);
}
if (!empty($undelivered_msg))
@@ -1264,6 +1275,9 @@ function phpbb_delete_user_pms($user_id)
$sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
WHERE ' . $db->sql_in_set('msg_id', $undelivered_msg);
$db->sql_query($sql);
+
+ // Delete Notifications
+ $phpbb_notifications->delete_notifications('pm', $undelivered_msg);
}
}
@@ -1306,6 +1320,9 @@ function phpbb_delete_user_pms($user_id)
$sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
WHERE ' . $db->sql_in_set('msg_id', $delete_ids);
$db->sql_query($sql);
+
+ // Delete Notifications
+ $phpbb_notifications->delete_notifications('pm', $delete_ids);
}
}
@@ -1543,6 +1560,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_notifications;
// We do not handle erasing pms here
if ($mode == 'delete')
@@ -1842,95 +1860,21 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
$db->sql_transaction('commit');
// Send Notifications
- if ($mode != 'edit')
- {
- pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message'], $data['msg_id']);
- }
-
- 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);
+ $pm_data = array_merge($data, array(
+ 'message_subject' => $subject,
+ 'recipients' => $recipients,
+ ));
- if (!sizeof($msg_list_ary))
+ if ($mode == 'edit')
{
- return;
+ $phpbb_notifications->update_notifications('pm', $pm_data);
}
-
- include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
- $messenger = new messenger();
-
- foreach ($msg_list_ary as $pos => $addr)
+ else
{
- $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']);
+ $phpbb_notifications->add_notifications('pm', $pm_data);
}
- unset($msg_list_ary);
-
- $messenger->save_queue();
- unset($messenger);
+ return $data['msg_id'];
}
/**
diff --git a/phpBB/includes/mcp/mcp_pm_reports.php b/phpBB/includes/mcp/mcp_pm_reports.php
index 24e531517c..227c89bb79 100644
--- a/phpBB/includes/mcp/mcp_pm_reports.php
+++ b/phpBB/includes/mcp/mcp_pm_reports.php
@@ -34,6 +34,7 @@ class mcp_pm_reports
{
global $auth, $db, $user, $template, $cache;
global $config, $phpbb_root_path, $phpEx, $action;
+ global $phpbb_notifications;
include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
include_once($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx);
@@ -89,6 +90,9 @@ class mcp_pm_reports
trigger_error('NO_REPORT');
}
+ // Mark the notification as read
+ $phpbb_notifications->mark_notifications_read_by_parent('report_pm', $report_id, $user->data['user_id']);
+
$pm_id = $report['pm_id'];
$report_id = $report['report_id'];
diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php
index b44685b8a3..b23e5f4e45 100644
--- a/phpBB/includes/mcp/mcp_queue.php
+++ b/phpBB/includes/mcp/mcp_queue.php
@@ -34,6 +34,7 @@ class mcp_queue
{
global $auth, $db, $user, $template, $cache;
global $config, $phpbb_root_path, $phpEx, $action;
+ global $phpbb_notifications;
include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
@@ -84,6 +85,9 @@ class mcp_queue
if (isset($topic_info[$topic_id]['topic_first_post_id']))
{
$post_id = (int) $topic_info[$topic_id]['topic_first_post_id'];
+
+ // Mark the notification as read
+ $phpbb_notifications->mark_notifications_read('topic_in_queue', $topic_id, $user->data['user_id']);
}
else
{
@@ -91,6 +95,9 @@ class mcp_queue
}
}
+ // Mark the notification as read
+ $phpbb_notifications->mark_notifications_read('post_in_queue', $post_id, $user->data['user_id']);
+
$post_info = get_post_data(array($post_id), 'm_approve', true);
if (!sizeof($post_info))
@@ -421,7 +428,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'],
@@ -451,7 +458,7 @@ function approve_post($post_id_list, $id, $mode)
{
global $db, $template, $user, $config;
global $phpEx, $phpbb_root_path;
- global $request;
+ global $request, $phpbb_notifications;
if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve')))
{
@@ -597,54 +604,39 @@ function approve_post($post_id_list, $id, $mode)
sync('forum', 'forum_id', array_keys($forum_id_list), true, true);
unset($topic_id_list, $forum_id_list);
- $messenger = new messenger();
-
- // Notify Poster?
- if ($notify_poster)
- {
- foreach ($post_info as $post_id => $post_data)
- {
- if ($post_data['poster_id'] == ANONYMOUS)
- {
- continue;
- }
-
- $email_template = ($post_data['post_id'] == $post_data['topic_first_post_id'] && $post_data['post_id'] == $post_data['topic_last_post_id']) ? 'topic_approved' : 'post_approved';
-
- $messenger->template($email_template, $post_data['user_lang']);
-
- $messenger->to($post_data['user_email'], $post_data['username']);
- $messenger->im($post_data['user_jabber'], $post_data['username']);
-
- $messenger->assign_vars(array(
- 'USERNAME' => htmlspecialchars_decode($post_data['username']),
- 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_data['post_subject'])),
- 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_data['topic_title'])),
-
- 'U_VIEW_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?f={$post_data['forum_id']}&t={$post_data['topic_id']}&e=0",
- 'U_VIEW_POST' => generate_board_url() . "/viewtopic.$phpEx?f={$post_data['forum_id']}&t={$post_data['topic_id']}&p=$post_id&e=$post_id")
- );
-
- $messenger->send($post_data['user_notify_type']);
- }
- }
-
- $messenger->save_queue();
-
// Send out normal user notifications
$email_sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']);
+ // Handle 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'])
{
+ // Delete topic in queue notifications
+ $phpbb_notifications->delete_notifications(array('topic_in_queue'), $post_data['topic_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);
+ $phpbb_notifications->add_notifications('topic', $post_data);
+
+ // Notify poster?
+ if ($notify_poster)
+ {
+ $phpbb_notifications->add_notifications('approve_topic', $post_data);
+ }
}
else
{
+ // Delete post in queue notification
+ $phpbb_notifications->delete_notifications(array('post_in_queue'), $post_id);
+
// 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);
+ $phpbb_notifications->add_notifications(array('quote', 'bookmark', 'post'), $post_data);
+
+ // Notify poster?
+ if ($notify_poster)
+ {
+ $phpbb_notifications->add_notifications('approve_post', $post_data);
+ }
}
}
@@ -734,7 +726,7 @@ function disapprove_post($post_id_list, $id, $mode)
{
global $db, $template, $user, $config;
global $phpEx, $phpbb_root_path;
- global $request;
+ global $request, $phpbb_notifications;
if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve')))
{
@@ -867,20 +859,28 @@ function disapprove_post($post_id_list, $id, $mode)
}
}
- $messenger = new messenger();
+ // Handle notifications (topic/post in queue)
+ 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'])
+ {
+ $phpbb_notifications->delete_notifications(array('topic_in_queue'), $post_data['topic_id']);
+ }
+ else
+ {
+ $phpbb_notifications->delete_notifications(array('post_in_queue'), $post_id);
+ }
+ }
// Notify Poster?
if ($notify_poster)
{
$lang_reasons = array();
+ // Handle notifications
foreach ($post_info as $post_id => $post_data)
{
- if ($post_data['poster_id'] == ANONYMOUS)
- {
- continue;
- }
-
+ $post_data['disapprove_reason'] = '';
if (isset($disapprove_reason_lang))
{
// Okay we need to get the reason from the posters language
@@ -906,33 +906,32 @@ function disapprove_post($post_id_list, $id, $mode)
}
}
- $email_disapprove_reason = $lang_reasons[$post_data['user_lang']];
- $email_disapprove_reason .= ($reason) ? "\n\n" . $reason : '';
+ $post_data['disapprove_reason'] = $lang_reasons[$post_data['user_lang']];
+ $post_data['disapprove_reason'] .= ($reason) ? "\n\n" . $reason : '';
}
- $email_template = ($post_data['post_id'] == $post_data['topic_first_post_id'] && $post_data['post_id'] == $post_data['topic_last_post_id']) ? 'topic_disapproved' : 'post_disapproved';
-
- $messenger->template($email_template, $post_data['user_lang']);
-
- $messenger->to($post_data['user_email'], $post_data['username']);
- $messenger->im($post_data['user_jabber'], $post_data['username']);
-
- $messenger->assign_vars(array(
- 'USERNAME' => htmlspecialchars_decode($post_data['username']),
- 'REASON' => htmlspecialchars_decode($email_disapprove_reason),
- 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_data['post_subject'])),
- 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_data['topic_title'])))
- );
-
- $messenger->send($post_data['user_notify_type']);
+ if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id'])
+ {
+ // Notify poster?
+ if ($notify_poster)
+ {
+ $phpbb_notifications->add_notifications('disapprove_topic', $post_data);
+ }
+ }
+ else
+ {
+ // Notify poster?
+ if ($notify_poster)
+ {
+ $phpbb_notifications->add_notifications('disapprove_post', $post_data);
+ }
+ }
}
unset($lang_reasons);
}
unset($post_info, $disapprove_reason, $email_disapprove_reason, $disapprove_reason_lang);
- $messenger->save_queue();
-
if ($num_disapproved_topics)
{
$success_msg = ($num_disapproved_topics == 1) ? 'TOPIC_DISAPPROVED_SUCCESS' : 'TOPICS_DISAPPROVED_SUCCESS';
diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php
index 2890cd56e2..7c6352a244 100644
--- a/phpBB/includes/mcp/mcp_reports.php
+++ b/phpBB/includes/mcp/mcp_reports.php
@@ -34,6 +34,7 @@ class mcp_reports
{
global $auth, $db, $user, $template, $cache;
global $config, $phpbb_root_path, $phpEx, $action;
+ global $phpbb_notifications;
include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
@@ -87,6 +88,9 @@ class mcp_reports
trigger_error('NO_REPORT');
}
+ // Mark the notification as read
+ $phpbb_notifications->mark_notifications_read('report_post', $post_id, $user->data['user_id']);
+
if (!$report_id && $report['report_closed'])
{
trigger_error('REPORT_CLOSED');
@@ -413,7 +417,7 @@ class mcp_reports
$base_url = $this->u_action . "&amp;f=$forum_id&amp;t=$topic_id&amp;st=$sort_days&amp;sk=$sort_key&amp;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_EXPLAIN' => ($mode == 'reports') ? $user->lang['MCP_REPORTS_OPEN_EXPLAIN'] : $user->lang['MCP_REPORTS_CLOSED_EXPLAIN'],
@@ -444,6 +448,7 @@ function close_report($report_id_list, $mode, $action, $pm = false)
{
global $db, $template, $user, $config, $auth;
global $phpEx, $phpbb_root_path;
+ global $phpbb_notifications;
$pm_where = ($pm) ? ' AND r.post_id = 0 ' : ' AND r.pm_id = 0 ';
$id_column = ($pm) ? 'pm_id' : 'post_id';
@@ -629,8 +634,6 @@ function close_report($report_id_list, $mode, $action, $pm = false)
}
}
- $messenger = new messenger();
-
// Notify reporters
if (sizeof($notify_reporters))
{
@@ -643,30 +646,23 @@ function close_report($report_id_list, $mode, $action, $pm = false)
$post_id = $reporter[$id_column];
- $messenger->template((($pm) ? 'pm_report_' : 'report_') . $action . 'd', $reporter['user_lang']);
-
- $messenger->to($reporter['user_email'], $reporter['username']);
- $messenger->im($reporter['user_jabber'], $reporter['username']);
-
if ($pm)
{
- $messenger->assign_vars(array(
- 'USERNAME' => htmlspecialchars_decode($reporter['username']),
- 'CLOSER_NAME' => htmlspecialchars_decode($user->data['username']),
- 'PM_SUBJECT' => htmlspecialchars_decode(censor_text($post_info[$post_id]['message_subject'])),
- ));
+ $phpbb_notifications->add_notifications('report_pm_closed', array_merge($post_info[$post_id], array(
+ 'reporter' => $reporter['user_id'],
+ 'closer_id' => $user->data['user_id'],
+ 'from_user_id' => $post_info[$post_id]['author_id'],
+ )));
+ $phpbb_notifications->delete_notifications('report_pm', $post_id);
}
else
{
- $messenger->assign_vars(array(
- 'USERNAME' => htmlspecialchars_decode($reporter['username']),
- 'CLOSER_NAME' => htmlspecialchars_decode($user->data['username']),
- 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_info[$post_id]['post_subject'])),
- 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_info[$post_id]['topic_title'])))
- );
+ $phpbb_notifications->add_notifications('report_post_closed', array_merge($post_info[$post_id], array(
+ 'reporter' => $reporter['user_id'],
+ 'closer_id' => $user->data['user_id'],
+ )));
+ $phpbb_notifications->delete_notifications('report_post', $post_id);
}
-
- $messenger->send($reporter['user_notify_type']);
}
}
@@ -681,8 +677,6 @@ function close_report($report_id_list, $mode, $action, $pm = false)
unset($notify_reporters, $post_info, $reports);
- $messenger->save_queue();
-
$success_msg = (sizeof($report_id_list) == 1) ? "{$pm_prefix}REPORT_" . strtoupper($action) . 'D_SUCCESS' : "{$pm_prefix}REPORTS_" . strtoupper($action) . 'D_SUCCESS';
}
else
diff --git a/phpBB/includes/notification/manager.php b/phpBB/includes/notification/manager.php
new file mode 100644
index 0000000000..03776de2b4
--- /dev/null
+++ b/phpBB/includes/notification/manager.php
@@ -0,0 +1,752 @@
+<?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_notification_manager
+{
+ protected $db, $cache, $template, $extension_manager, $user, $auth, $config, $phpbb_root_path, $php_ext = null;
+
+ /**
+ * Users loaded from the DB
+ *
+ * @var array Array of user data that we've loaded from the DB
+ */
+ protected $users = array();
+
+ public function __construct(dbal $db, phpbb_cache_driver_interface $cache, phpbb_template $template, phpbb_extension_manager $extension_manager, $user, phpbb_auth $auth, phpbb_config $config, $phpbb_root_path, $php_ext)
+ {
+ $this->db = $db;
+ $this->cache = $cache;
+ $this->template = $template;
+ $this->extension_manager = $extension_manager;
+ $this->user = $user;
+ $this->auth = $auth;
+ $this->config = $config;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * Load the user's notifications
+ *
+ * @param array $options Optional options to control what notifications are loaded
+ * notification_id Notification id to load (or array of notification ids)
+ * 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)
+ * all_unread Load all unread messages? If set to true, count_unread is set to true (Default: false)
+ * count_unread Count all unread messages? (Default: false)
+ */
+ public function load_notifications($options = array())
+ {
+ // Merge default options
+ $options = array_merge(array(
+ 'notification_id' => false,
+ 'user_id' => $this->user->data['user_id'],
+ 'order_by' => 'time',
+ 'order_dir' => 'DESC',
+ 'limit' => 0,
+ 'start' => 0,
+ 'all_unread' => false,
+ 'count_unread' => false,
+ 'count_total' => false,
+ ), $options);
+
+ // If all_unread, count_unread mus be true
+ $options['count_unread'] = ($options['all_unread']) ? true : $options['count_unread'];
+
+ // Anonymous users and bots never receive notifications
+ if ($options['user_id'] == $this->user->data['user_id'] && ($this->user->data['user_id'] == ANONYMOUS || $this->user->data['user_type'] == USER_IGNORE))
+ {
+ return array(
+ 'notifications' => array(),
+ 'unread_count' => 0,
+ 'total_count' => 0,
+ );
+ }
+
+ $notifications = $user_ids = array();
+ $load_special = array();
+ $total_count = $unread_count = 0;
+
+ if ($options['count_unread'])
+ {
+ // Get the total number of unread notifications
+ $sql = 'SELECT COUNT(*) AS count
+ FROM ' . NOTIFICATIONS_TABLE . '
+ WHERE user_id = ' . (int) $options['user_id'] . '
+ AND unread = 1
+ AND is_disabled = 0';
+ $result = $this->db->sql_query($sql);
+ $unread_count = (int) $this->db->sql_fetchfield('count', $result);
+ $this->db->sql_freeresult($result);
+ }
+
+ if ($options['count_total'])
+ {
+ // Get the total number of notifications
+ $sql = 'SELECT COUNT(*) AS count
+ FROM ' . NOTIFICATIONS_TABLE . '
+ WHERE user_id = ' . (int) $options['user_id'] . '
+ AND is_disabled = 0';
+ $result = $this->db->sql_query($sql);
+ $total_count = (int) $this->db->sql_fetchfield('count', $result);
+ $this->db->sql_freeresult($result);
+ }
+
+ $rowset = array();
+
+ // Get the main notifications
+ $sql = 'SELECT *
+ FROM ' . NOTIFICATIONS_TABLE . '
+ WHERE user_id = ' . (int) $options['user_id'] .
+ (($options['notification_id']) ? ((is_array($options['notification_id'])) ? ' AND ' . $this->db->sql_in_set('notification_id', $options['notification_id']) : ' AND notification_id = ' . (int) $options['notification_id']) : '') . '
+ AND is_disabled = 0
+ 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))
+ {
+ $rowset[$row['notification_id']] = $row;
+ }
+ $this->db->sql_freeresult($result);
+
+ // Get all unread notifications
+ if ($unread_count && $options['all_unread'] && !empty($rowset))
+ {
+ $sql = 'SELECT *
+ FROM ' . NOTIFICATIONS_TABLE . '
+ WHERE user_id = ' . (int) $options['user_id'] . '
+ AND unread = 1
+ AND ' . $this->db->sql_in_set('notification_id', array_keys($rowset), true) . '
+ AND is_disabled = 0
+ 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))
+ {
+ $rowset[$row['notification_id']] = $row;
+ }
+ $this->db->sql_freeresult($result);
+ }
+
+ foreach ($rowset as $row)
+ {
+ $item_type_class_name = $this->get_item_type_class_name($row['item_type'], true);
+
+ $notification = $this->get_item_type_class($item_type_class_name, $row);
+
+ // Array of user_ids to query all at once
+ $user_ids = array_merge($user_ids, $notification->users_to_query());
+
+ // Some notification types also require querying additional tables themselves
+ if (!isset($load_special[$row['item_type']]))
+ {
+ $load_special[$row['item_type']] = array();
+ }
+ $load_special[$row['item_type']] = array_merge($load_special[$row['item_type']], $notification->get_load_special());
+
+ $notifications[$row['notification_id']] = $notification;
+ }
+
+ $this->load_users($user_ids);
+
+ // Allow each type to load its own special items
+ foreach ($load_special as $item_type => $data)
+ {
+ $item_type_class_name = $this->get_item_type_class_name($item_type, true);
+
+ $item_class = $this->get_item_type_class($item_type_class_name);
+
+ $item_class->load_special($data, $notifications);
+ }
+
+ return array(
+ 'notifications' => $notifications,
+ 'unread_count' => $unread_count,
+ 'total_count' => $total_count,
+ );
+ }
+
+ /**
+ * Mark notifications read
+ *
+ * @param bool|string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types). False to mark read for all item types
+ * @param bool|int|array $item_id Item id or array of item ids. False to mark read for all item ids
+ * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
+ * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
+ */
+ public function mark_notifications_read($item_type, $item_id, $user_id, $time = false)
+ {
+ if (is_array($item_type))
+ {
+ foreach ($item_type as $type)
+ {
+ $this->mark_notifications_read($type, $item_id, $user_id, $time);
+ }
+
+ return;
+ }
+
+ $time = ($time) ?: time();
+
+ if ($item_type !== false)
+ {
+ $this->get_item_type_class_name($item_type);
+ }
+
+ $sql = 'UPDATE ' . NOTIFICATIONS_TABLE . "
+ SET unread = 0
+ WHERE time <= " . $time .
+ (($item_type !== false) ? ' AND ' . (is_array($item_type) ? $this->db->sql_in_set('item_type', $item_type) : " item_type = '" . $this->db->sql_escape($item_type) . "'") : '') .
+ (($item_id !== false) ? ' AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) : '') .
+ (($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : '');
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * Mark notifications read from a parent identifier
+ *
+ * @param string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
+ * @param bool|int|array $item_parent_id Item parent id or array of item parent ids. False to mark read for all item parent ids
+ * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
+ * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
+ */
+ public function mark_notifications_read_by_parent($item_type, $item_parent_id, $user_id, $time = false)
+ {
+ if (is_array($item_type))
+ {
+ foreach ($item_type as $type)
+ {
+ $this->mark_notifications_read_by_parent($type, $item_parent_id, $user_id, $time);
+ }
+
+ return;
+ }
+
+ $time = ($time) ?: time();
+
+ $item_type_class_name = $this->get_item_type_class_name($item_type);
+
+ $sql = 'UPDATE ' . NOTIFICATIONS_TABLE . "
+ SET unread = 0
+ WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
+ AND time <= " . $time .
+ (($item_parent_id !== false) ? ' AND ' . (is_array($item_parent_id) ? $this->db->sql_in_set('item_parent_id', $item_parent_id) : 'item_parent_id = ' . (int) $item_parent_id) : '') .
+ (($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : '');
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * Mark notifications read
+ *
+ * @param int|array $notification_id Notification id or array of notification ids.
+ * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
+ */
+ public function mark_notifications_read_by_id($notification_id, $time = false)
+ {
+ $time = ($time) ?: time();
+
+ $sql = 'UPDATE ' . NOTIFICATIONS_TABLE . "
+ SET unread = 0
+ WHERE time <= " . $time . '
+ AND ' . ((is_array($notification_id)) ? $this->db->sql_in_set('notification_id', $notification_id) : 'notification_id = ' . (int) $notification_id);
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * Add a notification
+ *
+ * @param string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
+ * Note: If you send an array of types, any user who could receive multiple notifications from this single item will only receive
+ * a single notification. If they MUST receive multiple notifications, call this function multiple times instead of sending an array
+ * @param array $data Data specific for this type that will be inserted
+ */
+ public function add_notifications($item_type, $data, $options = array())
+ {
+ $options = array_merge(array(
+ 'ignore_users' => array(),
+ ), $options);
+
+ if (is_array($item_type))
+ {
+ $notified_users = array();
+ $temp_options = $options;
+
+ foreach ($item_type as $type)
+ {
+ $temp_options['ignore_users'] = $options['ignore_users'] + $notified_users;
+ $notified_users += $this->add_notifications($type, $data, $temp_options);
+ }
+
+ return $notified_users;
+ }
+
+ $item_type_class_name = $this->get_item_type_class_name($item_type);
+
+ $item_id = $item_type_class_name::get_item_id($data);
+
+ // find out which users want to receive this type of notification
+ $notify_users = $this->get_item_type_class($item_type_class_name)->find_users_for_notification($data, $options);
+
+ $this->add_notifications_for_users($item_type, $data, $notify_users);
+
+ return $notify_users;
+ }
+
+ /**
+ * Add a notification for specific users
+ *
+ * @param string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
+ * @param array $data Data specific for this type that will be inserted
+ * @param array $notify_users User list to notify
+ */
+ public function add_notifications_for_users($item_type, $data, $notify_users)
+ {
+ if (is_array($item_type))
+ {
+ foreach ($item_type as $type)
+ {
+ $this->add_notifications_for_users($type, $data, $notify_users);
+ }
+
+ return;
+ }
+
+ $item_type_class_name = $this->get_item_type_class_name($item_type);
+
+ $item_id = $item_type_class_name::get_item_id($data);
+
+ $user_ids = array();
+ $notification_objects = $notification_methods = array();
+ $new_rows = array();
+
+ // Never send notifications to the anonymous user!
+ unset($notify_users[ANONYMOUS]);
+
+ // 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 . '
+ AND is_disabled = 0';
+ $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;
+ }
+
+ // Allow notifications to perform actions before creating the insert array (such as run a query to cache some data needed for all notifications)
+ $notification = $this->get_item_type_class($item_type_class_name);
+ $pre_create_data = $notification->pre_create_insert_array($data, $notify_users);
+ unset($notification);
+
+ // 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 = $this->get_item_type_class($item_type_class_name);
+
+ $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, $pre_create_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
+ 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]))
+ {
+ $method_class_name = 'phpbb_notification_method_' . $method;
+ $notification_methods[$method] = $this->get_method_class($method_class_name);
+ }
+
+ $notification_methods[$method]->add_to_queue($notification);
+ }
+ }
+ }
+
+ // 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)
+ {
+ $method->notify();
+ }
+ }
+
+ /**
+ * Update a notification
+ *
+ * @param string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
+ * @param array $data Data specific for this type that will be updated
+ */
+ public function update_notifications($item_type, $data)
+ {
+ if (is_array($item_type))
+ {
+ foreach ($item_type as $type)
+ {
+ $this->update_notifications($type, $data);
+ }
+
+ return;
+ }
+
+ $item_type_class_name = $this->get_item_type_class_name($item_type);
+
+ // Allow the notifications class to over-ride the update_notifications functionality
+ if (method_exists($item_type_class_name, 'update_notifications'))
+ {
+ // Return False to over-ride the rest of the update
+ if ($this->get_item_type_class($item_type_class_name)->update_notifications($data) === false)
+ {
+ return;
+ }
+ }
+
+ $item_id = $item_type_class_name::get_item_id($data);
+
+ $notification = $this->get_item_type_class($item_type_class_name);
+ $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|array $item_type Type identifier or array of item types (only acceptable if the $item_id is identical for the specified types)
+ * @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)
+ {
+ if (is_array($item_type))
+ {
+ foreach ($item_type as $type)
+ {
+ $this->delete_notifications($type, $item_id);
+ }
+
+ return;
+ }
+
+ $this->get_item_type_class_name($item_type);
+
+ $sql = 'DELETE FROM ' . NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
+ AND " . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id);
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * Get all of the subscription types
+ *
+ * @return array Array of item types
+ */
+ public function get_subscription_types()
+ {
+ $subscription_types = array();
+
+ foreach ($this->get_subscription_files('notification/type/') as $class_name => $file)
+ {
+ $class_name = $this->get_item_type_class_name($class_name);
+
+ $class = $this->get_item_type_class($class_name);
+
+ if ($class->is_available() && method_exists($class_name, 'get_item_type'))
+ {
+ $options = array_merge(array(
+ 'id' => $class_name::get_item_type(),
+ 'lang' => 'NOTIFICATION_TYPE_' . strtoupper($class_name::get_item_type()),
+ 'group' => 'NOTIFICATION_GROUP_MISCELLANEOUS',
+ ), (($class_name::$notification_option !== false) ? $class_name::$notification_option : array()));
+
+ $subscription_types[$options['group']][$options['id']] = $options;
+ }
+ }
+
+ // Move Miscellaneous to the very last section
+ if (isset($subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS']))
+ {
+ $miscellaneous = $subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS'];
+ unset($subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS']);
+ $subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS'] = $miscellaneous;
+ }
+
+ return $subscription_types;
+ }
+
+ /**
+ * Get all of the subscription methods
+ *
+ * @return array Array of methods
+ */
+ public function get_subscription_methods()
+ {
+ $subscription_methods = array();
+
+ foreach ($this->get_subscription_files('notification/method/') as $method_name => $file)
+ {
+ $class_name = 'phpbb_notification_method_' . $method_name;
+
+ $method = $this->get_method_class($class_name);
+
+ if ($method->is_available())
+ {
+ $subscription_methods[] = $method_name;
+ }
+ }
+
+ return $subscription_methods;
+ }
+
+ /**
+ * Get subscriptions
+ *
+ * @param bool|int $user_id The user_id to add the subscription for (bool false for current user)
+ * @param bool $only_global True to select only global subscription options (item_id = 0)
+ *
+ * @return array Subscriptions
+ */
+ public function get_subscriptions($user_id = false, $only_global = false)
+ {
+ $user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id;
+
+ $subscriptions = array();
+
+ $sql = 'SELECT *
+ FROM ' . USER_NOTIFICATIONS_TABLE . '
+ WHERE user_id = ' . (int) $user_id .
+ (($only_global) ? ' AND item_id = 0' : '');
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if ($only_global)
+ {
+ if (!isset($subscriptions[$row['item_type']]))
+ {
+ $subscriptions[$row['item_type']] = array();
+ }
+
+ $subscriptions[$row['item_type']][] = $row['method'];
+ }
+ else
+ {
+ $subscriptions[] = $row;
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ return $subscriptions;
+ }
+
+ /**
+ * Add a subscription
+ *
+ * @param string $item_type Type identifier of the subscription
+ * @param int $item_id The id of the item
+ * @param string $method The method of the notification e.g. '', 'email', or 'jabber'
+ * @param bool|int $user_id The user_id to add the subscription for (bool false for current user)
+ */
+ public function add_subscription($item_type, $item_id = 0, $method = '', $user_id = false)
+ {
+ $this->get_item_type_class_name($item_type);
+
+ $user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id;
+
+ $sql = 'INSERT INTO ' . USER_NOTIFICATIONS_TABLE . ' ' .
+ $this->db->sql_build_array('INSERT', array(
+ 'item_type' => $item_type,
+ 'item_id' => (int) $item_id,
+ 'user_id' => (int) $user_id,
+ 'method' => $method,
+ ));
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * Delete a subscription
+ *
+ * @param string $item_type Type identifier of the subscription
+ * @param int $item_id The id of the item
+ * @param string $method The method of the notification e.g. '', 'email', or 'jabber'
+ * @param bool|int $user_id The user_id to add the subscription for (bool false for current user)
+ */
+ public function delete_subscription($item_type, $item_id = 0, $method = '', $user_id = false)
+ {
+ $this->get_item_type_class_name($item_type);
+
+ $user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id;
+
+ $sql = 'DELETE FROM ' . USER_NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
+ AND item_id = " . (int) $item_id . '
+ AND user_id = ' .(int) $user_id . "
+ AND method = '" . $this->db->sql_escape($method) . "'";
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * Load user helper
+ *
+ * @param array $user_ids
+ */
+ public function load_users($user_ids)
+ {
+ $user_ids[] = ANONYMOUS;
+
+ // 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 (isset($this->users[$user_id])) ? $this->users[$user_id] : $this->users[ANONYMOUS];
+ }
+
+ /**
+ * 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);
+ }
+
+ if (strpos($item_type, 'ext_') === 0)
+ {
+ $item_type_ary = explode('-', substr($item_type, 4), 2);
+
+ return 'phpbb_ext_' . $item_type_ary[0] . '_notification_type_' . $item_type_ary[1];
+ }
+
+ return 'phpbb_notification_type_' . $item_type;
+ }
+
+ /**
+ * Helper to get the notifications item type class and set it up
+ */
+ public function get_item_type_class($item_type, $data = array())
+ {
+ if (!strpos($item_type, 'notification_type_'))
+ {
+ $item_class = $this->get_item_type_class_name($item_type);
+ $item_type = $item_class;
+ }
+
+ $item = new $item_type($this, $this->db, $this->cache, $this->template, $this->extension_manager, $this->user, $this->auth, $this->config, $this->phpbb_root_path, $this->php_ext);
+
+ $item->set_initial_data($data);
+
+ return $item;
+ }
+
+ /**
+ * Helper to get the notifications method class and set it up
+ */
+ public function get_method_class($method_name)
+ {
+ return new $method_name($this, $this->db, $this->cache, $this->template, $this->extension_manager, $this->user, $this->auth, $this->config, $this->phpbb_root_path, $this->php_ext);
+ }
+
+ /**
+ * Helper to get subscription related files with the finder
+ */
+ private function get_subscription_files($path)
+ {
+ $finder = $this->extension_manager->get_finder();
+
+ $subscription_files = array();
+
+ $files = $finder
+ ->core_path('includes/' . $path)
+ ->extension_directory($path)
+ ->get_files();
+ foreach ($files as $file)
+ {
+ $name = substr($file, strrpos($file, '/'));
+ $name = substr($name, 1, (strpos($name, '.' . $this->php_ext) - 1));
+
+ if ($name == 'interface' || $name == 'base')
+ {
+ continue;
+ }
+
+ if (!strpos($file, 'includes/')) // is an extension
+ {
+ $ext_name = substr($file, (strpos($file, 'ext/') + 4));
+ $ext_name = substr($ext_name, 0, strpos($ext_name, '/'));
+
+ $name = 'ext_' . $ext_name . '-' . $name;
+ }
+
+ $subscription_files[$name] = $file;
+ }
+
+ return $subscription_files;
+ }
+}
diff --git a/phpBB/includes/notification/method/base.php b/phpBB/includes/notification/method/base.php
new file mode 100644
index 0000000000..5457ca99b2
--- /dev/null
+++ b/phpBB/includes/notification/method/base.php
@@ -0,0 +1,83 @@
+<?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_notification_method_base implements phpbb_notification_method_interface
+{
+ protected $notification_manager, $db, $cache, $template, $extension_manager, $user, $auth, $config, $phpbb_root_path, $php_ext = null;
+
+ /**
+ * 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
+ *
+ * @var array
+ */
+ protected $queue = array();
+
+ public function __construct(phpbb_notification_manager $notification_manager, dbal $db, phpbb_cache_driver_interface $cache, phpbb_template $template, phpbb_extension_manager $extension_manager, $user, phpbb_auth $auth, phpbb_config $config, $phpbb_root_path, $php_ext)
+ {
+ $this->notification_manager = $notification_manager;
+ $this->db = $db;
+ $this->cache = $cache;
+ $this->template = $template;
+ $this->extension_manager = $extension_manager;
+ $this->user = $user;
+ $this->auth = $auth;
+ $this->config = $config;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * Add a notification to the queue
+ *
+ * @param phpbb_notification_type_interface $notification
+ */
+ public function add_to_queue(phpbb_notification_type_interface $notification)
+ {
+ $this->queue[] = $notification;
+ }
+
+ /**
+ * Empty the queue
+ */
+ protected function empty_queue()
+ {
+ $this->queue = array();
+ }
+}
diff --git a/phpBB/includes/notification/method/email.php b/phpBB/includes/notification/method/email.php
new file mode 100644
index 0000000000..c2e272aca1
--- /dev/null
+++ b/phpBB/includes/notification/method/email.php
@@ -0,0 +1,104 @@
+<?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_notification_method_email extends phpbb_notification_method_base
+{
+ /**
+ * Notify method (since jabber gets sent through the same messenger, we let the jabber class inherit from this to reduce code duplication)
+ *
+ * @var mixed
+ */
+ protected $notify_method = NOTIFY_EMAIL;
+
+ /**
+ * Is this method available for the user?
+ * This is checked on the notifications options
+ */
+ public function is_available()
+ {
+ // Email is always available
+ return true;
+ }
+
+ public function notify()
+ {
+ 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;
+ }
+
+ // We do not send emails to banned users
+ if (!function_exists('phpbb_get_banned_user_ids'))
+ {
+ include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
+ }
+ $banned_users = phpbb_get_banned_user_ids($user_ids);
+
+ // Load all the users we need
+ $this->notification_manager->load_users($user_ids);
+
+ // 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)
+ {
+ $user = $this->notification_manager->get_user($notification->user_id);
+
+ if ($user['user_type'] == USER_IGNORE || in_array($notification->user_id, $banned_users))
+ {
+ continue;
+ }
+
+ $messenger->template($notification->email_template, $user['user_lang']);
+
+ $messenger->to($user['user_email'], $user['username']);
+
+ $messenger->assign_vars(array_merge(array(
+ 'USERNAME' => $user['username'],
+
+ 'U_NOTIFICATION_SETTINGS' => generate_board_url() . '/ucp.' . $this->php_ext . '?i=ucp_notifications',
+ ), $notification->get_email_template_variables()));
+
+ $messenger->send($this->notify_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/notification/method/interface.php b/phpBB/includes/notification/method/interface.php
new file mode 100644
index 0000000000..4b990ec9fa
--- /dev/null
+++ b/phpBB/includes/notification/method/interface.php
@@ -0,0 +1,27 @@
+<?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_notification_method_interface
+{
+ public function is_available();
+
+ public function notify();
+}
diff --git a/phpBB/includes/notification/method/jabber.php b/phpBB/includes/notification/method/jabber.php
new file mode 100644
index 0000000000..664e387d61
--- /dev/null
+++ b/phpBB/includes/notification/method/jabber.php
@@ -0,0 +1,60 @@
+<?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 messages for notifications
+*
+* @package notifications
+*/
+class phpbb_notification_method_jabber extends phpbb_notification_method_email
+{
+ /**
+ * Notify method (since jabber gets sent through the same messenger, we let the jabber class inherit from this to reduce code duplication)
+ *
+ * @var mixed
+ */
+ protected $notify_method = NOTIFY_IM;
+
+ /**
+ * Is this method available for the user?
+ * This is checked on the notifications options
+ */
+ public function is_available()
+ {
+ return ($this->global_available() && $this->user->data['jabber']);
+ }
+
+ /**
+ * Is this method available at all?
+ * This is checked before notifications are sent
+ */
+ public function global_available()
+ {
+ return ($this->config['jab_enable'] && @extension_loaded('xml'));
+ }
+
+ public function notify()
+ {
+ if (!$this->global_available())
+ {
+ return;
+ }
+
+ return parent::notify();
+ }
+}
diff --git a/phpBB/includes/notification/type/approve_post.php b/phpBB/includes/notification/type/approve_post.php
new file mode 100644
index 0000000000..6ed9b6c67c
--- /dev/null
+++ b/phpBB/includes/notification/type/approve_post.php
@@ -0,0 +1,169 @@
+<?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
+* This class handles notifications for replies to a topic
+*
+* @package notifications
+*/
+class phpbb_notification_type_approve_post extends phpbb_notification_type_post
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = 'post_approved';
+
+ /**
+ * Language key used to output the text
+ *
+ * @var string
+ */
+ protected $language_key = 'NOTIFICATION_POST_APPROVED';
+
+ /**
+ * Notification option data (for outputting to the user)
+ *
+ * @var bool|array False if the service should use it's default data
+ * Array of data (including keys 'id', 'lang', and 'group')
+ */
+ public static $notification_option = array(
+ 'id' => 'moderation_queue',
+ 'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE',
+ 'group' => 'NOTIFICATION_GROUP_POSTING',
+ );
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_type_
+ */
+ public static function get_item_type()
+ {
+ return 'approve_post';
+ }
+
+ /**
+ * Is available
+ */
+ public function is_available()
+ {
+ return !$this->auth->acl_get('m_approve');
+ }
+
+ /**
+ * Find the users who want to receive notifications
+ *
+ * @param array $post Data from
+ *
+ * @return array
+ */
+ public function find_users_for_notification($post, $options = array())
+ {
+ $options = array_merge(array(
+ 'ignore_users' => array(),
+ ), $options);
+
+ $users = array();
+ $users[$post['poster_id']] = array('');
+
+ $auth_read = $this->auth->acl_get_list(array_keys($users), 'f_read', $post['forum_id']);
+
+ if (empty($auth_read))
+ {
+ return array();
+ }
+
+ $notify_users = array();
+
+ $sql = 'SELECT *
+ FROM ' . USER_NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::$notification_option['id'] . "'
+ AND " . $this->db->sql_in_set('user_id', $auth_read[$post['forum_id']]['f_read']);
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']]))
+ {
+ continue;
+ }
+
+ if (!isset($rowset[$row['user_id']]))
+ {
+ $notify_users[$row['user_id']] = array();
+ }
+
+ $notify_users[$row['user_id']][] = $row['method'];
+ }
+ $this->db->sql_freeresult($result);
+
+ return $notify_users;
+ }
+
+ /**
+ * Pre create insert array function
+ * This allows you to perform certain actions, like run a query
+ * and load data, before create_insert_array() is run. The data
+ * returned from this function will be sent to create_insert_array().
+ *
+ * @param array $post Post data from submit_post
+ * @param array $notify_users Notify users list
+ * Formated from find_users_for_notification()
+ * @return array Whatever you want to send to create_insert_array().
+ */
+ public function pre_create_insert_array($post, $notify_users)
+ {
+ /*if (!sizeof($notify_users))
+ {
+ return array();
+ }
+
+ // Mark the topic unread before the post
+ $sql = 'UPDATE ' . TOPICS_TRACK_TABLE . '
+ SET mark_time = ' . (int) ($post['post_time'] - 1) . '
+ WHERE topic_id = ' . (int) $post['topic_id'] . '
+ AND ' . $this->db->sql_in_set('user_id', array_keys($notify_users));
+ $this->db->sql_query($sql);*/
+
+ // In the parent class, this is used to check if the post is already
+ // read by a user and marks the notification read if it was marked read.
+ // Returning an empty array in effect, forces it to be marked as unread
+ // (and also saves a query)
+ return array();
+ }
+
+ /**
+ * Function for preparing the data for insertion in an SQL query
+ * (The service handles insertion)
+ *
+ * @param array $post Data from submit_post
+ * @param array $pre_create_data Data from pre_create_insert_array()
+ *
+ * @return array Array of data ready to be inserted into the database
+ */
+ public function create_insert_array($post, $pre_create_data = array())
+ {
+ $this->set_data('post_subject', $post['post_subject']);
+
+ $data = parent::create_insert_array($post, $pre_create_data);
+
+ $this->time = $data['time'] = time();
+
+ return $data;
+ }
+}
diff --git a/phpBB/includes/notification/type/approve_topic.php b/phpBB/includes/notification/type/approve_topic.php
new file mode 100644
index 0000000000..1ff5ae43bd
--- /dev/null
+++ b/phpBB/includes/notification/type/approve_topic.php
@@ -0,0 +1,165 @@
+<?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
+* This class handles notifications for replies to a topic
+*
+* @package notifications
+*/
+class phpbb_notification_type_approve_topic extends phpbb_notification_type_topic
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = 'topic_approved';
+
+ /**
+ * Language key used to output the text
+ *
+ * @var string
+ */
+ protected $language_key = 'NOTIFICATION_TOPIC_APPROVED';
+
+ /**
+ * Notification option data (for outputting to the user)
+ *
+ * @var bool|array False if the service should use it's default data
+ * Array of data (including keys 'id', 'lang', and 'group')
+ */
+ public static $notification_option = array(
+ 'id' => 'moderation_queue',
+ 'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE',
+ 'group' => 'NOTIFICATION_GROUP_POSTING',
+ );
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_type_
+ */
+ public static function get_item_type()
+ {
+ return 'approve_topic';
+ }
+
+ /**
+ * Is available
+ */
+ public function is_available()
+ {
+ return !$this->auth->acl_get('m_approve');
+ }
+
+ /**
+ * Find the users who want to receive notifications
+ *
+ * @param array $post Data from
+ *
+ * @return array
+ */
+ public function find_users_for_notification($post, $options = array())
+ {
+ $options = array_merge(array(
+ 'ignore_users' => array(),
+ ), $options);
+
+ $users = array();
+ $users[$post['poster_id']] = array('');
+
+ $auth_read = $this->auth->acl_get_list(array_keys($users), 'f_read', $post['forum_id']);
+
+ if (empty($auth_read))
+ {
+ return array();
+ }
+
+ $notify_users = array();
+
+ $sql = 'SELECT *
+ FROM ' . USER_NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::$notification_option['id'] . "'
+ AND " . $this->db->sql_in_set('user_id', $auth_read[$post['forum_id']]['f_read']);
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']]))
+ {
+ continue;
+ }
+
+ if (!isset($rowset[$row['user_id']]))
+ {
+ $notify_users[$row['user_id']] = array();
+ }
+
+ $notify_users[$row['user_id']][] = $row['method'];
+ }
+ $this->db->sql_freeresult($result);
+
+ return $notify_users;
+ }
+
+ /**
+ * Pre create insert array function
+ * This allows you to perform certain actions, like run a query
+ * and load data, before create_insert_array() is run. The data
+ * returned from this function will be sent to create_insert_array().
+ *
+ * @param array $post Post data from submit_post
+ * @param array $notify_users Notify users list
+ * Formated from find_users_for_notification()
+ * @return array Whatever you want to send to create_insert_array().
+ */
+ public function pre_create_insert_array($post, $notify_users)
+ {
+ /*if (!sizeof($notify_users))
+ {
+ return array();
+ }
+
+ // Mark the topic unread
+ $sql = 'DELETE FROM ' . TOPICS_TRACK_TABLE . '
+ WHERE topic_id = ' . (int) $post['topic_id'] . '
+ AND ' . $this->db->sql_in_set('user_id', array_keys($notify_users));
+ $this->db->sql_query($sql*/
+
+ // In the parent class, this is used to check if the post is already
+ // read by a user and marks the notification read if it was marked read.
+ // Returning an empty array in effect, forces it to be marked as unread
+ return array();
+ }
+
+ /**
+ * Function for preparing the data for insertion in an SQL query
+ * (The service handles insertion)
+ *
+ * @param array $post Data from submit_post
+ * @param array $pre_create_data Data from pre_create_insert_array()
+ *
+ * @return array Array of data ready to be inserted into the database
+ */
+ public function create_insert_array($post, $pre_create_data = array())
+ {
+ $data = parent::create_insert_array($post, $pre_create_data);
+
+ $this->time = $data['time'] = time();
+
+ return $data;
+ }
+}
diff --git a/phpBB/includes/notification/type/base.php b/phpBB/includes/notification/type/base.php
new file mode 100644
index 0000000000..afd6a9fc9b
--- /dev/null
+++ b/phpBB/includes/notification/type/base.php
@@ -0,0 +1,382 @@
+<?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_notification_type_base implements phpbb_notification_type_interface
+{
+ protected $notification_manager, $db, $cache, $template, $extension_manager, $user, $auth, $config, $phpbb_root_path, $php_ext = null;
+
+ /**
+ * Array of user data containing information needed to output the notifications to the template
+ *
+ * @var array
+ */
+ protected $users = array();
+
+ /**
+ * Notification option data (for outputting to the user)
+ *
+ * @var bool|array False if the service should use its default data
+ * Array of data (including keys 'id', 'lang', and 'group')
+ */
+ public static $notification_option = false;
+
+ /**
+ * Indentification data
+ * item_type
+ * item_id
+ * item_parent_id - Parent item id (ex: for topic => forum_id, for post => topic_id, etc)
+ * user_id
+ * unread
+ * is_disabled - EXTENSION AUTHORS TAKE NOTE! This is to prevent errors with notifications from extensions!
+ * - Set is_disabled to 1 for all your notifications when your extension is disabled so they are ignored and do not cause errors.
+ * - When your extension is enabled again, set is_disabled to 0 and your notifications will be working again.
+ *
+ * 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(phpbb_notification_manager $notification_manager, dbal $db, phpbb_cache_driver_interface $cache, phpbb_template $template, phpbb_extension_manager $extension_manager, $user, phpbb_auth $auth, phpbb_config $config, $phpbb_root_path, $php_ext)
+ {
+ $this->notification_manager = $notification_manager;
+ $this->db = $db;
+ $this->cache = $cache;
+ $this->template = $template;
+ $this->extension_manager = $extension_manager;
+ $this->user = $user;
+ $this->auth = $auth;
+ $this->config = $config;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * Set initial data from the database
+ *
+ * @param array $data Row directly from the database
+ */
+ public function set_initial_data($data = array())
+ {
+ // 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 (!isset($this->data[$name])) ? null : $this->data[$name];
+ }
+
+ public function __set($name, $value)
+ {
+ $this->data[$name] = $value;
+ }
+
+ public function __toString()
+ {
+ return (!empty($this->data)) ? var_export($this->data, true) : static::get_item_type();
+ }
+
+ /**
+ * 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 ($name === false) ? $this->data['data'] : ((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;
+ }
+
+ /**
+ * Prepare to output the notification to the template
+ */
+ public function prepare_for_display()
+ {
+ if ($this->get_url())
+ {
+ $u_mark_read = append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id);
+ }
+ else
+ {
+ $redirect = (($this->user->page['page_dir']) ? $this->user->page['page_dir'] . '/' : '') . $this->user->page['page_name'] . (($this->user->page['query_string']) ? '?' . $this->user->page['query_string'] : '');
+
+ $u_mark_read = append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id . '&amp;redirect=' . urlencode($redirect));
+ }
+
+ return array(
+ 'NOTIFICATION_ID' => $this->notification_id,
+
+ 'AVATAR' => $this->get_avatar(),
+
+ 'FORMATTED_TITLE' => $this->get_title(),
+
+ 'URL' => $this->get_url(),
+ 'TIME' => $this->user->format_date($this->time),
+
+ 'UNREAD' => $this->unread,
+
+ 'U_MARK_READ' => ($this->unread) ? $u_mark_read : '',
+ );
+ }
+
+ /**
+ * Mark this item read
+ *
+ * @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False)
+ * @return string
+ */
+ public function mark_read($return = false)
+ {
+ return $this->mark(false, $return);
+ }
+
+ /**
+ * Mark this item unread
+ *
+ * @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False)
+ * @return string
+ */
+ public function mark_unread($return = false)
+ {
+ return $this->mark(true, $return);
+ }
+
+ /**
+ * 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
+ * @param array $pre_create_data Data from pre_create_insert_array()
+ *
+ * @return array Array of data ready to be inserted into the database
+ */
+ public function create_insert_array($type_data, $pre_create_data = array())
+ {
+ // Defaults
+ $this->data = array_merge(array(
+ 'item_id' => static::get_item_id($type_data),
+ 'item_type' => $this->get_item_type(),
+ 'item_parent_id' => static::get_item_parent_id($type_data),
+
+ 'time' => time(),
+ 'unread' => true,
+
+ 'data' => array(),
+ ), $this->data);
+
+ $data = $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['time'], // Also unsetting time, since it always tries to change the time to current (if you actually need to change the time, over-ride this function)
+ $data['notification_id'],
+ $data['unread'],
+ $data['user_id']
+ );
+
+ return $data;
+ }
+
+ /**
+ * -------------- Fall back functions -------------------
+ */
+
+ /**
+ * 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
+ */
+ public function get_unsubscribe_url($method = false)
+ {
+ return false;
+ }
+
+ /**
+ * Get the user's avatar (fall-back)
+ */
+ public function get_avatar()
+ {
+ return '';
+ }
+
+ /**
+ * Get the special items to load (fall-back)
+ */
+ public function get_load_special()
+ {
+ return array();
+ }
+
+ /**
+ * Load the special items (fall-back)
+ */
+ public function load_special($data, $notifications)
+ {
+ return;
+ }
+
+ /**
+ * Is available (fall-back)
+ */
+ public function is_available()
+ {
+ return true;
+ }
+
+ /**
+ * Pre create insert array function
+ * This allows you to perform certain actions, like run a query
+ * and load data, before create_insert_array() is run. The data
+ * returned from this function will be sent to create_insert_array().
+ *
+ * @param array $type_data Data unique to this notification type
+ * @param array $notify_users Notify users list
+ * Formated from find_users_for_notification()
+ * @return array Whatever you want to send to create_insert_array().
+ */
+ public function pre_create_insert_array($type_data, $notify_users)
+ {
+ return array();
+ }
+
+ /**
+ * -------------- Helper functions -------------------
+ */
+
+ /**
+ * Find the users who want to receive notifications (helper)
+ *
+ * @param array $item_id The item_id to search for
+ *
+ * @return array
+ */
+ protected function _find_users_for_notification($item_id, $options)
+ {
+ $options = array_merge(array(
+ 'ignore_users' => array(),
+ ), $options);
+
+ $rowset = array();
+
+ $sql = 'SELECT *
+ FROM ' . USER_NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . static::get_item_type() . "'
+ AND item_id = " . (int) $item_id;
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']]))
+ {
+ continue;
+ }
+
+ if (!isset($rowset[$row['user_id']]))
+ {
+ $rowset[$row['user_id']] = array();
+ }
+
+ $rowset[$row['user_id']][] = $row['method'];
+ }
+ $this->db->sql_freeresult($result);
+
+ return $rowset;
+ }
+
+ /**
+ * Get avatar helper
+ *
+ * @param int $user_id
+ * @return string
+ */
+ protected function _get_avatar($user_id)
+ {
+ $user = $this->notification_manager->get_user($user_id);
+
+ if (!function_exists('get_user_avatar'))
+ {
+ include($this->phpbb_root_path . 'includes/functions_display.' . $this->php_ext);
+ }
+
+ return get_user_avatar($user['user_avatar'], $user['user_avatar_type'], $user['user_avatar_width'], $user['user_avatar_height'], $user['username'], false, 'notifications-avatar');
+ }
+
+ /**
+ * Mark this item read/unread helper
+ *
+ * @param bool $unread Unread (True/False) (Default: False)
+ * @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False)
+ * @return string
+ */
+ protected function mark($unread = true, $return = false)
+ {
+ $this->unread = (bool) $unread;
+
+ $where = array(
+ "item_type = '" . $this->db->sql_escape($this->item_type) . "'",
+ 'item_id = ' . (int) $this->item_id,
+ 'user_id = ' . (int) $this->user_id,
+ );
+ $where = implode(' AND ', $where);
+
+ if ($return)
+ {
+ return $where;
+ }
+
+ $sql = 'UPDATE ' . NOTIFICATIONS_TABLE . '
+ SET unread = ' . (int) $this->unread . '
+ WHERE ' . $where;
+ $this->db->sql_query($sql);
+ }
+}
diff --git a/phpBB/includes/notification/type/bookmark.php b/phpBB/includes/notification/type/bookmark.php
new file mode 100644
index 0000000000..e5435b5829
--- /dev/null
+++ b/phpBB/includes/notification/type/bookmark.php
@@ -0,0 +1,134 @@
+<?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;
+}
+
+/**
+* Bookmark updating notifications class
+* This class handles notifications for replies to a bookmarked topic
+*
+* @package notifications
+*/
+class phpbb_notification_type_bookmark extends phpbb_notification_type_post
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = 'notifications/bookmark';
+
+ /**
+ * Language key used to output the text
+ *
+ * @var string
+ */
+ protected $language_key = 'NOTIFICATION_BOOKMARK';
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_type_
+ */
+ public static function get_item_type()
+ {
+ return 'bookmark';
+ }
+
+ /**
+ * Find the users who want to receive notifications
+ *
+ * @param array $post Data from
+ *
+ * @return array
+ */
+ public function find_users_for_notification($post, $options = array())
+ {
+ $options = array_merge(array(
+ 'ignore_users' => array(),
+ ), $options);
+
+ $users = array();
+
+ $sql = 'SELECT user_id
+ FROM ' . BOOKMARKS_TABLE . '
+ WHERE ' . $this->db->sql_in_set('topic_id', $post['topic_id']) . '
+ AND user_id <> ' . (int) $post['poster_id'];
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $users[] = $row['user_id'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($users))
+ {
+ return array();
+ }
+
+ $auth_read = $this->auth->acl_get_list($users, 'f_read', $post['forum_id']);
+
+ if (empty($auth_read))
+ {
+ return array();
+ }
+
+ $notify_users = array();
+
+ $sql = 'SELECT *
+ FROM ' . USER_NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::get_item_type() . "'
+ AND " . $this->db->sql_in_set('user_id', $auth_read[$post['forum_id']]['f_read']);
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']]))
+ {
+ continue;
+ }
+
+ if (!isset($rowset[$row['user_id']]))
+ {
+ $notify_users[$row['user_id']] = array();
+ }
+
+ $notify_users[$row['user_id']][] = $row['method'];
+ }
+ $this->db->sql_freeresult($result);
+
+ // Try to find the users who already have been notified about replies and have not read the topic since and just update their notifications
+ $update_notifications = array();
+ $sql = 'SELECT *
+ FROM ' . NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::get_item_type() . "'
+ AND item_parent_id = " . (int) self::get_item_parent_id($post) . '
+ AND unread = 1
+ AND is_disabled = 0';
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ // Do not create a new notification
+ unset($notify_users[$row['user_id']]);
+
+ $notification = $this->notification_manager->get_item_type_class(self::get_item_type(), $row);
+ $sql = 'UPDATE ' . NOTIFICATIONS_TABLE . '
+ SET ' . $this->db->sql_build_array('UPDATE', $notification->add_responders($post)) . '
+ WHERE notification_id = ' . $row['notification_id'];
+ $this->db->sql_query($sql);
+ }
+ $this->db->sql_freeresult($result);
+
+ return $notify_users;
+ }
+}
diff --git a/phpBB/includes/notification/type/disapprove_post.php b/phpBB/includes/notification/type/disapprove_post.php
new file mode 100644
index 0000000000..8044a3e0ea
--- /dev/null
+++ b/phpBB/includes/notification/type/disapprove_post.php
@@ -0,0 +1,116 @@
+<?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
+* This class handles notifications for replies to a topic
+*
+* @package notifications
+*/
+class phpbb_notification_type_disapprove_post extends phpbb_notification_type_approve_post
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = 'post_disapproved';
+
+ /**
+ * Language key used to output the text
+ *
+ * @var string
+ */
+ protected $language_key = 'NOTIFICATION_POST_DISAPPROVED';
+
+ /**
+ * Notification option data (for outputting to the user)
+ *
+ * @var bool|array False if the service should use it's default data
+ * Array of data (including keys 'id', 'lang', and 'group')
+ */
+ public static $notification_option = array(
+ 'id' => 'moderation_queue',
+ 'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE',
+ 'group' => 'NOTIFICATION_GROUP_POSTING',
+ );
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_type_
+ */
+ public static function get_item_type()
+ {
+ return 'disapprove_post';
+ }
+
+ /**
+ * Get the HTML formatted title of this notification
+ *
+ * @return string
+ */
+ public function get_title()
+ {
+ return $this->user->lang(
+ $this->language_key,
+ censor_text($this->get_data('topic_title')),
+ $this->get_data('disapprove_reason')
+ );
+ }
+
+ /**
+ * Get the url to this item
+ *
+ * @return string URL
+ */
+ public function get_url()
+ {
+ return '';
+ }
+
+ /**
+ * Get email template variables
+ *
+ * @return array
+ */
+ public function get_email_template_variables()
+ {
+ return array_merge(parent::get_email_template_variables(), array(
+ 'REASON' => htmlspecialchars_decode($this->get_data('disapprove_reason')),
+ ));
+ }
+
+ /**
+ * Function for preparing the data for insertion in an SQL query
+ * (The service handles insertion)
+ *
+ * @param array $post Data from submit_post
+ * @param array $pre_create_data Data from pre_create_insert_array()
+ *
+ * @return array Array of data ready to be inserted into the database
+ */
+ public function create_insert_array($post, $pre_create_data = array())
+ {
+ $this->set_data('disapprove_reason', $post['disapprove_reason']);
+
+ $data = parent::create_insert_array($post);
+
+ $this->time = $data['time'] = time();
+
+ return $data;
+ }
+}
diff --git a/phpBB/includes/notification/type/disapprove_topic.php b/phpBB/includes/notification/type/disapprove_topic.php
new file mode 100644
index 0000000000..04fec87014
--- /dev/null
+++ b/phpBB/includes/notification/type/disapprove_topic.php
@@ -0,0 +1,116 @@
+<?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
+* This class handles notifications for replies to a topic
+*
+* @package notifications
+*/
+class phpbb_notification_type_disapprove_topic extends phpbb_notification_type_approve_topic
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = 'topic_disapproved';
+
+ /**
+ * Language key used to output the text
+ *
+ * @var string
+ */
+ protected $language_key = 'NOTIFICATION_TOPIC_DISAPPROVED';
+
+ /**
+ * Notification option data (for outputting to the user)
+ *
+ * @var bool|array False if the service should use it's default data
+ * Array of data (including keys 'id', 'lang', and 'group')
+ */
+ public static $notification_option = array(
+ 'id' => 'moderation_queue',
+ 'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE',
+ 'group' => 'NOTIFICATION_GROUP_POSTING',
+ );
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_type_
+ */
+ public static function get_item_type()
+ {
+ return 'disapprove_topic';
+ }
+
+ /**
+ * Get the HTML formatted title of this notification
+ *
+ * @return string
+ */
+ public function get_title()
+ {
+ return $this->user->lang(
+ $this->language_key,
+ censor_text($this->get_data('topic_title')),
+ $this->get_data('disapprove_reason')
+ );
+ }
+
+ /**
+ * Get the url to this item
+ *
+ * @return string URL
+ */
+ public function get_url()
+ {
+ return '';
+ }
+
+ /**
+ * Get email template variables
+ *
+ * @return array
+ */
+ public function get_email_template_variables()
+ {
+ return array_merge(parent::get_email_template_variables(), array(
+ 'REASON' => htmlspecialchars_decode($this->get_data('disapprove_reason')),
+ ));
+ }
+
+ /**
+ * Function for preparing the data for insertion in an SQL query
+ * (The service handles insertion)
+ *
+ * @param array $post Data from submit_post
+ * @param array $pre_create_data Data from pre_create_insert_array()
+ *
+ * @return array Array of data ready to be inserted into the database
+ */
+ public function create_insert_array($post, $pre_create_data = array())
+ {
+ $this->set_data('disapprove_reason', $post['disapprove_reason']);
+
+ $data = parent::create_insert_array($post, $pre_create_data);
+
+ $this->time = $data['time'] = time();
+
+ return $data;
+ }
+}
diff --git a/phpBB/includes/notification/type/interface.php b/phpBB/includes/notification/type/interface.php
new file mode 100644
index 0000000000..084a819af7
--- /dev/null
+++ b/phpBB/includes/notification/type/interface.php
@@ -0,0 +1,53 @@
+<?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_notification_type_interface
+{
+ public static function get_item_type();
+
+ public static function get_item_id($type_data);
+
+ public function is_available();
+
+ public function find_users_for_notification($type_data, $options);
+
+ public function get_title();
+
+ public function get_email_template_variables();
+
+ public function get_url();
+
+ public function get_unsubscribe_url($method);
+
+ public function mark_read($return);
+
+ public function mark_unread($return);
+
+ public function pre_create_insert_array($type_data, $notify_users);
+
+ public function create_insert_array($type_data, $pre_create_data);
+
+ public function users_to_query();
+
+ public function get_load_special();
+
+ public function load_special($data, $notifications);
+}
diff --git a/phpBB/includes/notification/type/pm.php b/phpBB/includes/notification/type/pm.php
new file mode 100644
index 0000000000..dc4bd3b3a5
--- /dev/null
+++ b/phpBB/includes/notification/type/pm.php
@@ -0,0 +1,186 @@
+<?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;
+}
+
+/**
+* Private message notifications class
+* This class handles notifications for private messages
+*
+* @package notifications
+*/
+class phpbb_notification_type_pm extends phpbb_notification_type_base
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = 'privmsg_notify';
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_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 (int) $pm['msg_id'];
+ }
+
+ /**
+ * Get the id of the parent
+ *
+ * @param array $pm The data from the pm
+ */
+ public static function get_item_parent_id($pm)
+ {
+ // No parent
+ return 0;
+ }
+
+ /**
+ * Find the users who want to receive notifications
+ *
+ * @param array $pm Data from
+ *
+ * @return array
+ */
+ public function find_users_for_notification($pm, $options = array())
+ {
+ $options = array_merge(array(
+ 'ignore_users' => array(),
+ ), $options);
+
+ if (!sizeof($pm['recipients']))
+ {
+ return array();
+ }
+
+ $this->notification_manager->load_users(array_keys($pm['recipients']));
+
+ $notify_users = array();
+
+ $sql = 'SELECT *
+ FROM ' . USER_NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::get_item_type() . "'
+ AND " . $this->db->sql_in_set('user_id', array_keys($pm['recipients'])) . '
+ AND user_id <> ' . $pm['from_user_id'];
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']]))
+ {
+ continue;
+ }
+
+ if (!isset($rowset[$row['user_id']]))
+ {
+ $notify_users[$row['user_id']] = array();
+ }
+
+ $notify_users[$row['user_id']][] = $row['method'];
+ }
+ $this->db->sql_freeresult($result);
+
+ 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
+ *
+ * @return string
+ */
+ public function get_title()
+ {
+ $user_data = $this->notification_manager->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 $this->user->lang('NOTIFICATION_PM', $username, $this->get_data('message_subject'));
+ }
+
+ /**
+ * Get email template variables
+ *
+ * @return array
+ */
+ public function get_email_template_variables()
+ {
+ $user_data = $this->notification_manager->get_user($this->get_data('from_user_id'));
+
+ return array(
+ 'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']),
+ 'SUBJECT' => htmlspecialchars_decode(censor_text($this->get_data('message_subject'))),
+
+ 'U_VIEW_MESSAGE' => generate_board_url() . '/ucp.' . $this->php_ext . "?i=pm&mode=view&p={$this->item_id}",
+ );
+ }
+
+ /**
+ * 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&amp;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['from_user_id']);
+ }
+
+ /**
+ * Function for preparing the data for insertion in an SQL query
+ * (The service handles insertion)
+ *
+ * @param array $post Data from submit_post
+ * @param array $pre_create_data Data from pre_create_insert_array()
+ *
+ * @return array Array of data ready to be inserted into the database
+ */
+ public function create_insert_array($pm, $pre_create_data = array())
+ {
+ $this->set_data('from_user_id', $pm['from_user_id']);
+
+ $this->set_data('message_subject', $pm['message_subject']);
+
+ return parent::create_insert_array($pm, $pre_create_data);
+ }
+}
diff --git a/phpBB/includes/notification/type/post.php b/phpBB/includes/notification/type/post.php
new file mode 100644
index 0000000000..0681b4418c
--- /dev/null
+++ b/phpBB/includes/notification/type/post.php
@@ -0,0 +1,385 @@
+<?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
+* This class handles notifications for replies to a topic
+*
+* @package notifications
+*/
+class phpbb_notification_type_post extends phpbb_notification_type_base
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = 'topic_notify';
+
+ /**
+ * Language key used to output the text
+ *
+ * @var string
+ */
+ protected $language_key = 'NOTIFICATION_POST';
+
+ /**
+ * Notification option data (for outputting to the user)
+ *
+ * @var bool|array False if the service should use it's default data
+ * Array of data (including keys 'id', 'lang', and 'group')
+ */
+ public static $notification_option = array(
+ 'group' => 'NOTIFICATION_GROUP_POSTING',
+ );
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_type_
+ */
+ public static function get_item_type()
+ {
+ return 'post';
+ }
+
+ /**
+ * Get the id of the item
+ *
+ * @param array $post The data from the post
+ */
+ public static function get_item_id($post)
+ {
+ return (int) $post['post_id'];
+ }
+
+ /**
+ * Get the id of the parent
+ *
+ * @param array $post The data from the post
+ */
+ public static function get_item_parent_id($post)
+ {
+ return (int) $post['topic_id'];
+ }
+
+ /**
+ * Find the users who want to receive notifications
+ *
+ * @param array $post Data from
+ *
+ * @return array
+ */
+ public function find_users_for_notification($post, $options = array())
+ {
+ $options = array_merge(array(
+ 'ignore_users' => array(),
+ ), $options);
+
+ // Let's continue to use the phpBB subscriptions system, at least for now.
+ // It may not be the nicest thing, but it is already working and it would be significant work to replace it
+ //$users = parent::_find_users_for_notification($phpbb_container, $post['topic_id']);
+
+ $users = array();
+
+ $sql = 'SELECT user_id
+ FROM ' . TOPICS_WATCH_TABLE . '
+ WHERE topic_id = ' . (int) $post['topic_id'] . '
+ AND notify_status = ' . NOTIFY_YES . '
+ AND user_id <> ' . (int) $post['poster_id'];
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $users[] = $row['user_id'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($users))
+ {
+ return array();
+ }
+
+ $auth_read = $this->auth->acl_get_list($users, 'f_read', $post['forum_id']);
+
+ if (empty($auth_read))
+ {
+ return array();
+ }
+
+ $notify_users = array();
+
+ $sql = 'SELECT *
+ FROM ' . USER_NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::get_item_type() . "'
+ AND " . $this->db->sql_in_set('user_id', $auth_read[$post['forum_id']]['f_read']);
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']]))
+ {
+ continue;
+ }
+
+ if (!isset($rowset[$row['user_id']]))
+ {
+ $notify_users[$row['user_id']] = array();
+ }
+
+ $notify_users[$row['user_id']][] = $row['method'];
+ }
+ $this->db->sql_freeresult($result);
+
+ // Try to find the users who already have been notified about replies and have not read the topic since and just update their notifications
+ $update_notifications = array();
+ $sql = 'SELECT *
+ FROM ' . NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::get_item_type() . "'
+ AND item_parent_id = " . (int) self::get_item_parent_id($post) . '
+ AND unread = 1
+ AND is_disabled = 0';
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ // Do not create a new notification
+ unset($notify_users[$row['user_id']]);
+
+ $notification = $this->notification_manager->get_item_type_class(self::get_item_type(), $row);
+ $sql = 'UPDATE ' . NOTIFICATIONS_TABLE . '
+ SET ' . $this->db->sql_build_array('UPDATE', $notification->add_responders($post)) . '
+ WHERE notification_id = ' . $row['notification_id'];
+ $this->db->sql_query($sql);
+ }
+ $this->db->sql_freeresult($result);
+
+ 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
+ *
+ * @return string
+ */
+ public function get_title()
+ {
+ $responders = $this->get_data('responders');
+ $usernames = array();
+
+ if (!is_array($responders))
+ {
+ $responders = array();
+ }
+
+ $responders = array_merge(array(array(
+ 'poster_id' => $this->get_data('poster_id'),
+ 'username' => $this->get_data('post_username'),
+ )), $responders);
+
+ foreach ($responders as $responder)
+ {
+ if ($responder['username'])
+ {
+ $usernames[] = $responder['username'];
+ }
+ else
+ {
+ $user_data = $this->notification_manager->get_user($responder['poster_id']);
+
+ $usernames[] = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']);
+ }
+ }
+
+ return $this->user->lang(
+ $this->language_key,
+ implode(', ', $usernames),
+ censor_text($this->get_data('topic_title'))
+ );
+ }
+
+ /**
+ * Get email template variables
+ *
+ * @return array
+ */
+ public function get_email_template_variables()
+ {
+ if ($this->get_data('post_username'))
+ {
+ $username = $this->get_data('post_username');
+ }
+ else
+ {
+ $user_data = $this->notification_manager->get_user($this->get_data('poster_id'));
+
+ $username = get_username_string('username', $user_data['user_id'], $user_data['username'], $user_data['user_colour']);
+ }
+
+ return array(
+ 'AUTHOR_NAME' => htmlspecialchars_decode($username),
+ 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($this->get_data('post_subject'))),
+ 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($this->get_data('topic_title'))),
+
+ 'U_VIEW_POST' => generate_board_url() . "/viewtopic.{$this->php_ext}?p={$this->item_id}#p{$this->item_id}",
+ 'U_NEWEST_POST' => generate_board_url() . "/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}&view=unread#unread",
+ 'U_TOPIC' => generate_board_url() . "/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}",
+ 'U_VIEW_TOPIC' => generate_board_url() . "/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}",
+ 'U_FORUM' => generate_board_url() . "/viewforum.{$this->php_ext}?f={$this->get_data('forum_id')}",
+ 'U_STOP_WATCHING_TOPIC' => generate_board_url() . "/viewtopic.{$this->php_ext}?uid={$this->user_id}&f={$this->get_data('forum_id')}&t={$this->item_parent_id}&unwatch=topic",
+ );
+ }
+
+ /**
+ * 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()
+ {
+ $responders = $this->get_data('responders');
+ $users = array(
+ $this->get_data('poster_id'),
+ );
+
+ if (is_array($responders))
+ {
+ foreach ($responders as $responder)
+ {
+ $users[] = $responder['poster_id'];
+ }
+ }
+
+ return $users;
+ }
+
+ /**
+ * Pre create insert array function
+ * This allows you to perform certain actions, like run a query
+ * and load data, before create_insert_array() is run. The data
+ * returned from this function will be sent to create_insert_array().
+ *
+ * @param array $post Post data from submit_post
+ * @param array $notify_users Notify users list
+ * Formated from find_users_for_notification()
+ * @return array Whatever you want to send to create_insert_array().
+ */
+ public function pre_create_insert_array($post, $notify_users)
+ {
+ if (!sizeof($notify_users))
+ {
+ return array();
+ }
+
+ $tracking_data = array();
+ $sql = 'SELECT user_id, mark_time FROM ' . TOPICS_TRACK_TABLE . '
+ WHERE topic_id = ' . (int) $post['topic_id'] . '
+ AND ' . $this->db->sql_in_set('user_id', array_keys($notify_users));
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $tracking_data[$row['user_id']] = $row['mark_time'];
+ }
+
+ return $tracking_data;
+ }
+
+ /**
+ * Function for preparing the data for insertion in an SQL query
+ * (The service handles insertion)
+ *
+ * @param array $post Data from submit_post
+ * @param array $pre_create_data Data from pre_create_insert_array()
+ *
+ * @return array Array of data ready to be inserted into the database
+ */
+ public function create_insert_array($post, $pre_create_data = array())
+ {
+ $this->set_data('poster_id', $post['poster_id']);
+
+ $this->set_data('topic_title', $post['topic_title']);
+
+ $this->set_data('post_subject', $post['post_subject']);
+
+ $this->set_data('post_username', (($post['poster_id'] == ANONYMOUS) ? $post['post_username'] : ''));
+
+ $this->set_data('forum_id', $post['forum_id']);
+
+ $this->set_data('forum_name', $post['forum_name']);
+
+ $this->time = $post['post_time'];
+
+ // Topics can be "read" before they are public (while awaiting approval).
+ // Make sure that if the user has read the topic, it's marked as read in the notification
+ if (isset($pre_create_data[$this->user_id]) && $pre_create_data[$this->user_id] >= $this->time)
+ {
+ $this->unread = false;
+ }
+
+ return parent::create_insert_array($post, $pre_create_data);
+ }
+
+ /**
+ * Add responders to the notification
+ *
+ * @param mixed $post
+ */
+ public function add_responders($post)
+ {
+ // Do not add them as a responder if they were the original poster that created the notification
+ if ($this->get_data('poster_id') == $post['poster_id'])
+ {
+ return array('data' => serialize($this->get_data(false)));
+ }
+
+ $responders = $this->get_data('responders');
+
+ $responders = ($responders === null) ? array() : $responders;
+
+ foreach ($responders as $responder)
+ {
+ // Do not add them as a responder multiple times
+ if ($responder['poster_id'] == $post['poster_id'])
+ {
+ return array('data' => serialize($this->get_data(false)));
+ }
+ }
+
+ $responders[] = array(
+ 'poster_id' => $post['poster_id'],
+ 'username' => (($post['poster_id'] == ANONYMOUS) ? $post['post_username'] : ''),
+ );
+
+ $this->set_data('responders', $responders);
+
+ return array('data' => serialize($this->get_data(false)));
+ }
+}
diff --git a/phpBB/includes/notification/type/post_in_queue.php b/phpBB/includes/notification/type/post_in_queue.php
new file mode 100644
index 0000000000..499fd1e8ed
--- /dev/null
+++ b/phpBB/includes/notification/type/post_in_queue.php
@@ -0,0 +1,154 @@
+<?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;
+}
+
+/**
+* Topic notifications class
+* This class handles notifications for new topics
+*
+* @package notifications
+*/
+class phpbb_notification_type_post_in_queue extends phpbb_notification_type_post
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = 'notifications/post_in_queue';
+
+ /**
+ * Language key used to output the text
+ *
+ * @var string
+ */
+ protected $language_key = 'NOTIFICATION_POST_IN_QUEUE';
+
+ /**
+ * Notification option data (for outputting to the user)
+ *
+ * @var bool|array False if the service should use it's default data
+ * Array of data (including keys 'id', 'lang', and 'group')
+ */
+ public static $notification_option = array(
+ 'id' => 'needs_approval',
+ 'lang' => 'NOTIFICATION_TYPE_IN_MODERATION_QUEUE',
+ 'group' => 'NOTIFICATION_GROUP_MODERATION',
+ );
+
+ /**
+ * Permission to check for (in find_users_for_notification)
+ *
+ * @var string Permission name
+ */
+ protected $permission = 'm_approve';
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_type_
+ */
+ public static function get_item_type()
+ {
+ return 'post_in_queue';
+ }
+
+ /**
+ * Is available
+ */
+ public function is_available()
+ {
+ $m_approve = $this->auth->acl_getf($this->permission, true);
+
+ return (!empty($m_approve));
+ }
+
+ /**
+ * Find the users who want to receive notifications
+ *
+ * @param array $post Data from the post
+ *
+ * @return array
+ */
+ public function find_users_for_notification($post, $options = array())
+ {
+ $options = array_merge(array(
+ 'ignore_users' => array(),
+ ), $options);
+
+ // 0 is for global
+ $auth_approve = $this->auth->acl_get_list(false, $this->permission, array($post['forum_id'], 0));
+
+ if (empty($auth_approve))
+ {
+ return array();
+ }
+
+ $auth_approve[$post['forum_id']] = array_unique(array_merge($auth_approve[$post['forum_id']], $auth_approve[0]));
+
+ $notify_users = array();
+
+ $sql = 'SELECT *
+ FROM ' . USER_NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::$notification_option['id'] . "'
+ AND " . $this->db->sql_in_set('user_id', $auth_approve[$post['forum_id']][$this->permission]);
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']]))
+ {
+ continue;
+ }
+
+ if (!isset($rowset[$row['user_id']]))
+ {
+ $notify_users[$row['user_id']] = array();
+ }
+
+ $notify_users[$row['user_id']][] = $row['method'];
+ }
+ $this->db->sql_freeresult($result);
+
+ return $notify_users;
+ }
+
+ /**
+ * Get the url to this item
+ *
+ * @return string URL
+ */
+ public function get_url()
+ {
+ return append_sid($this->phpbb_root_path . 'mcp.' . $this->php_ext, "i=queue&amp;mode=approve_details&amp;f={$this->get_data('forum_id')}&amp;p={$this->item_id}");
+ }
+
+ /**
+ * Function for preparing the data for insertion in an SQL query
+ * (The service handles insertion)
+ *
+ * @param array $post Data from submit_post
+ * @param array $pre_create_data Data from pre_create_insert_array()
+ *
+ * @return array Array of data ready to be inserted into the database
+ */
+ public function create_insert_array($post, $pre_create_data = array())
+ {
+ $data = parent::create_insert_array($post, $pre_create_data);
+
+ $this->time = $data['time'] = time();
+
+ return $data;
+ }
+}
diff --git a/phpBB/includes/notification/type/quote.php b/phpBB/includes/notification/type/quote.php
new file mode 100644
index 0000000000..0cc183346f
--- /dev/null
+++ b/phpBB/includes/notification/type/quote.php
@@ -0,0 +1,217 @@
+<?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 quoting notifications class
+* This class handles notifications for quoting users in a post
+*
+* @package notifications
+*/
+class phpbb_notification_type_quote extends phpbb_notification_type_post
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = 'notifications/quote';
+
+ /**
+ * regular expression to match to find usernames
+ *
+ * @var string
+ */
+ protected static $regular_expression_match = '#\[quote=&quot;(.+?)&quot;#';
+
+ /**
+ * Language key used to output the text
+ *
+ * @var string
+ */
+ protected $language_key = 'NOTIFICATION_QUOTE';
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_type_
+ */
+ public static function get_item_type()
+ {
+ return 'quote';
+ }
+
+ /**
+ * Find the users who want to receive notifications
+ *
+ * @param array $post Data from
+ *
+ * @return array
+ */
+ public function find_users_for_notification($post, $options = array())
+ {
+ $options = array_merge(array(
+ 'ignore_users' => array(),
+ ), $options);
+
+ $usernames = false;
+ preg_match_all(self::$regular_expression_match, $post['post_text'], $usernames);
+
+ if (empty($usernames[1]))
+ {
+ return array();
+ }
+
+ $usernames[1] = array_unique($usernames[1]);
+
+ $usernames = array_map('utf8_clean_string', $usernames[1]);
+
+ $users = array();
+
+ $sql = 'SELECT user_id
+ FROM ' . USERS_TABLE . '
+ WHERE ' . $this->db->sql_in_set('username_clean', $usernames) . '
+ AND user_id <> ' . (int) $post['poster_id'];
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $users[] = $row['user_id'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($users))
+ {
+ return array();
+ }
+
+ $auth_read = $this->auth->acl_get_list($users, 'f_read', $post['forum_id']);
+
+ if (empty($auth_read))
+ {
+ return array();
+ }
+
+ $notify_users = array();
+
+ $sql = 'SELECT *
+ FROM ' . USER_NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::get_item_type() . "'
+ AND " . $this->db->sql_in_set('user_id', $auth_read[$post['forum_id']]['f_read']);
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']]))
+ {
+ continue;
+ }
+
+ if (!isset($rowset[$row['user_id']]))
+ {
+ $notify_users[$row['user_id']] = array();
+ }
+
+ $notify_users[$row['user_id']][] = $row['method'];
+ }
+ $this->db->sql_freeresult($result);
+
+ // Try to find the users who already have been notified about replies and have not read the topic since and just update their notifications
+ $update_notifications = array();
+ $sql = 'SELECT *
+ FROM ' . NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::get_item_type() . "'
+ AND item_parent_id = " . (int) self::get_item_parent_id($post) . '
+ AND unread = 1
+ AND is_disabled = 0';
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ // Do not create a new notification
+ unset($notify_users[$row['user_id']]);
+
+ $notification = $this->notification_manager->get_item_type_class(self::get_item_type(), $row);
+ $sql = 'UPDATE ' . NOTIFICATIONS_TABLE . '
+ SET ' . $this->db->sql_build_array('UPDATE', $notification->add_responders($post)) . '
+ WHERE notification_id = ' . $row['notification_id'];
+ $this->db->sql_query($sql);
+ }
+ $this->db->sql_freeresult($result);
+
+ return $notify_users;
+ }
+
+ /**
+ * Update a notification
+ *
+ * @param array $data Data specific for this type that will be updated
+ */
+ public function update_notifications($post)
+ {
+ $old_notifications = array();
+ $sql = 'SELECT user_id
+ FROM ' . NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::get_item_type() . "'
+ AND item_id = " . self::get_item_id($post) . '
+ AND is_disabled = 0';
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $old_notifications[] = $row['user_id'];
+ }
+ $this->db->sql_freeresult($result);
+
+ // Find the new users to notify
+ $notifications = $this->find_users_for_notification($post);
+
+ // Find the notifications we must delete
+ $remove_notifications = array_diff($old_notifications, array_keys($notifications));
+
+ // Find the notifications we must add
+ $add_notifications = array();
+ foreach (array_diff(array_keys($notifications), $old_notifications) as $user_id)
+ {
+ $add_notifications[$user_id] = $notifications[$user_id];
+ }
+
+ // Add the necessary notifications
+ $this->notification_manager->add_notifications_for_users(self::get_item_type(), $post, $add_notifications);
+
+ // Remove the necessary notifications
+ if (!empty($remove_notifications))
+ {
+ $sql = 'DELETE FROM ' . NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::get_item_type() . "'
+ AND item_id = " . self::get_item_id($post) . '
+ AND ' . $this->db->sql_in_set('user_id', $remove_notifications);
+ $this->db->sql_query($sql);
+ }
+
+ // return true to continue with the update code in the notifications service (this will update the rest of the notifications)
+ return true;
+ }
+
+ /**
+ * Get email template variables
+ *
+ * @return array
+ */
+ public function get_email_template_variables()
+ {
+ $user_data = $this->notification_manager->get_user($this->get_data('poster_id'));
+
+ return array_merge(parent::get_email_template_variables(), array(
+ 'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']),
+ ));
+ }
+}
diff --git a/phpBB/includes/notification/type/report_pm.php b/phpBB/includes/notification/type/report_pm.php
new file mode 100644
index 0000000000..3327dbe734
--- /dev/null
+++ b/phpBB/includes/notification/type/report_pm.php
@@ -0,0 +1,242 @@
+<?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;
+}
+
+/**
+* Private message notifications class
+* This class handles notifications for reporting private messages
+*
+* @package notifications
+*/
+class phpbb_notification_type_report_pm extends phpbb_notification_type_pm
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = 'notifications/report_pm';
+
+ /**
+ * Language key used to output the text
+ *
+ * @var string
+ */
+ protected $language_key = 'NOTIFICATION_REPORT_PM';
+
+ /**
+ * Permission to check for (in find_users_for_notification)
+ *
+ * @var string Permission name
+ */
+ protected $permission = 'm_report';
+
+ /**
+ * Notification option data (for outputting to the user)
+ *
+ * @var bool|array False if the service should use it's default data
+ * Array of data (including keys 'id', 'lang', and 'group')
+ */
+ public static $notification_option = array(
+ 'id' => 'report',
+ 'lang' => 'NOTIFICATION_TYPE_REPORT',
+ 'group' => 'NOTIFICATION_GROUP_MODERATION',
+ );
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_type_
+ */
+ public static function get_item_type()
+ {
+ return 'report_pm';
+ }
+
+ /**
+ * Get the id of the parent
+ *
+ * @param array $pm The data from the pm
+ */
+ public static function get_item_parent_id($pm)
+ {
+ return (int) $pm['report_id'];
+ }
+
+ /**
+ * Is available
+ */
+ public function is_available()
+ {
+ $m_approve = $this->auth->acl_getf($this->permission, true);
+
+ return (!empty($m_approve));
+ }
+
+
+ /**
+ * Find the users who want to receive notifications
+ * (copied from post_in_queue)
+ *
+ * @param array $post Data from the post
+ *
+ * @return array
+ */
+ public function find_users_for_notification($post, $options = array())
+ {
+ $options = array_merge(array(
+ 'ignore_users' => array(),
+ ), $options);
+
+ // Global
+ $post['forum_id'] = 0;
+
+ $auth_approve = $this->auth->acl_get_list(false, $this->permission, $post['forum_id']);
+
+ if (empty($auth_approve))
+ {
+ return array();
+ }
+
+ $notify_users = array();
+
+ $sql = 'SELECT *
+ FROM ' . USER_NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::$notification_option['id'] . "'
+ AND " . $this->db->sql_in_set('user_id', $auth_approve[$post['forum_id']][$this->permission]) . '
+ AND user_id <> ' . $this->user->data['user_id'];
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']]))
+ {
+ continue;
+ }
+
+ if (!isset($rowset[$row['user_id']]))
+ {
+ $notify_users[$row['user_id']] = array();
+ }
+
+ $notify_users[$row['user_id']][] = $row['method'];
+ }
+ $this->db->sql_freeresult($result);
+
+ return $notify_users;
+ }
+
+ /**
+ * Get email template variables
+ *
+ * @return array
+ */
+ public function get_email_template_variables()
+ {
+ return array(
+ 'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']),
+ 'SUBJECT' => htmlspecialchars_decode(censor_text($this->get_data('message_subject'))),
+
+ 'U_VIEW_REPORT' => generate_board_url() . "mcp.{$this->php_ext}?r={$this->item_parent_id}&amp;i=pm_reports&amp;mode=pm_report_details",
+ );
+ }
+
+ /**
+ * Get the url to this item
+ *
+ * @return string URL
+ */
+ public function get_url()
+ {
+ return append_sid($this->phpbb_root_path . 'mcp.' . $this->php_ext, "r={$this->item_parent_id}&amp;i=pm_reports&amp;mode=pm_report_details");
+ }
+
+ /**
+ * Get the HTML formatted title of this notification
+ *
+ * @return string
+ */
+ public function get_title()
+ {
+ $this->user->add_lang('mcp');
+
+ $user_data = $this->notification_manager->get_user($this->get_data('reporter_id'));
+
+ $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']);
+
+ if ($this->get_data('report_text'))
+ {
+ return $this->user->lang(
+ $this->language_key,
+ $username,
+ censor_text($this->get_data('message_subject')),
+ $this->get_data('report_text')
+ );
+ }
+
+ if (isset($this->user->lang[$this->get_data('reason_title')]))
+ {
+ return $this->user->lang(
+ $this->language_key,
+ $username,
+ censor_text($this->get_data('message_subject')),
+ $this->user->lang[$this->get_data('reason_title')]
+ );
+ }
+
+ return $this->user->lang(
+ $this->language_key,
+ $username,
+ censor_text($this->get_data('message_subject')),
+ $this->get_data('reason_description')
+ );
+ }
+
+ /**
+ * Get the user's avatar
+ */
+ public function get_avatar()
+ {
+ return $this->_get_avatar($this->get_data('reporter_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['reporter_id']);
+ }
+
+ /**
+ * Function for preparing the data for insertion in an SQL query
+ * (The service handles insertion)
+ *
+ * @param array $post Data from submit_post
+ * @param array $pre_create_data Data from pre_create_insert_array()
+ *
+ * @return array Array of data ready to be inserted into the database
+ */
+ public function create_insert_array($post, $pre_create_data = array())
+ {
+ $this->set_data('reporter_id', $this->user->data['user_id']);
+ $this->set_data('reason_title', strtoupper($post['reason_title']));
+ $this->set_data('reason_description', $post['reason_description']);
+ $this->set_data('report_text', $post['report_text']);
+
+ return parent::create_insert_array($post, $pre_create_data);
+ }
+}
diff --git a/phpBB/includes/notification/type/report_pm_closed.php b/phpBB/includes/notification/type/report_pm_closed.php
new file mode 100644
index 0000000000..8d79c8446b
--- /dev/null
+++ b/phpBB/includes/notification/type/report_pm_closed.php
@@ -0,0 +1,146 @@
+<?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;
+}
+
+/**
+* Reported pm notifications class
+* This class handles notifications for reported pms
+*
+* @package notifications
+*/
+class phpbb_notification_type_report_pm_closed extends phpbb_notification_type_pm
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = '';
+
+ /**
+ * Language key used to output the text
+ *
+ * @var string
+ */
+ protected $language_key = 'NOTIFICATION_REPORT_CLOSED';
+
+ public function is_available()
+ {
+ return false;
+ }
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_type_
+ */
+ public static function get_item_type()
+ {
+ return 'report_pm_closed';
+ }
+
+ /**
+ * Find the users who want to receive notifications
+ *
+ * @param array $pm Data from
+ *
+ * @return array
+ */
+ public function find_users_for_notification($pm, $options = array())
+ {
+ if ($pm['reporter'] == $this->user->data['user_id'])
+ {
+ return array();
+ }
+
+ return array($pm['reporter'] => array(''));
+ }
+
+ /**
+ * Get email template variables
+ *
+ * @return array
+ */
+ public function get_email_template_variables()
+ {
+ return array();
+ }
+
+ /**
+ * Get the url to this item
+ *
+ * @return string URL
+ */
+ public function get_url()
+ {
+ return '';
+ }
+
+ /**
+ * Get the HTML formatted title of this notification
+ *
+ * @return string
+ */
+ public function get_title()
+ {
+ $user_data = $this->notification_manager->get_user($this->get_data('closer_id'));
+
+ $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']);
+
+ return $this->user->lang(
+ $this->language_key,
+ $username,
+ censor_text($this->get_data('message_subject'))
+ );
+ }
+
+ /**
+ * Get the user's avatar
+ */
+ public function get_avatar()
+ {
+ return $this->_get_avatar($this->get_data('closer_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['closer_id']);
+ }
+
+ /**
+ * Function for preparing the data for insertion in an SQL query
+ * (The service handles insertion)
+ *
+ * @param array $pm PM Data
+ * @param array $pre_create_data Data from pre_create_insert_array()
+ *
+ * @return array Array of data ready to be inserted into the database
+ */
+ public function create_insert_array($pm, $pre_create_data = array())
+ {
+ $this->set_data('closer_id', $pm['closer_id']);
+
+ $data = parent::create_insert_array($pm, $pre_create_data);
+
+ $this->time = $data['time'] = time();
+
+ return $data;
+ }
+}
diff --git a/phpBB/includes/notification/type/report_post.php b/phpBB/includes/notification/type/report_post.php
new file mode 100644
index 0000000000..151841ef02
--- /dev/null
+++ b/phpBB/includes/notification/type/report_post.php
@@ -0,0 +1,194 @@
+<?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;
+}
+
+/**
+* Reported post notifications class
+* This class handles notifications for reported posts
+*
+* @package notifications
+*/
+class phpbb_notification_type_report_post extends phpbb_notification_type_post_in_queue
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = 'notifications/report_post';
+
+ /**
+ * Language key used to output the text
+ *
+ * @var string
+ */
+ protected $language_key = 'NOTIFICATION_REPORT_POST';
+
+ /**
+ * Permission to check for (in find_users_for_notification)
+ *
+ * @var string Permission name
+ */
+ protected $permission = 'm_report';
+
+ /**
+ * Notification option data (for outputting to the user)
+ *
+ * @var bool|array False if the service should use it's default data
+ * Array of data (including keys 'id' and 'lang')
+ */
+ public static $notification_option = array(
+ 'id' => 'report',
+ 'lang' => 'NOTIFICATION_TYPE_REPORT',
+ 'group' => 'NOTIFICATION_GROUP_MODERATION',
+ );
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_type_
+ */
+ public static function get_item_type()
+ {
+ return 'report_post';
+ }
+
+ /**
+ * Find the users who want to receive notifications
+ *
+ * @param array $post Data from the post
+ *
+ * @return array
+ */
+ public function find_users_for_notification($post, $options = array())
+ {
+ $notify_users = parent::find_users_for_notification($post, $options);
+
+ // never notify reporter
+ unset($notify_users[$this->user->data['user_id']]);
+
+ return $notify_users;
+ }
+
+ /**
+ * Get email template variables
+ *
+ * @return array
+ */
+ public function get_email_template_variables()
+ {
+ $board_url = generate_board_url();
+
+ return array(
+ 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($this->get_data('post_subject'))),
+ 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($this->get_data('topic_title'))),
+
+ 'U_VIEW_REPORT' => "{$board_url}mcp.{$this->php_ext}?f={$this->get_data('forum_id')}&amp;p={$this->item_id}&amp;i=reports&amp;mode=report_details#reports",
+ 'U_VIEW_POST' => "{$board_url}/viewtopic.{$this->php_ext}?p={$this->item_id}#p{$this->item_id}",
+ 'U_NEWEST_POST' => "{$board_url}/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}&view=unread#unread",
+ 'U_TOPIC' => "{$board_url}/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}",
+ 'U_VIEW_TOPIC' => "{$board_url}/viewtopic.{$this->php_ext}?f={$this->get_data('forum_id')}&t={$this->item_parent_id}",
+ 'U_FORUM' => "{$board_url}/viewforum.{$this->php_ext}?f={$this->get_data('forum_id')}",
+ );
+ }
+
+ /**
+ * Get the url to this item
+ *
+ * @return string URL
+ */
+ public function get_url()
+ {
+ return append_sid($this->phpbb_root_path . 'mcp.' . $this->php_ext, "f={$this->get_data('forum_id')}&amp;p={$this->item_id}&amp;i=reports&amp;mode=report_details#reports");
+ }
+
+ /**
+ * Get the HTML formatted title of this notification
+ *
+ * @return string
+ */
+ public function get_title()
+ {
+ $this->user->add_lang('mcp');
+
+ $user_data = $this->notification_manager->get_user($this->get_data('reporter_id'));
+
+ $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']);
+
+ if ($this->get_data('report_text'))
+ {
+ return $this->user->lang(
+ $this->language_key,
+ $username,
+ censor_text($this->get_data('post_subject')),
+ $this->get_data('report_text')
+ );
+ }
+
+ if (isset($this->user->lang[$this->get_data('reason_title')]))
+ {
+ return $this->user->lang(
+ $this->language_key,
+ $username,
+ censor_text($this->get_data('post_subject')),
+ $this->user->lang[$this->get_data('reason_title')]
+ );
+ }
+
+ return $this->user->lang(
+ $this->language_key,
+ $username,
+ censor_text($this->get_data('post_subject')),
+ $this->get_data('reason_description')
+ );
+ }
+
+ /**
+ * Get the user's avatar
+ */
+ public function get_avatar()
+ {
+ return $this->_get_avatar($this->get_data('reporter_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['reporter_id']);
+ }
+
+ /**
+ * Function for preparing the data for insertion in an SQL query
+ * (The service handles insertion)
+ *
+ * @param array $post Data from submit_post
+ * @param array $pre_create_data Data from pre_create_insert_array()
+ *
+ * @return array Array of data ready to be inserted into the database
+ */
+ public function create_insert_array($post, $pre_create_data = array())
+ {
+ $this->set_data('reporter_id', $this->user->data['user_id']);
+ $this->set_data('reason_title', strtoupper($post['reason_title']));
+ $this->set_data('reason_description', $post['reason_description']);
+ $this->set_data('report_text', $post['report_text']);
+
+ return parent::create_insert_array($post, $pre_create_data);
+ }
+}
diff --git a/phpBB/includes/notification/type/report_post_closed.php b/phpBB/includes/notification/type/report_post_closed.php
new file mode 100644
index 0000000000..3e66bde9bc
--- /dev/null
+++ b/phpBB/includes/notification/type/report_post_closed.php
@@ -0,0 +1,146 @@
+<?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;
+}
+
+/**
+* Reported post notifications class
+* This class handles notifications for reported posts
+*
+* @package notifications
+*/
+class phpbb_notification_type_report_post_closed extends phpbb_notification_type_post
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = '';
+
+ /**
+ * Language key used to output the text
+ *
+ * @var string
+ */
+ protected $language_key = 'NOTIFICATION_REPORT_CLOSED';
+
+ public function is_available()
+ {
+ return false;
+ }
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_type_
+ */
+ public static function get_item_type()
+ {
+ return 'report_post_closed';
+ }
+
+ /**
+ * Find the users who want to receive notifications
+ *
+ * @param array $post Data from
+ *
+ * @return array
+ */
+ public function find_users_for_notification($post, $options = array())
+ {
+ if ($post['reporter'] == $this->user->data['user_id'])
+ {
+ return array();
+ }
+
+ return array($post['reporter'] => array(''));
+ }
+
+ /**
+ * Get email template variables
+ *
+ * @return array
+ */
+ public function get_email_template_variables()
+ {
+ return array();
+ }
+
+ /**
+ * Get the url to this item
+ *
+ * @return string URL
+ */
+ public function get_url()
+ {
+ return '';
+ }
+
+ /**
+ * Get the HTML formatted title of this notification
+ *
+ * @return string
+ */
+ public function get_title()
+ {
+ $user_data = $this->notification_manager->get_user($this->get_data('closer_id'));
+
+ $username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']);
+
+ return $this->user->lang(
+ $this->language_key,
+ $username,
+ censor_text($this->get_data('post_subject'))
+ );
+ }
+
+ /**
+ * Get the user's avatar
+ */
+ public function get_avatar()
+ {
+ return $this->_get_avatar($this->get_data('closer_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['closer_id']);
+ }
+
+ /**
+ * Function for preparing the data for insertion in an SQL query
+ * (The service handles insertion)
+ *
+ * @param array $post Data from submit_post
+ * @param array $pre_create_data Data from pre_create_insert_array()
+ *
+ * @return array Array of data ready to be inserted into the database
+ */
+ public function create_insert_array($post, $pre_create_data = array())
+ {
+ $this->set_data('closer_id', $post['closer_id']);
+
+ $data = parent::create_insert_array($post, $pre_create_data);
+
+ $this->time = $data['time'] = time();
+
+ return $data;
+ }
+}
diff --git a/phpBB/includes/notification/type/topic.php b/phpBB/includes/notification/type/topic.php
new file mode 100644
index 0000000000..a9beb469c3
--- /dev/null
+++ b/phpBB/includes/notification/type/topic.php
@@ -0,0 +1,293 @@
+<?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;
+}
+
+/**
+* Topic notifications class
+* This class handles notifications for new topics
+*
+* @package notifications
+*/
+class phpbb_notification_type_topic extends phpbb_notification_type_base
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = 'newtopic_notify';
+
+ /**
+ * Language key used to output the text
+ *
+ * @var string
+ */
+ protected $language_key = 'NOTIFICATION_TOPIC';
+
+ /**
+ * Notification option data (for outputting to the user)
+ *
+ * @var bool|array False if the service should use it's default data
+ * Array of data (including keys 'id', 'lang', and 'group')
+ */
+ public static $notification_option = array(
+ 'group' => 'NOTIFICATION_GROUP_POSTING',
+ );
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_type_
+ */
+ public static function get_item_type()
+ {
+ return 'topic';
+ }
+
+ /**
+ * Get the id of the item
+ *
+ * @param array $post The data from the post
+ */
+ public static function get_item_id($post)
+ {
+ return (int) $post['topic_id'];
+ }
+
+ /**
+ * Get the id of the parent
+ *
+ * @param array $post The data from the post
+ */
+ public static function get_item_parent_id($post)
+ {
+ return (int) $post['forum_id'];
+ }
+
+ /**
+ * Find the users who want to receive notifications
+ *
+ * @param array $topic Data from the topic
+ *
+ * @return array
+ */
+ public function find_users_for_notification($topic, $options = array())
+ {
+ $options = array_merge(array(
+ 'ignore_users' => array(),
+ ), $options);
+
+ // Let's continue to use the phpBB subscriptions system, at least for now.
+ // It may not be the nicest thing, but it is already working and it would be significant work to replace it
+ //$users = parent::_find_users_for_notification($phpbb_container, $topic['forum_id']);
+
+ $users = array();
+
+ $sql = 'SELECT user_id
+ FROM ' . FORUMS_WATCH_TABLE . '
+ WHERE forum_id = ' . (int) $topic['forum_id'] . '
+ AND notify_status = ' . NOTIFY_YES . '
+ AND user_id <> ' . (int) $topic['poster_id'];
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $users[] = $row['user_id'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($users))
+ {
+ return array();
+ }
+
+ $auth_read = $this->auth->acl_get_list($users, 'f_read', $topic['forum_id']);
+
+ if (empty($auth_read))
+ {
+ return array();
+ }
+
+ $notify_users = array();
+
+ $sql = 'SELECT *
+ FROM ' . USER_NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::get_item_type() . "'
+ AND " . $this->db->sql_in_set('user_id', $auth_read[$topic['forum_id']]['f_read']);
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']]))
+ {
+ continue;
+ }
+
+ if (!isset($rowset[$row['user_id']]))
+ {
+ $notify_users[$row['user_id']] = array();
+ }
+
+ $notify_users[$row['user_id']][] = $row['method'];
+ }
+ $this->db->sql_freeresult($result);
+
+ 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
+ *
+ * @return string
+ */
+ public function get_title()
+ {
+ if ($this->get_data('post_username'))
+ {
+ $username = $this->get_data('post_username');
+ }
+ else
+ {
+ $user_data = $this->notification_manager->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->user->lang(
+ $this->language_key,
+ $username,
+ censor_text($this->get_data('topic_title')),
+ $this->get_data('forum_name')
+ );
+ }
+
+ /**
+ * Get email template variables
+ *
+ * @return array
+ */
+ public function get_email_template_variables()
+ {
+ if ($this->get_data('post_username'))
+ {
+ $username = $this->get_data('post_username');
+ }
+ else
+ {
+ $user_data = $this->notification_manager->get_user($this->get_data('poster_id'));
+
+ $username = get_username_string('username', $user_data['user_id'], $user_data['username'], $user_data['user_colour']);
+ }
+
+ return array(
+ 'AUTHOR_NAME' => htmlspecialchars_decode($username),
+ 'FORUM_NAME' => htmlspecialchars_decode($this->get_data('forum_name')),
+ 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($this->get_data('topic_title'))),
+
+ 'U_TOPIC' => generate_board_url() . "/viewtopic.{$this->php_ext}?f={$this->item_parent_id}&t={$this->item_id}",
+ 'U_VIEW_TOPIC' => generate_board_url() . "/viewtopic.{$this->php_ext}?f={$this->item_parent_id}&t={$this->item_id}",
+ 'U_FORUM' => generate_board_url() . "/viewforum.{$this->php_ext}?f={$this->item_parent_id}",
+ 'U_STOP_WATCHING_FORUM' => generate_board_url() . "/viewforum.{$this->php_ext}?uid={$this->user_id}&f={$this->item_parent_id}&unwatch=forum",
+ );
+ }
+
+ /**
+ * Get the url to this item
+ *
+ * @return string URL
+ */
+ public function get_url()
+ {
+ return append_sid($this->phpbb_root_path . 'viewtopic.' . $this->php_ext, "f={$this->item_parent_id}&amp;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']);
+ }
+
+ /**
+ * Pre create insert array function
+ * This allows you to perform certain actions, like run a query
+ * and load data, before create_insert_array() is run. The data
+ * returned from this function will be sent to create_insert_array().
+ *
+ * @param array $post Post data from submit_post
+ * @param array $notify_users Notify users list
+ * Formated from find_users_for_notification()
+ * @return array Whatever you want to send to create_insert_array().
+ */
+ public function pre_create_insert_array($post, $notify_users)
+ {
+ if (!sizeof($notify_users))
+ {
+ return array();
+ }
+
+ $tracking_data = array();
+ $sql = 'SELECT user_id, mark_time FROM ' . TOPICS_TRACK_TABLE . '
+ WHERE topic_id = ' . (int) $post['topic_id'] . '
+ AND ' . $this->db->sql_in_set('user_id', array_keys($notify_users));
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $tracking_data[$row['user_id']] = $row['mark_time'];
+ }
+
+ return $tracking_data;
+ }
+
+ /**
+ * Function for preparing the data for insertion in an SQL query
+ * (The service handles insertion)
+ *
+ * @param array $post Data from submit_post
+ * @param array $pre_create_data Data from pre_create_insert_array()
+ *
+ * @return array Array of data ready to be inserted into the database
+ */
+ public function create_insert_array($post, $pre_create_data = array())
+ {
+ $this->set_data('poster_id', $post['poster_id']);
+
+ $this->set_data('topic_title', $post['topic_title']);
+
+ $this->set_data('post_username', (($post['poster_id'] == ANONYMOUS) ? $post['post_username'] : ''));
+
+ $this->set_data('forum_name', $post['forum_name']);
+
+ $this->time = $post['post_time'];
+
+ // Topics can be "read" before they are public (while awaiting approval).
+ // Make sure that if the user has read the topic, it's marked as read in the notification
+ if (isset($pre_create_data[$this->user_id]) && $pre_create_data[$this->user_id] >= $this->time)
+ {
+ $this->unread = false;
+ }
+
+ return parent::create_insert_array($post, $pre_create_data);
+ }
+}
diff --git a/phpBB/includes/notification/type/topic_in_queue.php b/phpBB/includes/notification/type/topic_in_queue.php
new file mode 100644
index 0000000000..eb14c098e1
--- /dev/null
+++ b/phpBB/includes/notification/type/topic_in_queue.php
@@ -0,0 +1,147 @@
+<?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;
+}
+
+/**
+* Topic notifications class
+* This class handles notifications for new topics
+*
+* @package notifications
+*/
+class phpbb_notification_type_topic_in_queue extends phpbb_notification_type_topic
+{
+ /**
+ * Email template to use to send notifications
+ *
+ * @var string
+ */
+ public $email_template = 'notifications/topic_in_queue';
+
+ /**
+ * Language key used to output the text
+ *
+ * @var string
+ */
+ protected $language_key = 'NOTIFICATION_TOPIC_IN_QUEUE';
+
+ /**
+ * Notification option data (for outputting to the user)
+ *
+ * @var bool|array False if the service should use it's default data
+ * Array of data (including keys 'id', 'lang', and 'group')
+ */
+ public static $notification_option = array(
+ 'id' => 'needs_approval',
+ 'lang' => 'NOTIFICATION_TYPE_IN_MODERATION_QUEUE',
+ 'group' => 'NOTIFICATION_GROUP_MODERATION',
+ );
+
+ /**
+ * Is available
+ */
+ public function is_available()
+ {
+ $m_approve = $this->auth->acl_getf('m_approve', true);
+
+ return (!empty($m_approve));
+ }
+
+ /**
+ * Get the type of notification this is
+ * phpbb_notification_type_
+ */
+ public static function get_item_type()
+ {
+ return 'topic_in_queue';
+ }
+
+ /**
+ * Find the users who want to receive notifications
+ *
+ * @param array $topic Data from the topic
+ *
+ * @return array
+ */
+ public function find_users_for_notification($topic, $options = array())
+ {
+ $options = array_merge(array(
+ 'ignore_users' => array(),
+ ), $options);
+
+ // 0 is for global
+ $auth_approve = $this->auth->acl_get_list(false, 'm_approve', array($topic['forum_id'], 0));
+
+ if (empty($auth_approve))
+ {
+ return array();
+ }
+
+ $auth_approve[$topic['forum_id']] = array_unique(array_merge($auth_approve[$topic['forum_id']], $auth_approve[0]));
+
+ $notify_users = array();
+
+ $sql = 'SELECT *
+ FROM ' . USER_NOTIFICATIONS_TABLE . "
+ WHERE item_type = '" . self::$notification_option['id'] . "'
+ AND " . $this->db->sql_in_set('user_id', $auth_approve[$topic['forum_id']]['m_approve']);
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']]))
+ {
+ continue;
+ }
+
+ if (!isset($rowset[$row['user_id']]))
+ {
+ $notify_users[$row['user_id']] = array();
+ }
+
+ $notify_users[$row['user_id']][] = $row['method'];
+ }
+ $this->db->sql_freeresult($result);
+
+ return $notify_users;
+ }
+
+ /**
+ * Get the url to this item
+ *
+ * @return string URL
+ */
+ public function get_url()
+ {
+ return append_sid($this->phpbb_root_path . 'mcp.' . $this->php_ext, "i=queue&amp;mode=approve_details&amp;f={$this->item_parent_id}&amp;t={$this->item_id}");
+ }
+
+ /**
+ * Function for preparing the data for insertion in an SQL query
+ * (The service handles insertion)
+ *
+ * @param array $topic Data from submit_post
+ * @param array $pre_create_data Data from pre_create_insert_array()
+ *
+ * @return array Array of data ready to be inserted into the database
+ */
+ public function create_insert_array($topic, $pre_create_data = array())
+ {
+ $data = parent::create_insert_array($topic, $pre_create_data);
+
+ $this->time = $data['time'] = time();
+
+ return $data;
+ }
+}
diff --git a/phpBB/includes/ucp/info/ucp_notifications.php b/phpBB/includes/ucp/info/ucp_notifications.php
new file mode 100644
index 0000000000..98d8b9db61
--- /dev/null
+++ b/phpBB/includes/ucp/info/ucp_notifications.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
+*
+*/
+
+/**
+* @package module_install
+*/
+class ucp_notifications_info
+{
+ function module()
+ {
+ return array(
+ 'filename' => 'ucp_notifications',
+ 'title' => 'UCP_NOTIFICATION_OPTIONS',
+ 'version' => '1.0.0',
+ 'modes' => array(
+ 'notification_options' => array('title' => 'UCP_NOTIFICATION_OPTIONS', 'auth' => '', 'cat' => array('UCP_PREFS')),
+ 'notification_list' => array('title' => 'UCP_NOTIFICATION_LIST', 'auth' => '', 'cat' => array('UCP_MAIN')),
+ ),
+ );
+ }
+
+ function install()
+ {
+ }
+
+ function uninstall()
+ {
+ }
+}
diff --git a/phpBB/includes/ucp/ucp_notifications.php b/phpBB/includes/ucp/ucp_notifications.php
new file mode 100644
index 0000000000..321730a64b
--- /dev/null
+++ b/phpBB/includes/ucp/ucp_notifications.php
@@ -0,0 +1,229 @@
+<?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;
+}
+
+class ucp_notifications
+{
+ public $u_action;
+
+ public function main($id, $mode)
+ {
+ global $config, $template, $user, $request, $phpbb_notifications;
+ global $phpbb_root_path, $phpEx;
+
+ add_form_key('ucp_notification');
+
+ $start = request_var('start', 0);
+ $form_time = min(request_var('form_time', 0), time());
+
+ switch ($mode)
+ {
+ case 'notification_options':
+ $subscriptions = $phpbb_notifications->get_subscriptions(false, true);
+
+ // Add/remove subscriptions
+ if ($request->is_set_post('submit'))
+ {
+ if (!check_form_key('ucp_notification'))
+ {
+ trigger_error('FORM_INVALID');
+ }
+
+ $notification_methods = $phpbb_notifications->get_subscription_methods();
+
+ foreach($phpbb_notifications->get_subscription_types() as $group => $subscription_types)
+ {
+ foreach($subscription_types as $type => $data)
+ {
+ if ($request->is_set_post($type . '_notification') && !isset($subscriptions[$type]))
+ {
+ // add
+ $phpbb_notifications->add_subscription($type);
+ }
+ else if (!$request->is_set_post($type . '_notification') && isset($subscriptions[$type]))
+ {
+ // remove
+ $phpbb_notifications->delete_subscription($type);
+ }
+
+ foreach($notification_methods as $method)
+ {
+ if ($request->is_set_post($type . '_' . $method) && (!isset($subscriptions[$type]) || !in_array($method, $subscriptions[$type])))
+ {
+ // add
+ $phpbb_notifications->add_subscription($type, 0, $method);
+ }
+ else if (!$request->is_set_post($type . '_' . $method) && isset($subscriptions[$type]) && in_array($method, $subscriptions[$type]))
+ {
+ // remove
+ $phpbb_notifications->delete_subscription($type, 0, $method);
+ }
+ }
+ }
+ }
+
+ meta_refresh(3, $this->u_action);
+ $message = $user->lang['PREFERENCES_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>');
+ trigger_error($message);
+ }
+
+ $this->output_notification_methods('notification_methods', $phpbb_notifications, $template, $user);
+
+ $this->output_notification_types('notification_types', $phpbb_notifications, $template, $user);
+
+ $this->tpl_name = 'ucp_notifications';
+ $this->page_title = 'UCP_NOTIFICATION_OPTIONS';
+ break;
+
+ case 'notification_list':
+ default:
+ // Mark all items read
+ if (request_var('mark', '') == 'all' && (confirm_box(true) || check_link_hash(request_var('token', ''), 'mark_all_notifications_read')))
+ {
+ if (confirm_box(true))
+ {
+ $phpbb_notifications->mark_notifications_read(false, false, $user->data['user_id'], $form_time);
+
+ meta_refresh(3, $this->u_action);
+ $message = $user->lang['NOTIFICATIONS_MARK_ALL_READ_SUCCESS'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>');
+ trigger_error($message);
+ }
+ else
+ {
+ confirm_box(false, 'NOTIFICATIONS_MARK_ALL_READ', build_hidden_fields(array(
+ 'mark' => 'all',
+ 'form_time' => $form_time,
+ )));
+ }
+ }
+
+ // Mark specific notifications read
+ if ($request->is_set_post('submit'))
+ {
+ if (!check_form_key('ucp_notification'))
+ {
+ trigger_error('FORM_INVALID');
+ }
+
+ $mark_read = request_var('mark', array(0));
+
+ if (!empty($mark_read))
+ {
+ $phpbb_notifications->mark_notifications_read_by_id($mark_read, $form_time);
+ }
+ }
+
+ $notifications = $phpbb_notifications->load_notifications(array(
+ 'start' => $start,
+ 'limit' => $config['topics_per_page'],
+ 'count_total' => true,
+ ));
+
+ foreach ($notifications['notifications'] as $notification)
+ {
+ $template->assign_block_vars('notification_list', $notification->prepare_for_display());
+ }
+
+ $base_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=ucp_notifications&amp;mode=notification_list");
+ phpbb_generate_template_pagination($template, $base_url, 'pagination', 'start', $notifications['total_count'], $config['topics_per_page'], $start);
+
+ $template->assign_vars(array(
+ 'PAGE_NUMBER' => phpbb_on_page($template, $user, $base_url, $notifications['total_count'], $config['topics_per_page'], $start),
+ 'TOTAL_COUNT' => $user->lang('NOTIFICATIONS_COUNT', $notifications['total_count']),
+ 'U_MARK_ALL' => $base_url . '&amp;mark=all&amp;token=' . generate_link_hash('mark_all_notifications_read'),
+ ));
+
+ $this->tpl_name = 'ucp_notifications';
+ $this->page_title = 'UCP_NOTIFICATION_LIST';
+ break;
+ }
+
+ $template->assign_vars(array(
+ 'TITLE' => $user->lang($this->page_title),
+ 'TITLE_EXPLAIN' => $user->lang($this->page_title . '_EXPLAIN'),
+
+ 'MODE' => $mode,
+
+ 'FORM_TIME' => time(),
+ ));
+ }
+
+ /**
+ * Output all the notification types to the template
+ *
+ * @param string $block
+ * @param phpbb_notification_manager $phpbb_notifications
+ * @param phpbb_template $template
+ * @param phpbb_user $user
+ */
+ public function output_notification_types($block = 'notification_types', phpbb_notification_manager $phpbb_notifications, phpbb_template $template, phpbb_user $user)
+ {
+ $notification_methods = $phpbb_notifications->get_subscription_methods();
+ $subscriptions = $phpbb_notifications->get_subscriptions(false, true);
+
+ foreach($phpbb_notifications->get_subscription_types() as $group => $subscription_types)
+ {
+ $template->assign_block_vars($block, array(
+ 'GROUP_NAME' => $user->lang($group),
+ ));
+
+ foreach($subscription_types as $type => $data)
+ {
+ $template->assign_block_vars($block, array(
+ 'TYPE' => $type,
+
+ 'NAME' => $user->lang($data['lang']),
+ 'EXPLAIN' => (isset($user->lang[$data['lang'] . '_EXPLAIN'])) ? $user->lang($data['lang'] . '_EXPLAIN') : '',
+
+ 'SUBSCRIBED' => (isset($subscriptions[$type])) ? true : false,
+ ));
+
+ foreach($notification_methods as $method)
+ {
+ $template->assign_block_vars($block . '.notification_methods', array(
+ 'METHOD' => $method,
+
+ 'NAME' => $user->lang('NOTIFICATION_METHOD_' . strtoupper($method)),
+
+ 'SUBSCRIBED' => (isset($subscriptions[$type]) && in_array($method, $subscriptions[$type])) ? true : false,
+ ));
+ }
+ }
+ }
+ }
+
+ /**
+ * Output all the notification methods to the template
+ *
+ * @param string $block
+ * @param phpbb_notification_manager $phpbb_notifications
+ * @param phpbb_template $template
+ * @param phpbb_user $user
+ */
+ public function output_notification_methods($block = 'notification_methods', phpbb_notification_manager $phpbb_notifications, phpbb_template $template, phpbb_user $user)
+ {
+ $notification_methods = $phpbb_notifications->get_subscription_methods();
+
+ foreach($notification_methods as $method)
+ {
+ $template->assign_block_vars($block, array(
+ 'METHOD' => $method,
+
+ 'NAME' => $user->lang('NOTIFICATION_METHOD_' . strtoupper($method)),
+ ));
+ }
+ }
+}
diff --git a/phpBB/includes/ucp/ucp_prefs.php b/phpBB/includes/ucp/ucp_prefs.php
index 2228bc7931..709d2a90b0 100644
--- a/phpBB/includes/ucp/ucp_prefs.php
+++ b/phpBB/includes/ucp/ucp_prefs.php
@@ -37,7 +37,6 @@ class ucp_prefs
case 'personal':
add_form_key('ucp_prefs_personal');
$data = array(
- 'notifymethod' => request_var('notifymethod', $user->data['user_notify_type']),
'dateformat' => request_var('dateformat', $user->data['user_dateformat'], true),
'lang' => basename(request_var('lang', $user->data['user_lang'])),
'style' => request_var('style', (int) $user->data['user_style']),
@@ -46,17 +45,9 @@ class ucp_prefs
'viewemail' => request_var('viewemail', (bool) $user->data['user_allow_viewemail']),
'massemail' => request_var('massemail', (bool) $user->data['user_allow_massemail']),
'hideonline' => request_var('hideonline', (bool) !$user->data['user_allow_viewonline']),
- 'notifypm' => request_var('notifypm', (bool) $user->data['user_notify_pm']),
- 'popuppm' => request_var('popuppm', (bool) $user->optionget('popuppm')),
'allowpm' => request_var('allowpm', (bool) $user->data['user_allow_pm']),
);
- if ($data['notifymethod'] == NOTIFY_IM && (!$config['jab_enable'] || !$user->data['user_jabber'] || !@extension_loaded('xml')))
- {
- // Jabber isnt enabled, or no jabber field filled in. Update the users table to be sure its correct.
- $data['notifymethod'] = NOTIFY_BOTH;
- }
-
if ($submit)
{
if ($config['override_user_style'])
@@ -81,15 +72,11 @@ class ucp_prefs
if (!sizeof($error))
{
- $user->optionset('popuppm', $data['popuppm']);
-
$sql_ary = array(
'user_allow_pm' => $data['allowpm'],
'user_allow_viewemail' => $data['viewemail'],
'user_allow_massemail' => $data['massemail'],
'user_allow_viewonline' => ($auth->acl_get('u_hideonline')) ? !$data['hideonline'] : $user->data['user_allow_viewonline'],
- 'user_notify_type' => $data['notifymethod'],
- 'user_notify_pm' => $data['notifypm'],
'user_options' => $user->data['user_options'],
'user_dateformat' => $data['dateformat'],
@@ -135,15 +122,10 @@ class ucp_prefs
$template->assign_vars(array(
'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '',
- 'S_NOTIFY_EMAIL' => ($data['notifymethod'] == NOTIFY_EMAIL) ? true : false,
- 'S_NOTIFY_IM' => ($data['notifymethod'] == NOTIFY_IM) ? true : false,
- 'S_NOTIFY_BOTH' => ($data['notifymethod'] == NOTIFY_BOTH) ? true : false,
'S_VIEW_EMAIL' => $data['viewemail'],
'S_MASS_EMAIL' => $data['massemail'],
'S_ALLOW_PM' => $data['allowpm'],
'S_HIDE_ONLINE' => $data['hideonline'],
- 'S_NOTIFY_PM' => $data['notifypm'],
- 'S_POPUP_PM' => $data['popuppm'],
'DATE_FORMAT' => $data['dateformat'],
'A_DATE_FORMAT' => addslashes($data['dateformat']),
diff --git a/phpBB/index.php b/phpBB/index.php
index 66e1b2114b..ac886be0ff 100644
--- a/phpBB/index.php
+++ b/phpBB/index.php
@@ -23,6 +23,28 @@ $user->session_begin();
$auth->acl($user->data);
$user->setup();
+// Mark notifications read
+if (($mark_notification = request_var('mark_notification', 0)))
+{
+ $notification = $phpbb_notifications->load_notifications(array(
+ 'notification_id' => $mark_notification
+ ));
+
+ if (isset($notification['notifications'][$mark_notification]))
+ {
+ $notification = $notification['notifications'][$mark_notification];
+
+ $notification->mark_read();
+
+ if (($redirect = request_var('redirect', '')))
+ {
+ redirect(append_sid($phpbb_root_path . $redirect));
+ }
+
+ redirect($notification->get_url());
+ }
+}
+
// Handle the display of extension front pages
if ($ext = $request->variable('ext', ''))
{
@@ -31,7 +53,7 @@ if ($ext = $request->variable('ext', ''))
if (!$phpbb_extension_manager->available($ext))
{
send_status_line(404, 'Not Found');
- trigger_error($user->lang('EXTENSION_DOES_NOT_EXIST', $ext));
+ trigger_error($user->lang('EXTENSION_DOES_NOT_EXIST', $ext));
}
else if (!$phpbb_extension_manager->enabled($ext))
{
diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php
index 542685a69d..73637122ce 100644
--- a/phpBB/install/database_update.php
+++ b/phpBB/install/database_update.php
@@ -110,6 +110,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_container = new ContainerBuilder();
$loader = new YamlFileLoader($phpbb_container, new FileLocator(__DIR__.'/../config'));
@@ -1117,6 +1125,47 @@ function database_update_info()
'ext_name' => array('UNIQUE', 'ext_name'),
),
),
+ NOTIFICATIONS_TABLE => array(
+ 'COLUMNS' => array(
+ 'notification_id' => array('UINT', NULL, 'auto_increment'),
+ 'item_type' => array('VCHAR:25', ''),
+ 'item_id' => array('UINT', 0),
+ 'item_parent_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ 'unread' => array('BOOL', 1),
+ 'is_disabled' => array('BOOL', 0),
+ 'time' => array('TIMESTAMP', 1),
+ 'data' => array('TEXT_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => 'notification_id',
+ 'KEYS' => array(
+ 'item_type' => array('INDEX', 'item_type'),
+ 'item_id' => array('INDEX', 'item_id'),
+ 'item_pid' => array('INDEX', 'item_parent_id'),
+ 'user_id' => array('INDEX', 'user_id'),
+ 'time' => array('INDEX', 'time'),
+ 'unread' => array('INDEX', 'unread'),
+ 'is_disabled' => array('INDEX', 'is_disabled'),
+ ),
+ ),
+ 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(
@@ -2418,6 +2467,20 @@ function change_database_data(&$no_updates, $version)
'auth' => '',
'cat' => 'UCP_PROFILE',
),
+ 'notification_options' => array(
+ 'base' => 'ucp_notifications',
+ 'class' => 'ucp',
+ 'title' => 'UCP_NOTIFICATION_OPTIONS',
+ 'auth' => '',
+ 'cat' => 'UCP_PREFS',
+ ),
+ 'notification_list' => array(
+ 'base' => 'ucp_notifications',
+ 'class' => 'ucp',
+ 'title' => 'UCP_NOTIFICATION_LIST',
+ 'auth' => '',
+ 'cat' => 'UCP_MAIN',
+ ),
);
_add_modules($modules_to_install);
@@ -2649,10 +2712,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']))
@@ -2685,13 +2748,18 @@ function change_database_data(&$no_updates, $version)
// After we have calculated the timezones we can delete user_dst column from user table.
$db_tools->sql_column_remove(USERS_TABLE, 'user_dst');
}
-
+
if (!isset($config['site_home_url']))
{
$config->set('site_home_url', '');
$config->set('site_home_text', '');
}
+ if (!isset($config['load_notifications']))
+ {
+ $config->set('load_notifications', 1);
+ }
+
break;
}
}
diff --git a/phpBB/install/schemas/firebird_schema.sql b/phpBB/install/schemas/firebird_schema.sql
index 588557b92a..1e4ae2e132 100644
--- a/phpBB/install/schemas/firebird_schema.sql
+++ b/phpBB/install/schemas/firebird_schema.sql
@@ -618,6 +618,40 @@ BEGIN
END;;
+# Table: 'phpbb_notifications'
+CREATE TABLE phpbb_notifications (
+ notification_id INTEGER NOT NULL,
+ item_type VARCHAR(25) CHARACTER SET NONE DEFAULT '' NOT NULL,
+ item_id INTEGER DEFAULT 0 NOT NULL,
+ item_parent_id INTEGER DEFAULT 0 NOT NULL,
+ user_id INTEGER DEFAULT 0 NOT NULL,
+ unread INTEGER DEFAULT 1 NOT NULL,
+ is_disabled INTEGER DEFAULT 0 NOT NULL,
+ time INTEGER DEFAULT 1 NOT NULL,
+ data BLOB SUB_TYPE TEXT CHARACTER SET UTF8 DEFAULT '' NOT NULL
+);;
+
+ALTER TABLE phpbb_notifications ADD PRIMARY KEY (notification_id);;
+
+CREATE INDEX phpbb_notifications_item_type ON phpbb_notifications(item_type);;
+CREATE INDEX phpbb_notifications_item_id ON phpbb_notifications(item_id);;
+CREATE INDEX phpbb_notifications_item_pid ON phpbb_notifications(item_parent_id);;
+CREATE INDEX phpbb_notifications_user_id ON phpbb_notifications(user_id);;
+CREATE INDEX phpbb_notifications_time ON phpbb_notifications(time);;
+CREATE INDEX phpbb_notifications_unread ON phpbb_notifications(unread);;
+CREATE INDEX phpbb_notifications_is_disabled ON phpbb_notifications(is_disabled);;
+
+CREATE GENERATOR phpbb_notifications_gen;;
+SET GENERATOR phpbb_notifications_gen TO 0;;
+
+CREATE TRIGGER t_phpbb_notifications FOR phpbb_notifications
+BEFORE INSERT
+AS
+BEGIN
+ NEW.notification_id = GEN_ID(phpbb_notifications_gen, 1);
+END;;
+
+
# Table: 'phpbb_poll_options'
CREATE TABLE phpbb_poll_options (
poll_option_id INTEGER DEFAULT 0 NOT NULL,
@@ -1201,6 +1235,19 @@ CREATE INDEX phpbb_topics_watch_topic_id ON phpbb_topics_watch(topic_id);;
CREATE INDEX phpbb_topics_watch_user_id ON phpbb_topics_watch(user_id);;
CREATE INDEX phpbb_topics_watch_notify_stat ON phpbb_topics_watch(notify_status);;
+# Table: 'phpbb_user_notifications'
+CREATE TABLE phpbb_user_notifications (
+ item_type VARCHAR(25) CHARACTER SET NONE DEFAULT '' NOT NULL,
+ item_id INTEGER DEFAULT 0 NOT NULL,
+ user_id INTEGER DEFAULT 0 NOT NULL,
+ method VARCHAR(25) CHARACTER SET NONE DEFAULT '' NOT NULL
+);;
+
+ALTER TABLE phpbb_user_notifications ADD PRIMARY KEY (item_type, item_id, user_id, method);;
+
+CREATE INDEX phpbb_user_notifications_it ON phpbb_user_notifications(item_type);;
+CREATE INDEX phpbb_user_notifications_uid ON phpbb_user_notifications(user_id);;
+
# Table: 'phpbb_user_group'
CREATE TABLE phpbb_user_group (
group_id INTEGER DEFAULT 0 NOT NULL,
diff --git a/phpBB/install/schemas/mssql_schema.sql b/phpBB/install/schemas/mssql_schema.sql
index 9d0e81a66d..5a397743c4 100644
--- a/phpBB/install/schemas/mssql_schema.sql
+++ b/phpBB/install/schemas/mssql_schema.sql
@@ -752,6 +752,51 @@ GO
/*
+ Table: 'phpbb_notifications'
+*/
+CREATE TABLE [phpbb_notifications] (
+ [notification_id] [int] IDENTITY (1, 1) NOT NULL ,
+ [item_type] [varchar] (25) DEFAULT ('') NOT NULL ,
+ [item_id] [int] DEFAULT (0) NOT NULL ,
+ [item_parent_id] [int] DEFAULT (0) NOT NULL ,
+ [user_id] [int] DEFAULT (0) NOT NULL ,
+ [unread] [int] DEFAULT (1) NOT NULL ,
+ [is_disabled] [int] DEFAULT (0) NOT NULL ,
+ [time] [int] DEFAULT (1) NOT NULL ,
+ [data] [varchar] (4000) DEFAULT ('') NOT NULL
+) ON [PRIMARY]
+GO
+
+ALTER TABLE [phpbb_notifications] WITH NOCHECK ADD
+ CONSTRAINT [PK_phpbb_notifications] PRIMARY KEY CLUSTERED
+ (
+ [notification_id]
+ ) ON [PRIMARY]
+GO
+
+CREATE INDEX [item_type] ON [phpbb_notifications]([item_type]) ON [PRIMARY]
+GO
+
+CREATE INDEX [item_id] ON [phpbb_notifications]([item_id]) ON [PRIMARY]
+GO
+
+CREATE INDEX [item_pid] ON [phpbb_notifications]([item_parent_id]) ON [PRIMARY]
+GO
+
+CREATE INDEX [user_id] ON [phpbb_notifications]([user_id]) ON [PRIMARY]
+GO
+
+CREATE INDEX [time] ON [phpbb_notifications]([time]) ON [PRIMARY]
+GO
+
+CREATE INDEX [unread] ON [phpbb_notifications]([unread]) ON [PRIMARY]
+GO
+
+CREATE INDEX [is_disabled] ON [phpbb_notifications]([is_disabled]) ON [PRIMARY]
+GO
+
+
+/*
Table: 'phpbb_poll_options'
*/
CREATE TABLE [phpbb_poll_options] (
@@ -1110,7 +1155,7 @@ CREATE TABLE [phpbb_reports] (
[report_closed] [int] DEFAULT (0) NOT NULL ,
[report_time] [int] DEFAULT (0) NOT NULL ,
[report_text] [text] DEFAULT ('') NOT NULL ,
- [reported_post_text] [text] DEFAULT ('') NOT NULL
+ [reported_post_text] [text] DEFAULT ('') NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
@@ -1475,6 +1520,34 @@ GO
/*
+ Table: 'phpbb_user_notifications'
+*/
+CREATE TABLE [phpbb_user_notifications] (
+ [item_type] [varchar] (25) DEFAULT ('') NOT NULL ,
+ [item_id] [int] DEFAULT (0) NOT NULL ,
+ [user_id] [int] DEFAULT (0) NOT NULL ,
+ [method] [varchar] (25) DEFAULT ('') NOT NULL
+) ON [PRIMARY]
+GO
+
+ALTER TABLE [phpbb_user_notifications] WITH NOCHECK ADD
+ CONSTRAINT [PK_phpbb_user_notifications] PRIMARY KEY CLUSTERED
+ (
+ [item_type],
+ [item_id],
+ [user_id],
+ [method]
+ ) ON [PRIMARY]
+GO
+
+CREATE INDEX [it] ON [phpbb_user_notifications]([item_type]) ON [PRIMARY]
+GO
+
+CREATE INDEX [uid] ON [phpbb_user_notifications]([user_id]) ON [PRIMARY]
+GO
+
+
+/*
Table: 'phpbb_user_group'
*/
CREATE TABLE [phpbb_user_group] (
diff --git a/phpBB/install/schemas/mysql_40_schema.sql b/phpBB/install/schemas/mysql_40_schema.sql
index e71afcd5b3..fd7f9a6025 100644
--- a/phpBB/install/schemas/mysql_40_schema.sql
+++ b/phpBB/install/schemas/mysql_40_schema.sql
@@ -430,6 +430,28 @@ CREATE TABLE phpbb_modules (
);
+# Table: 'phpbb_notifications'
+CREATE TABLE phpbb_notifications (
+ notification_id mediumint(8) UNSIGNED NOT NULL auto_increment,
+ item_type varbinary(25) DEFAULT '' NOT NULL,
+ item_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
+ item_parent_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
+ user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
+ unread tinyint(1) UNSIGNED DEFAULT '1' NOT NULL,
+ is_disabled tinyint(1) UNSIGNED DEFAULT '0' NOT NULL,
+ time int(11) UNSIGNED DEFAULT '1' NOT NULL,
+ data blob NOT NULL,
+ PRIMARY KEY (notification_id),
+ KEY item_type (item_type),
+ KEY item_id (item_id),
+ KEY item_pid (item_parent_id),
+ KEY user_id (user_id),
+ KEY time (time),
+ KEY unread (unread),
+ KEY is_disabled (is_disabled)
+);
+
+
# Table: 'phpbb_poll_options'
CREATE TABLE phpbb_poll_options (
poll_option_id tinyint(4) DEFAULT '0' NOT NULL,
@@ -849,6 +871,18 @@ CREATE TABLE phpbb_topics_watch (
);
+# Table: 'phpbb_user_notifications'
+CREATE TABLE phpbb_user_notifications (
+ item_type varbinary(25) DEFAULT '' NOT NULL,
+ item_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
+ user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
+ method varbinary(25) DEFAULT '' NOT NULL,
+ PRIMARY KEY (item_type, item_id, user_id, method),
+ KEY it (item_type),
+ KEY uid (user_id)
+);
+
+
# Table: 'phpbb_user_group'
CREATE TABLE phpbb_user_group (
group_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
diff --git a/phpBB/install/schemas/mysql_41_schema.sql b/phpBB/install/schemas/mysql_41_schema.sql
index 20af6f3566..8700b46c91 100644
--- a/phpBB/install/schemas/mysql_41_schema.sql
+++ b/phpBB/install/schemas/mysql_41_schema.sql
@@ -430,6 +430,28 @@ CREATE TABLE phpbb_modules (
) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+# Table: 'phpbb_notifications'
+CREATE TABLE phpbb_notifications (
+ notification_id mediumint(8) UNSIGNED NOT NULL auto_increment,
+ item_type varchar(25) DEFAULT '' NOT NULL,
+ item_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
+ item_parent_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
+ user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
+ unread tinyint(1) UNSIGNED DEFAULT '1' NOT NULL,
+ is_disabled tinyint(1) UNSIGNED DEFAULT '0' NOT NULL,
+ time int(11) UNSIGNED DEFAULT '1' NOT NULL,
+ data text NOT NULL,
+ PRIMARY KEY (notification_id),
+ KEY item_type (item_type),
+ KEY item_id (item_id),
+ KEY item_pid (item_parent_id),
+ KEY user_id (user_id),
+ KEY time (time),
+ KEY unread (unread),
+ KEY is_disabled (is_disabled)
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+
# Table: 'phpbb_poll_options'
CREATE TABLE phpbb_poll_options (
poll_option_id tinyint(4) DEFAULT '0' NOT NULL,
@@ -849,6 +871,18 @@ CREATE TABLE phpbb_topics_watch (
) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+# Table: 'phpbb_user_notifications'
+CREATE TABLE phpbb_user_notifications (
+ item_type varchar(25) DEFAULT '' NOT NULL,
+ item_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
+ user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
+ method varchar(25) DEFAULT '' NOT NULL,
+ PRIMARY KEY (item_type, item_id, user_id, method),
+ KEY it (item_type),
+ KEY uid (user_id)
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+
# Table: 'phpbb_user_group'
CREATE TABLE phpbb_user_group (
group_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql
index 04155fe28b..f2f22e2f5e 100644
--- a/phpBB/install/schemas/oracle_schema.sql
+++ b/phpBB/install/schemas/oracle_schema.sql
@@ -841,6 +841,54 @@ END;
/*
+ Table: 'phpbb_notifications'
+*/
+CREATE TABLE phpbb_notifications (
+ notification_id number(8) NOT NULL,
+ item_type varchar2(25) DEFAULT '' ,
+ item_id number(8) DEFAULT '0' NOT NULL,
+ item_parent_id number(8) DEFAULT '0' NOT NULL,
+ user_id number(8) DEFAULT '0' NOT NULL,
+ unread number(1) DEFAULT '1' NOT NULL,
+ is_disabled number(1) DEFAULT '0' NOT NULL,
+ time number(11) DEFAULT '1' NOT NULL,
+ data clob DEFAULT '' ,
+ CONSTRAINT pk_phpbb_notifications PRIMARY KEY (notification_id)
+)
+/
+
+CREATE INDEX phpbb_notifications_item_type ON phpbb_notifications (item_type)
+/
+CREATE INDEX phpbb_notifications_item_id ON phpbb_notifications (item_id)
+/
+CREATE INDEX phpbb_notifications_item_pid ON phpbb_notifications (item_parent_id)
+/
+CREATE INDEX phpbb_notifications_user_id ON phpbb_notifications (user_id)
+/
+CREATE INDEX phpbb_notifications_time ON phpbb_notifications (time)
+/
+CREATE INDEX phpbb_notifications_unread ON phpbb_notifications (unread)
+/
+CREATE INDEX phpbb_notifications_is_disabled ON phpbb_notifications (is_disabled)
+/
+
+CREATE SEQUENCE phpbb_notifications_seq
+/
+
+CREATE OR REPLACE TRIGGER t_phpbb_notifications
+BEFORE INSERT ON phpbb_notifications
+FOR EACH ROW WHEN (
+ new.notification_id IS NULL OR new.notification_id = 0
+)
+BEGIN
+ SELECT phpbb_notifications_seq.nextval
+ INTO :new.notification_id
+ FROM dual;
+END;
+/
+
+
+/*
Table: 'phpbb_poll_options'
*/
CREATE TABLE phpbb_poll_options (
@@ -1590,6 +1638,23 @@ CREATE INDEX phpbb_topics_watch_notify_stat ON phpbb_topics_watch (notify_status
/
/*
+ Table: 'phpbb_user_notifications'
+*/
+CREATE TABLE phpbb_user_notifications (
+ item_type varchar2(25) DEFAULT '' ,
+ item_id number(8) DEFAULT '0' NOT NULL,
+ user_id number(8) DEFAULT '0' NOT NULL,
+ method varchar2(25) DEFAULT '' ,
+ CONSTRAINT pk_phpbb_user_notifications PRIMARY KEY (item_type, item_id, user_id, method)
+)
+/
+
+CREATE INDEX phpbb_user_notifications_it ON phpbb_user_notifications (item_type)
+/
+CREATE INDEX phpbb_user_notifications_uid ON phpbb_user_notifications (user_id)
+/
+
+/*
Table: 'phpbb_user_group'
*/
CREATE TABLE phpbb_user_group (
diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql
index 659a32bf19..ffba657475 100644
--- a/phpBB/install/schemas/postgres_schema.sql
+++ b/phpBB/install/schemas/postgres_schema.sql
@@ -597,6 +597,32 @@ CREATE INDEX phpbb_modules_module_enabled ON phpbb_modules (module_enabled);
CREATE INDEX phpbb_modules_class_left_id ON phpbb_modules (module_class, left_id);
/*
+ Table: 'phpbb_notifications'
+*/
+CREATE SEQUENCE phpbb_notifications_seq;
+
+CREATE TABLE phpbb_notifications (
+ notification_id INT4 DEFAULT nextval('phpbb_notifications_seq'),
+ item_type varchar(25) DEFAULT '' NOT NULL,
+ item_id INT4 DEFAULT '0' NOT NULL CHECK (item_id >= 0),
+ item_parent_id INT4 DEFAULT '0' NOT NULL CHECK (item_parent_id >= 0),
+ user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0),
+ unread INT2 DEFAULT '1' NOT NULL CHECK (unread >= 0),
+ is_disabled INT2 DEFAULT '0' NOT NULL CHECK (is_disabled >= 0),
+ time INT4 DEFAULT '1' NOT NULL CHECK (time >= 0),
+ data varchar(4000) DEFAULT '' NOT NULL,
+ PRIMARY KEY (notification_id)
+);
+
+CREATE INDEX phpbb_notifications_item_type ON phpbb_notifications (item_type);
+CREATE INDEX phpbb_notifications_item_id ON phpbb_notifications (item_id);
+CREATE INDEX phpbb_notifications_item_pid ON phpbb_notifications (item_parent_id);
+CREATE INDEX phpbb_notifications_user_id ON phpbb_notifications (user_id);
+CREATE INDEX phpbb_notifications_time ON phpbb_notifications (time);
+CREATE INDEX phpbb_notifications_unread ON phpbb_notifications (unread);
+CREATE INDEX phpbb_notifications_is_disabled ON phpbb_notifications (is_disabled);
+
+/*
Table: 'phpbb_poll_options'
*/
CREATE TABLE phpbb_poll_options (
@@ -1094,6 +1120,20 @@ CREATE INDEX phpbb_topics_watch_user_id ON phpbb_topics_watch (user_id);
CREATE INDEX phpbb_topics_watch_notify_stat ON phpbb_topics_watch (notify_status);
/*
+ Table: 'phpbb_user_notifications'
+*/
+CREATE TABLE phpbb_user_notifications (
+ item_type varchar(25) DEFAULT '' NOT NULL,
+ item_id INT4 DEFAULT '0' NOT NULL CHECK (item_id >= 0),
+ user_id INT4 DEFAULT '0' NOT NULL CHECK (user_id >= 0),
+ method varchar(25) DEFAULT '' NOT NULL,
+ PRIMARY KEY (item_type, item_id, user_id, method)
+);
+
+CREATE INDEX phpbb_user_notifications_it ON phpbb_user_notifications (item_type);
+CREATE INDEX phpbb_user_notifications_uid ON phpbb_user_notifications (user_id);
+
+/*
Table: 'phpbb_user_group'
*/
CREATE TABLE phpbb_user_group (
diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql
index dbb5fd7481..0d47f4995e 100644
--- a/phpBB/install/schemas/schema_data.sql
+++ b/phpBB/install/schemas/schema_data.sql
@@ -175,6 +175,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jquery_cdn',
INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jumpbox', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_moderators', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_notifications', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_online', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_online_guests', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_online_time', '5');
diff --git a/phpBB/install/schemas/sqlite_schema.sql b/phpBB/install/schemas/sqlite_schema.sql
index 8360bc30ea..b63569ce3e 100644
--- a/phpBB/install/schemas/sqlite_schema.sql
+++ b/phpBB/install/schemas/sqlite_schema.sql
@@ -417,6 +417,27 @@ CREATE INDEX phpbb_modules_left_right_id ON phpbb_modules (left_id, right_id);
CREATE INDEX phpbb_modules_module_enabled ON phpbb_modules (module_enabled);
CREATE INDEX phpbb_modules_class_left_id ON phpbb_modules (module_class, left_id);
+# Table: 'phpbb_notifications'
+CREATE TABLE phpbb_notifications (
+ notification_id INTEGER PRIMARY KEY NOT NULL ,
+ item_type varchar(25) NOT NULL DEFAULT '',
+ item_id INTEGER UNSIGNED NOT NULL DEFAULT '0',
+ item_parent_id INTEGER UNSIGNED NOT NULL DEFAULT '0',
+ user_id INTEGER UNSIGNED NOT NULL DEFAULT '0',
+ unread INTEGER UNSIGNED NOT NULL DEFAULT '1',
+ is_disabled INTEGER UNSIGNED NOT NULL DEFAULT '0',
+ time INTEGER UNSIGNED NOT NULL DEFAULT '1',
+ data text(65535) NOT NULL DEFAULT ''
+);
+
+CREATE INDEX phpbb_notifications_item_type ON phpbb_notifications (item_type);
+CREATE INDEX phpbb_notifications_item_id ON phpbb_notifications (item_id);
+CREATE INDEX phpbb_notifications_item_pid ON phpbb_notifications (item_parent_id);
+CREATE INDEX phpbb_notifications_user_id ON phpbb_notifications (user_id);
+CREATE INDEX phpbb_notifications_time ON phpbb_notifications (time);
+CREATE INDEX phpbb_notifications_unread ON phpbb_notifications (unread);
+CREATE INDEX phpbb_notifications_is_disabled ON phpbb_notifications (is_disabled);
+
# Table: 'phpbb_poll_options'
CREATE TABLE phpbb_poll_options (
poll_option_id tinyint(4) NOT NULL DEFAULT '0',
@@ -823,6 +844,18 @@ CREATE INDEX phpbb_topics_watch_topic_id ON phpbb_topics_watch (topic_id);
CREATE INDEX phpbb_topics_watch_user_id ON phpbb_topics_watch (user_id);
CREATE INDEX phpbb_topics_watch_notify_stat ON phpbb_topics_watch (notify_status);
+# Table: 'phpbb_user_notifications'
+CREATE TABLE phpbb_user_notifications (
+ item_type varchar(25) NOT NULL DEFAULT '',
+ item_id INTEGER UNSIGNED NOT NULL DEFAULT '0',
+ user_id INTEGER UNSIGNED NOT NULL DEFAULT '0',
+ method varchar(25) NOT NULL DEFAULT '',
+ PRIMARY KEY (item_type, item_id, user_id, method)
+);
+
+CREATE INDEX phpbb_user_notifications_it ON phpbb_user_notifications (item_type);
+CREATE INDEX phpbb_user_notifications_uid ON phpbb_user_notifications (user_id);
+
# Table: 'phpbb_user_group'
CREATE TABLE phpbb_user_group (
group_id INTEGER UNSIGNED NOT NULL DEFAULT '0',
diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php
index 5eb10d50b3..0096a84878 100644
--- a/phpBB/language/en/acp/common.php
+++ b/phpBB/language/en/acp/common.php
@@ -250,6 +250,8 @@ $lang = array_merge($lang, array(
'IP' => 'User IP',
'IP_HOSTNAME' => 'IP addresses or hostnames',
+ 'LOAD_NOTIFICATIONS' => 'Display Notifications',
+ 'LOAD_NOTIFICATIONS_EXPLAIN' => 'Display the notifications list on every page (typically in the header).',
'LOGGED_IN_AS' => 'You are logged in as:',
'LOGIN_ADMIN' => 'To administer the board you must be an authenticated user.',
'LOGIN_ADMIN_CONFIRM' => 'To administer the board you must re-authenticate yourself.',
diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php
index e6022e3b79..75c681e86a 100644
--- a/phpBB/language/en/common.php
+++ b/phpBB/language/en/common.php
@@ -347,6 +347,7 @@ $lang = array_merge($lang, array(
'MARK' => 'Mark',
'MARK_ALL' => 'Mark all',
'MARK_FORUMS_READ' => 'Mark forums read',
+ 'MARK_READ' => 'Mark read',
'MARK_SUBFORUMS_READ' => 'Mark subforums read',
'MB' => 'MB',
'MIB' => 'MiB',
@@ -385,6 +386,25 @@ $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.',
+ 'NOTIFICATIONS' => 'Notifications',
+ 'NOTIFICATIONS_COUNT' => array(
+ 1 => '%d Notification',
+ 2 => '%d Notifications',
+ ),
+ 'NOTIFICATION_BOOKMARK' => '%1$s replied to the topic "%2$s" you have bookmarked.',
+ 'NOTIFICATION_PM' => '%1$s sent you a Private Message "%2$s".',
+ 'NOTIFICATION_POST' => '%1$s replied to the topic "%2$s".',
+ 'NOTIFICATION_POST_APPROVED' => 'Your post was approved "%2$s".',
+ 'NOTIFICATION_POST_DISAPPROVED' => 'Your post "%1$s" was disapproved for reason: "%2$s".',
+ 'NOTIFICATION_POST_IN_QUEUE' => 'A new post titled "%2$s" was posted by %1$s and needs approval.',
+ 'NOTIFICATION_QUOTE' => '%1$s quoted you in the post "%2$s".',
+ 'NOTIFICATION_REPORT_PM' => '%1$s reported a Private Message "%2$s" for reason: "%3$s".',
+ 'NOTIFICATION_REPORT_POST' => '%1$s reported a post "%2$s" for reason: "%3$s".',
+ 'NOTIFICATION_REPORT_CLOSED' => '%1$s closed the report you made for "%2$s".',
+ 'NOTIFICATION_TOPIC' => '%1$s posted a new topic "%2$s" in the forum "%3$s".',
+ 'NOTIFICATION_TOPIC_APPROVED' => 'Your topic "%2$s" in the forum "%3$s" was approved.',
+ 'NOTIFICATION_TOPIC_DISAPPROVED' => 'Your topic "%1$s" was disapproved for reason: "%2$s".',
+ 'NOTIFICATION_TOPIC_IN_QUEUE' => 'A new topic titled "%2$s" was posted by %1$s and needs approval.',
'NOTIFY_ADMIN' => 'Please notify the board administrator or webmaster.',
'NOTIFY_ADMIN_EMAIL' => 'Please notify the board administrator or webmaster: <a href="mailto:%1$s">%1$s</a>',
'NO_ACCESS_ATTACHMENT' => 'You are not allowed to access this file.',
@@ -572,6 +592,7 @@ $lang = array_merge($lang, array(
'SEARCH_UNREAD' => 'View unread posts',
'SEARCH_USER_POSTS' => 'Search user’s posts',
'SECONDS' => 'Seconds',
+ 'SEE_ALL' => 'See All',
'SELECT' => 'Select',
'SELECT_ALL_CODE' => 'Select all',
'SELECT_DESTINATION_FORUM' => 'Please select a destination forum',
diff --git a/phpBB/language/en/email/forum_notify.txt b/phpBB/language/en/email/forum_notify.txt
index 490780a0a6..66f3a68689 100644
--- a/phpBB/language/en/email/forum_notify.txt
+++ b/phpBB/language/en/email/forum_notify.txt
@@ -2,7 +2,7 @@ Subject: Forum post notification - "{FORUM_NAME}"
Hello {USERNAME},
-You are receiving this notification because you are watching the forum, "{FORUM_NAME}" at "{SITENAME}". This forum has received a new reply to the topic "{TOPIC_TITLE}"<!-- IF AUTHOR_NAME --> by {AUTHOR_NAME}<!-- ENDIF --> since your last visit. You can use the following link to view the last unread reply, no more notifications will be sent until you visit the topic.
+You are receiving this notification because you are watching the forum "{FORUM_NAME}" at "{SITENAME}". This forum has received a new reply to the topic "{TOPIC_TITLE}"<!-- IF AUTHOR_NAME --> by {AUTHOR_NAME}<!-- ENDIF --> since your last visit. You can use the following link to view the last unread reply, no more notifications will be sent until you visit the topic.
{U_NEWEST_POST}
diff --git a/phpBB/language/en/email/newtopic_notify.txt b/phpBB/language/en/email/newtopic_notify.txt
index eda1370938..d4f5cae620 100644
--- a/phpBB/language/en/email/newtopic_notify.txt
+++ b/phpBB/language/en/email/newtopic_notify.txt
@@ -2,7 +2,7 @@ Subject: New topic notification - "{FORUM_NAME}"
Hello {USERNAME},
-You are receiving this notification because you are watching the forum, "{FORUM_NAME}" at "{SITENAME}". This forum has received a new topic<!-- IF AUTHOR_NAME --> by {AUTHOR_NAME}<!-- ENDIF --> since your last visit, "{TOPIC_TITLE}". You can use the following link to view the forum, no more notifications will be sent until you visit the forum.
+You are receiving this notification because you are watching the forum "{FORUM_NAME}" at "{SITENAME}". This forum has received a new topic<!-- IF AUTHOR_NAME --> by {AUTHOR_NAME}<!-- ENDIF --> since your last visit, "{TOPIC_TITLE}". You can use the following link to view the forum, no more notifications will be sent until you visit the forum.
{U_FORUM}
diff --git a/phpBB/language/en/email/notifications/bookmark.txt b/phpBB/language/en/email/notifications/bookmark.txt
new file mode 100644
index 0000000000..95f17b5693
--- /dev/null
+++ b/phpBB/language/en/email/notifications/bookmark.txt
@@ -0,0 +1,20 @@
+Subject: Topic reply notification - "{TOPIC_TITLE}"
+
+Hello {USERNAME},
+
+You are receiving this notification because a topic you bookmarked, "{TOPIC_TITLE}" at "{SITENAME}", has received a reply since your last visit. You can use the following link to view the replies made, no more notifications will be sent until you visit the topic.
+
+If you want to view the newest post made since your last visit, click the following link:
+{U_NEWEST_POST}
+
+If you want to view the topic, click the following link:
+{U_TOPIC}
+
+If you want to view the forum, click the following link:
+{U_FORUM}
+
+If you no longer wish to receive updates about replies to bookmarks, please update your notification settings here:
+
+{U_NOTIFICATION_SETTINGS}
+
+{EMAIL_SIG}
diff --git a/phpBB/language/en/email/notifications/post_in_queue.txt b/phpBB/language/en/email/notifications/post_in_queue.txt
new file mode 100644
index 0000000000..8d56ce6c4d
--- /dev/null
+++ b/phpBB/language/en/email/notifications/post_in_queue.txt
@@ -0,0 +1,17 @@
+Subject: Topic reply notification - "{TOPIC_TITLE}"
+
+Hello {USERNAME},
+
+You are receiving this notification because the post "{POST_SUBJECT}" at "{SITENAME}" needs approval.
+
+If you want to view the post, click the following link:
+{U_VIEW_POST}
+
+If you want to view the topic, click the following link:
+{U_TOPIC}
+
+If you no longer wish to receive updates about replies to bookmarks, please update your notification settings here:
+
+{U_NOTIFICATION_SETTINGS}
+
+{EMAIL_SIG}
diff --git a/phpBB/language/en/email/notifications/quote.txt b/phpBB/language/en/email/notifications/quote.txt
new file mode 100644
index 0000000000..2b9525801f
--- /dev/null
+++ b/phpBB/language/en/email/notifications/quote.txt
@@ -0,0 +1,20 @@
+Subject: Topic reply notification - "{TOPIC_TITLE}"
+
+Hello {USERNAME},
+
+You are receiving this notification because "{AUTHOR_NAME}" quoted you in the topic "{TOPIC_TITLE}" at "{SITENAME}". You can use the following link to view the reply made.
+
+If you want to view the quoted post, click the following link:
+{U_VIEW_POST}
+
+If you want to view the topic, click the following link:
+{U_TOPIC}
+
+If you want to view the forum, click the following link:
+{U_FORUM}
+
+If you no longer wish to receive updates about replies quoting you, please update your notification settings here:
+
+{U_NOTIFICATION_SETTINGS}
+
+{EMAIL_SIG}
diff --git a/phpBB/language/en/email/notifications/report_pm.txt b/phpBB/language/en/email/notifications/report_pm.txt
new file mode 100644
index 0000000000..66ae82d074
--- /dev/null
+++ b/phpBB/language/en/email/notifications/report_pm.txt
@@ -0,0 +1,14 @@
+Subject: Topic reply notification - "{TOPIC_TITLE}"
+
+Hello {USERNAME},
+
+You are receiving this notification because a Private Message titled "{SUBJECT}" by "{AUTHOR_NAME}" at "{SITENAME}" was reported.
+
+If you want to view the report, click the following link:
+{U_VIEW_REPORT}
+
+If you no longer wish to receive updates about replies to bookmarks, please update your notification settings here:
+
+{U_NOTIFICATION_SETTINGS}
+
+{EMAIL_SIG}
diff --git a/phpBB/language/en/email/notifications/report_post.txt b/phpBB/language/en/email/notifications/report_post.txt
new file mode 100644
index 0000000000..46983be1ed
--- /dev/null
+++ b/phpBB/language/en/email/notifications/report_post.txt
@@ -0,0 +1,17 @@
+Subject: Topic reply notification - "{TOPIC_TITLE}"
+
+Hello {USERNAME},
+
+You are receiving this notification because the post "{POST_SUBJECT}" at "{SITENAME}" was reported.
+
+If you want to view the report, click the following link:
+{U_VIEW_REPORT}
+
+If you want to view the post, click the following link:
+{U_VIEW_POST}
+
+If you no longer wish to receive updates about replies to bookmarks, please update your notification settings here:
+
+{U_NOTIFICATION_SETTINGS}
+
+{EMAIL_SIG}
diff --git a/phpBB/language/en/email/notifications/topic_in_queue.txt b/phpBB/language/en/email/notifications/topic_in_queue.txt
new file mode 100644
index 0000000000..ae8f9e2484
--- /dev/null
+++ b/phpBB/language/en/email/notifications/topic_in_queue.txt
@@ -0,0 +1,17 @@
+Subject: Topic reply notification - "{TOPIC_TITLE}"
+
+Hello {USERNAME},
+
+You are receiving this notification because the topic "{TOPIC_TITLE}" at "{SITENAME}" needs approval.
+
+If you want to view the topic, click the following link:
+{U_VIEW_TOPIC}
+
+If you want to view the forum, click the following link:
+{U_FORUM}
+
+If you no longer wish to receive updates about replies to bookmarks, please update your notification settings here:
+
+{U_NOTIFICATION_SETTINGS}
+
+{EMAIL_SIG}
diff --git a/phpBB/language/en/email/topic_notify.txt b/phpBB/language/en/email/topic_notify.txt
index fcfbcc2abd..fa2481dd9a 100644
--- a/phpBB/language/en/email/topic_notify.txt
+++ b/phpBB/language/en/email/topic_notify.txt
@@ -2,7 +2,7 @@ Subject: Topic reply notification - "{TOPIC_TITLE}"
Hello {USERNAME},
-You are receiving this notification because you are watching the topic, "{TOPIC_TITLE}" at "{SITENAME}". This topic has received a reply<!-- IF AUTHOR_NAME --> by {AUTHOR_NAME}<!-- ENDIF --> since your last visit. You can use the following link to view the replies made, no more notifications will be sent until you visit the topic.
+You are receiving this notification because you are watching the topic "{TOPIC_TITLE}" at "{SITENAME}". This topic has received a reply<!-- IF AUTHOR_NAME --> by {AUTHOR_NAME}<!-- ENDIF --> since your last visit. You can use the following link to view the replies made, no more notifications will be sent until you visit the topic.
If you want to view the newest post made since your last visit, click the following link:
{U_NEWEST_POST}
diff --git a/phpBB/language/en/ucp.php b/phpBB/language/en/ucp.php
index 705b07b170..7c3960204a 100644
--- a/phpBB/language/en/ucp.php
+++ b/phpBB/language/en/ucp.php
@@ -288,6 +288,25 @@ $lang = array_merge($lang, array(
'NEW_PASSWORD' => 'New password',
'NEW_PASSWORD_CONFIRM_EMPTY' => 'You did not enter a confirm password.',
'NEW_PASSWORD_ERROR' => 'The passwords you entered do not match.',
+
+ 'NOTIFICATIONS_MARK_ALL_READ' => 'Mark all notifications read',
+ 'NOTIFICATIONS_MARK_ALL_READ_CONFIRM' => 'Are you sure you want to mark all notifications read?',
+ 'NOTIFICATIONS_MARK_ALL_READ_SUCCESS' => 'All notifications have been marked read successfully.',
+ 'NOTIFICATION_GROUP_MISCELLANEOUS' => 'Miscellaneous Notifications',
+ 'NOTIFICATION_GROUP_MODERATION' => 'Moderation Notifications',
+ 'NOTIFICATION_GROUP_POSTING' => 'Posting Notifications',
+ 'NOTIFICATION_METHOD_EMAIL' => 'Email',
+ 'NOTIFICATION_METHOD_JABBER' => 'Jabber',
+ 'NOTIFICATION_TYPE' => 'Notification type',
+ 'NOTIFICATION_TYPE_BOOKMARK' => 'Someone replies to a topic you have bookmarked',
+ 'NOTIFICATION_TYPE_IN_MODERATION_QUEUE' => 'A post or topic needs approval',
+ 'NOTIFICATION_TYPE_MODERATION_QUEUE' => 'Your topics/posts are approved or disapproved by a moderator',
+ 'NOTIFICATION_TYPE_PM' => 'Someone sends you a private message',
+ 'NOTIFICATION_TYPE_POST' => 'Someone replies to a topic you are subscribed to',
+ 'NOTIFICATION_TYPE_QUOTE' => 'Someone quotes you in a post',
+ 'NOTIFICATION_TYPE_REPORT' => 'Someone reports a post',
+ 'NOTIFICATION_TYPE_TOPIC' => 'Someone creates a topic in a forum you are subscribed to',
+
'NOTIFY_METHOD' => 'Notification method',
'NOTIFY_METHOD_BOTH' => 'Both',
'NOTIFY_METHOD_EMAIL' => 'Email only',
@@ -457,6 +476,11 @@ $lang = array_merge($lang, array(
'UCP_MSNM' => 'Windows Live Messenger',
'UCP_NO_ATTACHMENTS' => 'You have posted no files.',
+ 'UCP_NOTIFICATION_LIST' => 'Manage notifications',
+ 'UCP_NOTIFICATION_LIST_EXPLAIN' => 'Here you may view all past notifications.',
+ 'UCP_NOTIFICATION_OPTIONS' => 'Edit notification options',
+ 'UCP_NOTIFICATION_OPTIONS_EXPLAIN' => 'Here you can set your preferred notification methods for the board.',
+
'UCP_PREFS' => 'Board preferences',
'UCP_PREFS_PERSONAL' => 'Edit global settings',
'UCP_PREFS_POST' => 'Edit posting defaults',
diff --git a/phpBB/report.php b/phpBB/report.php
index 29b46a6211..9f3b09d5ba 100644
--- a/phpBB/report.php
+++ b/phpBB/report.php
@@ -131,7 +131,7 @@ else
$message .= '<br /><br />' . sprintf($user->lang['RETURN_PM'], '<a href="' . $redirect_url . '">', '</a>');
trigger_error($message);
}
-
+
$reported_post_text = $report_data['message_text'];
}
@@ -184,6 +184,11 @@ if ($submit && $reason_id)
$lang_return = $user->lang['RETURN_TOPIC'];
$lang_success = $user->lang['POST_REPORTED_SUCCESS'];
+
+ // Notify relevant users
+ $phpbb_notifications->add_notifications('report_post', array_merge($report_data, $row, $forum_data, array(
+ 'report_text' => $report_text,
+ )));
}
else
{
@@ -210,6 +215,13 @@ if ($submit && $reason_id)
$lang_return = $user->lang['RETURN_PM'];
$lang_success = $user->lang['PM_REPORTED_SUCCESS'];
+
+ // Notify relevant users
+ $phpbb_notifications->add_notifications('report_pm', array_merge($report_data, $row, array(
+ 'report_text' => $report_text,
+ 'from_user_id' => $report_data['author_id'],
+ 'report_id' => $report_id,
+ )));
}
meta_refresh(3, $redirect_url);
diff --git a/phpBB/styles/prosilver/template/ajax.js b/phpBB/styles/prosilver/template/ajax.js
index 54f34e4204..3c5e1a1c12 100644
--- a/phpBB/styles/prosilver/template/ajax.js
+++ b/phpBB/styles/prosilver/template/ajax.js
@@ -76,7 +76,18 @@ $('#qr_full_editor').click(function() {
});
});
+// Toggle notification list
+$('#notification_list_button').click(function() {
+ $('#notification_list').toggle();
+ return false;
+});
+$('#phpbb').click(function(e) {
+ var target = e.target;
+ if (!$(target).is('#notification_list') && !$(target).is('#notification_list_button') && !$(target).parents().is('#notification_list')) {
+ $('#notification_list').hide();
+ }
+});
/**
* This AJAXifies the quick-mod tools. The reason it cannot be a standard
diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html
index 0900222d09..21a1fde7ea 100644
--- a/phpBB/styles/prosilver/template/overall_header.html
+++ b/phpBB/styles/prosilver/template/overall_header.html
@@ -5,7 +5,7 @@
<meta name="keywords" content="" />
<meta name="description" content="" />
{META}
-<title><!-- IF not S_VIEWTOPIC and not S_VIEWFORUM -->{SITENAME} - <!-- ENDIF --><!-- IF S_IN_MCP -->{L_MCP} - <!-- ELSEIF S_IN_UCP -->{L_UCP} - <!-- ENDIF -->{PAGE_TITLE}<!-- IF S_VIEWTOPIC or S_VIEWFORUM --> - {SITENAME}<!-- ENDIF --></title>
+<title><!-- IF UNREAD_NOTIFICATIONS_COUNT -->({UNREAD_NOTIFICATIONS_COUNT}) <!-- ENDIF --><!-- IF not S_VIEWTOPIC and not S_VIEWFORUM -->{SITENAME} - <!-- ENDIF --><!-- IF S_IN_MCP -->{L_MCP} - <!-- ELSEIF S_IN_UCP -->{L_UCP} - <!-- ENDIF -->{PAGE_TITLE}<!-- IF S_VIEWTOPIC or S_VIEWFORUM --> - {SITENAME}<!-- ENDIF --></title>
<!-- IF S_ENABLE_FEEDS -->
<!-- IF S_ENABLE_FEEDS_OVERALL --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {SITENAME}" href="{U_FEED}" /><!-- ENDIF -->
@@ -130,9 +130,41 @@
<!-- IF not S_IS_BOT and S_USER_LOGGED_IN -->
<ul class="linklist leftside">
+ <!-- IF S_NOTIFICATIONS_DISPLAY -->
+ <li>
+ [ <a href="#" id="notification_list_button" title="{NOTIFICATIONS_COUNT}">{NOTIFICATIONS_COUNT}</a> ] &bull;
+ <div id="notification_list" class="notification_list">
+ <div class="header">
+ {L_NOTIFICATIONS}
+ </div>
+
+ <ul>
+ <!-- BEGIN notifications -->
+ <li class="<!-- IF notifications.UNREAD --> bg2<!-- ENDIF -->">
+ <!-- IF notifications.URL --><a href="<!-- IF notifications.UNREAD -->{notifications.U_MARK_READ}<!-- ELSE -->{notifications.URL}<!-- ENDIF -->"><!-- ENDIF -->
+ {notifications.AVATAR}
+ <div>
+ <p>{notifications.FORMATTED_TITLE}</p>
+ <p>{notifications.TIME}</p>
+
+ <!-- IF not notifications.URL and notifications.U_MARK_READ -->
+ <p><a href="{notifications.U_MARK_READ}">{L_MARK_READ}</a></p>
+ <!-- ENDIF -->
+ </div>
+ <!-- IF notifications.URL --></a><!-- ENDIF -->
+ </li>
+ <!-- END notifications -->
+ </ul>
+
+ <div class="footer">
+ <a href="{U_VIEW_ALL_NOTIFICATIONS}"><span>{L_SEE_ALL}</span></a>
+ </div>
+ </div>
+ </li>
+ <!-- ENDIF -->
<li class="icon-ucp">
<a href="{U_PROFILE}" title="{L_PROFILE}" accesskey="e">{L_PROFILE}</a>
- <!-- IF S_DISPLAY_PM --> (<a href="{U_PRIVATEMSGS}">{PRIVATE_MESSAGE_INFO}<!-- IF PRIVATE_MESSAGE_INFO_UNREAD -->, {PRIVATE_MESSAGE_INFO_UNREAD}<!-- ENDIF --></a>)<!-- ENDIF -->
+ <!-- IF not S_NOTIFICATIONS_DISPLAY and S_DISPLAY_PM --> (<a href="{U_PRIVATEMSGS}">{PRIVATE_MESSAGE_INFO}<!-- IF PRIVATE_MESSAGE_INFO_UNREAD -->, {PRIVATE_MESSAGE_INFO_UNREAD}<!-- ENDIF --></a>)<!-- ENDIF -->
<!-- IF S_DISPLAY_SEARCH --> &bull;
<a href="{U_SEARCH_SELF}">{L_SEARCH_SELF}</a>
<!-- ENDIF -->
diff --git a/phpBB/styles/prosilver/template/ucp_notifications.html b/phpBB/styles/prosilver/template/ucp_notifications.html
new file mode 100644
index 0000000000..728fe972b1
--- /dev/null
+++ b/phpBB/styles/prosilver/template/ucp_notifications.html
@@ -0,0 +1,124 @@
+<!-- INCLUDE ucp_header.html -->
+
+<form id="ucp" method="post" action="{S_UCP_ACTION}"{S_FORM_ENCTYPE}>
+
+<h2>{TITLE}</h2>
+<div class="panel">
+ <div class="inner">
+
+ <p>{TITLE_EXPLAIN}</p>
+
+ <!-- IF MODE == 'notification_options' -->
+ <ul class="topiclist">
+ <li class="header">
+ <dl>
+ <dt>{L_NOTIFICATION_TYPE}</dt>
+ <!-- BEGIN notification_methods -->
+ <dd class="mark">{notification_methods.NAME}</dd>
+ <!-- END notification_methods -->
+ <dd class="mark">{L_NOTIFICATIONS}</dd>
+ </dl>
+ </li>
+ </ul>
+ <ul class="topiclist cplist">
+
+ <!-- BEGIN notification_types -->
+ <!-- IF notification_types.GROUP_NAME -->
+ <li class="row bg3">
+ <dl>
+ <dt>
+ {notification_types.GROUP_NAME}
+ </dt>
+ </dl>
+ </li>
+ <!-- ELSE -->
+ <li class="row<!-- IF notification_types.S_ROW_COUNT is odd --> bg1<!-- ELSE --> bg2<!-- ENDIF -->">
+ <dl>
+ <dt>
+ {notification_types.NAME}
+ <!-- IF notification_types.EXPLAIN --><br />&nbsp; &nbsp;{notification_types.EXPLAIN}<!-- ENDIF -->
+ </dt>
+ <!-- BEGIN notification_methods -->
+ <dd class="mark"><input type="checkbox" name="{notification_types.TYPE}_{notification_methods.METHOD}"<!-- IF notification_methods.SUBSCRIBED --> checked="checked"<!-- ENDIF --> /> <dfn>{notification_methods.NAME}</dfn></dd>
+ <!-- END notification_methods -->
+ <dd class="mark"><input type="checkbox" name="{notification_types.TYPE}_notification"<!-- IF notification_types.SUBSCRIBED --> checked="checked"<!-- ENDIF --> /> <dfn>{notification_methods.NAME}</dfn></dd>
+ </dl>
+ </li>
+ <!-- ENDIF -->
+ <!-- END notification_types -->
+ </ul>
+ <!-- ELSE -->
+ <!-- IF .pagination or TOTAL_COUNT -->
+ <div class="topic-actions">
+ <div class="pagination">
+ <!-- IF U_MARK_ALL --><a href="{U_MARK_ALL}">{L_NOTIFICATIONS_MARK_ALL_READ}</a> &bull; <!-- ENDIF -->
+ <!-- IF TOTAL_COUNT -->{TOTAL_COUNT} &bull; <!-- ENDIF -->
+ <!-- IF .pagination -->
+ <!-- INCLUDE pagination.html -->
+ <!-- ELSE -->
+ {PAGE_NUMBER}
+ <!-- ENDIF -->
+ </div>
+ </div>
+ <!-- ENDIF -->
+
+ <div class="notification_list">
+ <ul class="topiclist">
+ <li class="header">
+ <dl>
+ <dt>{L_NOTIFICATIONS}</dt>
+ <dd class="mark">{L_MARK_READ}</dd>
+ </dl>
+ </li>
+ <!-- BEGIN notification_list -->
+ <li class="row<!-- IF notification_list.UNREAD --> bg3<!-- ELSE --><!-- IF notification_list.S_ROW_COUNT is odd --> bg1<!-- ELSE --> bg2<!-- ENDIF --><!-- ENDIF -->">
+ <dl>
+ <dt>
+ <!-- IF notification_list.URL --><a href="<!-- IF notification_list.UNREAD -->{notification_list.U_MARK_READ}<!-- ELSE -->{notification_list.URL}<!-- ENDIF -->"><!-- ENDIF -->
+ {notification_list.AVATAR}
+ <div>
+ <p>{notification_list.FORMATTED_TITLE}</p>
+ <p>{notification_list.TIME}</p>
+
+ <!-- IF not notification_list.URL and notification_list.U_MARK_READ -->
+ <p><a href="{notification_list.U_MARK_READ}">{L_MARK_READ}</a></p>
+ <!-- ENDIF -->
+ </div>
+ <!-- IF notification_list.URL --></a><!-- ENDIF -->
+ </dt>
+
+ <dd class="mark">&nbsp;<!-- IF notification_list.UNREAD --><input type="checkbox" name="mark[]" value="{notification_list.NOTIFICATION_ID}" /> <dfn>{L_MARK_READ}</dfn><!-- ENDIF -->&nbsp;</dd>
+ </dl>
+ </li>
+ <!-- END notification_list -->
+ </ul>
+ </div>
+
+ <!-- IF .pagination or TOTAL_COUNT -->
+ <div class="topic-actions">
+ <div class="pagination">
+ <!-- IF TOTAL_COUNT -->{TOTAL_COUNT} &bull; <!-- ENDIF -->
+ <!-- IF .pagination -->
+ <!-- INCLUDE pagination.html -->
+ <!-- ELSE -->
+ {PAGE_NUMBER}
+ <!-- ENDIF -->
+ </div>
+ </div>
+ <!-- ENDIF -->
+
+ <!-- ENDIF -->
+ </div>
+</div>
+
+
+<fieldset class="submit-buttons">
+ <input type="hidden" name="form_time" value="{FORM_TIME}" />
+ {S_HIDDEN_FIELDS}<input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
+ <input type="submit" name="submit" value="{L_SUBMIT}" class="button1" />
+ {S_FORM_TOKEN}
+</fieldset>
+
+</form>
+
+<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/prosilver/template/ucp_prefs_personal.html b/phpBB/styles/prosilver/template/ucp_prefs_personal.html
index 29c01e03b9..f03cb2af38 100644
--- a/phpBB/styles/prosilver/template/ucp_prefs_personal.html
+++ b/phpBB/styles/prosilver/template/ucp_prefs_personal.html
@@ -38,32 +38,8 @@
<label for="hideonline0"><input type="radio" name="hideonline" id="hideonline0" value="0"<!-- IF not S_HIDE_ONLINE --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
- <!-- ENDIF -->
- <!-- IF S_SELECT_NOTIFY -->
- <dl>
- <dt><label for="notifymethod0">{L_NOTIFY_METHOD}:</label></dt>
- <dd>
- <label for="notifymethod0"><input type="radio" name="notifymethod" id="notifymethod0" value="0"<!-- IF S_NOTIFY_EMAIL --> checked="checked"<!-- ENDIF --> /> {L_NOTIFY_METHOD_EMAIL}</label>
- <label for="notifymethod1"><input type="radio" name="notifymethod" id="notifymethod1" value="1"<!-- IF S_NOTIFY_IM --> checked="checked"<!-- ENDIF --> /> {L_NOTIFY_METHOD_IM}</label>
- <label for="notifymethod2"><input type="radio" name="notifymethod" id="notifymethod2" value="2"<!-- IF S_NOTIFY_BOTH --> checked="checked"<!-- ENDIF --> /> {L_NOTIFY_METHOD_BOTH}</label>
- </dd>
- </dl>
<!-- ENDIF -->
<dl>
- <dt><label for="notifypm1">{L_NOTIFY_ON_PM}:</label></dt>
- <dd>
- <label for="notifypm1"><input type="radio" name="notifypm" id="notifypm1" value="1"<!-- IF S_NOTIFY_PM --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
- <label for="notifypm0"><input type="radio" name="notifypm" id="notifypm0" value="0"<!-- IF not S_NOTIFY_PM --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
- </dd>
- </dl>
- <dl>
- <dt><label for="popuppm0">{L_POPUP_ON_PM}:</label></dt>
- <dd>
- <label for="popuppm1"><input type="radio" name="popuppm" id="popuppm1" value="1"<!-- IF S_POPUP_PM --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
- <label for="popuppm0"><input type="radio" name="popuppm" id="popuppm0" value="0"<!-- IF not S_POPUP_PM --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
- </dd>
- </dl>
- <dl>
<dt><label for="lang">{L_BOARD_LANGUAGE}:</label></dt>
<dd><select name="lang" id="lang">{S_LANG_OPTIONS}</select></dd>
</dl>
diff --git a/phpBB/styles/prosilver/theme/colours.css b/phpBB/styles/prosilver/theme/colours.css
index 29968cbb14..49e404a903 100644
--- a/phpBB/styles/prosilver/theme/colours.css
+++ b/phpBB/styles/prosilver/theme/colours.css
@@ -1,4 +1,4 @@
-/*
+/*
--------------------------------------------------------------
Colours and backgrounds for common.css
-------------------------------------------------------------- */
@@ -65,7 +65,7 @@ hr {
.panel {
background-color: #ECF1F3;
- color: #28313F;
+ color: #28313F;
}
.post:target .content {
@@ -219,7 +219,7 @@ p.rules {
background-image: none;
}
-/*
+/*
--------------------------------------------------------------
Colours and backgrounds for links.css
-------------------------------------------------------------- */
@@ -312,7 +312,7 @@ a.topictitle:active {
color: #105289;
}
-/* Profile searchresults */
+/* Profile searchresults */
.search .postprofile a {
color: #105289;
}
@@ -349,7 +349,7 @@ a.right:hover {
}
-/*
+/*
--------------------------------------------------------------
Colours and backgrounds for content.css
-------------------------------------------------------------- */
@@ -644,7 +644,7 @@ fieldset.polls dd div {
background-image: url("./en/icon_user_online.gif");
}
-/*
+/*
--------------------------------------------------------------
Colours and backgrounds for buttons.css
-------------------------------------------------------------- */
@@ -752,7 +752,7 @@ a.sendemail {
.pm_read { background-image: url("./images/topic_read.gif"); }
.pm_unread { background-image: url("./images/topic_unread.gif"); }
-/*
+/*
--------------------------------------------------------------
Colours and backgrounds for cp.css
-------------------------------------------------------------- */
@@ -921,7 +921,7 @@ dl.mini dt {
background-color: #EEE;
}
-/*
+/*
--------------------------------------------------------------
Colours and backgrounds for forms.css
-------------------------------------------------------------- */
@@ -976,7 +976,7 @@ fieldset.quick-login input.inputbox {
/* Input field styles
---------------------------------------- */
.inputbox {
- background-color: #FFFFFF;
+ background-color: #FFFFFF;
border-color: #B4BAC0;
color: #333333;
}
@@ -1044,3 +1044,16 @@ input.disabled {
background-color: #000000;
}
+#notification_list {
+ background-color: #FFFFFF;
+ border-color: #00608F;
+}
+
+#notification_list ul li:hover {
+ background-color: #CFE1F6;
+ color: #000000;
+}
+
+#notification_list > .header, .notification_list > .footer {
+ border-color: #00608F;
+} \ No newline at end of file
diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css
index 4b4fa263b1..863feb576b 100644
--- a/phpBB/styles/prosilver/theme/common.css
+++ b/phpBB/styles/prosilver/theme/common.css
@@ -9,8 +9,8 @@ b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
-article, aside, canvas, details, embed,
-figure, figcaption, footer, header, hgroup,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
@@ -21,7 +21,7 @@ time, mark, audio, video {
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
-article, aside, details, figcaption, figure,
+article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
@@ -164,7 +164,7 @@ ul ul, ol ul {
ol ol ul, ol ul ul, ul ol ul, ul ul ul {
list-style-type: square;
-}
+}
/* Main blocks
@@ -665,3 +665,75 @@ p.rules a {
.smilies {
vertical-align: text-bottom;
}
+
+#notification_list {
+ display: none;
+ position: absolute;
+ width: 330px;
+ z-index: 1;
+ border: 1px solid;
+ border-radius: 4px;
+ box-shadow: 4px 4px 5px;
+}
+
+#notification_list ul {
+ max-height: 350px;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+#notification_list ul li {
+ width: ;
+ padding: 10px;
+ margin: 0;
+ float: left;
+ border-bottom: 1px solid;
+ list-style-type: none;
+ font-size: 0.95em;
+ clear: both;
+}
+
+#notification_list ul li {
+ width: 310px;
+}
+
+#notification_list ul li:last-child {
+ border-bottom: 0px;
+}
+
+#notification_list > .header {
+ padding: 0 5px;
+ font-weight: bold;
+ border-bottom: 1px solid;
+}
+
+#notification_list > .footer {
+ text-align: center;
+ font-size: 1.2em;
+ border-top: 1px solid;
+}
+
+#notification_list ul li a, .notification_list dt > a, #notification_list > .footer > a {
+ display: block;
+}
+
+.notification_list ul li img {
+ float: left;
+ max-width: 50px;
+ max-height: 50px;
+ margin-right: 5px;
+}
+
+#notification_list ul li div {
+ width: 240px;
+ float: left;
+}
+
+.notification_list ul li p {
+ margin: 0;
+ word-wrap: break-word;
+}
+
+.notification_list ul.topiclist dt {
+ width: 88%;
+} \ No newline at end of file
diff --git a/phpBB/styles/subsilver2/template/overall_footer.html b/phpBB/styles/subsilver2/template/overall_footer.html
index 24c6f8105c..210159732e 100644
--- a/phpBB/styles/subsilver2/template/overall_footer.html
+++ b/phpBB/styles/subsilver2/template/overall_footer.html
@@ -12,5 +12,19 @@
<!-- IF S_JQUERY_FALLBACK --><script type="text/javascript">window.jQuery || document.write(unescape('%3Cscript src="{T_ASSETS_PATH}/javascript/jquery.js?assets_version={T_ASSETS_VERSION}" type="text/javascript"%3E%3C/script%3E'));</script><!-- ENDIF -->
{SCRIPTS}
+<script type="text/javascript">
+// <![CDATA[
+<!-- IF S_NOTIFICATIONS_DISPLAY -->
+$(document).click(function(e) {
+ var target = e.target;
+
+ if (!$(target).is('#notification_list') && !$(target).is('#notification_list_button') && !$(target).parents().is('#notification_list')) {
+ $('#notification_list').hide();
+ }
+});
+<!-- ENDIF -->
+// ]]>
+</script>
+
</body>
</html>
diff --git a/phpBB/styles/subsilver2/template/overall_header.html b/phpBB/styles/subsilver2/template/overall_header.html
index 8bedec4c9e..aec754c444 100644
--- a/phpBB/styles/subsilver2/template/overall_header.html
+++ b/phpBB/styles/subsilver2/template/overall_header.html
@@ -5,7 +5,7 @@
<meta name="keywords" content="" />
<meta name="description" content="" />
{META}
-<title><!-- IF not S_VIEWTOPIC and not S_VIEWFORUM -->{SITENAME} - <!-- ENDIF --><!-- IF S_IN_MCP -->{L_MCP} - <!-- ELSEIF S_IN_UCP -->{L_UCP} - <!-- ENDIF -->{PAGE_TITLE}<!-- IF S_VIEWTOPIC or S_VIEWFORUM --> - {SITENAME}<!-- ENDIF --></title>
+<title><!-- IF UNREAD_NOTIFICATIONS_COUNT -->({UNREAD_NOTIFICATIONS_COUNT}) <!-- ENDIF --><!-- IF not S_VIEWTOPIC and not S_VIEWFORUM -->{SITENAME} - <!-- ENDIF --><!-- IF S_IN_MCP -->{L_MCP} - <!-- ELSEIF S_IN_UCP -->{L_UCP} - <!-- ENDIF -->{PAGE_TITLE}<!-- IF S_VIEWTOPIC or S_VIEWFORUM --> - {SITENAME}<!-- ENDIF --></title>
<!-- IF S_ENABLE_FEEDS -->
<!-- IF S_ENABLE_FEEDS_OVERALL --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {SITENAME}" href="{U_FEED}" /><!-- ENDIF -->
@@ -149,12 +149,51 @@ function marklist(id, name, state)
<table width="100%" cellspacing="0">
<tr>
<td class="genmed">
+ <!-- IF S_NOTIFICATIONS_DISPLAY -->
+ [ <a href="#" id="notification_list_button" title="{NOTIFICATIONS_COUNT}" onclick="$('#notification_list').toggle(); return false;">{NOTIFICATIONS_COUNT}</a> ] &bull;
+ <div id="notification_list" class="notification_list">
+ <div class="row1 header">
+ {L_NOTIFICATIONS}
+ </div>
+
+ <div class="notification_scroll">
+ <table class="tablebg" width="310px" cellspacing="1">
+ <!-- BEGIN notifications -->
+ <tr class="row<!-- IF notifications.UNREAD -->2<!-- ELSE -->1<!-- ENDIF -->">
+ <!-- IF notifications.AVATAR -->
+ <td width="50px">
+ {notifications.AVATAR}
+ </td>
+ <td valign="top">
+ <!-- ELSE -->
+ <td colspan="2" valign="top">
+ <!-- ENDIF -->
+ <div class="notification_title">
+ <!-- IF notifications.URL --><a href="<!-- IF notifications.UNREAD -->{notifications.U_MARK_READ}<!-- ELSE -->{notifications.URL}<!-- ENDIF -->"><!-- ENDIF -->
+ {notifications.FORMATTED_TITLE}
+ <!-- IF notifications.URL --></a><!-- ENDIF -->
+ <br />{notifications.TIME}
+ <!-- IF not notifications.URL and notifications.UNREAD -->
+ <br /><a href="{notifications.U_MARK_READ}">{L_MARK_READ}</a>
+ <!-- ENDIF -->
+ </div>
+ </td>
+ </tr>
+ <!-- END notifications -->
+ </table>
+ </div>
+
+ <div class="row1 footer">
+ <a href="{U_VIEW_ALL_NOTIFICATIONS}"><span>{L_SEE_ALL}</span></a>
+ </div>
+ </div>
+ <!-- ENDIF -->
<!-- IF not S_IS_BOT --><a href="{U_LOGIN_LOGOUT}"><img src="{T_THEME_PATH}/images/icon_mini_login.gif" width="12" height="13" alt="*" /> {L_LOGIN_LOGOUT}</a>&nbsp;<!-- ENDIF -->
<!-- IF U_RESTORE_PERMISSIONS --> &nbsp;<a href="{U_RESTORE_PERMISSIONS}"><img src="{T_THEME_PATH}/images/icon_mini_login.gif" width="12" height="13" alt="*" /> {L_RESTORE_PERMISSIONS}</a><!-- ENDIF -->
<!-- IF S_BOARD_DISABLED and S_USER_LOGGED_IN --> &nbsp;<span style="color: red;">{L_BOARD_DISABLED}</span><!-- ENDIF -->
<!-- IF not S_IS_BOT -->
- <!-- IF S_USER_LOGGED_IN -->
- <!-- IF S_DISPLAY_PM --> &nbsp;<a href="{U_PRIVATEMSGS}"><img src="{T_THEME_PATH}/images/icon_mini_message.gif" width="12" height="13" alt="*" /> {PRIVATE_MESSAGE_INFO}<!-- IF PRIVATE_MESSAGE_INFO_UNREAD -->, {PRIVATE_MESSAGE_INFO_UNREAD}<!-- ENDIF --></a><!-- ENDIF -->
+ <!-- IF S_USER_LOGGED_IN-->
+ <!-- IF not S_NOTIFICATIONS_DISPLAY and S_DISPLAY_PM --> &nbsp;<a href="{U_PRIVATEMSGS}"><img src="{T_THEME_PATH}/images/icon_mini_message.gif" width="12" height="13" alt="*" /> {PRIVATE_MESSAGE_INFO}<!-- IF PRIVATE_MESSAGE_INFO_UNREAD -->, {PRIVATE_MESSAGE_INFO_UNREAD}<!-- ENDIF --></a><!-- ENDIF -->
<!-- ELSEIF S_REGISTER_ENABLED and not (S_SHOW_COPPA or S_REGISTRATION) --> &nbsp;<a href="{U_REGISTER}"><img src="{T_THEME_PATH}/images/icon_mini_register.gif" width="12" height="13" alt="*" /> {L_REGISTER}</a>
<!-- ENDIF -->
<!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/ucp_notifications.html b/phpBB/styles/subsilver2/template/ucp_notifications.html
new file mode 100644
index 0000000000..a2dc90c9f3
--- /dev/null
+++ b/phpBB/styles/subsilver2/template/ucp_notifications.html
@@ -0,0 +1,146 @@
+<!-- INCLUDE ucp_header.html -->
+
+<form id="ucp" method="post" action="{S_UCP_ACTION}"{S_FORM_ENCTYPE}>
+
+<table width="100%" cellspacing="1">
+ <tr>
+ <th colspan="4">{TITLE}</th>
+ </tr>
+ <tr>
+ <td class="row1" colspan="4" align="center"><span class="genmed">{TITLE_EXPLAIN}</span></td>
+ </tr>
+ <!-- IF MODE == 'notification_options' -->
+ <tr>
+ <th>{L_NOTIFICATION_TYPE}</th>
+ <th width="10%">{L_NOTIFICATIONS}</th>
+ <!-- BEGIN notification_methods -->
+ <th width="10%">{notification_methods.NAME}</th>
+ <!-- END notification_methods -->
+ </tr>
+
+ <!-- BEGIN notification_types -->
+ <!-- IF notification_types.GROUP_NAME -->
+ <tr>
+ <td class="row3" colspan="3">{notification_types.GROUP_NAME}</td>
+ </tr>
+ <!-- ELSE -->
+ <!-- IF notification_types.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
+ <td>
+ {notification_types.NAME}
+ <!-- IF notification_types.EXPLAIN --><br />&nbsp; &nbsp;{notification_types.EXPLAIN}<!-- ENDIF -->
+ </td>
+ <td align="center"><input type="checkbox" name="{notification_types.TYPE}_notification"<!-- IF notification_types.SUBSCRIBED --> checked="checked"<!-- ENDIF --> /></td>
+ <!-- BEGIN notification_methods -->
+ <td align="center"><input type="checkbox" name="{notification_types.TYPE}_{notification_methods.METHOD}"<!-- IF notification_methods.SUBSCRIBED --> checked="checked"<!-- ENDIF --> /></td>
+ <!-- END notification_methods -->
+ </tr>
+ <!-- ENDIF -->
+ <!-- END notification_types -->
+ <tr>
+ <td class="cat" colspan="3" align="center">
+ <input type="hidden" name="form_time" value="{FORM_TIME}" />
+ {S_HIDDEN_FIELDS}
+ <input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />&nbsp;&nbsp;
+ <input class="btnlite" type="reset" value="{L_RESET}" name="reset" />
+ {S_FORM_TOKEN}
+ </td>
+ </tr>
+ <!-- ELSE -->
+ <tr>
+ <td>
+ <table class="tablebg" width="100%" cellspacing="1" cellpadding="0">
+ <tr>
+ <td class="row1">
+ <table border="0" cellspacing="0" cellpadding="0" width="100%">
+ <tr>
+ <td align="{S_CONTENT_FLOW_BEGIN}">
+ <!-- IF TOTAL_COUNT -->
+ <table width="100%" cellspacing="1">
+ <tr>
+ <td class="nav" valign="middle" nowrap="nowrap">&nbsp;{PAGE_NUMBER}</td>
+ <td class="gensmall" nowrap="nowrap" width="100%">&nbsp;[ <b>{TOTAL_COUNT}</b> ]&nbsp;</td>
+ </tr>
+ </table>
+ <!-- ENDIF -->
+ </td>
+ <td align="{S_CONTENT_FLOW_END}"><!-- INCLUDE pagination.html --></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+
+ <div style="padding: 2px;"></div>
+
+ <div class="notification_list">
+ <table class="tablebg" width="100%" cellspacing="1">
+ <tr>
+ <td class="cat" colspan="3">
+ <table width="100%" cellspacing="0">
+ <tr class="nav">
+ <td align="{S_CONTENT_FLOW_END}" valign="middle"><!-- IF U_MARK_ALL --><a href="{U_MARK_ALL}">{L_NOTIFICATIONS_MARK_ALL_READ}</a><!-- ENDIF --></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <th colspan="2">{L_NOTIFICATIONS}</th>
+ <th width="15%">{L_MARK_READ}</th>
+ </tr>
+ <!-- BEGIN notification_list -->
+ <tr class="row<!-- IF notification_list.UNREAD -->3<!-- ELSEIF notification_list.S_ROW_COUNT is even -->1<!-- ELSE -->2<!-- ENDIF -->">
+ <!-- IF notification_list.AVATAR -->
+ <td width="50px">
+ {notification_list.AVATAR}
+ </td>
+ <td valign="top">
+ <!-- ELSE -->
+ <td colspan="2" valign="top" height="50px">
+ <!-- ENDIF -->
+ <!-- IF notification_list.URL --><a href="<!-- IF notification_list.UNREAD -->{notification_list.U_MARK_READ}<!-- ELSE -->{notification_list.URL}<!-- ENDIF -->"><!-- ENDIF -->
+ {notification_list.FORMATTED_TITLE}
+ <!-- IF notification_list.URL --></a><!-- ENDIF --><br />
+ {notification_list.TIME}
+ </td>
+ <td align="center">
+ <!-- IF notification_list.UNREAD --><input type="checkbox" name="mark[]" value="{notification_list.NOTIFICATION_ID}" /><!-- ENDIF -->
+ </td>
+ </tr>
+ <!-- END notification_list -->
+ <tr>
+ <td class="cat" colspan="3" align="center">
+ <input type="hidden" name="form_time" value="{FORM_TIME}" />
+ {S_HIDDEN_FIELDS}
+ <input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />&nbsp;&nbsp;
+ <input class="btnlite" type="reset" value="{L_RESET}" name="reset" />
+ {S_FORM_TOKEN}
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <div style="padding: 2px;"></div>
+
+ <!-- IF .pagination -->
+ <table class="tablebg" width="100%" cellspacing="1" cellpadding="0">
+ <tr>
+ <td class="row1">
+ <table border="0" cellspacing="0" cellpadding="0" width="100%">
+ <tr>
+ <td align="{S_CONTENT_FLOW_BEGIN}">
+ <!-- INCLUDE pagination.html -->
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ <!-- ENDIF -->
+ </td>
+ </tr>
+ <!-- ENDIF -->
+</table>
+
+</form>
+
+<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_prefs_personal.html b/phpBB/styles/subsilver2/template/ucp_prefs_personal.html
index bf0e67d68b..7f706eb97c 100644
--- a/phpBB/styles/subsilver2/template/ucp_prefs_personal.html
+++ b/phpBB/styles/subsilver2/template/ucp_prefs_personal.html
@@ -47,20 +47,6 @@
<td class="row2"><input type="radio" class="radio" name="hideonline" value="1"<!-- IF S_HIDE_ONLINE --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_YES}</span>&nbsp;&nbsp;<input type="radio" class="radio" name="hideonline" value="0"<!-- IF not S_HIDE_ONLINE --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_NO}</span></td>
</tr>
<!-- ENDIF -->
-<!-- IF S_SELECT_NOTIFY -->
- <tr>
- <td class="row1" width="50%"><b class="genmed">{L_NOTIFY_METHOD}:</b><br /><span class="gensmall">{L_NOTIFY_METHOD_EXPLAIN}</span></td>
- <td class="row2"><input type="radio" class="radio" name="notifymethod" value="0"<!-- IF S_NOTIFY_EMAIL --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_NOTIFY_METHOD_EMAIL}</span>&nbsp;&nbsp;<input type="radio" class="radio" name="notifymethod" value="1"<!-- IF S_NOTIFY_IM --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_NOTIFY_METHOD_IM}</span>&nbsp;&nbsp;<input type="radio" class="radio" name="notifymethod" value="2"<!-- IF S_NOTIFY_BOTH --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_NOTIFY_METHOD_BOTH}</span></td>
- </tr>
-<!-- ENDIF -->
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_NOTIFY_ON_PM}:</b></td>
- <td class="row2"><input type="radio" class="radio" name="notifypm" value="1"<!-- IF S_NOTIFY_PM --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_YES}</span>&nbsp;&nbsp;<input type="radio" class="radio" name="notifypm" value="0"<!-- IF not S_NOTIFY_PM --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_NO}</span></td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_POPUP_ON_PM}:</b></td>
- <td class="row2"><input type="radio" class="radio" name="popuppm" value="1"<!-- IF S_POPUP_PM --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_YES}</span>&nbsp;&nbsp;<input type="radio" class="radio" name="popuppm" value="0"<!-- IF not S_POPUP_PM --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_NO}</span></td>
-</tr>
<tr>
<td class="row1" width="50%"><b class="genmed">{L_BOARD_LANGUAGE}:</b></td>
<td class="row2"><select name="lang">{S_LANG_OPTIONS}</select></td>
diff --git a/phpBB/styles/subsilver2/theme/stylesheet.css b/phpBB/styles/subsilver2/theme/stylesheet.css
index 977e5c20c6..b41860d130 100644
--- a/phpBB/styles/subsilver2/theme/stylesheet.css
+++ b/phpBB/styles/subsilver2/theme/stylesheet.css
@@ -181,7 +181,7 @@ p.datetime {
p.searchbar {
padding: 2px 0;
white-space: nowrap;
-}
+}
p.searchbarreg {
margin: 0;
@@ -464,7 +464,7 @@ textarea {
background-color: #FAFAFA;
color: #333333;
font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif;
- font-size: 1.3em;
+ font-size: 1.3em;
line-height: 1.4em;
font-weight: normal;
border: 1px solid #A9B8C2;
@@ -1141,3 +1141,45 @@ a.imageset {
padding-right: 18px;
padding-left: 0;
}
+
+#notification_list {
+ display: none;
+ position: absolute;
+ width: 310px;
+ z-index: 1;
+}
+
+#notification_list .notification_scroll {
+ max-height: 350px;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+#notification_list .notification_title {
+ width: 240px;
+}
+
+#notification_list .header {
+ width: 298px;
+ padding: 5px;
+ font-weight: bold;
+ border: 1px solid #A9B8C2;
+ border-bottom: 0;
+}
+
+#notification_list .footer {
+ width: 300px;
+ text-align: center;
+ font-size: 1.2em;
+ border: 1px solid #A9B8C2;
+ border-top: 0;
+}
+
+.notification_list img {
+ max-width: 50px;
+ max-height: 50px;
+}
+
+#notification_list .footer > a {
+ display: block;
+} \ No newline at end of file