MediaWiki  REL1_20
WatchedItem.php
Go to the documentation of this file.
00001 <?php
00029 class WatchedItem {
00030         var $mTitle, $mUser, $id, $ns, $ti;
00031         private $loaded = false, $watched, $timestamp;
00032 
00039         public static function fromUserTitle( $user, $title ) {
00040                 $wl = new WatchedItem;
00041                 $wl->mUser = $user;
00042                 $wl->mTitle = $title;
00043                 $wl->id = $user->getId();
00044                 # Patch (also) for email notification on page changes T.Gries/M.Arndt 11.09.2004
00045                 # TG patch: here we do not consider pages and their talk pages equivalent - why should we ?
00046                 # The change results in talk-pages not automatically included in watchlists, when their parent page is included
00047                 # $wl->ns = $title->getNamespace() & ~1;
00048                 $wl->ns = $title->getNamespace();
00049 
00050                 $wl->ti = $title->getDBkey();
00051                 return $wl;
00052         }
00053 
00060         private function dbCond() {
00061                 return array( 'wl_user' => $this->id, 'wl_namespace' => $this->ns, 'wl_title' => $this->ti );
00062         }
00063 
00067         private function load() {
00068                 if ( $this->loaded ) {
00069                         return;
00070                 }
00071                 $this->loaded = true;
00072 
00073                 # Pages and their talk pages are considered equivalent for watching;
00074                 # remember that talk namespaces are numbered as page namespace+1.
00075 
00076                 $dbr = wfGetDB( DB_SLAVE );
00077                 $row = $dbr->selectRow( 'watchlist', 'wl_notificationtimestamp',
00078                         $this->dbCond(), __METHOD__ );
00079 
00080                 if ( $row === false ) {
00081                         $this->watched = false;
00082                 } else {
00083                         $this->watched = true;
00084                         $this->timestamp = $row->wl_notificationtimestamp;
00085                 }
00086         }
00087 
00092         public function isWatched() {
00093                 $this->load();
00094                 return $this->watched;
00095         }
00096 
00103         public function getNotificationTimestamp() {
00104                 $this->load();
00105                 if ( $this->watched ) {
00106                         return $this->timestamp;
00107                 } else {
00108                         return false;
00109                 }
00110         }
00111 
00118         public function resetNotificationTimestamp( $force = '' ) {
00119                 if ( $force != 'force' ) {
00120                         $this->load();
00121                         if ( !$this->watched || $this->timestamp === null ) {
00122                                 return;
00123                         }
00124                 }
00125 
00126                 // If the page is watched by the user (or may be watched), update the timestamp on any
00127                 // any matching rows
00128                 $dbw = wfGetDB( DB_MASTER );
00129                 $dbw->update( 'watchlist', array( 'wl_notificationtimestamp' => null ),
00130                         $this->dbCond(), __METHOD__ );
00131                 $this->timestamp = null;
00132         }
00133 
00139         public function addWatch() {
00140                 wfProfileIn( __METHOD__ );
00141 
00142                 // Use INSERT IGNORE to avoid overwriting the notification timestamp
00143                 // if there's already an entry for this page
00144                 $dbw = wfGetDB( DB_MASTER );
00145                 $dbw->insert( 'watchlist',
00146                   array(
00147                         'wl_user' => $this->id,
00148                         'wl_namespace' => MWNamespace::getSubject($this->ns),
00149                         'wl_title' => $this->ti,
00150                         'wl_notificationtimestamp' => null
00151                   ), __METHOD__, 'IGNORE' );
00152 
00153                 // Every single watched page needs now to be listed in watchlist;
00154                 // namespace:page and namespace_talk:page need separate entries:
00155                 $dbw->insert( 'watchlist',
00156                   array(
00157                         'wl_user' => $this->id,
00158                         'wl_namespace' => MWNamespace::getTalk($this->ns),
00159                         'wl_title' => $this->ti,
00160                         'wl_notificationtimestamp' => null
00161                   ), __METHOD__, 'IGNORE' );
00162 
00163                 $this->watched = true;
00164 
00165                 wfProfileOut( __METHOD__ );
00166                 return true;
00167         }
00168 
00173         public function removeWatch() {
00174                 wfProfileIn( __METHOD__ );
00175 
00176                 $success = false;
00177                 $dbw = wfGetDB( DB_MASTER );
00178                 $dbw->delete( 'watchlist',
00179                         array(
00180                                 'wl_user' => $this->id,
00181                                 'wl_namespace' => MWNamespace::getSubject($this->ns),
00182                                 'wl_title' => $this->ti
00183                         ), __METHOD__
00184                 );
00185                 if ( $dbw->affectedRows() ) {
00186                         $success = true;
00187                 }
00188 
00189                 # the following code compensates the new behaviour, introduced by the
00190                 # enotif patch, that every single watched page needs now to be listed
00191                 # in watchlist namespace:page and namespace_talk:page had separate
00192                 # entries: clear them
00193                 $dbw->delete( 'watchlist',
00194                         array(
00195                                 'wl_user' => $this->id,
00196                                 'wl_namespace' => MWNamespace::getTalk($this->ns),
00197                                 'wl_title' => $this->ti
00198                         ), __METHOD__
00199                 );
00200 
00201                 if ( $dbw->affectedRows() ) {
00202                         $success = true;
00203                 }
00204 
00205                 $this->watched = false;
00206 
00207                 wfProfileOut( __METHOD__ );
00208                 return $success;
00209         }
00210 
00218         public static function duplicateEntries( $ot, $nt ) {
00219                 WatchedItem::doDuplicateEntries( $ot->getSubjectPage(), $nt->getSubjectPage() );
00220                 WatchedItem::doDuplicateEntries( $ot->getTalkPage(), $nt->getTalkPage() );
00221         }
00222 
00231         private static function doDuplicateEntries( $ot, $nt ) {
00232                 $oldnamespace = $ot->getNamespace();
00233                 $newnamespace = $nt->getNamespace();
00234                 $oldtitle = $ot->getDBkey();
00235                 $newtitle = $nt->getDBkey();
00236 
00237                 $dbw = wfGetDB( DB_MASTER );
00238                 $res = $dbw->select( 'watchlist', 'wl_user',
00239                         array( 'wl_namespace' => $oldnamespace, 'wl_title' => $oldtitle ),
00240                         __METHOD__, 'FOR UPDATE'
00241                 );
00242                 # Construct array to replace into the watchlist
00243                 $values = array();
00244                 foreach ( $res as $s ) {
00245                         $values[] = array(
00246                                 'wl_user' => $s->wl_user,
00247                                 'wl_namespace' => $newnamespace,
00248                                 'wl_title' => $newtitle
00249                         );
00250                 }
00251 
00252                 if( empty( $values ) ) {
00253                         // Nothing to do
00254                         return true;
00255                 }
00256 
00257                 # Perform replace
00258                 # Note that multi-row replace is very efficient for MySQL but may be inefficient for
00259                 # some other DBMSes, mostly due to poor simulation by us
00260                 $dbw->replace( 'watchlist', array( array( 'wl_user', 'wl_namespace', 'wl_title' ) ), $values, __METHOD__ );
00261                 return true;
00262         }
00263 }