MediaWiki
REL1_20
|
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 }