diff options
Diffstat (limited to 'phpBB/includes')
27 files changed, 3506 insertions, 402 deletions
| 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 2480ca80fa..162b0046b5 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -1285,15 +1285,20 @@ 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_container;  	if ($mode == 'all')  	{  		if ($forum_id === false || !sizeof($forum_id))  		{ +			// Mark all forums read (index page) + +			// Mark all topic notifications read for this user +			$phpbb_notifications = $phpbb_container->get('notifications'); +			$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)  				$db->sql_query('DELETE FROM ' . TOPICS_TRACK_TABLE . " WHERE user_id = {$user->data['user_id']}");  				$db->sql_query('DELETE FROM ' . FORUMS_TRACK_TABLE . " WHERE user_id = {$user->data['user_id']}");  				$db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . time() . " WHERE user_id = {$user->data['user_id']}"); @@ -1330,6 +1335,24 @@ 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 = $phpbb_container->get('notifications'); +		$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; @@ -1424,6 +1447,11 @@ 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 = $phpbb_container->get('notifications'); +		$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 . ' @@ -4778,7 +4806,7 @@ function phpbb_http_login($param)  function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum')  {  	global $db, $config, $template, $SID, $_SID, $_EXTRA_URL, $user, $auth, $phpEx, $phpbb_root_path; -	global $phpbb_dispatcher; +	global $phpbb_dispatcher, $phpbb_container;  	if (defined('HEADER_INC'))  	{ @@ -4967,6 +4995,17 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0  		$timezone_name = $user->lang['timezones'][$timezone_name];  	} +	// Output the notifications +	$phpbb_notifications = $phpbb_container->get('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'], @@ -4981,6 +5020,8 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0  		'RECORD_USERS'					=> $l_online_record,  		'PRIVATE_MESSAGE_INFO'			=> $l_privmsgs_text,  		'PRIVATE_MESSAGE_INFO_UNREAD'	=> $l_privmsgs_text_unread, +		'NUM_UNREAD_NOTIFICATIONS'		=> $notifications['unread_count'], +		'NOTIFICATIONS_CNT'				=> $user->lang('NOTIFICATIONS_CNT', $notifications['unread_count']),  		'S_USER_NEW_PRIVMSG'			=> $user->data['user_new_privmsg'],  		'S_USER_UNREAD_PRIVMSG'			=> $user->data['user_unread_privmsg'], diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 5e2ee8c8f6..27128aafac 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_container;  	$approved_topics = 0;  	$forum_ids = $topic_ids = array(); @@ -715,6 +716,10 @@ 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 = $phpbb_container->get('notifications'); +	$phpbb_notifications->delete_notifications(array('topic', 'approve_topic', 'topic_in_queue'), $topic_ids); +  	return $return;  } @@ -724,6 +729,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_container;  	if ($where_type === 'range')  	{ @@ -892,6 +898,10 @@ 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 = $phpbb_container->get('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 c50395a5df..6262cee4ad 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -61,7 +61,7 @@ function generate_smilies($mode, $forum_id)  			'body' => 'posting_smilies.html')  		); -		generate_pagination(append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id), $smiley_count, $config['smilies_per_page'], $start);	 +		generate_pagination(append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id), $smiley_count, $config['smilies_per_page'], $start);  	}  	$display_link = false; @@ -1173,237 +1173,6 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id  	return true;  } -/** -* User Notification -*/ -function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id, $topic_id, $post_id) -{ -	global $db, $user, $config, $phpbb_root_path, $phpEx, $auth; - -	$topic_notification = ($mode == 'reply' || $mode == 'quote') ? true : false; -	$forum_notification = ($mode == 'post') ? true : false; - -	if (!$topic_notification && !$forum_notification) -	{ -		trigger_error('NO_MODE'); -	} - -	if (($topic_notification && !$config['allow_topic_notify']) || ($forum_notification && !$config['allow_forum_notify'])) -	{ -		return; -	} - -	$topic_title = ($topic_notification) ? $topic_title : $subject; -	$topic_title = censor_text($topic_title); - -	// Exclude guests, current user and banned users from notifications -	if (!function_exists('phpbb_get_banned_user_ids')) -	{ -		include($phpbb_root_path . 'includes/functions_user.' . $phpEx); -	} -	$sql_ignore_users = phpbb_get_banned_user_ids(); -	$sql_ignore_users[ANONYMOUS] = ANONYMOUS; -	$sql_ignore_users[$user->data['user_id']] = $user->data['user_id']; - -	$notify_rows = array(); - -	// -- get forum_userids	|| topic_userids -	$sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber -		FROM ' . (($topic_notification) ? TOPICS_WATCH_TABLE : FORUMS_WATCH_TABLE) . ' w, ' . USERS_TABLE . ' u -		WHERE w.' . (($topic_notification) ? 'topic_id' : 'forum_id') . ' = ' . (($topic_notification) ? $topic_id : $forum_id) . ' -			AND ' . $db->sql_in_set('w.user_id', $sql_ignore_users, true) . ' -			AND w.notify_status = ' . NOTIFY_YES . ' -			AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') -			AND u.user_id = w.user_id'; -	$result = $db->sql_query($sql); - -	while ($row = $db->sql_fetchrow($result)) -	{ -		$notify_user_id = (int) $row['user_id']; -		$notify_rows[$notify_user_id] = array( -			'user_id'		=> $notify_user_id, -			'username'		=> $row['username'], -			'user_email'	=> $row['user_email'], -			'user_jabber'	=> $row['user_jabber'], -			'user_lang'		=> $row['user_lang'], -			'notify_type'	=> ($topic_notification) ? 'topic' : 'forum', -			'template'		=> ($topic_notification) ? 'topic_notify' : 'newtopic_notify', -			'method'		=> $row['user_notify_type'], -			'allowed'		=> false -		); - -		// Add users who have been already notified to ignore list -		$sql_ignore_users[$notify_user_id] = $notify_user_id; -	} -	$db->sql_freeresult($result); - -	// forum notification is sent to those not already receiving topic notifications -	if ($topic_notification) -	{ -		$sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber -			FROM ' . FORUMS_WATCH_TABLE . ' fw, ' . USERS_TABLE . " u -			WHERE fw.forum_id = $forum_id -				AND " . $db->sql_in_set('fw.user_id', $sql_ignore_users, true) . ' -				AND fw.notify_status = ' . NOTIFY_YES . ' -				AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') -				AND u.user_id = fw.user_id'; -		$result = $db->sql_query($sql); - -		while ($row = $db->sql_fetchrow($result)) -		{ -			$notify_user_id = (int) $row['user_id']; -			$notify_rows[$notify_user_id] = array( -				'user_id'		=> $notify_user_id, -				'username'		=> $row['username'], -				'user_email'	=> $row['user_email'], -				'user_jabber'	=> $row['user_jabber'], -				'user_lang'		=> $row['user_lang'], -				'notify_type'	=> 'forum', -				'template'		=> 'forum_notify', -				'method'		=> $row['user_notify_type'], -				'allowed'		=> false -			); -		} -		$db->sql_freeresult($result); -	} - -	if (!sizeof($notify_rows)) -	{ -		return; -	} - -	// Make sure users are allowed to read the forum -	foreach ($auth->acl_get_list(array_keys($notify_rows), 'f_read', $forum_id) as $forum_id => $forum_ary) -	{ -		foreach ($forum_ary as $auth_option => $user_ary) -		{ -			foreach ($user_ary as $user_id) -			{ -				$notify_rows[$user_id]['allowed'] = true; -			} -		} -	} - -	// Now, we have to do a little step before really sending, we need to distinguish our users a little bit. ;) -	$msg_users = $delete_ids = $update_notification = array(); -	foreach ($notify_rows as $user_id => $row) -	{ -		if (!$row['allowed'] || !trim($row['user_email'])) -		{ -			$delete_ids[$row['notify_type']][] = $row['user_id']; -		} -		else -		{ -			$msg_users[] = $row; -			$update_notification[$row['notify_type']][] = $row['user_id']; - -			/* -			* We also update the forums watch table for this user when we are -			* sending out a topic notification to prevent sending out another -			* notification in case this user is also subscribed to the forum -			* this topic was posted in. -			* Since an UPDATE query is used, this has no effect on users only -			* subscribed to the topic (i.e. no row is created) and should not -			* be a performance issue. -			*/ -			if ($row['notify_type'] === 'topic') -			{ -				$update_notification['forum'][] = $row['user_id']; -			} -		} -	} -	unset($notify_rows); - -	// Now, we are able to really send out notifications -	if (sizeof($msg_users)) -	{ -		include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); -		$messenger = new messenger(); - -		$msg_list_ary = array(); -		foreach ($msg_users as $row) -		{ -			$pos = (!isset($msg_list_ary[$row['template']])) ? 0 : sizeof($msg_list_ary[$row['template']]); - -			$msg_list_ary[$row['template']][$pos]['method']	= $row['method']; -			$msg_list_ary[$row['template']][$pos]['email']	= $row['user_email']; -			$msg_list_ary[$row['template']][$pos]['jabber']	= $row['user_jabber']; -			$msg_list_ary[$row['template']][$pos]['name']	= $row['username']; -			$msg_list_ary[$row['template']][$pos]['lang']	= $row['user_lang']; -			$msg_list_ary[$row['template']][$pos]['user_id']= $row['user_id']; -		} -		unset($msg_users); - -		foreach ($msg_list_ary as $email_template => $email_list) -		{ -			foreach ($email_list as $addr) -			{ -				$messenger->template($email_template, $addr['lang']); - -				$messenger->to($addr['email'], $addr['name']); -				$messenger->im($addr['jabber'], $addr['name']); - -				$messenger->assign_vars(array( -					'USERNAME'		=> htmlspecialchars_decode($addr['name']), -					'TOPIC_TITLE'	=> htmlspecialchars_decode($topic_title), -					'FORUM_NAME'	=> htmlspecialchars_decode($forum_name), - -					'U_FORUM'				=> generate_board_url() . "/viewforum.$phpEx?f=$forum_id", -					'U_TOPIC'				=> generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id", -					'U_NEWEST_POST'			=> generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id&p=$post_id&e=$post_id", -					'U_STOP_WATCHING_TOPIC'	=> generate_board_url() . "/viewtopic.$phpEx?uid={$addr['user_id']}&f=$forum_id&t=$topic_id&unwatch=topic", -					'U_STOP_WATCHING_FORUM'	=> generate_board_url() . "/viewforum.$phpEx?uid={$addr['user_id']}&f=$forum_id&unwatch=forum", -				)); - -				$messenger->send($addr['method']); -			} -		} -		unset($msg_list_ary); - -		$messenger->save_queue(); -	} - -	// Handle the DB updates -	$db->sql_transaction('begin'); - -	if (!empty($update_notification['topic'])) -	{ -		$sql = 'UPDATE ' . TOPICS_WATCH_TABLE . ' -			SET notify_status = ' . NOTIFY_NO . " -			WHERE topic_id = $topic_id -				AND " . $db->sql_in_set('user_id', $update_notification['topic']); -		$db->sql_query($sql); -	} - -	if (!empty($update_notification['forum'])) -	{ -		$sql = 'UPDATE ' . FORUMS_WATCH_TABLE . ' -			SET notify_status = ' . NOTIFY_NO . " -			WHERE forum_id = $forum_id -				AND " . $db->sql_in_set('user_id', $update_notification['forum']); -		$db->sql_query($sql); -	} - -	// Now delete the user_ids not authorised to receive notifications on this topic/forum -	if (!empty($delete_ids['topic'])) -	{ -		$sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . " -			WHERE topic_id = $topic_id -				AND " . $db->sql_in_set('user_id', $delete_ids['topic']); -		$db->sql_query($sql); -	} - -	if (!empty($delete_ids['forum'])) -	{ -		$sql = 'DELETE FROM ' . FORUMS_WATCH_TABLE . " -			WHERE forum_id = $forum_id -				AND " . $db->sql_in_set('user_id', $delete_ids['forum']); -		$db->sql_query($sql); -	} - -	$db->sql_transaction('commit'); -} -  //  // Post handling functions  // @@ -1640,6 +1409,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data)  function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true)  {  	global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path; +	global $phpbb_container;  	// We do not handle erasing posts here  	if ($mode == 'delete') @@ -2450,9 +2220,57 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  	}  	// Send Notifications -	if (($mode == 'reply' || $mode == 'quote' || $mode == 'post') && $post_approval) +	$phpbb_notifications = $phpbb_container->get('notifications'); +	$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)  	{ -		user_notification($mode, $subject, $data['topic_title'], $data['forum_name'], $data['forum_id'], $data['topic_id'], $data['post_id']); +		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..8545cc7ef5 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -876,7 +876,11 @@ function update_unread_status($unread, $msg_id, $user_id, $folder_id)  		return;  	} -	global $db, $user; +	global $db, $user, $phpbb_container; + +	// Mark the PM as read +	$phpbb_notifications = $phpbb_container->get('notifications'); +	$phpbb_notifications->mark_notifications_read('pm', $msg_id, $user_id);  	$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "  		SET pm_unread = 0 @@ -982,6 +986,7 @@ function handle_mark_actions($user_id, $mark_action)  function delete_pm($user_id, $msg_ids, $folder_id)  {  	global $db, $user, $phpbb_root_path, $phpEx; +	global $phpbb_container;  	$user_id	= (int) $user_id;  	$folder_id	= (int) $folder_id; @@ -1093,6 +1098,10 @@ function delete_pm($user_id, $msg_ids, $folder_id)  		$user->data['user_unread_privmsg'] -= $num_unread;  	} +	// Delete Notifications +	$phpbb_notifications = $phpbb_container->get('notifications'); +	$phpbb_notifications->delete_notifications('pm', array_keys($delete_rows)); +  	// Now we have to check which messages we can delete completely  	$sql = 'SELECT msg_id  		FROM ' . PRIVMSGS_TO_TABLE . ' @@ -1137,6 +1146,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_container;  	$user_id = (int) $user_id; @@ -1253,6 +1263,10 @@ 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 = $phpbb_container->get('notifications'); +			$phpbb_notifications->delete_notifications('pm', $delivered_msg);  		}  		if (!empty($undelivered_msg)) @@ -1264,6 +1278,10 @@ 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 = $phpbb_container->get('notifications'); +			$phpbb_notifications->delete_notifications('pm', $undelivered_msg);  		}  	} @@ -1306,6 +1324,10 @@ 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 = $phpbb_container->get('notifications'); +			$phpbb_notifications->delete_notifications('pm', $delete_ids);  		}  	} @@ -1543,6 +1565,7 @@ function get_folder_status($folder_id, $folder)  function submit_pm($mode, $subject, &$data, $put_in_outbox = true)  {  	global $db, $auth, $config, $phpEx, $template, $user, $phpbb_root_path; +	global $phpbb_container;  	// We do not handle erasing pms here  	if ($mode == 'delete') @@ -1842,95 +1865,23 @@ 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); +	$phpbb_notifications = $phpbb_container->get('notifications'); -	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_queue.php b/phpBB/includes/mcp/mcp_queue.php index b44685b8a3..1d2caa38d5 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -421,7 +421,7 @@ class mcp_queue  				$base_url = $this->u_action . "&f=$forum_id&st=$sort_days&sk=$sort_key&sd=$sort_dir";  				phpbb_generate_template_pagination($template, $base_url, 'pagination', 'start', $total, $config['topics_per_page'], $start); -				 +  				// Now display the page  				$template->assign_vars(array(  					'L_DISPLAY_ITEMS'		=> ($mode == 'unapproved_posts') ? $user->lang['DISPLAY_POSTS'] : $user->lang['DISPLAY_TOPICS'], @@ -451,7 +451,7 @@ function approve_post($post_id_list, $id, $mode)  {  	global $db, $template, $user, $config;  	global $phpEx, $phpbb_root_path; -	global $request; +	global $request, $phpbb_container;  	if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve')))  	{ @@ -597,54 +597,40 @@ 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 +		$phpbb_notifications = $phpbb_container->get('notifications');  		foreach ($post_info as $post_id => $post_data)  		{  			if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id'])  			{ +				// 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 +720,7 @@ function disapprove_post($post_id_list, $id, $mode)  {  	global $db, $template, $user, $config;  	global $phpEx, $phpbb_root_path; -	global $request; +	global $request, $phpbb_container;  	if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve')))  	{ @@ -867,20 +853,29 @@ function disapprove_post($post_id_list, $id, $mode)  			}  		} -		$messenger = new messenger(); +		// Handle notifications (topic/post in queue) +		$phpbb_notifications = $phpbb_container->get('notifications'); +		foreach ($post_info as $post_id => $post_data) +		{ +			if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id']) +			{ +				$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 +901,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/notifications/method/base.php b/phpBB/includes/notifications/method/base.php new file mode 100644 index 0000000000..b860fcffda --- /dev/null +++ b/phpBB/includes/notifications/method/base.php @@ -0,0 +1,92 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Base notifications method class +* @package notifications +*/ +abstract class phpbb_notifications_method_base implements phpbb_notifications_method_interface +{ +	protected $phpbb_container; +	protected $service; +	protected $db; +	protected $user; +	protected $phpbb_root_path; +	protected $php_ext; + +	/** +	* Desired notifications +	* unique by (type, type_id, user_id, method) +	* if multiple methods are desired, multiple rows will exist. +	* +	* method of "none" will over-ride any other options +	* +	* item_type +	* item_id +	* user_id +	* method +	* 	none (will never receive notifications) +	* 	standard (listed in notifications window +	* 	popup? +	* 	email +	* 	jabber +	*	sms? +	*/ + +	/** +	* Queue of messages to be sent +	* +	* @var array +	*/ +	protected $queue = array(); + +	public function __construct(ContainerBuilder $phpbb_container) +	{ +		// phpBB Container +		$this->phpbb_container = $phpbb_container; + +		// Service +		$this->service = $phpbb_container->get('notifications'); + +		// Some common things we're going to use +		$this->db = $phpbb_container->get('dbal.conn'); +		$this->user = $phpbb_container->get('user'); + +		$this->phpbb_root_path = $phpbb_container->getParameter('core.root_path'); +		$this->php_ext = $phpbb_container->getParameter('core.php_ext'); +	} + +	/** +	* Add a notification to the queue +	* +	* @param phpbb_notifications_type_interface $notification +	*/ +	public function add_to_queue(phpbb_notifications_type_interface $notification) +	{ +		$this->queue[] = $notification; +	} + +	/** +	* Empty the queue +	*/ +	protected function empty_queue() +	{ +		$this->queue = array(); +	} +} diff --git a/phpBB/includes/notifications/method/email.php b/phpBB/includes/notifications/method/email.php new file mode 100644 index 0000000000..ebfc0c7c71 --- /dev/null +++ b/phpBB/includes/notifications/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_notifications_method_email extends phpbb_notifications_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_container->getParameter('core.root_path') . 'includes/functions_user.' . $this->phpbb_container->getParameter('core.php_ext')); +		} +		$banned_users = phpbb_get_banned_user_ids($user_ids); + +		// Load all the users we need +		$this->service->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->service->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/notifications/method/interface.php b/phpBB/includes/notifications/method/interface.php new file mode 100644 index 0000000000..820cf4fc12 --- /dev/null +++ b/phpBB/includes/notifications/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_notifications_method_interface +{ +	public function is_available(); + +	public function notify(); +} diff --git a/phpBB/includes/notifications/method/jabber.php b/phpBB/includes/notifications/method/jabber.php new file mode 100644 index 0000000000..738400a50e --- /dev/null +++ b/phpBB/includes/notifications/method/jabber.php @@ -0,0 +1,62 @@ +<?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_notifications_method_jabber extends phpbb_notifications_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->phpbb_container->get('user')->data['jabber']); +	} + +	/** +	* Is this method available at all? +	* This is checked before notifications are sent +	*/ +	public function global_available() +	{ +		$config = $this->phpbb_container->get('config'); + +		return ($config['jab_enable'] && @extension_loaded('xml')); +	} + +	public function notify() +	{ +		if (!$this->global_available()) +		{ +			return; +		} + +		return parent::notify(); +	} +} diff --git a/phpBB/includes/notifications/service.php b/phpBB/includes/notifications/service.php new file mode 100644 index 0000000000..ebf4cef12d --- /dev/null +++ b/phpBB/includes/notifications/service.php @@ -0,0 +1,688 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Notifications service class +* @package notifications +*/ +class phpbb_notifications_service +{ +	protected $phpbb_container; +	protected $db; + +	/** +	* Users loaded from the DB +	* +	* @var array Array of user data that we've loaded from the DB +	*/ +	protected $users = array(); + +	public function __construct(ContainerBuilder $phpbb_container) +	{ +		$this->phpbb_container = $phpbb_container; + +		// Some common things we're going to use +		$this->db = $phpbb_container->get('dbal.conn'); +	} + +	/** +	* Load the user's notifications +	* +	* @param array $options Optional options to control what notifications are loaded +	*				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()) +	{ +		$user = $this->phpbb_container->get('user'); + +		// Merge default options +		$options = array_merge(array( +			'notification_id'	=> false, +			'user_id'			=> $user->data['user_id'], +			'order_by'			=> 'time', +			'order_dir'			=> 'DESC', +			'limit'				=> 0, +			'start'				=> 0, +			'all_unread'		=> false, +			'count_unread'		=> 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'] == $user->data['user_id'] && ($user->data['user_id'] == ANONYMOUS || $user->data['user_type'] == USER_IGNORE)) +		{ +			return array( +				'notifications'		=> array(), +				'unread_count'		=> 0, +			); +		} + +		$notifications = $user_ids = array(); +		$load_special = array(); +		$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'; +			$result = $this->db->sql_query($sql); +			$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']) : '') . ' +				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 ($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) . ' +					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 = new $item_type_class_name($this->phpbb_container, $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[] = $notification; +		} + +		$this->load_users($user_ids); + +		// Allow each type to load it's own special items +		foreach ($load_special as $item_type => $data) +		{ +			$item_type_class_name = $this->get_item_type_class_name($item_type, true); + +			$item_type_class_name::load_special($this->phpbb_container, $data, $notifications); +		} + +		return array( +			'notifications'		=> $notifications, +			'unread_count'		=> $count, +		); +	} + +	/** +	* Mark notifications read +	* +	* @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_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(); + +		$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_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 = $item_type_class_name::find_users_for_notification($this->phpbb_container, $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 +		// todo Users should not receive notifications from multiple events from the same item (ex: for a topic reply with a quote including your username) +		//		Probably should be handled within each type? +		$sql = 'SELECT user_id +			FROM ' . NOTIFICATIONS_TABLE . " +			WHERE item_type = '" . $this->db->sql_escape($item_type) . "' +				AND item_id = " . (int) $item_id; +		$result = $this->db->sql_query($sql); +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			unset($notify_users[$row['user_id']]); +		} +		$this->db->sql_freeresult($result); + +		if (!sizeof($notify_users)) +		{ +			return; +		} + +		// Go through each user so we can insert a row in the DB and then notify them by their desired means +		foreach ($notify_users as $user => $methods) +		{ +			$notification = new $item_type_class_name($this->phpbb_container); + +			$notification->user_id = (int) $user; + +			// Store the creation array in our new rows that will be inserted later +			$new_rows[] = $notification->create_insert_array($data); + +			// Users are needed to send notifications +			$user_ids = array_merge($user_ids, $notification->users_to_query()); + +			foreach ($methods as $method) +			{ +				// setup the notification methods and add the notification to the queue +				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_notifications_method_' . $method; +						$notification_methods[$method] = new $method_class_name($this->phpbb_container); +					} + +					$notification_methods[$method]->add_to_queue($notification); +				} +			} +		} + +		// insert into the db +		$this->db->sql_multi_insert(NOTIFICATIONS_TABLE, $new_rows); + +		// 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 ($item_type_class_name::update_notifications($this->phpbb_container, $data) === false) +			{ +				return; +			} +		} + +		$item_id = $item_type_class_name::get_item_id($data); + +		$notification = new $item_type_class_name($this->phpbb_container); +		$update_array = $notification->create_update_array($data); + +		$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('notifications/type/') as $class => $file) +		{ +			$class = $this->get_item_type_class_name($class); + +			if (!class_exists($class)) +			{ +				include($file); +			} + +			if ($class::is_available($this->phpbb_container) && method_exists($class, 'get_item_type')) +			{ +				if ($class::$notification_option === false) +				{ +					$subscription_types[$class::get_item_type()] = $class::get_item_type(); +				} +				else +				{ +					$subscription_types[$class::$notification_option['id']] = $class::$notification_option; +				} +			} +		} + +		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('notifications/method/') as $method_name => $file) +		{ +			$class_name = 'phpbb_notifications_method_' . $method_name; + +			if (!class_exists($class_name)) +			{ +				include($file); +			} + +			$method = new $class_name($this->phpbb_container); + +			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->phpbb_container->get('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->phpbb_container->get('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->phpbb_container->get('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); +		} + +		return 'phpbb_notifications_type_' . $item_type; +	} + +	/** +	* Helper to get subscription related files with the finder +	*/ +	private function get_subscription_files($path) +	{ +		$ext_manager = $this->phpbb_container->get('ext.manager'); +		$php_ext = $this->phpbb_container->getParameter('core.php_ext'); + +		$finder = $ext_manager->get_finder(); + +		$subscription_files = array(); + +		$files = $finder +			->core_path('includes/' . $path) +			->extension_directory($path) +			->get_files(); +		foreach ($files as $file) +		{ +			$class = substr($file, strrpos($file, '/')); +			$class = substr($class, 1, (strpos($class, '.' . $php_ext) - 1)); + +			if ($class == 'interface' || $class == 'base') +			{ +				continue; +			} + +			$subscription_files[$class] = $file; +		} + +		return $subscription_files; +	} +} diff --git a/phpBB/includes/notifications/type/approve_post.php b/phpBB/includes/notifications/type/approve_post.php new file mode 100644 index 0000000000..912b9082a2 --- /dev/null +++ b/phpBB/includes/notifications/type/approve_post.php @@ -0,0 +1,132 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Post notifications class +* This class handles notifications for replies to a topic +* +* @package notifications +*/ +class phpbb_notifications_type_approve_post extends phpbb_notifications_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' and 'lang') +	*/ +	public static $notification_option = array( +		'id'	=> 'moderation_queue', +		'lang'	=> 'NOTIFICATION_TYPE_MODERATION_QUEUE', +	); + +	/** +	* Get the type of notification this is +	* phpbb_notifications_type_ +	*/ +	public static function get_item_type() +	{ +		return 'approve_post'; +	} + +	/** +	* Find the users who want to receive notifications +	* +	* @param ContainerBuilder $phpbb_container +	* @param array $post Data from +	* +	* @return array +	*/ +	public static function find_users_for_notification(ContainerBuilder $phpbb_container, $post, $options = array()) +	{ +		$options = array_merge(array( +			'ignore_users'		=> array(), +		), $options); + +		$db = $phpbb_container->get('dbal.conn'); + +		$users = array(); +		$users[$post['poster_id']] = array(''); + +		$auth_read = $phpbb_container->get('auth')->acl_get_list(array_keys($users), 'f_read', $post['forum_id']); + +		if (empty($auth_read)) +		{ +			return array(); +		} + +		$notify_users = array(); + +		$sql = 'SELECT * +			FROM ' . USER_NOTIFICATIONS_TABLE . " +			WHERE item_type = '" . self::$notification_option['id'] . "' +				AND " . $db->sql_in_set('user_id', $auth_read[$post['forum_id']]['f_read']); +		$result = $db->sql_query($sql); +		while ($row = $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']; +		} +		$db->sql_freeresult($result); + +		return $notify_users; +	} + +	/** +	* Function for preparing the data for insertion in an SQL query +	* (The service handles insertion) +	* +	* @param array $post Data from submit_post +	* +	* @return array Array of data ready to be inserted into the database +	*/ +	public function create_insert_array($post) +	{ +		$this->set_data('post_subject', $post['post_subject']); + +		$data = parent::create_insert_array($post); + +		$this->time = $data['time'] = time(); + +		return $data; +	} +} diff --git a/phpBB/includes/notifications/type/approve_topic.php b/phpBB/includes/notifications/type/approve_topic.php new file mode 100644 index 0000000000..e0e3a38e46 --- /dev/null +++ b/phpBB/includes/notifications/type/approve_topic.php @@ -0,0 +1,130 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Post notifications class +* This class handles notifications for replies to a topic +* +* @package notifications +*/ +class phpbb_notifications_type_approve_topic extends phpbb_notifications_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' and 'lang') +	*/ +	public static $notification_option = array( +		'id'	=> 'moderation_queue', +		'lang'	=> 'NOTIFICATION_TYPE_MODERATION_QUEUE', +	); + +	/** +	* Get the type of notification this is +	* phpbb_notifications_type_ +	*/ +	public static function get_item_type() +	{ +		return 'approve_topic'; +	} + +	/** +	* Find the users who want to receive notifications +	* +	* @param ContainerBuilder $phpbb_container +	* @param array $post Data from +	* +	* @return array +	*/ +	public static function find_users_for_notification(ContainerBuilder $phpbb_container, $post, $options = array()) +	{ +		$options = array_merge(array( +			'ignore_users'		=> array(), +		), $options); + +		$db = $phpbb_container->get('dbal.conn'); + +		$users = array(); +		$users[$post['poster_id']] = array(''); + +		$auth_read = $phpbb_container->get('auth')->acl_get_list(array_keys($users), 'f_read', $post['forum_id']); + +		if (empty($auth_read)) +		{ +			return array(); +		} + +		$notify_users = array(); + +		$sql = 'SELECT * +			FROM ' . USER_NOTIFICATIONS_TABLE . " +			WHERE item_type = '" . self::$notification_option['id'] . "' +				AND " . $db->sql_in_set('user_id', $auth_read[$post['forum_id']]['f_read']); +		$result = $db->sql_query($sql); +		while ($row = $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']; +		} +		$db->sql_freeresult($result); + +		return $notify_users; +	} + +	/** +	* Function for preparing the data for insertion in an SQL query +	* (The service handles insertion) +	* +	* @param array $post Data from submit_post +	* +	* @return array Array of data ready to be inserted into the database +	*/ +	public function create_insert_array($post) +	{ +		$data = parent::create_insert_array($post); + +		$this->time = $data['time'] = time(); + +		return $data; +	} +} diff --git a/phpBB/includes/notifications/type/base.php b/phpBB/includes/notifications/type/base.php new file mode 100644 index 0000000000..01720b4554 --- /dev/null +++ b/phpBB/includes/notifications/type/base.php @@ -0,0 +1,345 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Base notifications class +* @package notifications +*/ +abstract class phpbb_notifications_type_base implements phpbb_notifications_type_interface +{ +	protected $phpbb_container; +	protected $service; +	protected $db; +	protected $phpbb_root_path; +	protected $php_ext; + +	/** +	* Array of user data containing information needed to output the notifications to the template +	* +	* @var array +	*/ +	protected $users = array(); + +	/** +	* 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 = 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 +	* +	* time +	* data (special serialized field that each notification type can use to store stuff) +	* +	* @var array $data Notification row from the database +	* 		This must be private, all interaction should use __get(), __set(), get_data(), set_data() +	*/ +	private $data = array(); + +	public function __construct(ContainerBuilder $phpbb_container, $data = array()) +	{ +		// phpBB Container +		$this->phpbb_container = $phpbb_container; + +		// Service +		$this->service = $phpbb_container->get('notifications'); + +		// Some common things we're going to use +		$this->db = $phpbb_container->get('dbal.conn'); + +		$this->phpbb_root_path = $phpbb_container->getParameter('core.root_path'); +		$this->php_ext = $phpbb_container->getParameter('core.php_ext'); + +		// The row from the database (unless this is a new notification we're going to add) +		$this->data = $data; +		$this->data['data'] = (isset($this->data['data'])) ? unserialize($this->data['data']) : array(); +	} + +	public function __get($name) +	{ +		return $this->data[$name]; +	} + +	public function __set($name, $value) +	{ +		$this->data[$name] = $value; +	} + +	/** +	* Get special data (only important for the classes that extend this) +	* +	* @param string $name Name of the variable to get +	* +	* @return mixed +	*/ +	protected function get_data($name) +	{ +		return (isset($this->data['data'][$name])) ? $this->data['data'][$name] : null; +	} + +	/** +	* Set special data (only important for the classes that extend this) +	* +	* @param string $name Name of the variable to set +	* @param mixed $value Value to set to the variable +	*/ +	protected function set_data($name, $value) +	{ +		$this->data['data'][$name] = $value; +	} + +	/** +	* Prepare to output the notification to the template +	*/ +	public function prepare_for_display() +	{ +		$user = $this->phpbb_container->get('user'); + +		return array( +			'AVATAR'			=> $this->get_avatar(), + +			'FORMATTED_TITLE'	=> $this->get_title(), + +			'URL'				=> $this->get_url(), +			'TIME'	   			=> $user->format_date($this->time), + +			'UNREAD'			=> $this->unread, + +			'U_MARK_READ'		=> append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'mark_notification[]=' . $this->notification_id), +		); +	} + +	/** +	* 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 = true) +	{ +		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 = true) +	{ +		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 +	* +	* @return array Array of data ready to be inserted into the database +	*/ +	public function create_insert_array($type_data) +	{ +		// 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['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 static function load_special(ContainerBuilder $phpbb_container, $data, $notifications) +	{ +		return; +	} + +	/** +	* Is available (fall-back) +	*/ +	public static function is_available(ContainerBuilder $phpbb_container) +	{ +		return true; +	} + +	/** +	* -------------- Helper functions ------------------- +	*/ + +	/** +	* Find the users who want to receive notifications (helper) +	* +	* @param ContainerBuilder $phpbb_container +	* @param array $item_id The item_id to search for +	* +	* @return array +	*/ +	protected static function _find_users_for_notification(ContainerBuilder $phpbb_container, $item_id, $options) +	{ +		$options = array_merge(array( +			'ignore_users'		=> array(), +		), $options); + +		$db = $phpbb_container->get('dbal.conn'); + +		$rowset = array(); + +		$sql = 'SELECT * +			FROM ' . USER_NOTIFICATIONS_TABLE . " +			WHERE item_type = '" . static::get_item_type() . "' +				AND item_id = " . (int) $item_id; +		$result = $db->sql_query($sql); +		while ($row = $db->sql_fetchrow($result)) +		{ +			if (isset($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']; +		} +		$db->sql_freeresult($result); + +		return $rowset; +	} + +	/** +	* Get avatar helper +	* +	* @param int $user_id +	* @return string +	*/ +	protected function _get_avatar($user_id) +	{ +		$user = $this->service->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) +	{ +		$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 = ' . (bool) $unread . ' +			WHERE ' . $where; +		$this->db->sql_query($sql); +	} +} diff --git a/phpBB/includes/notifications/type/bookmark.php b/phpBB/includes/notifications/type/bookmark.php new file mode 100644 index 0000000000..a452583c77 --- /dev/null +++ b/phpBB/includes/notifications/type/bookmark.php @@ -0,0 +1,117 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Bookmark updating notifications class +* This class handles notifications for replies to a bookmarked topic +* +* @package notifications +*/ +class phpbb_notifications_type_bookmark extends phpbb_notifications_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_notifications_type_ +	*/ +	public static function get_item_type() +	{ +		return 'bookmark'; +	} + +	/** +	* Find the users who want to receive notifications +	* +	* @param ContainerBuilder $phpbb_container +	* @param array $post Data from +	* +	* @return array +	*/ +	public static function find_users_for_notification(ContainerBuilder $phpbb_container, $post, $options = array()) +	{ +		$options = array_merge(array( +			'ignore_users'		=> array(), +		), $options); + +		$db = $phpbb_container->get('dbal.conn'); + +		$users = array(); + +		$sql = 'SELECT user_id +			FROM ' . BOOKMARKS_TABLE . ' +			WHERE ' . $db->sql_in_set('topic_id', $post['topic_id']) . ' +				AND user_id <> ' . (int) $post['poster_id']; +		$result = $db->sql_query($sql); +		while ($row = $db->sql_fetchrow($result)) +		{ +			$users[] = $row['user_id']; +		} +		$db->sql_freeresult($result); + +		if (empty($users)) +		{ +			return array(); +		} + +		$auth_read = $phpbb_container->get('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 " . $db->sql_in_set('user_id', $auth_read[$post['forum_id']]['f_read']); +		$result = $db->sql_query($sql); +		while ($row = $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']; +		} +		$db->sql_freeresult($result); + +		return $notify_users; +	} +} diff --git a/phpBB/includes/notifications/type/disapprove_post.php b/phpBB/includes/notifications/type/disapprove_post.php new file mode 100644 index 0000000000..6911af5b08 --- /dev/null +++ b/phpBB/includes/notifications/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 +* +*/ + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Post notifications class +* This class handles notifications for replies to a topic +* +* @package notifications +*/ +class phpbb_notifications_type_disapprove_post extends phpbb_notifications_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' and 'lang') +	*/ +	public static $notification_option = array( +		'id'	=> 'moderation_queue', +		'lang'	=> 'NOTIFICATION_TYPE_MODERATION_QUEUE', +	); + +	/** +	* Get the type of notification this is +	* phpbb_notifications_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->phpbb_container->get('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 +	* +	* @return array Array of data ready to be inserted into the database +	*/ +	public function create_insert_array($post) +	{ +		$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/notifications/type/disapprove_topic.php b/phpBB/includes/notifications/type/disapprove_topic.php new file mode 100644 index 0000000000..dab5ec1b02 --- /dev/null +++ b/phpBB/includes/notifications/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 +* +*/ + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Post notifications class +* This class handles notifications for replies to a topic +* +* @package notifications +*/ +class phpbb_notifications_type_disapprove_topic extends phpbb_notifications_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' and 'lang') +	*/ +	public static $notification_option = array( +		'id'	=> 'moderation_queue', +		'lang'	=> 'NOTIFICATION_TYPE_MODERATION_QUEUE', +	); + +	/** +	* Get the type of notification this is +	* phpbb_notifications_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->phpbb_container->get('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 +	* +	* @return array Array of data ready to be inserted into the database +	*/ +	public function create_insert_array($post) +	{ +		$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/notifications/type/interface.php b/phpBB/includes/notifications/type/interface.php new file mode 100644 index 0000000000..95c307013e --- /dev/null +++ b/phpBB/includes/notifications/type/interface.php @@ -0,0 +1,49 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Base notifications interface +* @package notifications +*/ +interface phpbb_notifications_type_interface +{ +	public static function get_item_type(); + +	public static function get_item_id($type_data); + +	public static function is_available(ContainerBuilder $phpbb_container); + +	public static function find_users_for_notification(ContainerBuilder $phpbb_container, $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 create_insert_array($type_data); + +	public function get_load_special(); + +	public static function load_special(ContainerBuilder $phpbb_container, $data, $notifications); +} diff --git a/phpBB/includes/notifications/type/pm.php b/phpBB/includes/notifications/type/pm.php new file mode 100644 index 0000000000..f0730f285c --- /dev/null +++ b/phpBB/includes/notifications/type/pm.php @@ -0,0 +1,191 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Private message notifications class +* This class handles notifications for private messages +* +* @package notifications +*/ +class phpbb_notifications_type_pm extends phpbb_notifications_type_base +{ +	/** +	* Email template to use to send notifications +	* +	* @var string +	*/ +	public $email_template = 'privmsg_notify'; + +	/** +	* Get the type of notification this is +	* phpbb_notifications_type_ +	*/ +	public static function get_item_type() +	{ +		return 'pm'; +	} + +	/** +	* Get the id of the +	* +	* @param array $pm The data from the private message +	*/ +	public static function get_item_id($pm) +	{ +		return (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 ContainerBuilder $phpbb_container +	* @param array $pm Data from +	* +	* @return array +	*/ +	public static function find_users_for_notification(ContainerBuilder $phpbb_container, $pm, $options = array()) +	{ +		$options = array_merge(array( +			'ignore_users'		=> array(), +		), $options); + +		$service = $phpbb_container->get('notifications'); +		$db = $phpbb_container->get('dbal.conn'); +		$user = $phpbb_container->get('user'); + +		if (!sizeof($pm['recipients'])) +		{ +			return array(); +		} + +		$service->load_users(array_keys($pm['recipients'])); + +		$notify_users = array(); + +		$sql = 'SELECT * +			FROM ' . USER_NOTIFICATIONS_TABLE . " +			WHERE item_type = '" . self::get_item_type() . "' +				AND " . $db->sql_in_set('user_id', array_keys($pm['recipients'])); +		$result = $db->sql_query($sql); +		while ($row = $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']; +		} +		$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->service->get_user($this->get_data('from_user_id')); + +		$username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']); + +		return $this->phpbb_container->get('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->service->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&mode=view&p={$this->item_id}"); +	} + +	/** +	* Users needed to query before this notification can be displayed +	* +	* @return array Array of user_ids +	*/ +	public function users_to_query() +	{ +		return array($this->data['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 +	* +	* @return array Array of data ready to be inserted into the database +	*/ +	public function create_insert_array($pm) +	{ +		$this->set_data('from_user_id', $pm['from_user_id']); + +		$this->set_data('message_subject', $pm['message_subject']); + +		return parent::create_insert_array($pm); +	} +} diff --git a/phpBB/includes/notifications/type/post.php b/phpBB/includes/notifications/type/post.php new file mode 100644 index 0000000000..d654a2e3a3 --- /dev/null +++ b/phpBB/includes/notifications/type/post.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 +* +*/ + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Post notifications class +* This class handles notifications for replies to a topic +* +* @package notifications +*/ +class phpbb_notifications_type_post extends phpbb_notifications_type_base +{ +	/** +	* 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'; + +	/** +	* Get the type of notification this is +	* phpbb_notifications_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 ContainerBuilder $phpbb_container +	* @param array $post Data from +	* +	* @return array +	*/ +	public static function find_users_for_notification(ContainerBuilder $phpbb_container, $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']); + +		$db = $phpbb_container->get('dbal.conn'); + +		$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 = $db->sql_query($sql); +		while ($row = $db->sql_fetchrow($result)) +		{ +			$users[] = $row['user_id']; +		} +		$db->sql_freeresult($result); + +		if (empty($users)) +		{ +			return array(); +		} + +		$auth_read = $phpbb_container->get('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 " . $db->sql_in_set('user_id', $auth_read[$post['forum_id']]['f_read']); +		$result = $db->sql_query($sql); +		while ($row = $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']; +		} +		$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->service->get_user($this->get_data('poster_id')); + +			$username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']); +		} + +		return $this->phpbb_container->get('user')->lang( +			$this->language_key, +			$username, +			censor_text($this->get_data('topic_title')) +		); +	} + +	/** +	* Get email template variables +	* +	* @return array +	*/ +	public function get_email_template_variables() +	{ +		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_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() +	{ +		return array($this->data['poster_id']); +	} + +	/** +	* Function for preparing the data for insertion in an SQL query +	* (The service handles insertion) +	* +	* @param array $post Data from submit_post +	* +	* @return array Array of data ready to be inserted into the database +	*/ +	public function create_insert_array($post) +	{ +		$this->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']; + +		return parent::create_insert_array($post); +	} +} diff --git a/phpBB/includes/notifications/type/post_in_queue.php b/phpBB/includes/notifications/type/post_in_queue.php new file mode 100644 index 0000000000..64f68c07e2 --- /dev/null +++ b/phpBB/includes/notifications/type/post_in_queue.php @@ -0,0 +1,137 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Topic notifications class +* This class handles notifications for new topics +* +* @package notifications +*/ +class phpbb_notifications_type_post_in_queue extends phpbb_notifications_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' and 'lang') +	*/ +	public static $notification_option = array( +		'id'	=> 'needs_approval', +		'lang'	=> 'NOTIFICATION_TYPE_IN_MODERATION_QUEUE', +	); + +	/** +	* Get the type of notification this is +	* phpbb_notifications_type_ +	*/ +	public static function get_item_type() +	{ +		return 'post_in_queue'; +	} + +	/** +	* Is available +	*/ +	public static function is_available(ContainerBuilder $phpbb_container) +	{ +		$m_approve = $phpbb_container->get('auth')->acl_getf('m_approve', true); + +		return (!empty($m_approve)); +	} + +	/** +	* Find the users who want to receive notifications +	* +	* @param ContainerBuilder $phpbb_container +	* @param array $post Data from the post +	* +	* @return array +	*/ +	public static function find_users_for_notification(ContainerBuilder $phpbb_container, $post, $options = array()) +	{ +		$options = array_merge(array( +			'ignore_users'		=> array(), +		), $options); + +		$db = $phpbb_container->get('dbal.conn'); + +		$auth_approve = $phpbb_container->get('auth')->acl_get_list(false, 'm_approve', $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 " . $db->sql_in_set('user_id', $auth_approve[$post['forum_id']]['m_approve']); +		$result = $db->sql_query($sql); +		while ($row = $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']; +		} +		$db->sql_freeresult($result); + +		return $notify_users; +	} + +	/** +	* Function for preparing the data for insertion in an SQL query +	* (The service handles insertion) +	* +	* @param array $post Data from submit_post +	* +	* @return array Array of data ready to be inserted into the database +	*/ +	public function create_insert_array($post) +	{ +		$data = parent::create_insert_array($post); + +		$this->time = $data['time'] = time(); + +		return $data; +	} +} diff --git a/phpBB/includes/notifications/type/quote.php b/phpBB/includes/notifications/type/quote.php new file mode 100644 index 0000000000..f162b37126 --- /dev/null +++ b/phpBB/includes/notifications/type/quote.php @@ -0,0 +1,209 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Post quoting notifications class +* This class handles notifications for quoting users in a post +* +* @package notifications +*/ +class phpbb_notifications_type_quote extends phpbb_notifications_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="(.+?)"#'; + +	/** +	* Language key used to output the text +	* +	* @var string +	*/ +	protected $language_key = 'NOTIFICATION_QUOTE'; + +	/** +	* Get the type of notification this is +	* phpbb_notifications_type_ +	*/ +	public static function get_item_type() +	{ +		return 'quote'; +	} + +	/** +	* Find the users who want to receive notifications +	* +	* @param ContainerBuilder $phpbb_container +	* @param array $post Data from +	* +	* @return array +	*/ +	public static function find_users_for_notification(ContainerBuilder $phpbb_container, $post, $options = array()) +	{ +		$options = array_merge(array( +			'ignore_users'		=> array(), +		), $options); + +		$db = $phpbb_container->get('dbal.conn'); + +		$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 ' . $db->sql_in_set('username_clean', $usernames) . ' +				AND user_id <> ' . (int) $post['poster_id']; +		$result = $db->sql_query($sql); +		while ($row = $db->sql_fetchrow($result)) +		{ +			$users[] = $row['user_id']; +		} +		$db->sql_freeresult($result); + +		if (empty($users)) +		{ +			return array(); +		} + +		$auth_read = $phpbb_container->get('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 " . $db->sql_in_set('user_id', $auth_read[$post['forum_id']]['f_read']); +		$result = $db->sql_query($sql); +		while ($row = $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']; +		} +		$db->sql_freeresult($result); + +		return $notify_users; +	} + +	/** +	* Update a notification +	* +	* @param ContainerBuilder $phpbb_container +	* @param array $data Data specific for this type that will be updated +	*/ +	public static function update_notifications(ContainerBuilder $phpbb_container, $post) +	{ +		$service = $phpbb_container->get('notifications'); +		$db = $phpbb_container->get('dbal.conn'); + +		$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); +		$result = $db->sql_query($sql); +		while ($row = $db->sql_fetchrow($result)) +		{ +			$old_notifications[] = $row['user_id']; +		} +		$db->sql_freeresult($result); + +		// Find the new users to notify +		$notifications = self::find_users_for_notification($phpbb_container, $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]; +		} + +		// todo Adding notifications while editing a post can be funky. +		// If the user has read the topic/post already, and the user is newly quoted it an edit, +		// The notification will be stuck as unread until another post is made and the user visits +		// the topic again because the posts will not be marked as read since the topic is already +		// marked as read + +		// Add the necessary notifications +		$service->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 ' . $db->sql_in_set('user_id', $remove_notifications); +			$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->service->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/notifications/type/topic.php b/phpBB/includes/notifications/type/topic.php new file mode 100644 index 0000000000..ddef0147ba --- /dev/null +++ b/phpBB/includes/notifications/type/topic.php @@ -0,0 +1,237 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Topic notifications class +* This class handles notifications for new topics +* +* @package notifications +*/ +class phpbb_notifications_type_topic extends phpbb_notifications_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'; + +	/** +	* Get the type of notification this is +	* phpbb_notifications_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 ContainerBuilder $phpbb_container +	* @param array $topic Data from the topic +	* +	* @return array +	*/ +	public static function find_users_for_notification(ContainerBuilder $phpbb_container, $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']); + +		$db = $phpbb_container->get('dbal.conn'); + +		$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 = $db->sql_query($sql); +		while ($row = $db->sql_fetchrow($result)) +		{ +			$users[] = $row['user_id']; +		} +		$db->sql_freeresult($result); + +		if (empty($users)) +		{ +			return array(); +		} + +		$auth_read = $phpbb_container->get('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 " . $db->sql_in_set('user_id', $auth_read[$topic['forum_id']]['f_read']); +		$result = $db->sql_query($sql); +		while ($row = $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']; +		} +		$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->service->get_user($this->get_data('poster_id')); + +			$username = get_username_string('no_profile', $user_data['user_id'], $user_data['username'], $user_data['user_colour']); +		} + +		return $this->phpbb_container->get('user')->lang( +			$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() +	{ +		return array( +			'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}&t={$this->item_id}"); +	} + +	/** +	* Users needed to query before this notification can be displayed +	* +	* @return array Array of user_ids +	*/ +	public function users_to_query() +	{ +		return array($this->data['poster_id']); +	} + +	/** +	* Function for preparing the data for insertion in an SQL query +	* (The service handles insertion) +	* +	* @param array $post Data from submit_post +	* +	* @return array Array of data ready to be inserted into the database +	*/ +	public function create_insert_array($post) +	{ +		$this->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']; + +		return parent::create_insert_array($post); +	} +} diff --git a/phpBB/includes/notifications/type/topic_in_queue.php b/phpBB/includes/notifications/type/topic_in_queue.php new file mode 100644 index 0000000000..dc7f7aa105 --- /dev/null +++ b/phpBB/includes/notifications/type/topic_in_queue.php @@ -0,0 +1,137 @@ +<?php +/** +* +* @package notifications +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Topic notifications class +* This class handles notifications for new topics +* +* @package notifications +*/ +class phpbb_notifications_type_topic_in_queue extends phpbb_notifications_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' and 'lang') +	*/ +	public static $notification_option = array( +		'id'	=> 'needs_approval', +		'lang'	=> 'NOTIFICATION_TYPE_IN_MODERATION_QUEUE', +	); + +	/** +	* Is available +	*/ +	public static function is_available(ContainerBuilder $phpbb_container) +	{ +		$m_approve = $phpbb_container->get('auth')->acl_getf('m_approve', true); + +		return (!empty($m_approve)); +	} + +	/** +	* Get the type of notification this is +	* phpbb_notifications_type_ +	*/ +	public static function get_item_type() +	{ +		return 'topic_in_queue'; +	} + +	/** +	* Find the users who want to receive notifications +	* +	* @param ContainerBuilder $phpbb_container +	* @param array $topic Data from the topic +	* +	* @return array +	*/ +	public static function find_users_for_notification(ContainerBuilder $phpbb_container, $topic, $options = array()) +	{ +		$options = array_merge(array( +			'ignore_users'		=> array(), +		), $options); + +		$db = $phpbb_container->get('dbal.conn'); + +		$auth_approve = $phpbb_container->get('auth')->acl_get_list(false, 'm_approve', $topic['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 " . $db->sql_in_set('user_id', $auth_approve[$topic['forum_id']]['m_approve']); +		$result = $db->sql_query($sql); +		while ($row = $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']; +		} +		$db->sql_freeresult($result); + +		return $notify_users; +	} + +	/** +	* Function for preparing the data for insertion in an SQL query +	* (The service handles insertion) +	* +	* @param array $topic Data from submit_post +	* +	* @return array Array of data ready to be inserted into the database +	*/ +	public function create_insert_array($topic) +	{ +		$data = parent::create_insert_array($topic); + +		$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..4bc9ae2cea --- /dev/null +++ b/phpBB/includes/ucp/info/ucp_notifications.php @@ -0,0 +1,34 @@ +<?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_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..950b70a156 --- /dev/null +++ b/phpBB/includes/ucp/ucp_notifications.php @@ -0,0 +1,141 @@ +<?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 $phpbb_container; + +		add_form_key('ucp_notification_options'); + +		$phpbb_notifications = $phpbb_container->get('notifications'); +		$template = $phpbb_container->get('template'); +		$user = $phpbb_container->get('user'); +		$request = $phpbb_container->get('request'); + +		$subscriptions = $phpbb_notifications->get_subscriptions(false, true); + +		// Add/remove subscriptions +		if ($request->is_set_post('submit')) +		{ +			if (!check_form_key('ucp_notification_options')) +			{ +				trigger_error('FORM_INVALID'); +			} + +			$notification_methods = $phpbb_notifications->get_subscription_methods(); + +			foreach($phpbb_notifications->get_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); +					} +				} +			} +		} + +		// todo include language files for extensions? + +		$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_NOTIFICATIONS'; +	} + +	/** +	* Output all the notification types to the template +	* +	* @param string $block +	* @param phpbb_notifications_service $phpbb_notifications +	* @param phpbb_template $template +	* @param phpbb_user $user +	*/ +	public function output_notification_types($block = 'notification_types', phpbb_notifications_service $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 $type => $data) +		{ +			$template->assign_block_vars($block, array( +				'TYPE'				=> $type, + +				'NAME'				=> (is_array($data) && isset($data['lang'])) ? $user->lang($data['lang']) : $user->lang('NOTIFICATION_TYPE_' . strtoupper($type)), + +				'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_notifications_service $phpbb_notifications +	* @param phpbb_template $template +	* @param phpbb_user $user +	*/ +	public function output_notification_methods($block = 'notification_methods', phpbb_notifications_service $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']), | 
