Deprecated Title::userIsWatching(); use User::isWatched() instead.
authorAlexandre Emsenhuber <ialex.wiki@gmail.com>
Sat, 9 Jun 2012 21:16:15 +0000 (23:16 +0200)
committerAlexandre Emsenhuber <ialex.wiki@gmail.com>
Fri, 29 Jun 2012 21:22:35 +0000 (23:22 +0200)
* The problem is that Title::userIsWatching() relies on $wgUser,
  which is not suitable on every case. Instead User::isWatched()
  requires both an User and a Title object.
* Replaced all core calls from the former to the latter
* Added a cache in User for the WatchedItem instances so we do not
  need to do a database request every time something want to know
  whether a page is watched or not, which can happen several times
  per request.

Change-Id: Ifa9c55b7ffb487ce6893c74df233eedc7654dc5e

12 files changed:
includes/Article.php
includes/EditPage.php
includes/FileDeleteForm.php
includes/ProtectionForm.php
includes/SkinLegacy.php
includes/SkinTemplate.php
includes/Title.php
includes/User.php
includes/api/ApiBase.php
includes/specials/SpecialMovepage.php
includes/specials/SpecialUpload.php
skins/Vector.php

index dcde2cf..03a5cfc 100644 (file)
@@ -1369,10 +1369,12 @@ class Article extends Page {
 
                        $this->doDelete( $reason, $suppress );
 
-                       if ( $request->getCheck( 'wpWatch' ) && $user->isLoggedIn() ) {
-                               WatchAction::doWatch( $title, $user );
-                       } elseif ( $title->userIsWatching() ) {
-                               WatchAction::doUnwatch( $title, $user );
+                       if ( $user->isLoggedIn() && $request->getCheck( 'wpWatch' ) != $user->isWatched( $title ) ) {
+                               if ( $request->getCheck( 'wpWatch' ) ) {
+                                       WatchAction::doWatch( $title, $user );
+                               } else {
+                                       WatchAction::doUnwatch( $title, $user );
+                               }
                        }
 
                        return;
@@ -1436,7 +1438,7 @@ class Article extends Page {
                } else {
                        $suppress = '';
                }
-               $checkWatch = $user->getBoolOption( 'watchdeletion' ) || $this->getTitle()->userIsWatching();
+               $checkWatch = $user->getBoolOption( 'watchdeletion' ) || $user->isWatched( $this->getTitle() );
 
                $form = Xml::openElement( 'form', array( 'method' => 'post',
                        'action' => $this->getTitle()->getLocalURL( 'action=delete' ), 'id' => 'deleteconfirm' ) ) .
index f533016..1f526cc 100644 (file)
@@ -756,7 +756,7 @@ class EditPage {
                } elseif ( $wgUser->getOption( 'watchcreations' ) && !$this->mTitle->exists() ) {
                        # Watch creations
                        $this->watchthis = true;
-               } elseif ( $this->mTitle->userIsWatching() ) {
+               } elseif ( $wgUser->isWatched( $this->mTitle ) ) {
                        # Already watched
                        $this->watchthis = true;
                }
@@ -1470,7 +1470,7 @@ class EditPage {
         */
        protected function commitWatch() {
                global $wgUser;
-               if ( $this->watchthis xor $this->mTitle->userIsWatching() ) {
+               if ( $wgUser->isLoggedIn() && $this->watchthis != $wgUser->isWatched( $this->mTitle ) ) {
                        $dbw = wfGetDB( DB_MASTER );
                        $dbw->begin( __METHOD__ );
                        if ( $this->watchthis ) {
index 9d6ab65..18343f3 100644 (file)
@@ -119,10 +119,12 @@ class FileDeleteForm {
                                // file, otherwise go back to the description page
                                $wgOut->addReturnTo( $this->oldimage ? $this->title : Title::newMainPage() );
 
-                               if ( $wgRequest->getCheck( 'wpWatch' ) && $wgUser->isLoggedIn() ) {
-                                       WatchAction::doWatch( $this->title, $wgUser );
-                               } elseif ( $this->title->userIsWatching() ) {
-                                       WatchAction::doUnwatch( $this->title, $wgUser );
+                               if ( $wgUser->isLoggedIn() && $wgRequest->getCheck( 'wpWatch' ) != $wgUser->isWatched( $this->title ) ) {
+                                       if ( $wgRequest->getCheck( 'wpWatch' ) ) {
+                                               WatchAction::doWatch( $this->title, $wgUser );
+                                       } else {
+                                               WatchAction::doUnwatch( $this->title, $wgUser );
+                                       }
                                }
                        }
                        return;
@@ -210,7 +212,7 @@ class FileDeleteForm {
                        $suppress = '';
                }
 
-               $checkWatch = $wgUser->getBoolOption( 'watchdeletion' ) || $this->title->userIsWatching();
+               $checkWatch = $wgUser->getBoolOption( 'watchdeletion' ) || $wgUser->isWatched( $this->title );
                $form = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getAction(),
                        'id' => 'mw-img-deleteconfirm' ) ) .
                        Xml::openElement( 'fieldset' ) .
index dbe06d4..31ed87f 100644 (file)
@@ -318,10 +318,12 @@ class ProtectionForm {
                        return false;
                }
 
-               if ( $wgRequest->getCheck( 'mwProtectWatch' ) && $wgUser->isLoggedIn() ) {
-                       WatchAction::doWatch( $this->mTitle, $wgUser );
-               } elseif ( $this->mTitle->userIsWatching() ) {
-                       WatchAction::doUnwatch( $this->mTitle, $wgUser );
+               if ( $wgUser->isLoggedIn() && $wgRequest->getCheck( 'mwProtectWatch' ) != $wgUser->isWatched( $this->mTitle ) ) {
+                       if ( $wgRequest->getCheck( 'mwProtectWatch' ) ) {
+                               WatchAction::doWatch( $this->mTitle, $wgUser );
+                       } else {
+                               WatchAction::doUnwatch( $this->mTitle, $wgUser );
+                       }
                }
                return true;
        }
index e1ec897..18bc29f 100644 (file)
@@ -638,7 +638,7 @@ class LegacyTemplate extends BaseTemplate {
                $title = $this->getSkin()->getTitle();
 
                if ( $wgOut->isArticleRelated() ) {
-                       if ( $title->userIsWatching() ) {
+                       if ( $wgUser->isWatched( $title ) ) {
                                $text = wfMsg( 'unwatchthispage' );
                                $query = array(
                                        'action' => 'unwatch',
index b3dfc9b..4028e78 100644 (file)
@@ -258,7 +258,7 @@ class SkinTemplate extends Skin {
                /* XXX currently unused, might get useful later
                $tpl->set( 'editable', ( !$title->isSpecialPage() ) );
                $tpl->set( 'exists', $title->getArticleID() != 0 );
-               $tpl->set( 'watch', $title->userIsWatching() ? 'unwatch' : 'watch' );
+               $tpl->set( 'watch', $user->isWatched( $title ) ? 'unwatch' : 'watch' );
                $tpl->set( 'protect', count( $title->isProtected() ) ? 'unprotect' : 'protect' );
                $tpl->set( 'helppage', $this->msg( 'helppage' )->text() );
                */
@@ -974,7 +974,7 @@ class SkinTemplate extends Skin {
                                         * a change to that procedure these messages will have to remain as
                                         * the global versions.
                                         */
-                                       $mode = $title->userIsWatching() ? 'unwatch' : 'watch';
+                                       $mode = $user->isWatched( $title ) ? 'unwatch' : 'watch';
                                        $token = WatchAction::getWatchToken( $title, $user, $mode );
                                        $content_navigation['actions'][$mode] = array(
                                                'class' => $onPage && ( $action == 'watch' || $action == 'unwatch' ) ? 'selected' : false,
index 439d5af..40a4e6a 100644 (file)
@@ -1516,6 +1516,7 @@ class Title {
        /**
         * Is $wgUser watching this page?
         *
+        * @deprecated in 1.20; use User::isWatched() instead.
         * @return Bool
         */
        public function userIsWatching() {
index 01407b1..5fc0773 100644 (file)
@@ -65,6 +65,11 @@ class User {
        const MW_USER_VERSION = MW_USER_VERSION;
        const EDIT_TOKEN_SUFFIX = EDIT_TOKEN_SUFFIX;
 
+       /**
+        * Maximum items in $mWatchedItems
+        */
+       const MAX_WATCHED_ITEMS_CACHE = 100;
+
        /**
         * Array of Strings List of member variables which are saved to the
         * shared cache (memcached). Any operation which changes the
@@ -219,6 +224,11 @@ class User {
         */
        private $mBlockedFromCreateAccount = false;
 
+       /**
+        * @var Array
+        */
+       private $mWatchedItems = array();
+
        static $idCacheByName = array();
 
        /**
@@ -2613,14 +2623,34 @@ class User {
                return RequestContext::getMain()->getSkin();
        }
 
+       /**
+        * Get a WatchedItem for this user and $title.
+        *
+        * @param $title Title
+        * @return WatchedItem
+        */
+       public function getWatchedItem( $title ) {
+               $key = $title->getNamespace() . ':' . $title->getDBkey();
+
+               if ( isset( $this->mWatchedItems[$key] ) ) {
+                       return $this->mWatchedItems[$key];
+               }
+
+               if ( count( $this->mWatchedItems ) >= self::MAX_WATCHED_ITEMS_CACHE ) {
+                       $this->mWatchedItems = array();
+               }
+
+               $this->mWatchedItems[$key] = WatchedItem::fromUserTitle( $this, $title );
+               return $this->mWatchedItems[$key];
+       }
+
        /**
         * Check the watched status of an article.
         * @param $title Title of the article to look at
         * @return Bool
         */
        public function isWatched( $title ) {
-               $wl = WatchedItem::fromUserTitle( $this, $title );
-               return $wl->isWatched();
+               return $this->getWatchedItem( $title )->isWatched();
        }
 
        /**
@@ -2628,8 +2658,7 @@ class User {
         * @param $title Title of the article to look at
         */
        public function addWatch( $title ) {
-               $wl = WatchedItem::fromUserTitle( $this, $title );
-               $wl->addWatch();
+               $this->getWatchedItem( $title )->addWatch();
                $this->invalidateCache();
        }
 
@@ -2638,8 +2667,7 @@ class User {
         * @param $title Title of the article to look at
         */
        public function removeWatch( $title ) {
-               $wl = WatchedItem::fromUserTitle( $this, $title );
-               $wl->removeWatch();
+               $this->getWatchedItem( $title )->removeWatch();
                $this->invalidateCache();
        }
 
index 6a9be24..883a3c0 100644 (file)
@@ -825,7 +825,7 @@ abstract class ApiBase extends ContextSource {
         */
        protected function getWatchlistValue ( $watchlist, $titleObj, $userOption = null ) {
 
-               $userWatching = $titleObj->userIsWatching();
+               $userWatching = $this->getUser()->isWatched( $titleObj );
 
                switch ( $watchlist ) {
                        case 'watch':
index a512ee6..ea73763 100644 (file)
@@ -358,7 +358,7 @@ class MovePageForm extends UnlistedSpecialPage {
                }
 
                $watchChecked = $user->isLoggedIn() && ($this->watch || $user->getBoolOption( 'watchmoves' )
-                       || $this->oldTitle->userIsWatching());
+                       || $user->isWatched( $this->oldTitle ) );
                # Don't allow watching if user is not logged in
                if( $user->isLoggedIn() ) {
                        $out->addHTML( "
index 91631f8..3072408 100644 (file)
@@ -516,7 +516,7 @@ class SpecialUpload extends SpecialPage {
                if( $local && $local->exists() ) {
                        // We're uploading a new version of an existing file.
                        // No creation, so don't watch it if we're not already.
-                       return $local->getTitle()->userIsWatching();
+                       return $this->getUser()->isWatched( $local->getTitle() );
                } else {
                        // New page should get watched if that's our option.
                        return $this->getUser()->getOption( 'watchcreations' );
index 6ac3f08..be07ba8 100644 (file)
@@ -103,7 +103,7 @@ class VectorTemplate extends BaseTemplate {
                $nav = $this->data['content_navigation'];
 
                if ( $wgVectorUseIconWatch ) {
-                       $mode = $this->getSkin()->getRelevantTitle()->userIsWatching() ? 'unwatch' : 'watch';
+                       $mode = $this->getSkin()->getUser()->isWatched( $this->getSkin()->getRelevantTitle() ) ? 'unwatch' : 'watch';
                        if ( isset( $nav['actions'][$mode] ) ) {
                                $nav['views'][$mode] = $nav['actions'][$mode];
                                $nav['views'][$mode]['class'] = rtrim( 'icon ' . $nav['views'][$mode]['class'], ' ' );