From 3241ebcbcc8c16c2f2a30b91d500a86f95e4da4c Mon Sep 17 00:00:00 2001 From: Roan Kattouw Date: Mon, 2 Mar 2009 12:15:28 +0000 Subject: [PATCH] (bug 10172) Move setting the "changed since last visit" flags out of the job queue: * Move up the UPDATE query on wl_notificationtimestamp up to before scheduling the EnotifyNotifyJob * Move up the SELECT query fetching the users to be notified to before the UPDATE, and use its result for a more efficient UPDATE * Pass actuallyNotifyOnPageChange() and the EnotifyNotifyJob an array of user IDs * Add UserArray::newFromIDs() --- RELEASE-NOTES | 5 +- includes/EnotifNotifyJob.php | 3 +- includes/UserArray.php | 11 ++++ includes/UserMailer.php | 101 ++++++++++++++++------------------- 4 files changed, 64 insertions(+), 56 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 12801ce7f3..2dd0deda3a 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -225,10 +225,13 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN * (bug 17546) Correct Tongan language native name is "lea faka-Tonga" * (bug 17621) Special:WantedFiles has no link to Special:Whatlinkshere * (bug 17460) Client ecoding is now correctly set for PostgreSQL -* (bug 17648) Prevent floats from intruding into edit area in previews if no toolbar present +* (bug 17648) Prevent floats from intruding into edit area in previews if no + toolbar present * (bug 16899) DISPLAYTITLE should allow Arabic and Persian harakats * (bug 17692) Added (list of members) link to 'user' in Special:Listgrouprights * (bug 17707) Show file destination as plain text if &wpForReUpload=1 +* (bug 10172) Moved setting of "changed since last visit" flags out of the job + queue == API changes in 1.15 == * (bug 16858) Revamped list=deletedrevs to make listing deleted contributions diff --git a/includes/EnotifNotifyJob.php b/includes/EnotifNotifyJob.php index 31fcb0d5c6..f7178d0f38 100644 --- a/includes/EnotifNotifyJob.php +++ b/includes/EnotifNotifyJob.php @@ -26,7 +26,8 @@ class EnotifNotifyJob extends Job { $this->params['timestamp'], $this->params['summary'], $this->params['minorEdit'], - $this->params['oldid'] + $this->params['oldid'], + $this->params['watchers'] ); return true; } diff --git a/includes/UserArray.php b/includes/UserArray.php index a2f54b7f27..d48a4440bf 100644 --- a/includes/UserArray.php +++ b/includes/UserArray.php @@ -12,6 +12,17 @@ abstract class UserArray implements Iterator { return $userArray; } + static function newFromIDs( $ids ) { + $ids = array_map( 'intval', (array)$ids ); // paranoia + if ( !$ids ) + // Database::select() doesn't like empty arrays + return new ArrayIterator(array()); + $dbr = wfGetDB( DB_SLAVE ); + $res = $dbr->select( 'user', '*', array( 'user_id' => $ids ), + __METHOD__ ); + return self::newFromResult( $res ); + } + protected static function newFromResult_internal( $res ) { $userArray = new UserArrayFromResult( $res ); return $userArray; diff --git a/includes/UserMailer.php b/includes/UserMailer.php index 7728abf329..55ab703517 100644 --- a/includes/UserMailer.php +++ b/includes/UserMailer.php @@ -281,11 +281,42 @@ class EmailNotification { * @param $oldid (default: false) */ function notifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid = false) { - global $wgEnotifUseJobQ; + global $wgEnotifUseJobQ, $wgEnotifWatchlist, $wgShowUpdatedMarker; - if( $title->getNamespace() < 0 ) + if ($title->getNamespace() < 0) return; + // Build a list of users to notfiy + $watchers = array(); + if ($wgEnotifWatchlist || $wgShowUpdatedMarker) { + $dbw = wfGetDB( DB_MASTER ); + $res = $dbw->select( array( 'watchlist' ), + array( 'wl_user' ), + array( + 'wl_title' => $title->getDBkey(), + 'wl_namespace' => $title->getNamespace(), + 'wl_user != ' . intval( $editor->getID() ), + 'wl_notificationtimestamp IS NULL', + ), __METHOD__ + ); + while ($row = $dbw->fetchObject( $res ) ) { + $watchers[] = intval( $row->wl_user ); + } + if ($watchers) { + // Update wl_notificationtimestamp for all watching users except + // the editor + $dbw->begin(); + $dbw->update( 'watchlist', + array( /* SET */ + 'wl_notificationtimestamp' => $dbw->timestamp( $timestamp ) + ), array( /* WHERE */ + 'wl_user' => $watchers + ), __METHOD__ + ); + $dbw->commit(); + } + } + if ($wgEnotifUseJobQ) { $params = array( "editor" => $editor->getName(), @@ -293,11 +324,12 @@ class EmailNotification { "timestamp" => $timestamp, "summary" => $summary, "minorEdit" => $minorEdit, - "oldid" => $oldid); + "oldid" => $oldid, + "watchers" => $watchers); $job = new EnotifNotifyJob( $title, $params ); $job->insert(); } else { - $this->actuallyNotifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid); + $this->actuallyNotifyOnPageChange( $editor, $title, $timestamp, $summary, $minorEdit, $oldid, $watchers ); } } @@ -310,15 +342,16 @@ class EmailNotification { * * @param $editor User object * @param $title Title object - * @param $timestamp - * @param $summary - * @param $minorEdit - * @param $oldid (default: false) + * @param $timestamp string Edit timestamp + * @param $summary string Edit summary + * @param $minorEdit bool + * @param $oldid int Revision ID + * @param $watchers array of user IDs */ - function actuallyNotifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid=false) { + function actuallyNotifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid, $watchers) { # we use $wgPasswordSender as sender's address global $wgEnotifWatchlist; - global $wgEnotifMinorEdits, $wgEnotifUserTalk, $wgShowUpdatedMarker; + global $wgEnotifMinorEdits, $wgEnotifUserTalk; global $wgEnotifImpersonal; wfProfileIn( __METHOD__ ); @@ -363,30 +396,12 @@ class EmailNotification { if ( $wgEnotifWatchlist ) { // Send updates to watchers other than the current editor - $userCondition = 'wl_user != ' . intval( $editor->getID() ); - if ( $userTalkId !== false ) { - // Already sent an email to this person - $userCondition .= ' AND wl_user != ' . intval( $userTalkId ); - } - $dbr = wfGetDB( DB_SLAVE ); - - list( $user ) = $dbr->tableNamesN( 'user' ); - $res = $dbr->select( array( 'watchlist', 'user' ), - array( "$user.*" ), - array( - 'wl_user=user_id', - 'wl_title' => $title->getDBkey(), - 'wl_namespace' => $title->getNamespace(), - $userCondition, - 'wl_notificationtimestamp IS NULL', - ), __METHOD__ - ); - $userArray = UserArray::newFromResult( $res ); - + $userArray = UserArray::newFromIDs( $watchers ); foreach ( $userArray as $watchingUser ) { if ( $watchingUser->getOption( 'enotifwatchlistpages' ) && ( !$minorEdit || $watchingUser->getOption('enotifminoredits') ) && - $watchingUser->isEmailConfirmed() ) + $watchingUser->isEmailConfirmed() && + $watchingUser->getID() != $userTalkId ) { $this->compose( $watchingUser ); } @@ -400,31 +415,9 @@ class EmailNotification { $this->compose( $user ); } - $latestTimestamp = Revision::getTimestampFromId( $title, $title->getLatestRevID(GAID_FOR_UPDATE) ); - // Do not update watchlists if something else already did. - if ( $timestamp >= $latestTimestamp && ($wgShowUpdatedMarker || $wgEnotifWatchlist) ) { - # Mark the changed watch-listed page with a timestamp, so that the page is - # listed with an "updated since your last visit" icon in the watch list. Do - # not do this to users for their own edits. - $dbw = wfGetDB( DB_MASTER ); - $dbw->begin(); - $dbw->update( 'watchlist', - array( /* SET */ - 'wl_notificationtimestamp' => $dbw->timestamp($timestamp) - ), array( /* WHERE */ - 'wl_title' => $title->getDBkey(), - 'wl_namespace' => $title->getNamespace(), - 'wl_notificationtimestamp IS NULL', // store oldest unseen change time - 'wl_user != ' . intval( $editor->getID() ) - ), __METHOD__ - ); - $dbw->commit(); - } - $this->sendMails(); - wfProfileOut( __METHOD__ ); - } # function NotifyOnChange + } /** * @private -- 2.20.1