MDL-25057 mod_forum: Stop duplicating forum_read posts from cron

This also includes an upgrade script to delete the existing duplicates.
This commit is contained in:
Andrew Nicols 2014-10-29 09:28:55 +08:00
parent b7ff40301d
commit 611a5ef714
3 changed files with 70 additions and 45 deletions

View File

@ -200,5 +200,29 @@ function xmldb_forum_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2014081900, 'forum');
}
if ($oldversion < 2014103000) {
// Find records with multiple userid/postid combinations and find the lowest ID.
// Later we will remove all those which don't match this ID.
$sql = "
SELECT MIN(id) as lowid, userid, postid
FROM {forum_read}
GROUP BY userid, postid
HAVING COUNT(id) > 1";
if ($duplicatedrows = $DB->get_recordset_sql($sql)) {
foreach ($duplicatedrows as $row) {
$DB->delete_records_select('forum_read', 'userid = ? AND postid = ? AND id <> ?', array(
$row->userid,
$row->postid,
$row->lowid,
));
}
}
$duplicatedrows->close();
// Forum savepoint reached.
upgrade_mod_savepoint(true, 2014103000, 'forum');
}
return true;
}

View File

@ -5962,57 +5962,58 @@ function forum_tp_mark_posts_read($user, $postids) {
return $status;
}
list($usql, $params) = $DB->get_in_or_equal($postids);
$params[] = $user->id;
list($usql, $postidparams) = $DB->get_in_or_equal($postids, SQL_PARAMS_NAMED, 'postid');
$sql = "SELECT id
FROM {forum_read}
WHERE postid $usql AND userid = ?";
if ($existing = $DB->get_records_sql($sql, $params)) {
$existing = array_keys($existing);
$insertparams = array(
'userid1' => $user->id,
'userid2' => $user->id,
'userid3' => $user->id,
'firstread' => $now,
'lastread' => $now,
'cutoffdate' => $cutoffdate,
);
$params = array_merge($postidparams, $insertparams);
if ($CFG->forum_allowforcedreadtracking) {
$trackingsql = "AND (f.trackingtype = ".FORUM_TRACKING_FORCED."
OR (f.trackingtype = ".FORUM_TRACKING_OPTIONAL." AND tf.id IS NULL))";
} else {
$existing = array();
$trackingsql = "AND ((f.trackingtype = ".FORUM_TRACKING_OPTIONAL." OR f.trackingtype = ".FORUM_TRACKING_FORCED.")
AND tf.id IS NULL)";
}
$new = array_diff($postids, $existing);
// First insert any new entries.
$sql = "INSERT INTO {forum_read} (userid, postid, discussionid, forumid, firstread, lastread)
if ($new) {
list($usql, $new_params) = $DB->get_in_or_equal($new);
$params = array($user->id, $now, $now, $user->id);
$params = array_merge($params, $new_params);
$params[] = $cutoffdate;
SELECT :userid1, p.id, p.discussion, d.forum, :firstread, :lastread
FROM {forum_posts} p
JOIN {forum_discussions} d ON d.id = p.discussion
JOIN {forum} f ON f.id = d.forum
LEFT JOIN {forum_track_prefs} tf ON (tf.userid = :userid2 AND tf.forumid = f.id)
LEFT JOIN {forum_read} fr ON (
fr.userid = :userid3
AND fr.postid = p.id
AND fr.discussionid = d.id
AND fr.forumid = f.id
)
WHERE p.id $usql
AND p.modified >= :cutoffdate
$trackingsql
AND fr.id IS NULL";
if ($CFG->forum_allowforcedreadtracking) {
$trackingsql = "AND (f.trackingtype = ".FORUM_TRACKING_FORCED."
OR (f.trackingtype = ".FORUM_TRACKING_OPTIONAL." AND tf.id IS NULL))";
} else {
$trackingsql = "AND ((f.trackingtype = ".FORUM_TRACKING_OPTIONAL." OR f.trackingtype = ".FORUM_TRACKING_FORCED.")
AND tf.id IS NULL)";
}
$status = $DB->execute($sql, $params) && $status;
$sql = "INSERT INTO {forum_read} (userid, postid, discussionid, forumid, firstread, lastread)
SELECT ?, p.id, p.discussion, d.forum, ?, ?
FROM {forum_posts} p
JOIN {forum_discussions} d ON d.id = p.discussion
JOIN {forum} f ON f.id = d.forum
LEFT JOIN {forum_track_prefs} tf ON (tf.userid = ? AND tf.forumid = f.id)
WHERE p.id $usql
AND p.modified >= ?
$trackingsql";
$status = $DB->execute($sql, $params) && $status;
}
if ($existing) {
list($usql, $new_params) = $DB->get_in_or_equal($existing);
$params = array($now, $user->id);
$params = array_merge($params, $new_params);
$sql = "UPDATE {forum_read}
SET lastread = ?
WHERE userid = ? AND postid $usql";
$status = $DB->execute($sql, $params) && $status;
}
// Then update all records.
$updateparams = array(
'userid' => $user->id,
'lastread' => $now,
);
$params = array_merge($postidparams, $updateparams);
$status = $DB->set_field_select('forum_read', 'lastread', $now, '
userid = :userid
AND lastread <> :lastread
AND postid ' . $usql,
$params) && $status;
return $status;
}

View File

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2014082101; // The current module version (Date: YYYYMMDDXX)
$plugin->version = 2014103000; // The current module version (Date: YYYYMMDDXX)
$plugin->requires = 2014050800; // Requires this Moodle version
$plugin->component = 'mod_forum'; // Full name of the plugin (used for diagnostics)