Revision: 51638 Author: werdna Date: 2009-06-09 12:27:15 +0000 (Tue, 09 Jun 2009)
Log Message: ----------- Reimplemented writeMessageStateForUpdated thread: * Improve cross-database compatibility (and code readability) by using proper generation methods. * Basic implementation of LQT email notification. * TODO : Implement email notification for discussions on a user's talk page. Modified Paths: -------------- trunk/extensions/LiquidThreads/LiquidThreads.php trunk/extensions/LiquidThreads/Lqt.i18n.php trunk/extensions/LiquidThreads/LqtFunctions.php trunk/extensions/LiquidThreads/classes/LqtNewMessages.php trunk/extensions/LiquidThreads/classes/LqtThread.php trunk/extensions/LiquidThreads/classes/LqtThreads.php trunk/extensions/LiquidThreads/classes/LqtView.php Modified: trunk/extensions/LiquidThreads/LiquidThreads.php =================================================================== --- trunk/extensions/LiquidThreads/LiquidThreads.php 2009-06-09 11:05:46 UTC (rev 51637) +++ trunk/extensions/LiquidThreads/LiquidThreads.php 2009-06-09 12:27:15 UTC (rev 51638) @@ -49,6 +49,7 @@ $wgHooks['OldChangesListRecentChangesLine'][] = 'LqtDispatch::customizeOldChangesList'; $wgHooks['SkinTemplateOutputPageBeforeExec'][] = 'LqtDispatch::setNewtalkHTML'; $wgHooks['TitleGetRestrictions'][] = 'Thread::getRestrictionsForTitle'; +$wgHooks['GetPreferences'][] = 'lqtGetPreferences'; // Special pages $wgSpecialPages['DeleteThread'] = 'SpecialDeleteThread'; @@ -91,6 +92,9 @@ $wgLogHeaders['liquidthreads'] = 'lqt-log-header'; $wgLogActionsHandlers['liquidthreads/move'] = 'lqtFormatMoveLogEntry'; +// Preferences +$wgDefaultUserOptions['lqtnotifytalk'] = true; + /** CONFIGURATION SECTION */ /* Number of days a thread needs to have existed to be considered for summarizing and archival */ @@ -105,3 +109,6 @@ /* Allows switching LiquidThreads off for regular talk pages (intended for testing and transition) */ $wgLqtTalkPages = true; + +/* Whether or not to activate LiquidThreads email notifications */ +$wgLqtEnotif = true; Modified: trunk/extensions/LiquidThreads/Lqt.i18n.php =================================================================== --- trunk/extensions/LiquidThreads/Lqt.i18n.php 2009-06-09 11:05:46 UTC (rev 51637) +++ trunk/extensions/LiquidThreads/Lqt.i18n.php 2009-06-09 12:27:15 UTC (rev 51638) @@ -151,6 +151,23 @@ 'lqt-log-name' => 'Threaded discussion log', 'lqt-log-header' => 'This log details actions taken on discussion threads.', 'lqt-log-action-move' => 'moved [[$1]] from [[$2]] to [[$3]].', + + // Preferences + 'lqt-preference-notify-talk' => 'Email me when somebody replies to a thread I am watching', + + // Email notification + 'lqt-enotif-subject-reply' => '{{SITENAME}} discussion - Reply: $1', + 'lqt-enotif-subject-newthread' => '{{SITENAME}} discussion - New thread: $1', + 'lqt-enotif-newthread' => "Hi $1, +This is a notification from {{SITENAME}} that a new thread on $5, '$2', +was created on $3 at $4. + +You can see it at <$6>", + 'lqt-enotif-reply' => "Hi $1, +This is a notification from {{SITENAME}} that a new reply to '$2' on $5, +was created on $3 at $4. + +You can see it at <$6>", ); /** Message documentation (Message documentation) Modified: trunk/extensions/LiquidThreads/LqtFunctions.php =================================================================== --- trunk/extensions/LiquidThreads/LqtFunctions.php 2009-06-09 11:05:46 UTC (rev 51637) +++ trunk/extensions/LiquidThreads/LqtFunctions.php 2009-06-09 12:27:15 UTC (rev 51638) @@ -102,3 +102,15 @@ return wfMsgExt( 'lqt-log-action-move', 'parseinline', array( $title->getPrefixedText(), $parameters[0], $parameters[1] ) ); } + +function lqtGetPreferences( $user, &$preferences ) { + wfLoadExtensionMessages( 'LiquidThreads' ); + $preferences['lqtnotifytalk'] = + array( + 'type' => 'toggle', + 'label-message' => 'lqt-preference-notify-talk', + 'section' => 'personal/email' + ); + + return true; +} Modified: trunk/extensions/LiquidThreads/classes/LqtNewMessages.php =================================================================== --- trunk/extensions/LiquidThreads/classes/LqtNewMessages.php 2009-06-09 11:05:46 UTC (rev 51637) +++ trunk/extensions/LiquidThreads/classes/LqtNewMessages.php 2009-06-09 12:27:15 UTC (rev 51638) @@ -40,40 +40,167 @@ * Write a user_message_state for each user who is watching the thread. * If the thread is on a user's talkpage, set that user's newtalk. */ - static function writeMessageStateForUpdatedThread( $t ) { + static function writeMessageStateForUpdatedThread( $t, $type, $changeUser ) { global $wgDBprefix, $wgUser; + + wfDebugLog( 'LiquidThreads', 'Doing notifications' ); if ( $t->article()->getTitle()->getNamespace() == NS_USER ) { $name = $t->article()->getTitle()->getDBkey(); list( $name ) = split( '/', $name ); // subpages $user = User::newFromName( $name ); - if ( $user && $user->getID() != $wgUser->getID() ) { + if ( $user && $user->getID() != $changeUser->getID() ) { $user->setNewtalk( true ); } } $dbw =& wfGetDB( DB_MASTER ); - $talkpage_t = $t->article()->getTitle(); + $talkpage_t = $t->article()->getTitle()->getSubjectPage(); $root_t = $t->root()->getTitle(); $q_talkpage_t = $dbw->addQuotes( $talkpage_t->getDBkey() ); $q_root_t = $dbw->addQuotes( $root_t->getDBkey() ); // Select any applicable watchlist entries for the thread. - $where_clause = <<<SQL -( - (wl_namespace = {$talkpage_t->getNamespace()} and wl_title = $q_talkpage_t ) -or (wl_namespace = {$root_t->getNamespace()} and wl_title = $q_root_t ) -) -SQL; + $talkpageWhere = array( 'wl_namespace' => $talkpage_t->getNamespace(), + 'wl_title' => $talkpage_t->getDBkey() ); + $rootWhere = array( 'wl_namespace' => $root_t->getNamespace(), + 'wl_title' => $root_t->getDBkey() ); + + $talkpageWhere = $dbw->makeList( $talkpageWhere, LIST_AND ); + $rootWhere = $dbw->makeList( $rootWhere, LIST_AND ); + + $where_clause = $dbw->makeList( array( $talkpageWhere, $rootWhere ), LIST_OR ); // it sucks to not have 'on duplicate key update'. first update users who already have a ums for this thread // and who have already read it, by setting their state to unread. - $dbw->query( "update {$wgDBprefix}user_message_state, {$wgDBprefix}watchlist set ums_read_timestamp = null where ums_user = wl_user and ums_thread = {$t->id()} and $where_clause" ); - - $dbw->query( "insert ignore into {$wgDBprefix}user_message_state (ums_user, ums_thread) select user_id, {$t->id()} from {$wgDBprefix}user, {$wgDBprefix}watchlist where user_id = wl_user and $where_clause;" ); + + // Pull users to update the message state for, including whether or not a + // user_message_state row exists for them, and whether or not to send an email + // notification. + $dbr = wfGetDB( DB_SLAVE ); + $res = $dbr->select( array( 'watchlist', 'user_message_state', 'user_properties' ), + array( 'wl_user', 'ums_user', 'ums_read_timestamp', 'up_value' ), + $where_clause, __METHOD__, array(), + array( 'user_message_state' => + array( 'left join', array( 'ums_user=wl_user', + 'ums_thread' => $t->id() ) ), + 'user_properties' => array( + 'left join', + array( 'up_user=wl_user', + 'up_property' => 'lqtnotifytalk', + ) + ), + ) + ); + + $insert_rows = array(); + $update_tuples = array(); + $notify_users = array(); + while( $row = $dbr->fetchObject( $res ) ) { + // Don't notify yourself + if ( $changeUser->getId() == $row->wl_user ) + continue; + + if ( $row->ums_read_timestamp ) { + $conds = array( 'ums_user' => $row->ums_user, + 'ums_thread' => $t->id() ); + $update_tuples[$row->ums_user.$t->id()] = $dbw->makeList( $conds, LIST_AND ); + } elseif ( $row->ums_user ) { + // It's already positive. + } else { + $insert_rows[] = + array( + 'ums_user' => $row->wl_user, + 'ums_thread' => $t->id(), + ); + } + + if ( ( is_null($row->up_value) && User::getDefaultOption( 'lqtnotifytalk' ) ) + || $row->up_value ) { + $notify_users[] = $row->wl_user; + } + } + + // Avoids duplicates + $update_tuples = array_values( $update_tuples ); + + // Do the actual updates + if ( count($insert_rows) ) { + $dbw->insert( 'user_message_state', $insert_rows, __METHOD__, array( 'IGNORE' ) ); + } + if ( count($update_tuples) ) { + $where = $dbw->makeList( $update_tuples, LIST_OR ); + + $dbw->update( 'user_message_state', array( 'ums_read_timestamp' => null ), + array($where), __METHOD__ ); + } + + if ( count($notify_users) ) { + self::notifyUsersByMail( $t, $notify_users, wfTimestampNow(), $type ); + } } + + static function notifyUsersByMail( $t, $watching_users, $timestamp, $type ) { + wfLoadExtensionMessages( 'LiquidThreads' ); + $messages = array( + Threads::CHANGE_REPLY_CREATED => 'lqt-enotif-reply', + Threads::CHANGE_NEW_THREAD => 'lqt-enotif-newthread', + ); + $subjects = array( + Threads::CHANGE_REPLY_CREATED => 'lqt-enotif-subject-reply', + Threads::CHANGE_NEW_THREAD => 'lqt-enotif-subject-newthread', + ); + + if ( !isset($messages[$type]) || !isset($subjects[$type]) ) { + wfDebugLog( 'LiquidThreads', "Email notification failed: type $type unrecognised" ); + return; + } else { + $msgName = $messages[$type]; + $subjectMsg = $subjects[$type]; + } + + // Send email notification, fetching all the data in one go + $dbr = wfGetDB( DB_SLAVE ); + $res = $dbr->select( array( 'user', 'user_properties' ), '*', + array( 'user_id' => $watching_users ), __METHOD__, array(), + array( 'user_properties' => + array( 'left join', + array( + 'up_user=user_id', + 'up_property' => 'timecorrection' + ) + ) + ) + ); + + while( $row = $dbr->fetchObject( $res ) ) { + $u = User::newFromRow( $row ); + + global $wgLang; + + $permalink = LqtView::permalinkUrl( $t ); + + // Adjust with time correction + $adjustedTimestamp = $wgLang->userAdjust( $timestamp, $row->up_value ); + + $date = $wgLang->date( $adjustedTimestamp ); + $time = $wgLang->time( $adjustedTimestamp ); + + $talkPage = $t->article()->getTitle()->getPrefixedText(); + $msg = wfMsg( $msgName, $u->getName(), $t->subjectWithoutIncrement(), + $date, $time, $talkPage, $permalink ); + + global $wgPasswordSender; + + $from = new MailAddress( $wgPasswordSender, 'WikiAdmin' ); + $to = new MailAddress( $u ); + $subject = wfMsg( $subjectMsg, $t->subjectWithoutIncrement() ); + + UserMailer::send( $to, $from, $subject, $msg ); + } + } static function newUserMessages( $user ) { global $wgDBprefix; Modified: trunk/extensions/LiquidThreads/classes/LqtThread.php =================================================================== --- trunk/extensions/LiquidThreads/classes/LqtThread.php 2009-06-09 11:05:46 UTC (rev 51637) +++ trunk/extensions/LiquidThreads/classes/LqtThread.php 2009-06-09 12:27:15 UTC (rev 51638) @@ -160,7 +160,7 @@ __METHOD__ ); if ( $change_type == Threads::CHANGE_EDITED_ROOT ) { - NewMessages::writeMessageStateForUpdatedThread( $this ); + NewMessages::writeMessageStateForUpdatedThread( $this, $change_type, $wgUser ); } } Modified: trunk/extensions/LiquidThreads/classes/LqtThreads.php =================================================================== --- trunk/extensions/LiquidThreads/classes/LqtThreads.php 2009-06-09 11:05:46 UTC (rev 51637) +++ trunk/extensions/LiquidThreads/classes/LqtThreads.php 2009-06-09 12:27:15 UTC (rev 51638) @@ -105,7 +105,7 @@ self::createTalkpageIfNeeded( $article ); - NewMessages::writeMessageStateForUpdatedThread( $newthread ); + NewMessages::writeMessageStateForUpdatedThread( $newthread, $change_type, $wgUser ); return $newthread; } Modified: trunk/extensions/LiquidThreads/classes/LqtView.php =================================================================== --- trunk/extensions/LiquidThreads/classes/LqtView.php 2009-06-09 11:05:46 UTC (rev 51637) +++ trunk/extensions/LiquidThreads/classes/LqtView.php 2009-06-09 12:27:15 UTC (rev 51638) @@ -176,6 +176,18 @@ if ( is_array( $query ) ) $query = self::queryStringFromArray( $query ); return $thread->root()->getTitle()->getFullUrl( $query ); } + + static function permalink( $thread, $text = null, $method = null, $operand = null, + $sk = null, $attribs = array() ) { + if ( is_null($sk) ) { + global $wgUser; + $sk = $wgUser->getSkin(); + } + + list( $title, $query ) = self::permalinkData( $thread, $method, $operand ); + + return $sk->link( $title, $text, $attribs, $query ); + } static function permalinkUrlWithDiff( $thread ) { $changed_thread = $thread->changeObject(); _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs