Commit 60167828 authored by Richard Mansfield's avatar Richard Mansfield
Browse files

Get unread message count from user table (bug #854403)



Also keeps the count in the $USER object up to date whenever the
user deletes or reads a notification.

When new notifications are generated for a live user by another user,
or on cron, the logged-in user's unread count is reloaded from the
database into the session either on hitting the inbox, or whenever
$USER is committed for some other reason.

The code to reload the background fields on commit of the LiveUser
object has been changed to ensure that it still works at upgrade time,
where the 'reload' column doesn't exist in the user table yet, but
*does* exist in the User object.

Change-Id: I9c9a81bf77d0927352902dee0d989d6122757b47
Signed-off-by: default avatarRichard Mansfield <richard.mansfield@catalyst.net.nz>
parent 4b3117e4
......@@ -36,7 +36,12 @@ $delete = param_integer('delete', 0);
if ($readone) {
set_field('notification_internal_activity', 'read', 1, 'id', $readone, 'usr', $USER->get('id'));
json_reply(false, null);
$unread = $USER->add_unread(-1);
$data = array(
'newunreadcount' => $unread,
'newimage' => $THEME->get_url($unread ? 'images/newemail.gif' : 'images/email.gif'),
);
json_reply(false, array('data' => $data));
}
require_once(get_config('libroot') . 'activity.php');
......@@ -60,14 +65,19 @@ if ($markasread) {
'id IN (' . join(',', $ids) . ') AND usr = ?',
array($USER->get('id'))
);
$newunread = $USER->add_unread(-count($ids));
}
$message = get_string('markedasread', 'activity');
}
else if ($delete) {
$ids = array();
$deleteunread = 0; // Remember the number of unread messages being deleted
foreach ($_GET as $k => $v) {
if (preg_match('/^delete\-(\d+)$/',$k,$m)) {
$ids[] = $m[1];
if (isset($_GET['unread-' . $m[1]])) {
$deleteunread++;
}
}
}
if ($ids) {
......@@ -92,6 +102,9 @@ else if ($delete) {
"id IN ($strids) AND usr = ?",
array($userid)
);
if ($deleteunread) {
$newunread = $USER->add_unread(-$deleteunread);
}
db_commit();
}
$message = get_string('deletednotifications', 'activity', count($ids));
......@@ -99,13 +112,9 @@ else if ($delete) {
$newhtml = activitylist_html($type, $limit, $offset);
if ($message) {
safe_require('notification', 'internal');
$newhtml['newunreadcount'] = call_static_method(
generate_class_name('notification', 'internal'),
'unread_count',
$USER->get('id')
);
if (isset($newunread)) {
$newhtml['newunreadcount'] = $newunread;
$newhtml['newimage'] = $THEME->get_url($newunread ? 'images/newemail.gif' : 'images/email.gif');
}
json_reply(false, (object) array('message' => $message, 'data' => $newhtml));
......@@ -35,6 +35,10 @@ require(dirname(dirname(dirname(__FILE__))) . '/init.php');
require_once('pieforms/pieform.php');
define('TITLE', get_string('inbox'));
// Make sure the unread message count is up to date whenever the
// user hits this page.
$USER->reload_background_fields();
$installedtypes = get_records_assoc(
'activity_type', '', '',
'plugintype,pluginname,name',
......@@ -90,6 +94,11 @@ function markread(form, action) {
if (action == 'read') {
pd['markasread'] = 1;
} else if (action == 'del') {
// If deleting, also pass the ids of unread messages, so we can update
// the unread message count as accurately as possible.
forEach(getElementsByTagAndClassName('input', 'tocheckread', form), function(cb) {
pd[cb.name] = 0;
});
pd['delete'] = 1;
}
......@@ -101,9 +110,7 @@ function markread(form, action) {
sendjsonrequest('index.json.php', pd, 'GET', function (data) {
paginator.updateResults(data);
if (data.newunreadcount && typeof(data.newunreadcount) != 'undefined') {
updateUnreadCount(data.newunreadcount, 'reset');
}
updateUnreadCount(data);
});
}
......@@ -120,7 +127,7 @@ function showHideMessage(id) {
var pd = {'readone':id};
sendjsonrequest('index.json.php', pd, 'GET', function(data) {
swapDOM(unread, IMG({'src' : {$star}, 'alt' : {$strread}}));
updateUnreadCount(1, 'decrement');
updateUnreadCount(data);
});
}
removeElementClass(message, 'hidden');
......@@ -234,6 +241,8 @@ function delete_all_notifications_submit() {
' . join(',', array_map('db_quote', $ids)) . '
)'
);
// The update_unread_delete db trigger on notification_internal_activity
// will update the unread column on the usr table.
}
db_commit();
......
......@@ -96,7 +96,8 @@ class User {
'sesskey' => '',
'ctime' => null,
'views' => array(),
'showhomeinfo' => 1
'showhomeinfo' => 1,
'unread' => 0,
);
$this->attributes = array();
......@@ -1224,29 +1225,35 @@ class LiveUser extends User {
$this->changed = false;
}
public function commit() {
if ($this->changed == false) {
return;
}
// Fields which can't be changed in the session, but which may have
// changed in the db. They should be reloaded.
/**
* Some fields may have been changed in the db by some other process, and
* should be occasionally reloaded into the session.
*/
public function reload_background_fields() {
$reload = array(
'active' => 'active',
'deleted' => 'deleted',
'expiry' => db_format_tsfield('expiry'),
'expirymailsent' => 'expirymailsent',
'inactivemailsent' => 'inactivemailsent',
'suspendedctime' => db_format_tsfield('suspendedctime'),
'suspendedreason' => 'suspendedreason',
'suspendedcusr' => 'suspendedcusr',
'quota' => 'quota',
'active', 'deleted', 'expiry', 'expirymailsent', 'inactivemailsent', 'suspendedctime', 'suspendedreason',
'suspendedcusr', 'quota', 'unread',
);
$r = get_record('usr', 'id', $this->id, null, null, null, null, join(',', $reload));
foreach (array_keys($reload) as $k) {
if ($r->$k != $this->$k) {
$this->$k = $r->$k;
$tsfields = array('expiry', 'suspendedctime');
$record = get_record('usr', 'id', $this->id);
foreach ($reload as $f) {
if (!isset($record->$f)) {
continue;
}
if (in_array($f, $tsfields)) {
$record->$f = strtotime($record->$f);
}
if ($record->$f != $this->$f) {
$this->$f = $record->$f;
}
}
}
public function commit() {
if ($this->changed == false) {
return;
}
$this->reload_background_fields();
parent::commit();
}
......@@ -1478,6 +1485,15 @@ class LiveUser extends User {
'mimetype' => $mimetype,
));
}
public function add_unread($n) {
// The unread property can change any time a notification is processed on
// cron, so it's reloaded from the db in commit(), every time the last
// access time is saved. This just updates it in the session.
$new = $this->get('unread') + $n;
$this->SESSION->set('user/unread', $new);
return $new;
}
}
function is_site_closed($adminuser) {
......
......@@ -43,7 +43,7 @@ addLoadEvent(function() {
var pd = {'readone':id};
sendjsonrequest(config.wwwroot + 'account/activity/index.json.php', pd, 'GET', function(data) {
removeElementClass(element, 'unread');
updateUnreadCount(1, 'decrement');
updateUnreadCount(data);
});
}
});
......
......@@ -708,21 +708,22 @@ function quotaUpdate(quotaused, quota) {
}
}
function updateUnreadCount(n, decrement) {
var newcount = -1;
var countnode = getFirstElementByTagAndClassName('span', 'unreadmessagecount', 'right-nav');
if (!countnode) {
function updateUnreadCount(data) {
var inboxmenu = getFirstElementByTagAndClassName(null, 'inbox', 'right-nav');
if (!inboxmenu) {
return;
}
if (decrement == 'decrement') {
var oldcount = parseInt(countnode.innerHTML);
newcount = (oldcount - n);
}
else {
newcount = n;
if (typeof(data.data.newunreadcount) != 'undefined') {
var countnode = getFirstElementByTagAndClassName('span', 'unreadmessagecount', inboxmenu);
if (countnode) {
countnode.innerHTML = data.data.newunreadcount;
}
}
if (newcount > -1) {
countnode.innerHTML = newcount;
if (data.data.newimage) {
var oldimage = getFirstElementByTagAndClassName('img', null, inboxmenu);
if (oldimage) {
setNodeAttribute(oldimage, 'src', data.data.newimage);
}
}
}
......
......@@ -480,6 +480,8 @@ abstract class ActivityType {
}
}
// The user's unread message count does not need to be updated from $changes->read
// because of the db trigger on notification_internal_activity.
}
public function notify_users() {
......
......@@ -845,8 +845,6 @@ function jsstrings() {
'unknownerror',
'loading',
'showtags',
'unreadmessages',
'unreadmessage',
'couldnotgethelp',
'password',
'username',
......@@ -2245,7 +2243,7 @@ function right_nav() {
global $USER, $THEME;
safe_require('notification', 'internal');
$unread = call_static_method(generate_class_name('notification', 'internal'), 'unread_count', $USER->get('id'));
$unread = $USER->get('unread');
$menu = array(
'settings' => array(
......@@ -2259,7 +2257,7 @@ function right_nav() {
'inbox' => array(
'path' => 'inbox',
'url' => 'account/activity',
'icon' => $THEME->get_url('images/email.gif'),
'icon' => $THEME->get_url($unread ? 'images/newemail.gif' : 'images/email.gif'),
'alt' => get_string('inbox'),
'count' => $unread,
'countclass' => 'unreadmessagecount',
......
......@@ -89,18 +89,6 @@ class PluginNotificationInternal extends PluginNotification {
}
}
/**
* this method is only implemented in internal & is used for the header
*/
public static function unread_count($userid) {
static $unreadcount = array();
if (!isset($unreadcount[$userid])) {
$unreadcount[$userid] = count_records('notification_internal_activity', 'usr', $userid, 'read', 0);
}
return $unreadcount[$userid];
}
public static function get_event_subscriptions() {
$subscriptions = array(
(object)array(
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment