From 129abc445773ce09f60c8fd34c3c4f7d2d090d90 Mon Sep 17 00:00:00 2001 From: Rob Church Date: Thu, 5 Jul 2007 18:20:46 +0000 Subject: [PATCH] Improvements to the watchlist editor per Brion; diff the current watchlist against the list of wanted titles, speeds things up, avoids resetting notification timestamps and lets us show a couple of natty lists which make the user feel warm and fuzzy inside. Also, ignore titles which can't be watched - special, media, interwiki etc. --- includes/Namespace.php | 12 ++++++- includes/Title.php | 19 ++++++++++ includes/WatchlistEditor.php | 58 +++++++++++++++++++++++-------- languages/messages/MessagesEn.php | 2 ++ maintenance/language/messages.inc | 2 ++ 5 files changed, 77 insertions(+), 16 deletions(-) diff --git a/includes/Namespace.php b/includes/Namespace.php index e50f3f8d15..ebb2bce6b3 100644 --- a/includes/Namespace.php +++ b/includes/Namespace.php @@ -134,7 +134,17 @@ class Namespace { public static function isContent( $index ) { global $wgContentNamespaces; return $index == NS_MAIN || in_array( $index, $wgContentNamespaces ); - } + } + + /** + * Can pages in a namespace be watched? + * + * @param int $index + * @return bool + */ + public static function isWatchable( $index ) { + return $index >= NS_MAIN; + } } diff --git a/includes/Title.php b/includes/Title.php index 34b94126ae..d089d8ac7f 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -2305,6 +2305,16 @@ class Title { # Return true if there was no history return $row === false; } + + /** + * Can this title be added to a user's watchlist? + * + * @return bool + */ + public function isWatchable() { + return !$this->isExternal() + && Namespace::isWatchable( $this->getNamespace() ); + } /** * Get categories to which this Title belongs and return an array of @@ -2429,6 +2439,15 @@ class Title { && $this->getNamespace() == $title->getNamespace() && $this->getDbkey() === $title->getDbkey(); } + + /** + * Return a string representation of this title + * + * @return string + */ + public function __toString() { + return $this->getPrefixedText(); + } /** * Check if page exists diff --git a/includes/WatchlistEditor.php b/includes/WatchlistEditor.php index 938fbd59b2..729ac295a3 100644 --- a/includes/WatchlistEditor.php +++ b/includes/WatchlistEditor.php @@ -43,11 +43,23 @@ class WatchlistEditor { case self::EDIT_RAW: $output->setPageTitle( wfMsg( 'watchlistedit-raw-title' ) ); if( $request->wasPosted() && $this->checkToken( $request, $user ) ) { - $titles = $this->extractTitles( $request->getText( 'titles' ) ); - $this->clearWatchlist( $user ); - $this->watchTitles( $titles, $user ); + $current = $this->getWatchlist( $user ); + $wanted = $this->extractTitles( $request->getText( 'titles' ) ); + $toWatch = array_diff( $wanted, $current ); + $toUnwatch = array_diff( $current, $wanted ); + $this->watchTitles( $toWatch, $user ); + $this->unwatchTitles( $toUnwatch, $user ); $user->invalidateCache(); - $output->addHtml( wfMsgExt( 'watchlistedit-raw-done', 'parse' ) ); + if( count( $toWatch ) > 0 || count( $toUnwatch ) > 0 ) + $output->addHtml( wfMsgExt( 'watchlistedit-raw-done', 'parse' ) ); + if( ( $count = count( $toWatch ) ) > 0 ) { + $output->addHtml( wfMsgExt( 'watchlistedit-raw-added', 'parse', $count ) ); + $this->showTitles( $toWatch, $output, $user->getSkin() ); + } + if( ( $count = count( $toUnwatch ) ) > 0 ) { + $output->addHtml( wfMsgExt( 'watchlistedit-raw-removed', 'parse', $count ) ); + $this->showTitles( $toUnwatch, $output, $user->getSkin() ); + } } $this->showRawForm( $output, $user ); break; @@ -78,7 +90,7 @@ class WatchlistEditor { /** * Extract a list of titles from a text list; if we're given - * an array, convert each item into a Title + * an array, convert each item into a Title (ignores unwatchable titles) * * @param mixed $list * @return array @@ -94,7 +106,7 @@ class WatchlistEditor { $text = trim( $text ); if( strlen( $text ) > 0 ) { $title = Title::newFromText( $text ); - if( $title instanceof Title ) + if( $title instanceof Title && $title->isWatchable() ) $titles[] = $title; } } @@ -138,6 +150,27 @@ class WatchlistEditor { return ceil( $row->count / 2 ); // Paranoia } + /** + * Get a list of titles on a user's watchlist, excluding talk pages + * + * @param User $user + * @return array + */ + private function getWatchlist( $user ) { + $titles = array(); + $dbr = wfGetDB( DB_SLAVE ); + $res = $dbr->select( 'watchlist', '*', array( 'wl_user' => $user->getId() ), __METHOD__ ); + if( $res && $dbr->numRows( $res ) > 0 ) { + while( $row = $dbr->fetchObject( $res ) ) { + $title = Title::makeTitleSafe( $row->wl_namespace, $row->wl_title ); + if( $title instanceof Title && !$title->isTalkPage() ) + $titles[] = $title; + } + $dbr->freeResult( $res ); + } + return $titles; + } + /** * Get a list of titles on a user's watchlist, excluding talk pages, * and return as a two-dimensional array with namespace, title and @@ -146,7 +179,7 @@ class WatchlistEditor { * @param User $user * @return array */ - private function getWatchlist( $user ) { + private function getWatchlistInfo( $user ) { $titles = array(); $dbr = wfGetDB( DB_SLAVE ); $uid = intval( $user->getId() ); @@ -293,7 +326,7 @@ class WatchlistEditor { $form .= Xml::hidden( 'token', $user->editToken( 'watchlistedit' ) ); $form .= '
' . wfMsgHtml( 'watchlistedit-normal-legend' ) . ''; $form .= wfMsgExt( 'watchlistedit-normal-explain', 'parse' ); - foreach( $this->getWatchlist( $user ) as $namespace => $pages ) { + foreach( $this->getWatchlistInfo( $user ) as $namespace => $pages ) { $form .= '

' . $this->getNamespaceHeading( $namespace ) . '

'; $form .= '
'; diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index 21fb6c207d..504456860a 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -2909,5 +2909,7 @@ $1', 'watchlistedit-raw-titles' => 'Titles:', 'watchlistedit-raw-submit' => 'Update Watchlist', 'watchlistedit-raw-done' => 'Your watchlist has been updated.', +'watchlistedit-raw-added' => '{{PLURAL:$1|1 title was|$1 titles were}} added:', +'watchlistedit-raw-removed' => '{{PLURAL:$1|1 title was|$1 titles were}} removed:', ); \ No newline at end of file diff --git a/maintenance/language/messages.inc b/maintenance/language/messages.inc index fa0ede304f..9b87411033 100644 --- a/maintenance/language/messages.inc +++ b/maintenance/language/messages.inc @@ -2141,6 +2141,8 @@ $wgMessageStructure = array( 'watchlistedit-raw-titles', 'watchlistedit-raw-submit', 'watchlistedit-raw-done', + 'watchlistedit-raw-added', + 'watchlistedit-raw-removed', ), ); /** Comments for each block */ -- 2.20.1