diff options
Diffstat (limited to 'includes/specials/SpecialEditWatchlist.php')
-rw-r--r-- | includes/specials/SpecialEditWatchlist.php | 215 |
1 files changed, 130 insertions, 85 deletions
diff --git a/includes/specials/SpecialEditWatchlist.php b/includes/specials/SpecialEditWatchlist.php index 23cd9aa6..501552e9 100644 --- a/includes/specials/SpecialEditWatchlist.php +++ b/includes/specials/SpecialEditWatchlist.php @@ -35,7 +35,6 @@ * @author Rob Church <robchur@gmail.com> */ class SpecialEditWatchlist extends UnlistedSpecialPage { - /** * Editing modes */ @@ -49,8 +48,8 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { private $badItems = array(); - public function __construct(){ - parent::__construct( 'EditWatchlist' ); + public function __construct() { + parent::__construct( 'EditWatchlist', 'editmywatchlist' ); } /** @@ -64,7 +63,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { $out = $this->getOutput(); # Anons don't get a watchlist - if( $this->getUser()->isAnon() ) { + if ( $this->getUser()->isAnon() ) { $out->setPageTitle( $this->msg( 'watchnologin' ) ); $llink = Linker::linkKnown( SpecialPage::getTitleFor( 'Userlogin' ), @@ -73,27 +72,29 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { array( 'returnto' => $this->getTitle()->getPrefixedText() ) ); $out->addHTML( $this->msg( 'watchlistanontext' )->rawParams( $llink )->parse() ); + return; } $this->checkPermissions(); + $this->checkReadOnly(); $this->outputHeader(); - $out->addSubtitle( $this->msg( 'watchlistfor2', $this->getUser()->getName() - )->rawParams( SpecialEditWatchlist::buildTools( null ) ) ); + $out->addSubtitle( $this->msg( 'watchlistfor2', $this->getUser()->getName() ) + ->rawParams( SpecialEditWatchlist::buildTools( null ) ) ); # B/C: $mode used to be waaay down the parameter list, and the first parameter # was $wgUser - if( $mode instanceof User ){ + if ( $mode instanceof User ) { $args = func_get_args(); - if( count( $args >= 4 ) ){ + if ( count( $args ) >= 4 ) { $mode = $args[3]; } } $mode = self::getMode( $this->getRequest(), $mode ); - switch( $mode ) { + switch ( $mode ) { case self::EDIT_CLEAR: // The "Clear" link scared people too much. // Pass on to the raw editor, from which it's very easy to clear. @@ -101,7 +102,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { case self::EDIT_RAW: $out->setPageTitle( $this->msg( 'watchlistedit-raw-title' ) ); $form = $this->getRawForm(); - if( $form->show() ){ + if ( $form->show() ) { $out->addHTML( $this->successMessage ); $out->addReturnTo( SpecialPage::getTitleFor( 'Watchlist' ) ); } @@ -111,7 +112,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { default: $out->setPageTitle( $this->msg( 'watchlistedit-normal-title' ) ); $form = $this->getNormalForm(); - if( $form->show() ){ + if ( $form->show() ) { $out->addHTML( $this->successMessage ); $out->addReturnTo( SpecialPage::getTitleFor( 'Watchlist' ) ); } elseif ( $this->toc !== false ) { @@ -130,15 +131,17 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { */ private function extractTitles( $list ) { $list = explode( "\n", trim( $list ) ); - if( !is_array( $list ) ) { + if ( !is_array( $list ) ) { return array(); } + $titles = array(); - foreach( $list as $text ) { + + foreach ( $list as $text ) { $text = trim( $text ); - if( strlen( $text ) > 0 ) { + if ( strlen( $text ) > 0 ) { $title = Title::newFromText( $text ); - if( $title instanceof Title && $title->isWatchable() ) { + if ( $title instanceof Title && $title->isWatchable() ) { $titles[] = $title; } } @@ -147,54 +150,57 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { GenderCache::singleton()->doTitlesArray( $titles ); $list = array(); - foreach( $titles as $title ) { + /** @var Title $title */ + foreach ( $titles as $title ) { $list[] = $title->getPrefixedText(); } + return array_unique( $list ); } - public function submitRaw( $data ){ + public function submitRaw( $data ) { $wanted = $this->extractTitles( $data['Titles'] ); $current = $this->getWatchlist(); - if( count( $wanted ) > 0 ) { + if ( count( $wanted ) > 0 ) { $toWatch = array_diff( $wanted, $current ); $toUnwatch = array_diff( $current, $wanted ); $this->watchTitles( $toWatch ); $this->unwatchTitles( $toUnwatch ); $this->getUser()->invalidateCache(); - if( count( $toWatch ) > 0 || count( $toUnwatch ) > 0 ){ + if ( count( $toWatch ) > 0 || count( $toUnwatch ) > 0 ) { $this->successMessage = $this->msg( 'watchlistedit-raw-done' )->parse(); } else { return false; } - if( count( $toWatch ) > 0 ) { + if ( count( $toWatch ) > 0 ) { $this->successMessage .= ' ' . $this->msg( 'watchlistedit-raw-added' - )->numParams( count( $toWatch ) )->parse(); + )->numParams( count( $toWatch ) )->parse(); $this->showTitles( $toWatch, $this->successMessage ); } - if( count( $toUnwatch ) > 0 ) { + if ( count( $toUnwatch ) > 0 ) { $this->successMessage .= ' ' . $this->msg( 'watchlistedit-raw-removed' - )->numParams( count( $toUnwatch ) )->parse(); + )->numParams( count( $toUnwatch ) )->parse(); $this->showTitles( $toUnwatch, $this->successMessage ); } } else { $this->clearWatchlist(); $this->getUser()->invalidateCache(); - if( count( $current ) > 0 ){ + if ( count( $current ) > 0 ) { $this->successMessage = $this->msg( 'watchlistedit-raw-done' )->parse(); } else { return false; } - $this->successMessage .= ' ' . $this->msg( 'watchlistedit-raw-removed' - )->numParams( count( $current ) )->parse(); + $this->successMessage .= ' ' . $this->msg( 'watchlistedit-raw-removed' ) + ->numParams( count( $current ) )->parse(); $this->showTitles( $current, $this->successMessage ); } + return true; } @@ -204,36 +210,42 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { * $titles can be an array of strings or Title objects; the former * is preferred, since Titles are very memory-heavy * - * @param $titles array of strings, or Title objects + * @param array $titles of strings, or Title objects * @param $output String */ private function showTitles( $titles, &$output ) { $talk = $this->msg( 'talkpagelinktext' )->escaped(); // Do a batch existence check $batch = new LinkBatch(); - foreach( $titles as $title ) { - if( !$title instanceof Title ) { + foreach ( $titles as $title ) { + if ( !$title instanceof Title ) { $title = Title::newFromText( $title ); } - if( $title instanceof Title ) { + + if ( $title instanceof Title ) { $batch->addObj( $title ); $batch->addObj( $title->getTalkPage() ); } } + $batch->execute(); + // Print out the list $output .= "<ul>\n"; - foreach( $titles as $title ) { - if( !$title instanceof Title ) { + + foreach ( $titles as $title ) { + if ( !$title instanceof Title ) { $title = Title::newFromText( $title ); } - if( $title instanceof Title ) { + + if ( $title instanceof Title ) { $output .= "<li>" . Linker::link( $title ) . ' (' . Linker::link( $title->getTalkPage(), $talk ) . ")</li>\n"; } } + $output .= "</ul>\n"; } @@ -246,6 +258,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { private function getWatchlist() { $list = array(); $dbr = wfGetDB( DB_MASTER ); + $res = $dbr->select( 'watchlist', array( @@ -255,10 +268,12 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { ), __METHOD__ ); - if( $res->numRows() > 0 ) { + + if ( $res->numRows() > 0 ) { $titles = array(); foreach ( $res as $row ) { $title = Title::makeTitleSafe( $row->wl_namespace, $row->wl_title ); + if ( $this->checkTitle( $title, $row->wl_namespace, $row->wl_title ) && !$title->isTalkPage() ) { @@ -269,11 +284,13 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { GenderCache::singleton()->doTitlesArray( $titles ); - foreach( $titles as $title ) { + foreach ( $titles as $title ) { $list[] = $title->getPrefixedText(); } } + $this->cleanupWatchlist(); + return $list; } @@ -289,13 +306,14 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { $res = $dbr->select( array( 'watchlist' ), - array( 'wl_namespace', 'wl_title' ), + array( 'wl_namespace', 'wl_title' ), array( 'wl_user' => $this->getUser()->getId() ), __METHOD__, array( 'ORDER BY' => array( 'wl_namespace', 'wl_title' ) ) ); $lb = new LinkBatch(); + foreach ( $res as $row ) { $lb->add( $row->wl_namespace, $row->wl_title ); if ( !MWNamespace::isTalk( $row->wl_namespace ) ) { @@ -304,6 +322,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { } $lb->execute(); + return $titles; } @@ -312,7 +331,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { * * @param Title $title * @param int $namespace - * @param String $dbKey + * @param string $dbKey * @return bool: Whether this item is valid */ private function checkTitle( $title, $namespace, $dbKey ) { @@ -323,12 +342,14 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { ) { $title = false; // unrecoverable } + if ( !$title || $title->getNamespace() != $namespace || $title->getDBkey() != $dbKey ) { $this->badItems[] = array( $title, $namespace, $dbKey ); } + return (bool)$title; } @@ -336,16 +357,17 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { * Attempts to clean up broken items */ private function cleanupWatchlist() { - if( !count( $this->badItems ) ) { + if ( !count( $this->badItems ) ) { return; //nothing to do } + $dbw = wfGetDB( DB_MASTER ); $user = $this->getUser(); + foreach ( $this->badItems as $row ) { list( $title, $namespace, $dbKey ) = $row; - wfDebug( "User {$user->getName()} has broken watchlist item ns($namespace):$dbKey, " - . ( $title ? 'cleaning up' : 'deleting' ) . ".\n" - ); + $action = $title ? 'cleaning up' : 'deleting'; + wfDebug( "User {$user->getName()} has broken watchlist item ns($namespace):$dbKey, $action.\n" ); $dbw->delete( 'watchlist', array( @@ -381,30 +403,33 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { * $titles can be an array of strings or Title objects; the former * is preferred, since Titles are very memory-heavy * - * @param $titles Array of strings, or Title objects + * @param array $titles of strings, or Title objects */ private function watchTitles( $titles ) { $dbw = wfGetDB( DB_MASTER ); $rows = array(); - foreach( $titles as $title ) { - if( !$title instanceof Title ) { + + foreach ( $titles as $title ) { + if ( !$title instanceof Title ) { $title = Title::newFromText( $title ); } - if( $title instanceof Title ) { + + if ( $title instanceof Title ) { $rows[] = array( 'wl_user' => $this->getUser()->getId(), - 'wl_namespace' => ( $title->getNamespace() & ~1 ), + 'wl_namespace' => MWNamespace::getSubject( $title->getNamespace() ), 'wl_title' => $title->getDBkey(), 'wl_notificationtimestamp' => null, ); $rows[] = array( 'wl_user' => $this->getUser()->getId(), - 'wl_namespace' => ( $title->getNamespace() | 1 ), + 'wl_namespace' => MWNamespace::getTalk( $title->getNamespace() ), 'wl_title' => $title->getDBkey(), 'wl_notificationtimestamp' => null, ); } } + $dbw->insert( 'watchlist', $rows, __METHOD__, 'IGNORE' ); } @@ -414,33 +439,37 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { * $titles can be an array of strings or Title objects; the former * is preferred, since Titles are very memory-heavy * - * @param $titles Array of strings, or Title objects + * @param array $titles of strings, or Title objects */ private function unwatchTitles( $titles ) { $dbw = wfGetDB( DB_MASTER ); - foreach( $titles as $title ) { - if( !$title instanceof Title ) { + + foreach ( $titles as $title ) { + if ( !$title instanceof Title ) { $title = Title::newFromText( $title ); } - if( $title instanceof Title ) { + + if ( $title instanceof Title ) { $dbw->delete( 'watchlist', array( 'wl_user' => $this->getUser()->getId(), - 'wl_namespace' => ( $title->getNamespace() & ~1 ), + 'wl_namespace' => MWNamespace::getSubject( $title->getNamespace() ), 'wl_title' => $title->getDBkey(), ), __METHOD__ ); + $dbw->delete( 'watchlist', array( 'wl_user' => $this->getUser()->getId(), - 'wl_namespace' => ( $title->getNamespace() | 1 ), + 'wl_namespace' => MWNamespace::getTalk( $title->getNamespace() ), 'wl_title' => $title->getDBkey(), ), __METHOD__ ); + $page = WikiPage::factory( $title ); wfRunHooks( 'UnwatchArticleComplete', array( $this->getUser(), &$page ) ); } @@ -450,15 +479,16 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { public function submitNormal( $data ) { $removed = array(); - foreach( $data as $titles ) { + foreach ( $data as $titles ) { $this->unwatchTitles( $titles ); $removed = array_merge( $removed, $titles ); } - if( count( $removed ) > 0 ) { + if ( count( $removed ) > 0 ) { $this->successMessage = $this->msg( 'watchlistedit-normal-done' - )->numParams( count( $removed ) )->parse(); + )->numParams( count( $removed ) )->parse(); $this->showTitles( $removed, $this->successMessage ); + return true; } else { return false; @@ -470,26 +500,27 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { * * @return HTMLForm */ - protected function getNormalForm(){ + protected function getNormalForm() { global $wgContLang; $fields = array(); $count = 0; - foreach( $this->getWatchlistInfo() as $namespace => $pages ){ + foreach ( $this->getWatchlistInfo() as $namespace => $pages ) { if ( $namespace >= 0 ) { - $fields['TitlesNs'.$namespace] = array( + $fields['TitlesNs' . $namespace] = array( 'class' => 'EditWatchlistCheckboxSeriesField', 'options' => array(), 'section' => "ns$namespace", ); } - foreach( array_keys( $pages ) as $dbkey ){ + foreach ( array_keys( $pages ) as $dbkey ) { $title = Title::makeTitleSafe( $namespace, $dbkey ); + if ( $this->checkTitle( $title, $namespace, $dbkey ) ) { $text = $this->buildRemoveLine( $title ); - $fields['TitlesNs'.$namespace]['options'][$text] = htmlspecialchars( $title->getPrefixedText() ); + $fields['TitlesNs' . $namespace]['options'][$text] = $title->getPrefixedText(); $count++; } } @@ -499,30 +530,33 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { if ( count( $fields ) > 1 && $count > 30 ) { $this->toc = Linker::tocIndent(); $tocLength = 0; - foreach( $fields as $data ) { + foreach ( $fields as $data ) { # strip out the 'ns' prefix from the section name: $ns = substr( $data['section'], 2 ); - $nsText = ($ns == NS_MAIN) + $nsText = ( $ns == NS_MAIN ) ? $this->msg( 'blanknamespace' )->escaped() : htmlspecialchars( $wgContLang->getFormattedNsText( $ns ) ); $this->toc .= Linker::tocLine( "editwatchlist-{$data['section']}", $nsText, $this->getLanguage()->formatNum( ++$tocLength ), 1 ) . Linker::tocLineEnd(); } + $this->toc = Linker::tocList( $this->toc ); } else { $this->toc = false; } - $form = new EditWatchlistNormalHTMLForm( $fields, $this->getContext() ); - $form->setTitle( $this->getTitle() ); + $context = new DerivativeContext( $this->getContext() ); + $context->setTitle( $this->getTitle() ); // Remove subpage + $form = new EditWatchlistNormalHTMLForm( $fields, $context ); $form->setSubmitTextMsg( 'watchlistedit-normal-submit' ); # Used message keys: 'accesskey-watchlistedit-normal-submit', 'tooltip-watchlistedit-normal-submit' - $form->setSubmitTooltip('watchlistedit-normal-submit'); + $form->setSubmitTooltip( 'watchlistedit-normal-submit' ); $form->setWrapperLegendMsg( 'watchlistedit-normal-legend' ); $form->addHeaderText( $this->msg( 'watchlistedit-normal-explain' )->parse() ); $form->setSubmitCallback( array( $this, 'submitNormal' ) ); + return $form; } @@ -534,12 +568,15 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { */ private function buildRemoveLine( $title ) { $link = Linker::link( $title ); - if( $title->isRedirect() ) { + + if ( $title->isRedirect() ) { // Linker already makes class mw-redirect, so this is redundant $link = '<span class="watchlistredir">' . $link . '</span>'; } + $tools[] = Linker::link( $title->getTalkPage(), $this->msg( 'talkpagelinktext' )->escaped() ); - if( $title->exists() ) { + + if ( $title->exists() ) { $tools[] = Linker::linkKnown( $title, $this->msg( 'history_short' )->escaped(), @@ -547,7 +584,8 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { array( 'action' => 'history' ) ); } - if( $title->getNamespace() == NS_USER && !$title->isSubpage() ) { + + if ( $title->getNamespace() == NS_USER && !$title->isSubpage() ) { $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Contributions', $title->getText() ), $this->msg( 'contributions' )->escaped() @@ -564,7 +602,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { * * @return HTMLForm */ - protected function getRawForm(){ + protected function getRawForm() { $titles = implode( $this->getWatchlist(), "\n" ); $fields = array( 'Titles' => array( @@ -573,14 +611,16 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { 'default' => $titles, ), ); - $form = new HTMLForm( $fields, $this->getContext() ); - $form->setTitle( $this->getTitle( 'raw' ) ); + $context = new DerivativeContext( $this->getContext() ); + $context->setTitle( $this->getTitle( 'raw' ) ); // Reset subpage + $form = new HTMLForm( $fields, $context ); $form->setSubmitTextMsg( 'watchlistedit-raw-submit' ); # Used message keys: 'accesskey-watchlistedit-raw-submit', 'tooltip-watchlistedit-raw-submit' - $form->setSubmitTooltip('watchlistedit-raw-submit'); + $form->setSubmitTooltip( 'watchlistedit-raw-submit' ); $form->setWrapperLegendMsg( 'watchlistedit-raw-legend' ); $form->addHeaderText( $this->msg( 'watchlistedit-raw-explain' )->parse() ); $form->setSubmitCallback( array( $this, 'submitRaw' ) ); + return $form; } @@ -594,19 +634,17 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { */ public static function getMode( $request, $par ) { $mode = strtolower( $request->getVal( 'action', $par ) ); - switch( $mode ) { + + switch ( $mode ) { case 'clear': case self::EDIT_CLEAR: return self::EDIT_CLEAR; - case 'raw': case self::EDIT_RAW: return self::EDIT_RAW; - case 'edit': case self::EDIT_NORMAL: return self::EDIT_NORMAL; - default: return false; } @@ -628,32 +666,39 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { 'edit' => array( 'EditWatchlist', false ), 'raw' => array( 'EditWatchlist', 'raw' ), ); - foreach( $modes as $mode => $arr ) { + + foreach ( $modes as $mode => $arr ) { // can use messages 'watchlisttools-view', 'watchlisttools-edit', 'watchlisttools-raw' $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( $arr[0], $arr[1] ), wfMessage( "watchlisttools-{$mode}" )->escaped() ); } - return Html::rawElement( 'span', - array( 'class' => 'mw-watchlist-toollinks' ), - wfMessage( 'parentheses', $wgLang->pipeList( $tools ) )->text() ); + + return Html::rawElement( + 'span', + array( 'class' => 'mw-watchlist-toollinks' ), + wfMessage( 'parentheses', $wgLang->pipeList( $tools ) )->text() + ); } } # B/C since 1.18 -class WatchlistEditor extends SpecialEditWatchlist {} +class WatchlistEditor extends SpecialEditWatchlist { +} /** * Extend HTMLForm purely so we can have a more sane way of getting the section headers */ class EditWatchlistNormalHTMLForm extends HTMLForm { - public function getLegend( $namespace ){ + public function getLegend( $namespace ) { $namespace = substr( $namespace, 2 ); + return $namespace == NS_MAIN ? $this->msg( 'blanknamespace' )->escaped() : htmlspecialchars( $this->getContext()->getLanguage()->getFormattedNsText( $namespace ) ); } + public function getBody() { return $this->displaySection( $this->mFieldTree, '', 'editwatchlist-' ); } @@ -667,8 +712,8 @@ class EditWatchlistCheckboxSeriesField extends HTMLMultiSelectField { * form is open (bug 32126), but we know that invalid items will * be harmless so we can override it here. * - * @param $value String the value the field was submitted with - * @param $alldata Array the data collected from the form + * @param string $value the value the field was submitted with + * @param array $alldata the data collected from the form * @return Mixed Bool true on success, or String error to display. */ function validate( $value, $alldata ) { |