Version 2.1.0
This commit is contained in:
399
core/notifications.php
Normal file
399
core/notifications.php
Normal file
@@ -0,0 +1,399 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* @package phpBB Extension - mChat
|
||||
* @copyright (c) 2018 kasimi - https://kasimi.net
|
||||
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
|
||||
*
|
||||
*/
|
||||
|
||||
namespace dmzx\mchat\core;
|
||||
|
||||
use phpbb\auth\auth;
|
||||
use phpbb\event\dispatcher_interface;
|
||||
use phpbb\language\language;
|
||||
use phpbb\textformatter\parser_interface;
|
||||
use phpbb\user;
|
||||
use phpbb\db\driver\driver_interface as db_interface;
|
||||
|
||||
class notifications
|
||||
{
|
||||
/**
|
||||
* Value of the phpbb_mchat.post_id field for login notification
|
||||
* messages if the user session is visible at the time of login
|
||||
*/
|
||||
const LOGIN_VISIBLE = 1;
|
||||
|
||||
/**
|
||||
* Value of the phpbb_mchat.post_id field for login notification
|
||||
* messages if the user session is hidden at the time of login
|
||||
*/
|
||||
const LOGIN_HIDDEN = 2;
|
||||
|
||||
/**
|
||||
* A notification of a new topic, quote, edit or reply
|
||||
*/
|
||||
const POST = 3;
|
||||
|
||||
/** @var settings */
|
||||
protected $mchat_settings;
|
||||
|
||||
/** @var user */
|
||||
protected $user;
|
||||
|
||||
/** @var language */
|
||||
protected $lang;
|
||||
|
||||
/** @var auth */
|
||||
protected $auth;
|
||||
|
||||
/** @var db_interface */
|
||||
protected $db;
|
||||
|
||||
/** @var dispatcher_interface */
|
||||
protected $dispatcher;
|
||||
|
||||
/** @var parser_interface */
|
||||
protected $textformatter_parser;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param settings $mchat_settings
|
||||
* @param user $user
|
||||
* @param language $lang
|
||||
* @param auth $auth
|
||||
* @param db_interface $db
|
||||
* @param dispatcher_interface $dispatcher
|
||||
* @param parser_interface $textformatter_parser
|
||||
*/
|
||||
public function __construct(
|
||||
settings $mchat_settings,
|
||||
user $user,
|
||||
language $lang,
|
||||
auth $auth,
|
||||
db_interface $db,
|
||||
dispatcher_interface $dispatcher,
|
||||
parser_interface $textformatter_parser
|
||||
)
|
||||
{
|
||||
$this->mchat_settings = $mchat_settings;
|
||||
$this->user = $user;
|
||||
$this->lang = $lang;
|
||||
$this->auth = $auth;
|
||||
$this->db = $db;
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->textformatter_parser = $textformatter_parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not the given message row is a notification
|
||||
*
|
||||
* @param array $row The message row
|
||||
* @return int the notification type, or 0 if the $row is not a notification
|
||||
*/
|
||||
public function is_notification($row)
|
||||
{
|
||||
// If post_id is 0 it's not a notification
|
||||
if (isset($row['post_id']) && $row['post_id'])
|
||||
{
|
||||
// If forum_id is 0 it's a login notification
|
||||
if (isset($row['forum_id']) && !$row['forum_id'])
|
||||
{
|
||||
// post_id is either LOGIN_VISIBLE or LOGIN_HIDDEN
|
||||
return $row['post_id'];
|
||||
}
|
||||
|
||||
return self::POST;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the post rows for notifications and converts their language keys
|
||||
*
|
||||
* @param array $rows The rows to modify
|
||||
* @return array
|
||||
*/
|
||||
public function process($rows)
|
||||
{
|
||||
// All language keys of valid notifications for which we need to fetch post information
|
||||
// from the database. We need to check for them here because notifications in < 2.0.0-RC6
|
||||
// are plain text and don't need to be processed.
|
||||
$notification_lang = [
|
||||
'MCHAT_NEW_POST',
|
||||
'MCHAT_NEW_QUOTE',
|
||||
'MCHAT_NEW_EDIT',
|
||||
'MCHAT_NEW_REPLY',
|
||||
'MCHAT_NEW_LOGIN',
|
||||
];
|
||||
|
||||
$notification_langs = array_merge(
|
||||
// Raw notification messages in phpBB < 3.2
|
||||
array_combine($notification_lang, $notification_lang),
|
||||
// XML notification messages in phpBB >= 3.2
|
||||
array_combine(array_map([$this->textformatter_parser, 'parse'], $notification_lang), $notification_lang)
|
||||
);
|
||||
|
||||
$notifications = [];
|
||||
$post_ids = [];
|
||||
|
||||
foreach ($rows as $i => $row)
|
||||
{
|
||||
$type = $this->is_notification($row);
|
||||
|
||||
if ($type && isset($notification_langs[$row['message']]))
|
||||
{
|
||||
$notifications[$i] = $type;
|
||||
|
||||
if ($type == self::POST)
|
||||
{
|
||||
$post_ids[$i] = $row['post_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$notification_post_data = $this->mchat_get_post_data($post_ids);
|
||||
|
||||
foreach ($notifications as $i => $type)
|
||||
{
|
||||
$lang_key = $notification_langs[$rows[$i]['message']];
|
||||
$post_data = $type == self::POST ? $notification_post_data[$post_ids[$i]] : null;
|
||||
$rows[$i] = $this->process_notification($rows[$i], $type, $lang_key, $post_data);
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches post subjects and their forum names. If a post_id can't be found the value for the post_id is set to null.
|
||||
*
|
||||
* @param array $post_ids
|
||||
* @return array
|
||||
*/
|
||||
protected function mchat_get_post_data($post_ids)
|
||||
{
|
||||
if (!$post_ids)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
$sql_array = [
|
||||
'SELECT' => 'p.post_id, p.post_subject, f.forum_id, f.forum_name',
|
||||
'FROM' => [POSTS_TABLE => 'p', FORUMS_TABLE => 'f'],
|
||||
'WHERE' => 'p.forum_id = f.forum_id AND ' . $this->db->sql_in_set('p.post_id', $post_ids),
|
||||
];
|
||||
|
||||
$sql = $this->db->sql_build_query('SELECT', $sql_array);
|
||||
$result = $this->db->sql_query($sql);
|
||||
$rows = $this->db->sql_fetchrowset($result);
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
$post_subjects = [];
|
||||
|
||||
foreach ($rows as $row)
|
||||
{
|
||||
$post_subjects[$row['post_id']] = [
|
||||
'post_subject' => $row['post_subject'],
|
||||
'forum_id' => $row['forum_id'],
|
||||
'forum_name' => $row['forum_name'],
|
||||
];
|
||||
}
|
||||
|
||||
// Map IDs of missing posts to null
|
||||
$missing_post_subjects = array_fill_keys(array_diff($post_ids, array_keys($post_subjects)), null);
|
||||
|
||||
return $post_subjects + $missing_post_subjects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the message field of the post row so that it can be passed to generate_text_for_display()
|
||||
*
|
||||
* @param array $row
|
||||
* @param int $type
|
||||
* @param string $lang_key
|
||||
* @param array $post_data
|
||||
* @return array
|
||||
*/
|
||||
protected function process_notification($row, $type, $lang_key, $post_data = null)
|
||||
{
|
||||
$lang_args = [];
|
||||
$replacements = [];
|
||||
|
||||
$post_subject_placeholder = '%POST_SUBJECT%';
|
||||
$forum_name_placeholder = '%FORUM_NAME%';
|
||||
|
||||
if ($type == self::POST)
|
||||
{
|
||||
if ($post_data)
|
||||
{
|
||||
$viewtopic_url = append_sid($this->mchat_settings->url('viewtopic', true), [
|
||||
'p' => $row['post_id'],
|
||||
'#' => 'p' . $row['post_id'],
|
||||
]);
|
||||
|
||||
// We prefer $post_data because it was fetched from the forums table just now.
|
||||
// $row might contain outdated data if a post was moved to a new forum.
|
||||
$forum_id = isset($post_data['forum_id']) ? $post_data['forum_id'] : $row['forum_id'];
|
||||
|
||||
$viewforum_url = append_sid($this->mchat_settings->url('viewforum', true), [
|
||||
'f' => $forum_id,
|
||||
]);
|
||||
|
||||
$lang_args[] = '[url=' . $viewtopic_url . ']' . $post_subject_placeholder . '[/url]';
|
||||
$lang_args[] = '[url=' . $viewforum_url . ']' . $forum_name_placeholder . '[/url]';
|
||||
|
||||
$replacements = [
|
||||
$post_subject_placeholder => $post_data['post_subject'],
|
||||
$forum_name_placeholder => $post_data['forum_name'],
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
$lang_key .= '_DELETED';
|
||||
}
|
||||
}
|
||||
else if ($type == self::LOGIN_HIDDEN)
|
||||
{
|
||||
$row['username'] = '<em>' . $row['username'] . '</em>';
|
||||
}
|
||||
|
||||
$row['message'] = $this->lang->lang_array($lang_key, $lang_args);
|
||||
|
||||
// Quick'n'dirty check if BBCodes are in the message
|
||||
if (strpos($row['message'], '[') !== false)
|
||||
{
|
||||
generate_text_for_storage($row['message'], $row['bbcode_uid'], $row['bbcode_bitfield'], $row['bbcode_options'], true, true, true, true, true, true, true, 'mchat');
|
||||
}
|
||||
|
||||
$row['message'] = strtr($row['message'], $replacements);
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a message with posting information into the database
|
||||
*
|
||||
* @param string $mode One of post|quote|edit|reply
|
||||
* @param int $forum_id
|
||||
* @param int $post_id
|
||||
*/
|
||||
public function insert_post($mode, $forum_id, $post_id)
|
||||
{
|
||||
$this->insert($mode, $forum_id, $post_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a message with login information into the database
|
||||
*
|
||||
* @param bool $is_hidden
|
||||
*/
|
||||
public function insert_login($is_hidden)
|
||||
{
|
||||
$this->insert('login', 0, $is_hidden ? self::LOGIN_HIDDEN : self::LOGIN_VISIBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a message with posting or login information into the database
|
||||
*
|
||||
* @param string $mode One of post|quote|edit|reply|login
|
||||
* @param int $forum_id
|
||||
* @param int $post_id Can be 0 if mode is login.
|
||||
*/
|
||||
protected function insert($mode, $forum_id, $post_id)
|
||||
{
|
||||
$mode_config = [
|
||||
'post' => 'mchat_posts_topic',
|
||||
'quote' => 'mchat_posts_quote',
|
||||
'edit' => 'mchat_posts_edit',
|
||||
'reply' => 'mchat_posts_reply',
|
||||
'login' => 'mchat_posts_login',
|
||||
];
|
||||
|
||||
$is_mode_enabled = !empty($mode_config[$mode]) && $this->mchat_settings->cfg($mode_config[$mode]) && (!$this->mchat_settings->cfg('mchat_posts_auth_check') || $this->can_use_mchat());
|
||||
|
||||
$sql_array = [
|
||||
'forum_id' => (int) $forum_id,
|
||||
'post_id' => (int) $post_id,
|
||||
'user_id' => (int) $this->user->data['user_id'],
|
||||
'user_ip' => $this->user->ip,
|
||||
'message' => $this->textformatter_parser->parse('MCHAT_NEW_' . strtoupper($mode)),
|
||||
'message_time' => time(),
|
||||
];
|
||||
|
||||
/**
|
||||
* Event that allows to modify data of a posting or login notification before it is inserted in the database
|
||||
*
|
||||
* @event dmzx.mchat.insert_posting_before
|
||||
* @var string mode The posting mode, one of post|quote|edit|reply|login
|
||||
* @var int forum_id The ID of the forum where the post was made, or 0 if mode is login.
|
||||
* @var int post_id The ID of the post that was made. If mode is login this value is
|
||||
* one of the constants LOGIN_HIDDEN|LOGIN_VISIBLE
|
||||
* @var array is_mode_enabled Whether or not the posting should be added to the database.
|
||||
* @var array sql_array An array containing the data that is about to be inserted into the messages table.
|
||||
* @since 2.0.0-RC6
|
||||
* @changed 2.1.0-RC1 Removed is_hidden_login
|
||||
*/
|
||||
$vars = [
|
||||
'mode',
|
||||
'forum_id',
|
||||
'post_id',
|
||||
'is_mode_enabled',
|
||||
'sql_array',
|
||||
];
|
||||
extract($this->dispatcher->trigger_event('dmzx.mchat.insert_posting_before', compact($vars)));
|
||||
|
||||
if ($is_mode_enabled)
|
||||
{
|
||||
$sql = 'INSERT INTO ' . $this->mchat_settings->get_table_mchat() . ' ' . $this->db->sql_build_array('INSERT', $sql_array);
|
||||
$this->db->sql_query($sql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The user might have just logged in successfully in which case the permissions haven't been updated yet.
|
||||
* Let's do that here so that notifications are recorded correctly.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function can_use_mchat()
|
||||
{
|
||||
if ($this->auth->acl_get('u_mchat_use'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$auth = new auth();
|
||||
$auth->acl($this->user->data);
|
||||
return $auth->acl_get('u_mchat_use');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an SQL WHERE condition to include or exlude notifacation
|
||||
* messages based on the current user's settings and permissions
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_sql_where()
|
||||
{
|
||||
// Exclude all post notifications
|
||||
if (!$this->mchat_settings->cfg('mchat_posts'))
|
||||
{
|
||||
return 'm.post_id = 0';
|
||||
}
|
||||
|
||||
// If the current user doesn't have permission to see hidden users, exclude their login posts
|
||||
if (!$this->auth->acl_get('u_viewonline'))
|
||||
{
|
||||
return implode(' OR ', [
|
||||
'm.post_id <> ' . self::LOGIN_HIDDEN, // Exclude all notifications that were created by hidden users ...
|
||||
'm.user_id = ' . (int) $this->user->data['user_id'], // ... but include all login notifications of the current user
|
||||
'm.forum_id <> 0', // ... and include all post notifications
|
||||
]);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user