diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2013-01-18 16:46:04 +0100 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2013-01-18 16:46:04 +0100 |
commit | 63601400e476c6cf43d985f3e7b9864681695ed4 (patch) | |
tree | f7846203a952e38aaf66989d0a4702779f549962 /includes/specials | |
parent | 8ff01378c9e0207f9169b81966a51def645b6a51 (diff) |
Update to MediaWiki 1.20.2
this update includes:
* adjusted Arch Linux skin
* updated FluxBBAuthPlugin
* patch for https://bugzilla.wikimedia.org/show_bug.cgi?id=44024
Diffstat (limited to 'includes/specials')
80 files changed, 2740 insertions, 1561 deletions
diff --git a/includes/specials/SpecialActiveusers.php b/includes/specials/SpecialActiveusers.php index 617a8026..c5aa2389 100644 --- a/includes/specials/SpecialActiveusers.php +++ b/includes/specials/SpecialActiveusers.php @@ -40,7 +40,12 @@ class ActiveUsersPager extends UsersPager { /** * @var Array */ - protected $groups; + protected $hideGroups = array(); + + /** + * @var Array + */ + protected $hideRights = array(); /** * @param $context IContextSource @@ -73,12 +78,11 @@ class ActiveUsersPager extends UsersPager { $this->opts->fetchValuesFromRequest( $this->getRequest() ); - $this->groups = array(); if ( $this->opts->getValue( 'hidebots' ) == 1 ) { - $this->groups['bot'] = true; + $this->hideRights[] = 'bot'; } if ( $this->opts->getValue( 'hidesysops' ) == 1 ) { - $this->groups['sysop'] = true; + $this->hideGroups[] = 'sysop'; } } @@ -90,8 +94,8 @@ class ActiveUsersPager extends UsersPager { $dbr = wfGetDB( DB_SLAVE ); $conds = array( 'rc_user > 0' ); // Users - no anons $conds[] = 'ipb_deleted IS NULL'; // don't show hidden names - $conds[] = "rc_log_type IS NULL OR rc_log_type != 'newusers'"; - $conds[] = "rc_timestamp >= '{$dbr->timestamp( wfTimestamp( TS_UNIX ) - $this->RCMaxAge*24*3600 )}'"; + $conds[] = 'rc_log_type IS NULL OR rc_log_type != ' . $dbr->addQuotes( 'newusers' ); + $conds[] = 'rc_timestamp >= ' . $dbr->addQuotes( $dbr->timestamp( wfTimestamp( TS_UNIX ) - $this->RCMaxAge*24*3600 ) ); if( $this->requestedUser != '' ) { $conds[] = 'rc_user_text >= ' . $dbr->addQuotes( $this->requestedUser ); @@ -99,19 +103,23 @@ class ActiveUsersPager extends UsersPager { $query = array( 'tables' => array( 'recentchanges', 'user', 'ipblocks' ), - 'fields' => array( 'rc_user_text AS user_name', // inheritance + 'fields' => array( 'user_name' => 'rc_user_text', // inheritance 'rc_user_text', // for Pager 'user_id', - 'COUNT(*) AS recentedits', - 'MAX(ipb_user) AS blocked' + 'recentedits' => 'COUNT(*)', + 'blocked' => 'MAX(ipb_user)' ), 'options' => array( - 'GROUP BY' => 'rc_user_text, user_id', + 'GROUP BY' => array( 'rc_user_text', 'user_id' ), 'USE INDEX' => array( 'recentchanges' => 'rc_user_text' ) ), 'join_conds' => array( 'user' => array( 'INNER JOIN', 'rc_user_text=user_name' ), - 'ipblocks' => array( 'LEFT JOIN', 'user_id=ipb_user AND ipb_auto=0 AND ipb_deleted=1' ), + 'ipblocks' => array( 'LEFT JOIN', array( + 'user_id=ipb_user', + 'ipb_auto' => 0, + 'ipb_deleted' => 1 + )), ), 'conds' => $conds ); @@ -127,12 +135,30 @@ class ActiveUsersPager extends UsersPager { $lang = $this->getLanguage(); $list = array(); - foreach( self::getGroups( $row->user_id ) as $group ) { - if ( isset( $this->groups[$group] ) ) { - return; + $user = User::newFromId( $row->user_id ); + + // User right filter + foreach( $this->hideRights as $right ) { + // Calling User::getRights() within the loop so that + // if the hideRights() filter is empty, we don't have to + // trigger the lazy-init of the big userrights array in the + // User object + if ( in_array( $right, $user->getRights() ) ) { + return ''; + } + } + + // User group filter + // Note: This is a different loop than for user rights, + // because we're reusing it to build the group links + // at the same time + foreach( $user->getGroups() as $group ) { + if ( in_array( $group, $this->hideGroups ) ) { + return ''; } $list[] = self::buildGroupLink( $group, $userName ); } + $groups = $lang->commaList( $list ); $item = $lang->specialList( $ulinks, $groups ); diff --git a/includes/specials/SpecialAllmessages.php b/includes/specials/SpecialAllmessages.php index 2bfea4c3..fe9d41e5 100644 --- a/includes/specials/SpecialAllmessages.php +++ b/includes/specials/SpecialAllmessages.php @@ -146,8 +146,9 @@ class AllmessagesTablePager extends TablePager { function buildForm() { global $wgScript; - $languages = Language::getLanguageNames( false ); - ksort( $languages ); + $attrs = array( 'id' => 'mw-allmessages-form-lang', 'name' => 'lang' ); + $msg = wfMessage( 'allmessages-language' ); + $langSelect = Xml::languageSelector( $this->langcode, false, null, $attrs, $msg ); $out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'mw-allmessages-form' ) ) . Xml::fieldset( $this->msg( 'allmessages-filter-legend' )->text() ) . @@ -187,18 +188,8 @@ class AllmessagesTablePager extends TablePager { "</td>\n </tr> <tr>\n - <td class=\"mw-label\">" . - Xml::label( $this->msg( 'allmessages-language' )->text(), 'mw-allmessages-form-lang' ) . - "</td>\n - <td class=\"mw-input\">" . - Xml::openElement( 'select', array( 'id' => 'mw-allmessages-form-lang', 'name' => 'lang' ) ); - - foreach( $languages as $lang => $name ) { - $selected = $lang == $this->langcode; - $out .= Xml::option( $lang . ' - ' . $name, $lang, $selected ) . "\n"; - } - $out .= Xml::closeElement( 'select' ) . - "</td>\n + <td class=\"mw-label\">" . $langSelect[0] . "</td>\n + <td class=\"mw-input\">" . $langSelect[1] . "</td>\n </tr>" . '<tr> @@ -290,6 +281,7 @@ class AllmessagesTablePager extends TablePager { /** * This function normally does a database query to get the results; we need * to make a pretend result using a FakeResultWrapper. + * @return FakeResultWrapper */ function reallyDoQuery( $offset, $limit, $descending ) { $result = new FakeResultWrapper( array() ); @@ -369,7 +361,7 @@ class AllmessagesTablePager extends TablePager { array( 'broken' ) ); } - return $title . ' (' . $talk . ')'; + return $title . ' ' . $this->msg( 'parentheses' )->rawParams( $talk )->escaped(); case 'am_default' : case 'am_actual' : diff --git a/includes/specials/SpecialAllpages.php b/includes/specials/SpecialAllpages.php index 960a327a..0f8b2557 100644 --- a/includes/specials/SpecialAllpages.php +++ b/includes/specials/SpecialAllpages.php @@ -30,24 +30,37 @@ class SpecialAllpages extends IncludableSpecialPage { /** * Maximum number of pages to show on single subpage. + * + * @var int $maxPerPage */ protected $maxPerPage = 345; /** * Maximum number of pages to show on single index subpage. + * + * @var int $maxLineCount */ protected $maxLineCount = 100; /** * Maximum number of chars to show for an entry. + * + * @var int $maxPageLength */ protected $maxPageLength = 70; /** * Determines, which message describes the input field 'nsfrom'. + * + * @var string $nsfromMsg */ protected $nsfromMsg = 'allpagesfrom'; + /** + * Constructor + * + * @param $name string: name of the special page, as seen in links and URLs (default: 'Allpages') + */ function __construct( $name = 'Allpages' ){ parent::__construct( $name ); } @@ -70,6 +83,7 @@ class SpecialAllpages extends IncludableSpecialPage { $from = $request->getVal( 'from', null ); $to = $request->getVal( 'to', null ); $namespace = $request->getInt( 'namespace' ); + $hideredirects = $request->getBool( 'hideredirects', false ); $namespaces = $wgContLang->getNamespaces(); @@ -81,11 +95,11 @@ class SpecialAllpages extends IncludableSpecialPage { $out->addModuleStyles( 'mediawiki.special' ); if( $par !== null ) { - $this->showChunk( $namespace, $par, $to ); + $this->showChunk( $namespace, $par, $to, $hideredirects ); } elseif( $from !== null && $to === null ) { - $this->showChunk( $namespace, $from, $to ); + $this->showChunk( $namespace, $from, $to, $hideredirects ); } else { - $this->showToplevel( $namespace, $from, $to ); + $this->showToplevel( $namespace, $from, $to, $hideredirects ); } } @@ -95,8 +109,10 @@ class SpecialAllpages extends IncludableSpecialPage { * @param $namespace Integer: a namespace constant (default NS_MAIN). * @param $from String: dbKey we are starting listing at. * @param $to String: dbKey we are ending listing at. + * @param $hideredirects Bool: dont show redirects (default FALSE) + * @return string */ - function namespaceForm( $namespace = NS_MAIN, $from = '', $to = '' ) { + function namespaceForm( $namespace = NS_MAIN, $from = '', $to = '', $hideredirects = false ) { global $wgScript; $t = $this->getTitle(); @@ -131,6 +147,12 @@ class SpecialAllpages extends IncludableSpecialPage { array( 'selected' => $namespace ), array( 'name' => 'namespace', 'id' => 'namespace' ) ) . ' ' . + Xml::checkLabel( + $this->msg( 'allpages-hide-redirects' )->text(), + 'hideredirects', + 'hideredirects', + $hideredirects + ) . ' ' . Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . " </td> </tr>"; @@ -145,8 +167,9 @@ class SpecialAllpages extends IncludableSpecialPage { * @param $namespace Integer (default NS_MAIN) * @param $from String: list all pages from this name * @param $to String: list all pages to this name + * @param $hideredirects Bool: dont show redirects (default FALSE) */ - function showToplevel( $namespace = NS_MAIN, $from = '', $to = '' ) { + function showToplevel( $namespace = NS_MAIN, $from = '', $to = '', $hideredirects = false ) { $output = $this->getOutput(); # TODO: Either make this *much* faster or cache the title index points @@ -156,6 +179,10 @@ class SpecialAllpages extends IncludableSpecialPage { $out = ""; $where = array( 'page_namespace' => $namespace ); + if ( $hideredirects ) { + $where[ 'page_is_redirect' ] = 0; + } + $from = Title::makeTitleSafe( $namespace, $from ); $to = Title::makeTitleSafe( $namespace, $to ); $from = ( $from && $from->isLocal() ) ? $from->getDBkey() : null; @@ -224,9 +251,9 @@ class SpecialAllpages extends IncludableSpecialPage { // Instead, display the first section directly. if( count( $lines ) <= 2 ) { if( !empty($lines) ) { - $this->showChunk( $namespace, $from, $to ); + $this->showChunk( $namespace, $from, $to, $hideredirects ); } else { - $output->addHTML( $this->namespaceForm( $namespace, $from, $to ) ); + $output->addHTML( $this->namespaceForm( $namespace, $from, $to, $hideredirects ) ); } return; } @@ -236,10 +263,10 @@ class SpecialAllpages extends IncludableSpecialPage { while( count ( $lines ) > 0 ) { $inpoint = array_shift( $lines ); $outpoint = array_shift( $lines ); - $out .= $this->showline( $inpoint, $outpoint, $namespace ); + $out .= $this->showline( $inpoint, $outpoint, $namespace, $hideredirects ); } $out .= Xml::closeElement( 'table' ); - $nsForm = $this->namespaceForm( $namespace, $from, $to ); + $nsForm = $this->namespaceForm( $namespace, $from, $to, $hideredirects ); # Is there more? if( $this->including() ) { @@ -270,8 +297,10 @@ class SpecialAllpages extends IncludableSpecialPage { * @param $inpoint String: lower limit of pagenames * @param $outpoint String: upper limit of pagenames * @param $namespace Integer (Default NS_MAIN) + * @param $hideredirects Bool: dont show redirects (default FALSE) + * @return string */ - function showline( $inpoint, $outpoint, $namespace = NS_MAIN ) { + function showline( $inpoint, $outpoint, $namespace = NS_MAIN, $hideredirects ) { global $wgContLang; $inpointf = htmlspecialchars( str_replace( '_', ' ', $inpoint ) ); $outpointf = htmlspecialchars( str_replace( '_', ' ', $outpoint ) ); @@ -280,8 +309,14 @@ class SpecialAllpages extends IncludableSpecialPage { $outpointf = $wgContLang->truncate( $outpointf, $this->maxPageLength ); $queryparams = $namespace ? "namespace=$namespace&" : ''; + + $queryhideredirects = array(); + if ($hideredirects) { + $queryhideredirects[ 'hideredirects' ] = 1; + } + $special = $this->getTitle(); - $link = htmlspecialchars( $special->getLocalUrl( $queryparams . 'from=' . urlencode($inpoint) . '&to=' . urlencode($outpoint) ) ); + $link = htmlspecialchars( $special->getLocalUrl( $queryparams . 'from=' . urlencode($inpoint) . '&to=' . urlencode($outpoint), $queryhideredirects ) ); $out = $this->msg( 'alphaindexline' )->rawParams( "<a href=\"$link\">$inpointf</a></td><td>", @@ -294,8 +329,9 @@ class SpecialAllpages extends IncludableSpecialPage { * @param $namespace Integer (Default NS_MAIN) * @param $from String: list all pages from this name (default FALSE) * @param $to String: list all pages to this name (default FALSE) + * @param $hideredirects Bool: dont show redirects (default FALSE) */ - function showChunk( $namespace = NS_MAIN, $from = false, $to = false ) { + function showChunk( $namespace = NS_MAIN, $from = false, $to = false, $hideredirects = false ) { global $wgContLang; $output = $this->getOutput(); @@ -319,6 +355,11 @@ class SpecialAllpages extends IncludableSpecialPage { 'page_namespace' => $namespace, 'page_title >= ' . $dbr->addQuotes( $fromKey ) ); + + if ( $hideredirects ) { + $conds[ 'page_is_redirect' ] = 0; + } + if( $toKey !== "" ) { $conds[] = 'page_title <= ' . $dbr->addQuotes( $toKey ); } @@ -406,7 +447,7 @@ class SpecialAllpages extends IncludableSpecialPage { $self = $this->getTitle(); - $nsForm = $this->namespaceForm( $namespace, $from, $to ); + $nsForm = $this->namespaceForm( $namespace, $from, $to, $hideredirects ); $out2 = Xml::openElement( 'table', array( 'class' => 'mw-allpages-table-form' ) ). '<tr> <td>' . @@ -422,6 +463,9 @@ class SpecialAllpages extends IncludableSpecialPage { if( $namespace ) $query['namespace'] = $namespace; + if( $hideredirects ) + $query['hideredirects'] = $hideredirects; + $prevLink = Linker::linkKnown( $self, $this->msg( 'prevpage', $pt )->escaped(), @@ -433,12 +477,15 @@ class SpecialAllpages extends IncludableSpecialPage { if( $n == $this->maxPerPage && $s = $res->fetchObject() ) { # $s is the first link of the next chunk - $t = Title::MakeTitle($namespace, $s->page_title); + $t = Title::makeTitle($namespace, $s->page_title); $query = array( 'from' => $t->getText() ); if( $namespace ) $query['namespace'] = $namespace; + if( $hideredirects ) + $query['hideredirects'] = $hideredirects; + $nextLink = Linker::linkKnown( $self, $this->msg( 'nextpage', $t->getText() )->escaped(), diff --git a/includes/specials/SpecialAncientpages.php b/includes/specials/SpecialAncientpages.php index 1203e1fd..6e3d49bd 100644 --- a/includes/specials/SpecialAncientpages.php +++ b/includes/specials/SpecialAncientpages.php @@ -41,9 +41,9 @@ class AncientPagesPage extends QueryPage { function getQueryInfo() { return array( 'tables' => array( 'page', 'revision' ), - 'fields' => array( 'page_namespace AS namespace', - 'page_title AS title', - 'rev_timestamp AS value' ), + 'fields' => array( 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'rev_timestamp' ), 'conds' => array( 'page_namespace' => MWNamespace::getContentNamespaces(), 'page_is_redirect' => 0, 'page_latest=rev_id' ) diff --git a/includes/specials/SpecialBlock.php b/includes/specials/SpecialBlock.php index da8eed1b..1d6656ab 100644 --- a/includes/specials/SpecialBlock.php +++ b/includes/specials/SpecialBlock.php @@ -106,9 +106,9 @@ class SpecialBlock extends FormSpecialPage { $form->setSubmitTextMsg( $msg ); # Don't need to do anything if the form has been posted - if( !$this->getRequest()->wasPosted() && $this->preErrors ){ + if ( !$this->getRequest()->wasPosted() && $this->preErrors ) { $s = HTMLForm::formatErrors( $this->preErrors ); - if( $s ){ + if ( $s ) { $form->addHeaderText( Html::rawElement( 'div', array( 'class' => 'error' ), @@ -122,7 +122,7 @@ class SpecialBlock extends FormSpecialPage { * Get the HTMLForm descriptor array for the block form * @return Array */ - protected function getFormFields(){ + protected function getFormFields() { global $wgBlockAllowsUTEdit; $user = $this->getUser(); @@ -144,6 +144,7 @@ class SpecialBlock extends FormSpecialPage { 'tabindex' => '2', 'options' => self::getSuggestedDurations(), 'other' => $this->msg( 'ipbother' )->text(), + 'default' => $this->msg( 'ipb-default-expiry' )->inContentLanguage()->text(), ), 'Reason' => array( 'type' => 'selectandother', @@ -157,14 +158,14 @@ class SpecialBlock extends FormSpecialPage { ), ); - if( self::canBlockEmail( $user ) ) { + if ( self::canBlockEmail( $user ) ) { $a['DisableEmail'] = array( 'type' => 'check', 'label-message' => 'ipbemailban', ); } - if( $wgBlockAllowsUTEdit ){ + if ( $wgBlockAllowsUTEdit ) { $a['DisableUTEdit'] = array( 'type' => 'check', 'label-message' => 'ipb-disableusertalk', @@ -179,7 +180,7 @@ class SpecialBlock extends FormSpecialPage { ); # Allow some users to hide name from block log, blocklist and listusers - if( $user->isAllowed( 'hideuser' ) ) { + if ( $user->isAllowed( 'hideuser' ) ) { $a['HideUser'] = array( 'type' => 'check', 'label-message' => 'ipbhidename', @@ -188,7 +189,7 @@ class SpecialBlock extends FormSpecialPage { } # Watchlist their user page? (Only if user is logged in) - if( $user->isLoggedIn() ) { + if ( $user->isLoggedIn() ) { $a['Watch'] = array( 'type' => 'check', 'label-message' => 'ipbwatchuser', @@ -227,7 +228,7 @@ class SpecialBlock extends FormSpecialPage { * @return Bool whether fields were altered (that is, whether the target is * already blocked) */ - protected function maybeAlterFormDefaults( &$fields ){ + protected function maybeAlterFormDefaults( &$fields ) { # This will be overwritten by request data $fields['Target']['default'] = (string)$this->target; @@ -236,7 +237,7 @@ class SpecialBlock extends FormSpecialPage { $block = Block::newFromTarget( $this->target ); - if( $block instanceof Block && !$block->mAuto # The block exists and isn't an autoblock + if ( $block instanceof Block && !$block->mAuto # The block exists and isn't an autoblock && ( $this->type != Block::TYPE_RANGE # The block isn't a rangeblock || $block->getTarget() == $this->target ) # or if it is, the range is what we're about to block ) @@ -245,15 +246,15 @@ class SpecialBlock extends FormSpecialPage { $fields['CreateAccount']['default'] = $block->prevents( 'createaccount' ); $fields['AutoBlock']['default'] = $block->isAutoblocking(); - if( isset( $fields['DisableEmail'] ) ){ + if ( isset( $fields['DisableEmail'] ) ) { $fields['DisableEmail']['default'] = $block->prevents( 'sendemail' ); } - if( isset( $fields['HideUser'] ) ){ + if ( isset( $fields['HideUser'] ) ) { $fields['HideUser']['default'] = $block->mHideName; } - if( isset( $fields['DisableUTEdit'] ) ){ + if ( isset( $fields['DisableUTEdit'] ) ) { $fields['DisableUTEdit']['default'] = $block->prevents( 'editownusertalk' ); } @@ -265,7 +266,7 @@ class SpecialBlock extends FormSpecialPage { $fields['Reason']['default'] = ''; } - if( $this->getRequest()->wasPosted() ){ + if ( $this->getRequest()->wasPosted() ) { # Ok, so we got a POST submission asking us to reblock a user. So show the # confirm checkbox; the user will only see it if they haven't previously $fields['Confirm']['type'] = 'check'; @@ -276,25 +277,25 @@ class SpecialBlock extends FormSpecialPage { $fields['Confirm']['default'] = 1; } - if( $block->mExpiry == 'infinity' ) { - $fields['Expiry']['default'] = 'indefinite'; + if ( $block->mExpiry == 'infinity' ) { + $fields['Expiry']['default'] = 'infinite'; } else { $fields['Expiry']['default'] = wfTimestamp( TS_RFC2822, $block->mExpiry ); } $this->alreadyBlocked = true; - $this->preErrors[] = array( 'ipb-needreblock', (string)$block->getTarget() ); + $this->preErrors[] = array( 'ipb-needreblock', wfEscapeWikiText( (string)$block->getTarget() ) ); } # We always need confirmation to do HideUser - if( $this->requestedHideUser ){ + if ( $this->requestedHideUser ) { $fields['Confirm']['type'] = 'check'; unset( $fields['Confirm']['default'] ); $this->preErrors[] = 'ipb-confirmhideuser'; } # Or if the user is trying to block themselves - if( (string)$this->target === $this->getUser()->getName() ){ + if ( (string)$this->target === $this->getUser()->getName() ) { $fields['Confirm']['type'] = 'check'; unset( $fields['Confirm']['default'] ); $this->preErrors[] = 'ipb-blockingself'; @@ -303,16 +304,19 @@ class SpecialBlock extends FormSpecialPage { /** * Add header elements like block log entries, etc. + * @return String */ - protected function preText(){ + protected function preText() { + $this->getOutput()->addModules( 'mediawiki.special.block' ); + $text = $this->msg( 'blockiptext' )->parse(); $otherBlockMessages = array(); - if( $this->target !== null ) { + if ( $this->target !== null ) { # Get other blocks, i.e. from GlobalBlocking or TorBlock extension wfRunHooks( 'OtherBlockLogLink', array( &$otherBlockMessages, $this->target ) ); - if( count( $otherBlockMessages ) ) { + if ( count( $otherBlockMessages ) ) { $s = Html::rawElement( 'h2', array(), @@ -321,7 +325,7 @@ class SpecialBlock extends FormSpecialPage { $list = ''; - foreach( $otherBlockMessages as $link ) { + foreach ( $otherBlockMessages as $link ) { $list .= Html::rawElement( 'li', array(), $link ) . "\n"; } @@ -342,9 +346,11 @@ class SpecialBlock extends FormSpecialPage { * Add footer elements to the form * @return string */ - protected function postText(){ + protected function postText() { + $links = array(); + # Link to the user's contributions, if applicable - if( $this->target instanceof User ){ + if ( $this->target instanceof User ) { $contribsPage = SpecialPage::getTitleFor( 'Contributions', $this->target->getName() ); $links[] = Linker::link( $contribsPage, @@ -353,8 +359,8 @@ class SpecialBlock extends FormSpecialPage { } # Link to unblock the specified user, or to a blank unblock form - if( $this->target instanceof User ) { - $message = $this->msg( 'ipb-unblock-addr', $this->target->getName() )->parse(); + if ( $this->target instanceof User ) { + $message = $this->msg( 'ipb-unblock-addr', wfEscapeWikiText( $this->target->getName() ) )->parse(); $list = SpecialPage::getTitleFor( 'Unblock', $this->target->getName() ); } else { $message = $this->msg( 'ipb-unblock' )->parse(); @@ -386,35 +392,35 @@ class SpecialBlock extends FormSpecialPage { $this->getLanguage()->pipeList( $links ) ); - if( $this->target instanceof User ){ + $userTitle = self::getTargetUserTitle( $this->target ); + if ( $userTitle ) { # Get relevant extracts from the block and suppression logs, if possible - $userpage = $this->target->getUserPage(); $out = ''; LogEventsList::showLogExtract( $out, 'block', - $userpage, + $userTitle, '', array( 'lim' => 10, - 'msgKey' => array( 'blocklog-showlog', $userpage->getText() ), + 'msgKey' => array( 'blocklog-showlog', $userTitle->getText() ), 'showIfEmpty' => false ) ); $text .= $out; # Add suppression block entries if allowed - if( $user->isAllowed( 'suppressionlog' ) ) { + if ( $user->isAllowed( 'suppressionlog' ) ) { LogEventsList::showLogExtract( $out, 'suppress', - $userpage, + $userTitle, '', array( 'lim' => 10, 'conds' => array( 'log_action' => array( 'block', 'reblock', 'unblock' ) ), - 'msgKey' => array( 'blocklog-showsuppresslog', $userpage->getText() ), + 'msgKey' => array( 'blocklog-showsuppresslog', $userTitle->getText() ), 'showIfEmpty' => false ) ); @@ -427,6 +433,21 @@ class SpecialBlock extends FormSpecialPage { } /** + * Get a user page target for things like logs. + * This handles account and IP range targets. + * @param $target User|string + * @return Title|null + */ + protected static function getTargetUserTitle( $target ) { + if ( $target instanceof User ) { + return $target->getUserPage(); + } elseif ( IP::isIPAddress( $target ) ) { + return Title::makeTitleSafe( NS_USER, $target ); + } + return null; + } + + /** * Determine the target of the block, and the type of target * TODO: should be in Block.php? * @param $par String subpage parameter passed to setup, or data value from @@ -434,18 +455,18 @@ class SpecialBlock extends FormSpecialPage { * @param $request WebRequest optionally try and get data from a request too * @return array( User|string|null, Block::TYPE_ constant|null ) */ - public static function getTargetAndType( $par, WebRequest $request = null ){ + public static function getTargetAndType( $par, WebRequest $request = null ) { $i = 0; $target = null; - while( true ){ - switch( $i++ ){ + while( true ) { + switch( $i++ ) { case 0: # The HTMLForm will check wpTarget first and only if it doesn't get # a value use the default, which will be generated from the options # below; so this has to have a higher precedence here than $par, or # we could end up with different values in $this->target and the HTMLForm! - if( $request instanceof WebRequest ){ + if ( $request instanceof WebRequest ) { $target = $request->getText( 'wpTarget', null ); } break; @@ -453,13 +474,13 @@ class SpecialBlock extends FormSpecialPage { $target = $par; break; case 2: - if( $request instanceof WebRequest ){ + if ( $request instanceof WebRequest ) { $target = $request->getText( 'ip', null ); } break; case 3: # B/C @since 1.18 - if( $request instanceof WebRequest ){ + if ( $request instanceof WebRequest ) { $target = $request->getText( 'wpBlockAddress', null ); } break; @@ -469,7 +490,7 @@ class SpecialBlock extends FormSpecialPage { list( $target, $type ) = Block::parseTarget( $target ); - if( $type !== null ){ + if ( $type !== null ) { return array( $target, $type ); } } @@ -490,9 +511,9 @@ class SpecialBlock extends FormSpecialPage { list( $target, $type ) = self::getTargetAndType( $value ); - if( $type == Block::TYPE_USER ){ + if ( $type == Block::TYPE_USER ) { # TODO: why do we not have a User->exists() method? - if( !$target->getId() ){ + if ( !$target->getId() ) { return $form->msg( 'nosuchusershort', wfEscapeWikiText( $target->getName() ) ); } @@ -502,31 +523,31 @@ class SpecialBlock extends FormSpecialPage { return $form->msg( 'badaccess', $status ); } - } elseif( $type == Block::TYPE_RANGE ){ + } elseif ( $type == Block::TYPE_RANGE ) { list( $ip, $range ) = explode( '/', $target, 2 ); - if( ( IP::isIPv4( $ip ) && $wgBlockCIDRLimit['IPv4'] == 32 ) + if ( ( IP::isIPv4( $ip ) && $wgBlockCIDRLimit['IPv4'] == 32 ) || ( IP::isIPv6( $ip ) && $wgBlockCIDRLimit['IPv6'] == 128 ) ) { # Range block effectively disabled return $form->msg( 'range_block_disabled' ); } - if( ( IP::isIPv4( $ip ) && $range > 32 ) + if ( ( IP::isIPv4( $ip ) && $range > 32 ) || ( IP::isIPv6( $ip ) && $range > 128 ) ) { # Dodgy range return $form->msg( 'ip_range_invalid' ); } - if( IP::isIPv4( $ip ) && $range < $wgBlockCIDRLimit['IPv4'] ) { + if ( IP::isIPv4( $ip ) && $range < $wgBlockCIDRLimit['IPv4'] ) { return $form->msg( 'ip_range_toolarge', $wgBlockCIDRLimit['IPv4'] ); } - if( IP::isIPv6( $ip ) && $range < $wgBlockCIDRLimit['IPv6'] ) { + if ( IP::isIPv6( $ip ) && $range < $wgBlockCIDRLimit['IPv6'] ) { return $form->msg( 'ip_range_toolarge', $wgBlockCIDRLimit['IPv6'] ); } - } elseif( $type == Block::TYPE_IP ){ + } elseif ( $type == Block::TYPE_IP ) { # All is well } else { return $form->msg( 'badipaddress' ); @@ -551,7 +572,7 @@ class SpecialBlock extends FormSpecialPage { * @param $context IContextSource * @return Bool|String */ - public static function processForm( array $data, IContextSource $context ){ + public static function processForm( array $data, IContextSource $context ) { global $wgBlockAllowsUTEdit; $performer = $context->getUser(); @@ -564,7 +585,7 @@ class SpecialBlock extends FormSpecialPage { $data['Confirm'] = !in_array( $data['Confirm'], array( '', '0', null, false ), true ); list( $target, $type ) = self::getTargetAndType( $data['Target'] ); - if( $type == Block::TYPE_USER ){ + if ( $type == Block::TYPE_USER ) { $user = $target; $target = $user->getName(); $userId = $user->getId(); @@ -576,14 +597,14 @@ class SpecialBlock extends FormSpecialPage { # since both $data['PreviousTarget'] and $target are normalized # but $data['target'] gets overriden by (non-normalized) request variable # from previous request. - if( $target === $performer->getName() && + if ( $target === $performer->getName() && ( $data['PreviousTarget'] !== $target || !$data['Confirm'] ) ) { return array( 'ipb-blockingself' ); } - } elseif( $type == Block::TYPE_RANGE ){ + } elseif ( $type == Block::TYPE_RANGE ) { $userId = 0; - } elseif( $type == Block::TYPE_IP ){ + } elseif ( $type == Block::TYPE_IP ) { $target = $target->getName(); $userId = 0; } else { @@ -591,24 +612,24 @@ class SpecialBlock extends FormSpecialPage { return array( 'badipaddress' ); } - if( ( strlen( $data['Expiry'] ) == 0) || ( strlen( $data['Expiry'] ) > 50 ) + if ( ( strlen( $data['Expiry'] ) == 0) || ( strlen( $data['Expiry'] ) > 50 ) || !self::parseExpiryInput( $data['Expiry'] ) ) { return array( 'ipb_expiry_invalid' ); } - if( !isset( $data['DisableEmail'] ) ){ + if ( !isset( $data['DisableEmail'] ) ) { $data['DisableEmail'] = false; } # If the user has done the form 'properly', they won't even have been given the # option to suppress-block unless they have the 'hideuser' permission - if( !isset( $data['HideUser'] ) ){ + if ( !isset( $data['HideUser'] ) ) { $data['HideUser'] = false; } - if( $data['HideUser'] ) { - if( !$performer->isAllowed('hideuser') ){ + if ( $data['HideUser'] ) { + if ( !$performer->isAllowed('hideuser') ) { # this codepath is unreachable except by a malicious user spoofing forms, # or by race conditions (user has oversight and sysop, loads block form, # and is de-oversighted before submission); so need to fail completely @@ -617,16 +638,16 @@ class SpecialBlock extends FormSpecialPage { } # Recheck params here... - if( $type != Block::TYPE_USER ) { + if ( $type != Block::TYPE_USER ) { $data['HideUser'] = false; # IP users should not be hidden - } elseif( !in_array( $data['Expiry'], array( 'infinite', 'infinity', 'indefinite' ) ) ) { + } elseif ( !in_array( $data['Expiry'], array( 'infinite', 'infinity', 'indefinite' ) ) ) { # Bad expiry. return array( 'ipb_expiry_temp' ); - } elseif( $user->getEditCount() > self::HIDEUSER_CONTRIBLIMIT ) { + } elseif ( $user->getEditCount() > self::HIDEUSER_CONTRIBLIMIT ) { # Typically, the user should have a handful of edits. # Disallow hiding users with many edits for performance. return array( 'ipb_hide_invalid' ); - } elseif( !$data['Confirm'] ){ + } elseif ( !$data['Confirm'] ) { return array( 'ipb-confirmhideuser' ); } } @@ -644,15 +665,15 @@ class SpecialBlock extends FormSpecialPage { $block->isAutoblocking( $data['AutoBlock'] ); $block->mHideName = $data['HideUser']; - if( !wfRunHooks( 'BlockIp', array( &$block, &$performer ) ) ) { + if ( !wfRunHooks( 'BlockIp', array( &$block, &$performer ) ) ) { return array( 'hookaborted' ); } # Try to insert block. Is there a conflicting block? $status = $block->insert(); - if( !$status ) { + if ( !$status ) { # Show form unless the user is already aware of this... - if( !$data['Confirm'] || ( array_key_exists( 'PreviousTarget', $data ) + if ( !$data['Confirm'] || ( array_key_exists( 'PreviousTarget', $data ) && $data['PreviousTarget'] !== $target ) ) { return array( array( 'ipb_already_blocked', $block->getTarget() ) ); @@ -662,13 +683,13 @@ class SpecialBlock extends FormSpecialPage { # be sure the user is blocked by now it should work for our purposes $currentBlock = Block::newFromTarget( $target ); - if( $block->equals( $currentBlock ) ) { + if ( $block->equals( $currentBlock ) ) { return array( array( 'ipb_already_blocked', $block->getTarget() ) ); } # If the name was hidden and the blocking user cannot hide # names, then don't allow any block changes... - if( $currentBlock->mHideName && !$performer->isAllowed( 'hideuser' ) ) { + if ( $currentBlock->mHideName && !$performer->isAllowed( 'hideuser' ) ) { return array( 'cant-see-hidden-user' ); } @@ -677,12 +698,12 @@ class SpecialBlock extends FormSpecialPage { $logaction = 'reblock'; # Unset _deleted fields if requested - if( $currentBlock->mHideName && !$data['HideUser'] ) { + if ( $currentBlock->mHideName && !$data['HideUser'] ) { RevisionDeleteUser::unsuppressUserName( $target, $userId ); } # If hiding/unhiding a name, this should go in the private logs - if( (bool)$currentBlock->mHideName ){ + if ( (bool)$currentBlock->mHideName ) { $data['HideUser'] = true; } } @@ -693,12 +714,12 @@ class SpecialBlock extends FormSpecialPage { wfRunHooks( 'BlockIpComplete', array( $block, $performer ) ); # Set *_deleted fields if requested - if( $data['HideUser'] ) { + if ( $data['HideUser'] ) { RevisionDeleteUser::suppressUserName( $target, $userId ); } # Can't watch a rangeblock - if( $type != Block::TYPE_RANGE && $data['Watch'] ) { + if ( $type != Block::TYPE_RANGE && $data['Watch'] ) { $performer->addWatch( Title::makeTitle( NS_USER, $target ) ); } @@ -736,18 +757,18 @@ class SpecialBlock extends FormSpecialPage { * the wiki's content language * @return Array */ - public static function getSuggestedDurations( $lang = null ){ + public static function getSuggestedDurations( $lang = null ) { $a = array(); $msg = $lang === null ? wfMessage( 'ipboptions' )->inContentLanguage()->text() : wfMessage( 'ipboptions' )->inLanguage( $lang )->text(); - if( $msg == '-' ){ + if ( $msg == '-' ) { return array(); } - foreach( explode( ',', $msg ) as $option ) { - if( strpos( $option, ':' ) === false ){ + foreach ( explode( ',', $msg ) as $option ) { + if ( strpos( $option, ':' ) === false ) { $option = "$option:$option"; } @@ -766,7 +787,7 @@ class SpecialBlock extends FormSpecialPage { */ public static function parseExpiryInput( $expiry ) { static $infinity; - if( $infinity == null ){ + if ( $infinity == null ) { $infinity = wfGetDB( DB_SLAVE )->getInfinity(); } @@ -811,8 +832,8 @@ class SpecialBlock extends FormSpecialPage { $user = User::newFromName( $user ); } - if( $performer->isBlocked() ){ - if( $user instanceof User && $user->getId() == $performer->getId() ) { + if ( $performer->isBlocked() ) { + if ( $user instanceof User && $user->getId() == $performer->getId() ) { # User is trying to unblock themselves if ( $performer->isAllowed( 'unblockself' ) ) { return true; @@ -836,40 +857,41 @@ class SpecialBlock extends FormSpecialPage { * reader for this block, to provide more information in the logs * @param $data Array from HTMLForm data * @param $type Block::TYPE_ constant (USER, RANGE, or IP) - * @return array + * @return string */ protected static function blockLogFlags( array $data, $type ) { global $wgBlockAllowsUTEdit; $flags = array(); - # when blocking a user the option 'anononly' is not available/has no effect -> do not write this into log - if( !$data['HardBlock'] && $type != Block::TYPE_USER ){ + # when blocking a user the option 'anononly' is not available/has no effect + # -> do not write this into log + if ( !$data['HardBlock'] && $type != Block::TYPE_USER ) { // For grepping: message block-log-flags-anononly $flags[] = 'anononly'; } - if( $data['CreateAccount'] ){ + if ( $data['CreateAccount'] ) { // For grepping: message block-log-flags-nocreate $flags[] = 'nocreate'; } # Same as anononly, this is not displayed when blocking an IP address - if( !$data['AutoBlock'] && $type == Block::TYPE_USER ){ + if ( !$data['AutoBlock'] && $type == Block::TYPE_USER ) { // For grepping: message block-log-flags-noautoblock $flags[] = 'noautoblock'; } - if( $data['DisableEmail'] ){ + if ( $data['DisableEmail'] ) { // For grepping: message block-log-flags-noemail $flags[] = 'noemail'; } - if( $wgBlockAllowsUTEdit && $data['DisableUTEdit'] ){ + if ( $wgBlockAllowsUTEdit && $data['DisableUTEdit'] ) { // For grepping: message block-log-flags-nousertalk $flags[] = 'nousertalk'; } - if( $data['HideUser'] ){ + if ( $data['HideUser'] ) { // For grepping: message block-log-flags-hiddenname $flags[] = 'hiddenname'; } @@ -894,7 +916,7 @@ class SpecialBlock extends FormSpecialPage { public function onSuccess() { $out = $this->getOutput(); $out->setPageTitle( $this->msg( 'blockipsuccesssub' ) ); - $out->addWikiMsg( 'blockipsuccesstext', $this->target ); + $out->addWikiMsg( 'blockipsuccesstext', wfEscapeWikiText( $this->target ) ); } } diff --git a/includes/specials/SpecialBlockList.php b/includes/specials/SpecialBlockList.php index 0a3a28fe..7143d5bc 100644 --- a/includes/specials/SpecialBlockList.php +++ b/includes/specials/SpecialBlockList.php @@ -372,7 +372,7 @@ class BlockListPager extends TablePager { 'ipb_user', 'ipb_by', 'ipb_by_text', - 'user_name AS by_user_name', + 'by_user_name' => 'user_name', 'ipb_reason', 'ipb_timestamp', 'ipb_auto', diff --git a/includes/specials/SpecialBooksources.php b/includes/specials/SpecialBooksources.php index 48ca4f05..bf7de3f5 100644 --- a/includes/specials/SpecialBooksources.php +++ b/includes/specials/SpecialBooksources.php @@ -46,7 +46,7 @@ class SpecialBookSources extends SpecialPage { /** * Show the special page * - * @param $isbn ISBN passed as a subpage parameter + * @param $isbn string ISBN passed as a subpage parameter */ public function execute( $isbn ) { $this->setHeaders(); @@ -63,7 +63,8 @@ class SpecialBookSources extends SpecialPage { /** * Returns whether a given ISBN (10 or 13) is valid. True indicates validity. - * @param isbn ISBN passed for check + * @param isbn string ISBN passed for check + * @return bool */ public static function isValidISBN( $isbn ) { $isbn = self::cleanIsbn( $isbn ); @@ -100,7 +101,7 @@ class SpecialBookSources extends SpecialPage { /** * Trim ISBN and remove characters which aren't required * - * @param $isbn Unclean ISBN + * @param $isbn string Unclean ISBN * @return string */ private static function cleanIsbn( $isbn ) { @@ -142,7 +143,7 @@ class SpecialBookSources extends SpecialPage { $page = $this->msg( 'booksources' )->inContentLanguage()->text(); $title = Title::makeTitleSafe( NS_PROJECT, $page ); # Show list in content language if( is_object( $title ) && $title->exists() ) { - $rev = Revision::newFromTitle( $title ); + $rev = Revision::newFromTitle( $title, false, Revision::READ_NORMAL ); $this->getOutput()->addWikiText( str_replace( 'MAGICNUMBER', $this->isbn, $rev->getText() ) ); return true; } @@ -160,8 +161,8 @@ class SpecialBookSources extends SpecialPage { /** * Format a book source list item * - * @param $label Book source label - * @param $url Book source URL + * @param $label string Book source label + * @param $url string Book source URL * @return string */ private function makeListItem( $label, $url ) { diff --git a/includes/specials/SpecialBrokenRedirects.php b/includes/specials/SpecialBrokenRedirects.php index b8dbe9e8..8119e6d1 100644 --- a/includes/specials/SpecialBrokenRedirects.php +++ b/includes/specials/SpecialBrokenRedirects.php @@ -27,7 +27,7 @@ * * @ingroup SpecialPage */ -class BrokenRedirectsPage extends PageQueryPage { +class BrokenRedirectsPage extends QueryPage { function __construct( $name = 'BrokenRedirects' ) { parent::__construct( $name ); @@ -45,9 +45,9 @@ class BrokenRedirectsPage extends PageQueryPage { return array( 'tables' => array( 'redirect', 'p1' => 'page', 'p2' => 'page' ), - 'fields' => array( 'p1.page_namespace AS namespace', - 'p1.page_title AS title', - 'p1.page_title AS value', + 'fields' => array( 'namespace' => 'p1.page_namespace', + 'title' => 'p1.page_title', + 'value' => 'p1.page_title', 'rd_namespace', 'rd_title' ), diff --git a/includes/specials/SpecialCachedPage.php b/includes/specials/SpecialCachedPage.php new file mode 100644 index 00000000..b3f6c720 --- /dev/null +++ b/includes/specials/SpecialCachedPage.php @@ -0,0 +1,198 @@ +<?php + +/** + * Abstract special page class with scaffolding for caching HTML and other values + * in a single blob. + * + * Before using any of the caching functionality, call startCache. + * After the last call to either getCachedValue or addCachedHTML, call saveCache. + * + * To get a cached value or compute it, use getCachedValue like this: + * $this->getCachedValue( $callback ); + * + * To add HTML that should be cached, use addCachedHTML like this: + * $this->addCachedHTML( $callback ); + * + * The callback function is only called when needed, so do all your expensive + * computations here. This function should returns the HTML to be cached. + * It should not add anything to the PageOutput object! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + * @ingroup SpecialPage + * @author Jeroen De Dauw < jeroendedauw@gmail.com > + * @since 1.20 + */ +abstract class SpecialCachedPage extends SpecialPage implements ICacheHelper { + + /** + * CacheHelper object to which we forward the non-SpecialPage specific caching work. + * Initialized in startCache. + * + * @since 1.20 + * @var CacheHelper + */ + protected $cacheHelper; + + /** + * If the cache is enabled or not. + * + * @since 1.20 + * @var boolean + */ + protected $cacheEnabled = true; + + /** + * Gets called after @see SpecialPage::execute. + * + * @since 1.20 + * + * @param $subPage string|null + */ + protected function afterExecute( $subPage ) { + $this->saveCache(); + + parent::afterExecute( $subPage ); + } + + /** + * Sets if the cache should be enabled or not. + * + * @since 1.20 + * @param boolean $cacheEnabled + */ + public function setCacheEnabled( $cacheEnabled ) { + $this->cacheHelper->setCacheEnabled( $cacheEnabled ); + } + + /** + * Initializes the caching. + * Should be called before the first time anything is added via addCachedHTML. + * + * @since 1.20 + * + * @param integer|null $cacheExpiry Sets the cache expiry, either ttl in seconds or unix timestamp. + * @param boolean|null $cacheEnabled Sets if the cache should be enabled or not. + */ + public function startCache( $cacheExpiry = null, $cacheEnabled = null ) { + if ( !isset( $this->cacheHelper ) ) { + $this->cacheHelper = new CacheHelper(); + + $this->cacheHelper->setCacheEnabled( $this->cacheEnabled ); + $this->cacheHelper->setOnInitializedHandler( array( $this, 'onCacheInitialized' ) ); + + $keyArgs = $this->getCacheKey(); + + if ( array_key_exists( 'action', $keyArgs ) && $keyArgs['action'] === 'purge' ) { + unset( $keyArgs['action'] ); + } + + $this->cacheHelper->setCacheKey( $keyArgs ); + + if ( $this->getRequest()->getText( 'action' ) === 'purge' ) { + $this->cacheHelper->rebuildOnDemand(); + } + } + + $this->cacheHelper->startCache( $cacheExpiry, $cacheEnabled ); + } + + /** + * Get a cached value if available or compute it if not and then cache it if possible. + * The provided $computeFunction is only called when the computation needs to happen + * and should return a result value. $args are arguments that will be passed to the + * compute function when called. + * + * @since 1.20 + * + * @param {function} $computeFunction + * @param array|mixed $args + * @param string|null $key + * + * @return mixed + */ + public function getCachedValue( $computeFunction, $args = array(), $key = null ) { + return $this->cacheHelper->getCachedValue( $computeFunction, $args, $key ); + } + + /** + * Add some HTML to be cached. + * This is done by providing a callback function that should + * return the HTML to be added. It will only be called if the + * item is not in the cache yet or when the cache has been invalidated. + * + * @since 1.20 + * + * @param {function} $computeFunction + * @param array $args + * @param string|null $key + */ + public function addCachedHTML( $computeFunction, $args = array(), $key = null ) { + $this->getOutput()->addHTML( $this->cacheHelper->getCachedValue( $computeFunction, $args, $key ) ); + } + + /** + * Saves the HTML to the cache in case it got recomputed. + * Should be called after the last time anything is added via addCachedHTML. + * + * @since 1.20 + */ + public function saveCache() { + if ( isset( $this->cacheHelper ) ) { + $this->cacheHelper->saveCache(); + } + } + + /** + * Sets the time to live for the cache, in seconds or a unix timestamp indicating the point of expiry. + * + * @since 1.20 + * + * @param integer $cacheExpiry + */ + public function setExpiry( $cacheExpiry ) { + $this->cacheHelper->setExpiry( $cacheExpiry ); + } + + /** + * Returns the variables used to constructed the cache key in an array. + * + * @since 1.20 + * + * @return array + */ + protected function getCacheKey() { + return array( + $this->mName, + $this->getLanguage()->getCode() + ); + } + + /** + * Gets called after the cache got initialized. + * + * @since 1.20 + * + * @param boolean $hasCached + */ + public function onCacheInitialized( $hasCached ) { + if ( $hasCached ) { + $this->getOutput()->setSubtitle( $this->cacheHelper->getCachedNotice( $this->getContext() ) ); + } + } + +} diff --git a/includes/specials/SpecialCategories.php b/includes/specials/SpecialCategories.php index 338cd706..1232e3fa 100644 --- a/includes/specials/SpecialCategories.php +++ b/includes/specials/SpecialCategories.php @@ -59,16 +59,13 @@ class SpecialCategories extends SpecialPage { * @ingroup SpecialPage Pager */ class CategoryPager extends AlphabeticPager { - private $conds = array( 'cat_pages > 0' ); - function __construct( IContextSource $context, $from ) { parent::__construct( $context ); $from = str_replace( ' ', '_', $from ); if( $from !== '' ) { $from = Title::capitalize( $from, NS_CATEGORY ); - $dbr = wfGetDB( DB_SLAVE ); - $this->conds[] = 'cat_title >= ' . $dbr->addQuotes( $from ); - $this->setOffset( '' ); + $this->setOffset( $from ); + $this->setIncludeOffset( true ); } } @@ -76,7 +73,7 @@ class CategoryPager extends AlphabeticPager { return array( 'tables' => array( 'category' ), 'fields' => array( 'cat_title','cat_pages' ), - 'conds' => $this->conds, + 'conds' => array( 'cat_pages > 0' ), 'options' => array( 'USE INDEX' => 'cat_title' ), ); } diff --git a/includes/specials/SpecialChangeEmail.php b/includes/specials/SpecialChangeEmail.php index 0f85f516..fc726106 100644 --- a/includes/specials/SpecialChangeEmail.php +++ b/includes/specials/SpecialChangeEmail.php @@ -27,10 +27,26 @@ * @ingroup SpecialPage */ class SpecialChangeEmail extends UnlistedSpecialPage { + + /** + * Users password + * @var string + */ + protected $mPassword; + + /** + * Users new email address + * @var string + */ + protected $mNewEmail; + public function __construct() { parent::__construct( 'ChangeEmail' ); } + /** + * @return Bool + */ function isListed() { global $wgAuth; return $wgAuth->allowPropChange( 'emailaddress' ); @@ -42,11 +58,13 @@ class SpecialChangeEmail extends UnlistedSpecialPage { function execute( $par ) { global $wgAuth; - $this->checkReadOnly(); - $this->setHeaders(); $this->outputHeader(); + $out = $this->getOutput(); + $out->disallowUserJs(); + $out->addModules( 'mediawiki.special.changeemail' ); + if ( !$wgAuth->allowPropChange( 'emailaddress' ) ) { $this->error( 'cannotchangeemail' ); return; @@ -65,9 +83,7 @@ class SpecialChangeEmail extends UnlistedSpecialPage { return; } - $out = $this->getOutput(); - $out->disallowUserJs(); - $out->addModules( 'mediawiki.special.changeemail' ); + $this->checkReadOnly(); $this->mPassword = $request->getVal( 'wpPassword' ); $this->mNewEmail = $request->getVal( 'wpNewEmail' ); @@ -90,6 +106,9 @@ class SpecialChangeEmail extends UnlistedSpecialPage { $this->showForm(); } + /** + * @param $type string + */ protected function doReturnTo( $type = 'hard' ) { $titleObj = Title::newFromText( $this->getRequest()->getVal( 'returnto' ) ); if ( !$titleObj instanceof Title ) { @@ -102,11 +121,15 @@ class SpecialChangeEmail extends UnlistedSpecialPage { } } + /** + * @param $msg string + */ protected function error( $msg ) { $this->getOutput()->wrapWikiMsg( "<p class='error'>\n$1\n</p>", $msg ); } protected function showForm() { + global $wgRequirePasswordforEmailChange; $user = $this->getUser(); $oldEmailText = $user->getEmail() @@ -123,13 +146,20 @@ class SpecialChangeEmail extends UnlistedSpecialPage { Html::hidden( 'token', $user->getEditToken() ) . "\n" . Html::hidden( 'returnto', $this->getRequest()->getVal( 'returnto' ) ) . "\n" . $this->msg( 'changeemail-text' )->parseAsBlock() . "\n" . - Xml::openElement( 'table', array( 'id' => 'mw-changeemail-table' ) ) . "\n" . - $this->pretty( array( - array( 'wpName', 'username', 'text', $user->getName() ), - array( 'wpOldEmail', 'changeemail-oldemail', 'text', $oldEmailText ), - array( 'wpNewEmail', 'changeemail-newemail', 'input', $this->mNewEmail ), - array( 'wpPassword', 'yourpassword', 'password', $this->mPassword ), - ) ) . "\n" . + Xml::openElement( 'table', array( 'id' => 'mw-changeemail-table' ) ) . "\n" + ); + $items = array( + array( 'wpName', 'username', 'text', $user->getName() ), + array( 'wpOldEmail', 'changeemail-oldemail', 'text', $oldEmailText ), + array( 'wpNewEmail', 'changeemail-newemail', 'input', $this->mNewEmail ), + ); + if ( $wgRequirePasswordforEmailChange ) { + $items[] = array( 'wpPassword', 'yourpassword', 'password', $this->mPassword ); + } + + $this->getOutput()->addHTML( + $this->pretty( $items ) . + "\n" . "<tr>\n" . "<td></td>\n" . '<td class="mw-input">' . @@ -143,6 +173,10 @@ class SpecialChangeEmail extends UnlistedSpecialPage { ); } + /** + * @param $fields array + * @return string + */ protected function pretty( $fields ) { $out = ''; foreach ( $fields as $list ) { @@ -173,6 +207,9 @@ class SpecialChangeEmail extends UnlistedSpecialPage { } /** + * @param $user User + * @param $pass string + * @param $newaddr string * @return bool|string true or string on success, false on failure */ protected function attemptChange( User $user, $pass, $newaddr ) { @@ -187,7 +224,8 @@ class SpecialChangeEmail extends UnlistedSpecialPage { return false; } - if ( !$user->checkTemporaryPassword( $pass ) && !$user->checkPassword( $pass ) ) { + global $wgRequirePasswordforEmailChange; + if ( $wgRequirePasswordforEmailChange && !$user->checkTemporaryPassword( $pass ) && !$user->checkPassword( $pass ) ) { $this->error( 'wrongpassword' ); return false; } @@ -196,18 +234,20 @@ class SpecialChangeEmail extends UnlistedSpecialPage { LoginForm::clearLoginThrottle( $user->getName() ); } - list( $status, $info ) = Preferences::trySetUserEmail( $user, $newaddr ); - if ( $status !== true ) { - if ( $status instanceof Status ) { - $this->getOutput()->addHTML( - '<p class="error">' . - $this->getOutput()->parseInline( $status->getWikiText( $info ) ) . - '</p>' ); - } + $oldaddr = $user->getEmail(); + $status = $user->setEmailWithConfirmation( $newaddr ); + if ( !$status->isGood() ) { + $this->getOutput()->addHTML( + '<p class="error">' . + $this->getOutput()->parseInline( $status->getWikiText( 'mailerror' ) ) . + '</p>' ); return false; } + wfRunHooks( 'PrefsEmailAudit', array( $user, $oldaddr, $newaddr ) ); + $user->saveSettings(); - return $info ? $info : true; + + return $status->value; } } diff --git a/includes/specials/SpecialChangePassword.php b/includes/specials/SpecialChangePassword.php index f6482ef5..41b3b255 100644 --- a/includes/specials/SpecialChangePassword.php +++ b/includes/specials/SpecialChangePassword.php @@ -37,7 +37,9 @@ class SpecialChangePassword extends UnlistedSpecialPage { function execute( $par ) { global $wgAuth; - $this->checkReadOnly(); + $this->setHeaders(); + $this->outputHeader(); + $this->getOutput()->disallowUserJs(); $request = $this->getRequest(); $this->mUserName = trim( $request->getVal( 'wpName' ) ); @@ -46,10 +48,6 @@ class SpecialChangePassword extends UnlistedSpecialPage { $this->mRetype = $request->getVal( 'wpRetype' ); $this->mDomain = $request->getVal( 'wpDomain' ); - $this->setHeaders(); - $this->outputHeader(); - $this->getOutput()->disallowUserJs(); - $user = $this->getUser(); if( !$request->wasPosted() && !$user->isLoggedIn() ) { $this->error( $this->msg( 'resetpass-no-info' )->text() ); @@ -61,12 +59,11 @@ class SpecialChangePassword extends UnlistedSpecialPage { return; } + $this->checkReadOnly(); + if( $request->wasPosted() && $user->matchEditToken( $request->getVal( 'token' ) ) ) { try { - if ( isset( $_SESSION['wsDomain'] ) ) { - $this->mDomain = $_SESSION['wsDomain']; - } - $wgAuth->setDomain( $this->mDomain ); + $this->mDomain = $wgAuth->getDomain(); if( !$wgAuth->allowPasswordChange() ) { $this->error( $this->msg( 'resetpass_forbidden' )->text() ); return; @@ -136,6 +133,15 @@ class SpecialChangePassword extends UnlistedSpecialPage { $oldpassMsg = 'oldpassword'; $submitMsg = 'resetpass-submit-loggedin'; } + $extraFields = array(); + wfRunHooks( 'ChangePasswordForm', array( &$extraFields ) ); + $prettyFields = array( + array( 'wpName', 'username', 'text', $this->mUserName ), + array( 'wpPassword', $oldpassMsg, 'password', $this->mOldpass ), + array( 'wpNewPassword', 'newpassword', 'password', null ), + array( 'wpRetype', 'retypenew', 'password', null ), + ); + $prettyFields = array_merge( $prettyFields, $extraFields ); $this->getOutput()->addHTML( Xml::fieldset( $this->msg( 'resetpass_header' )->text() ) . Xml::openElement( 'form', @@ -149,12 +155,7 @@ class SpecialChangePassword extends UnlistedSpecialPage { Html::hidden( 'returnto', $this->getRequest()->getVal( 'returnto' ) ) . "\n" . $this->msg( 'resetpass_text' )->parseAsBlock() . "\n" . Xml::openElement( 'table', array( 'id' => 'mw-resetpass-table' ) ) . "\n" . - $this->pretty( array( - array( 'wpName', 'username', 'text', $this->mUserName ), - array( 'wpPassword', $oldpassMsg, 'password', $this->mOldpass ), - array( 'wpNewPassword', 'newpassword', 'password', null ), - array( 'wpRetype', 'retypenew', 'password', null ), - ) ) . "\n" . + $this->pretty( $prettyFields ) . "\n" . $rememberMe . "<tr>\n" . "<td></td>\n" . diff --git a/includes/specials/SpecialConfirmemail.php b/includes/specials/SpecialConfirmemail.php index 912f7733..3e9ce128 100644 --- a/includes/specials/SpecialConfirmemail.php +++ b/includes/specials/SpecialConfirmemail.php @@ -110,7 +110,7 @@ class EmailConfirmation extends UnlistedSpecialPage { * Attempt to confirm the user's email address and show success or failure * as needed; if successful, take the user to log in * - * @param $code Confirmation code + * @param $code string Confirmation code */ function attemptConfirm( $code ) { $user = User::newFromConfirmationCode( $code ); @@ -156,7 +156,7 @@ class EmailInvalidation extends UnlistedSpecialPage { * Attempt to invalidate the user's email address and show success or failure * as needed; if successful, link to main page * - * @param $code Confirmation code + * @param $code string Confirmation code */ function attemptInvalidate( $code ) { $user = User::newFromConfirmationCode( $code ); diff --git a/includes/specials/SpecialContributions.php b/includes/specials/SpecialContributions.php index 31df4a9b..54f8e261 100644 --- a/includes/specials/SpecialContributions.php +++ b/includes/specials/SpecialContributions.php @@ -44,10 +44,7 @@ class SpecialContributions extends SpecialPage { $this->opts = array(); $request = $this->getRequest(); - if ( $par == 'newbies' ) { - $target = 'newbies'; - $this->opts['contribs'] = 'newbie'; - } elseif ( $par !== null ) { + if ( $par !== null ) { $target = $par; } else { $target = $request->getVal( 'target' ); @@ -57,6 +54,9 @@ class SpecialContributions extends SpecialPage { if ( $request->getVal( 'contribs' ) == 'newbie' ) { $target = 'newbies'; $this->opts['contribs'] = 'newbie'; + } elseif ( $par === 'newbies' ) { // b/c for WMF + $target = 'newbies'; + $this->opts['contribs'] = 'newbie'; } else { $this->opts['contribs'] = 'user'; } @@ -192,18 +192,20 @@ class SpecialContributions extends SpecialPage { } $out->preventClickjacking( $pager->getPreventClickjacking() ); + # Show the appropriate "footer" message - WHOIS tools, etc. - if ( $this->opts['contribs'] != 'newbie' ) { + if ( $this->opts['contribs'] == 'newbie' ) { + $message = 'sp-contributions-footer-newbies'; + } elseif( IP::isIPAddress( $target ) ) { + $message = 'sp-contributions-footer-anon'; + } elseif( $userObj->isAnon() ) { + // No message for non-existing users + $message = ''; + } else { $message = 'sp-contributions-footer'; - if ( IP::isIPAddress( $target ) ) { - $message = 'sp-contributions-footer-anon'; - } else { - if ( $userObj->isAnon() ) { - // No message for non-existing users - return; - } - } + } + if( $message ) { if ( !$this->msg( $message, $target )->isDisabled() ) { $out->wrapWikiMsg( "<div class='mw-contributions-footer'>\n$1\n</div>", @@ -227,12 +229,15 @@ class SpecialContributions extends SpecialPage { } $nt = $userObj->getUserPage(); $talk = $userObj->getTalkPage(); + $links = ''; if ( $talk ) { $tools = $this->getUserLinks( $nt, $talk, $userObj ); $links = $this->getLanguage()->pipeList( $tools ); // Show a note if the user is blocked and display the last block log entry. - if ( $userObj->isBlocked() ) { + // Do not expose the autoblocks, since that may lead to a leak of accounts' IPs, + // and also this will display a totally irrelevant log entry as a current block. + if ( $userObj->isBlocked() && $userObj->getBlock()->getType() != Block::TYPE_AUTO ) { $out = $this->getOutput(); // showLogExtract() wants first parameter by reference LogEventsList::showLogExtract( $out, @@ -258,9 +263,11 @@ class SpecialContributions extends SpecialPage { // languages that want to put the "for" bit right after $user but before // $links. If 'contribsub' is around, use it for reverse compatibility, // otherwise use 'contribsub2'. + // @todo Should this be removed at some point? $oldMsg = $this->msg( 'contribsub' ); if ( $oldMsg->exists() ) { - return $oldMsg->rawParams( "$user ($links)" ); + $linksWithParentheses = $this->msg( 'parentheses' )->rawParams( $links )->escaped(); + return $oldMsg->rawParams( "$user $linksWithParentheses" ); } else { return $this->msg( 'contribsub2' )->rawParams( $user, $links ); } @@ -331,7 +338,7 @@ class SpecialContributions extends SpecialPage { # Add a link to change user rights for privileged users $userrightsPage = new UserrightsPage(); $userrightsPage->setContext( $this->getContext() ); - if ( $id !== null && $userrightsPage->userCanChangeRights( $target ) ) { + if ( $userrightsPage->userCanChangeRights( $target ) ) { $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Userrights', $username ), $this->msg( 'sp-contributions-userrights' )->escaped() @@ -434,7 +441,7 @@ class SpecialContributions extends SpecialPage { 'target', $this->opts['target'], 'text', - array( 'size' => '20', 'required' => '', 'class' => 'mw-input' ) + + array( 'size' => '40', 'required' => '', 'class' => 'mw-input' ) + ( $this->opts['target'] ? array() : array( 'autofocus' ) ) ) . ' ' @@ -449,7 +456,15 @@ class SpecialContributions extends SpecialPage { ) ) . Xml::tags( 'td', null, - Xml::namespaceSelector( $this->opts['namespace'], '' ) . ' ' . + Html::namespaceSelector( array( + 'selected' => $this->opts['namespace'], + 'all' => '', + ), array( + 'name' => 'namespace', + 'id' => 'namespace', + 'class' => 'namespaceselector', + ) ) . + ' ' . Html::rawElement( 'span', array( 'style' => 'white-space: nowrap' ), Xml::checkLabel( $this->msg( 'invert' )->text(), @@ -542,6 +557,11 @@ class ContribsPager extends ReverseChronologicalPager { var $namespace = '', $mDb; var $preventClickjacking = false; + /** + * @var array + */ + protected $mParentLens; + function __construct( IContextSource $context, array $options ) { parent::__construct( $context ); @@ -574,6 +594,66 @@ class ContribsPager extends ReverseChronologicalPager { return $query; } + /** + * This method basically executes the exact same code as the parent class, though with + * a hook added, to allow extentions to add additional queries. + * + * @param $offset String: index offset, inclusive + * @param $limit Integer: exact query limit + * @param $descending Boolean: query direction, false for ascending, true for descending + * @return ResultWrapper + */ + function reallyDoQuery( $offset, $limit, $descending ) { + list( $tables, $fields, $conds, $fname, $options, $join_conds ) = $this->buildQueryInfo( $offset, $limit, $descending ); + $pager = $this; + + /* + * This hook will allow extensions to add in additional queries, so they can get their data + * in My Contributions as well. Extensions should append their results to the $data array. + * + * Extension queries have to implement the navbar requirement as well. They should + * - have a column aliased as $pager->getIndexField() + * - have LIMIT set + * - have a WHERE-clause that compares the $pager->getIndexField()-equivalent column to the offset + * - have the ORDER BY specified based upon the details provided by the navbar + * + * See includes/Pager.php buildQueryInfo() method on how to build LIMIT, WHERE & ORDER BY + * + * &$data: an array of results of all contribs queries + * $pager: the ContribsPager object hooked into + * $offset: see phpdoc above + * $limit: see phpdoc above + * $descending: see phpdoc above + */ + $data = array( $this->mDb->select( $tables, $fields, $conds, $fname, $options, $join_conds ) ); + wfRunHooks( 'ContribsPager::reallyDoQuery', array( &$data, $pager, $offset, $limit, $descending ) ); + + $result = array(); + + // loop all results and collect them in an array + foreach ( $data as $j => $query ) { + foreach ( $query as $i => $row ) { + // use index column as key, allowing us to easily sort in PHP + $result[$row->{$this->getIndexField()} . "-$i"] = $row; + } + } + + // sort results + if ( $descending ) { + ksort( $result ); + } else { + krsort( $result ); + } + + // enforce limit + $result = array_slice( $result, 0, $limit ); + + // get rid of array keys + $result = array_values( $result ); + + return new FakeResultWrapper( $result ); + } + function getQueryInfo() { list( $tables, $index, $userCond, $join_cond ) = $this->getUserCond(); @@ -624,20 +704,30 @@ class ContribsPager extends ReverseChronologicalPager { $join_conds = array(); $tables = array( 'revision', 'page', 'user' ); if ( $this->contribs == 'newbie' ) { - $tables[] = 'user_groups'; $max = $this->mDb->selectField( 'user', 'max(user_id)', false, __METHOD__ ); $condition[] = 'rev_user >' . (int)( $max - $max / 100 ); - $condition[] = 'ug_group IS NULL'; $index = 'user_timestamp'; - # @todo FIXME: Other groups may have 'bot' rights - $join_conds['user_groups'] = array( 'LEFT JOIN', "ug_user = rev_user AND ug_group = 'bot'" ); + # ignore local groups with the bot right + # @todo FIXME: Global groups may have 'bot' rights + $groupsWithBotPermission = User::getGroupsWithPermission( 'bot' ); + if( count( $groupsWithBotPermission ) ) { + $tables[] = 'user_groups'; + $condition[] = 'ug_group IS NULL'; + $join_conds['user_groups'] = array( + 'LEFT JOIN', array( + 'ug_user = rev_user', + 'ug_group' => $groupsWithBotPermission + ) + ); + } } else { - if ( IP::isIPAddress( $this->target ) ) { + $uid = User::idFromName( $this->target ); + if ( $uid ) { + $condition['rev_user'] = $uid; + $index = 'user_timestamp'; + } else { $condition['rev_user_text'] = $this->target; $index = 'usertext_timestamp'; - } else { - $condition['rev_user'] = User::idFromName( $this->target ); - $index = 'user_timestamp'; } } if ( $this->deletedOnly ) { @@ -678,52 +768,29 @@ class ContribsPager extends ReverseChronologicalPager { } function doBatchLookups() { - $this->mResult->rewind(); - $revIds = array(); - foreach ( $this->mResult as $row ) { - if( $row->rev_parent_id ) { - $revIds[] = $row->rev_parent_id; - } - } - $this->mParentLens = $this->getParentLengths( $revIds ); - $this->mResult->rewind(); // reset - # Do a link batch query $this->mResult->seek( 0 ); + $revIds = array(); $batch = new LinkBatch(); # Give some pointers to make (last) links foreach ( $this->mResult as $row ) { - if ( $this->contribs === 'newbie' ) { // multiple users - $batch->add( NS_USER, $row->user_name ); - $batch->add( NS_USER_TALK, $row->user_name ); + if( isset( $row->rev_parent_id ) && $row->rev_parent_id ) { + $revIds[] = $row->rev_parent_id; + } + if ( isset( $row->rev_id ) ) { + if ( $this->contribs === 'newbie' ) { // multiple users + $batch->add( NS_USER, $row->user_name ); + $batch->add( NS_USER_TALK, $row->user_name ); + } + $batch->add( $row->page_namespace, $row->page_title ); } - $batch->add( $row->page_namespace, $row->page_title ); } + $this->mParentLens = Revision::getParentLengths( $this->getDatabase(), $revIds ); $batch->execute(); $this->mResult->seek( 0 ); } /** - * Do a batched query to get the parent revision lengths - */ - private function getParentLengths( array $revIds ) { - $revLens = array(); - if ( !$revIds ) { - return $revLens; // empty - } - wfProfileIn( __METHOD__ ); - $res = $this->getDatabase()->select( 'revision', - array( 'rev_id', 'rev_len' ), - array( 'rev_id' => $revIds ), - __METHOD__ ); - foreach ( $res as $row ) { - $revLens[$row->rev_id] = $row->rev_len; - } - wfProfileOut( __METHOD__ ); - return $revLens; - } - - /** * @return string */ function getStartBody() { @@ -746,142 +813,153 @@ class ContribsPager extends ReverseChronologicalPager { * was not written by the target user. * * @todo This would probably look a lot nicer in a table. + * @param $row + * @return string */ function formatRow( $row ) { wfProfileIn( __METHOD__ ); - $rev = new Revision( $row ); + $ret = ''; $classes = array(); - $page = Title::newFromRow( $row ); - $link = Linker::link( - $page, - htmlspecialchars( $page->getPrefixedText() ), - array(), - $page->isRedirect() ? array( 'redirect' => 'no' ) : array() - ); - # Mark current revisions - $topmarktext = ''; - if ( $row->rev_id == $row->page_latest ) { - $topmarktext .= '<span class="mw-uctop">' . $this->messages['uctop'] . '</span>'; - # Add rollback link - if ( !$row->page_is_new && $page->quickUserCan( 'rollback' ) - && $page->quickUserCan( 'edit' ) ) - { - $this->preventClickjacking(); - $topmarktext .= ' ' . Linker::generateRollback( $rev ); + /* + * There may be more than just revision rows. To make sure that we'll only be processing + * revisions here, let's _try_ to build a revision out of our row (without displaying + * notices though) and then trying to grab data from the built object. If we succeed, + * we're definitely dealing with revision data and we may proceed, if not, we'll leave it + * to extensions to subscribe to the hook to parse the row. + */ + wfSuppressWarnings(); + $rev = new Revision( $row ); + $validRevision = $rev->getParentId() !== null; + wfRestoreWarnings(); + + if ( $validRevision ) { + $classes = array(); + + $page = Title::newFromRow( $row ); + $link = Linker::link( + $page, + htmlspecialchars( $page->getPrefixedText() ), + array( 'class' => 'mw-contributions-title' ), + $page->isRedirect() ? array( 'redirect' => 'no' ) : array() + ); + # Mark current revisions + $topmarktext = ''; + $user = $this->getUser(); + if ( $row->rev_id == $row->page_latest ) { + $topmarktext .= '<span class="mw-uctop">' . $this->messages['uctop'] . '</span>'; + # Add rollback link + if ( !$row->page_is_new && $page->quickUserCan( 'rollback', $user ) + && $page->quickUserCan( 'edit', $user ) ) + { + $this->preventClickjacking(); + $topmarktext .= ' ' . Linker::generateRollback( $rev, $this->getContext() ); + } } - } - $user = $this->getUser(); - # Is there a visible previous revision? - if ( $rev->userCan( Revision::DELETED_TEXT, $user ) && $rev->getParentId() !== 0 ) { - $difftext = Linker::linkKnown( + # Is there a visible previous revision? + if ( $rev->userCan( Revision::DELETED_TEXT, $user ) && $rev->getParentId() !== 0 ) { + $difftext = Linker::linkKnown( + $page, + $this->messages['diff'], + array(), + array( + 'diff' => 'prev', + 'oldid' => $row->rev_id + ) + ); + } else { + $difftext = $this->messages['diff']; + } + $histlink = Linker::linkKnown( $page, - $this->messages['diff'], + $this->messages['hist'], array(), - array( - 'diff' => 'prev', - 'oldid' => $row->rev_id - ) + array( 'action' => 'history' ) ); - } else { - $difftext = $this->messages['diff']; - } - $histlink = Linker::linkKnown( - $page, - $this->messages['hist'], - array(), - array( 'action' => 'history' ) - ); - if ( $row->rev_parent_id === null ) { - // For some reason rev_parent_id isn't populated for this row. - // Its rumoured this is true on wikipedia for some revisions (bug 34922). - // Next best thing is to have the total number of bytes. - $chardiff = ' . . ' . Linker::formatRevisionSize( $row->rev_len ) . ' . . '; - } else { - $parentLen = isset( $this->mParentLens[$row->rev_parent_id] ) ? $this->mParentLens[$row->rev_parent_id] : 0; - $chardiff = ' . . ' . ChangesList::showCharacterDifference( - $parentLen, $row->rev_len ) . ' . . '; - } + if ( $row->rev_parent_id === null ) { + // For some reason rev_parent_id isn't populated for this row. + // Its rumoured this is true on wikipedia for some revisions (bug 34922). + // Next best thing is to have the total number of bytes. + $chardiff = ' <span class="mw-changeslist-separator">. .</span> ' . Linker::formatRevisionSize( $row->rev_len ) . ' <span class="mw-changeslist-separator">. .</span> '; + } else { + $parentLen = isset( $this->mParentLens[$row->rev_parent_id] ) ? $this->mParentLens[$row->rev_parent_id] : 0; + $chardiff = ' <span class="mw-changeslist-separator">. .</span> ' . ChangesList::showCharacterDifference( + $parentLen, $row->rev_len, $this->getContext() ) . ' <span class="mw-changeslist-separator">. .</span> '; + } - $lang = $this->getLanguage(); - $comment = $lang->getDirMark() . Linker::revComment( $rev, false, true ); - $date = $lang->userTimeAndDate( $row->rev_timestamp, $user ); - if ( $rev->userCan( Revision::DELETED_TEXT, $user ) ) { - $d = Linker::linkKnown( - $page, - htmlspecialchars( $date ), - array(), - array( 'oldid' => intval( $row->rev_id ) ) - ); - } else { - $d = htmlspecialchars( $date ); - } - if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) { - $d = '<span class="history-deleted">' . $d . '</span>'; - } + $lang = $this->getLanguage(); + $comment = $lang->getDirMark() . Linker::revComment( $rev, false, true ); + $date = $lang->userTimeAndDate( $row->rev_timestamp, $user ); + if ( $rev->userCan( Revision::DELETED_TEXT, $user ) ) { + $d = Linker::linkKnown( + $page, + htmlspecialchars( $date ), + array( 'class' => 'mw-changeslist-date' ), + array( 'oldid' => intval( $row->rev_id ) ) + ); + } else { + $d = htmlspecialchars( $date ); + } + if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) { + $d = '<span class="history-deleted">' . $d . '</span>'; + } - # Show user names for /newbies as there may be different users. - # Note that we already excluded rows with hidden user names. - if ( $this->contribs == 'newbie' ) { - $userlink = ' . . ' . Linker::userLink( $rev->getUser(), $rev->getUserText() ); - $userlink .= ' ' . $this->msg( 'parentheses' )->rawParams( - Linker::userTalkLink( $rev->getUser(), $rev->getUserText() ) )->escaped() . ' '; - } else { - $userlink = ''; - } + # Show user names for /newbies as there may be different users. + # Note that we already excluded rows with hidden user names. + if ( $this->contribs == 'newbie' ) { + $userlink = ' . . ' . Linker::userLink( $rev->getUser(), $rev->getUserText() ); + $userlink .= ' ' . $this->msg( 'parentheses' )->rawParams( + Linker::userTalkLink( $rev->getUser(), $rev->getUserText() ) )->escaped() . ' '; + } else { + $userlink = ''; + } - if ( $rev->getParentId() === 0 ) { - $nflag = ChangesList::flag( 'newpage' ); - } else { - $nflag = ''; - } + if ( $rev->getParentId() === 0 ) { + $nflag = ChangesList::flag( 'newpage' ); + } else { + $nflag = ''; + } - if ( $rev->isMinor() ) { - $mflag = ChangesList::flag( 'minor' ); - } else { - $mflag = ''; - } + if ( $rev->isMinor() ) { + $mflag = ChangesList::flag( 'minor' ); + } else { + $mflag = ''; + } - $del = Linker::getRevDeleteLink( $user, $rev, $page ); - if ( $del !== '' ) { - $del .= ' '; - } + $del = Linker::getRevDeleteLink( $user, $rev, $page ); + if ( $del !== '' ) { + $del .= ' '; + } - $diffHistLinks = '(' . $difftext . $this->messages['pipe-separator'] . $histlink . ')'; - $ret = "{$del}{$d} {$diffHistLinks}{$chardiff}{$nflag}{$mflag} {$link}{$userlink} {$comment} {$topmarktext}"; + $diffHistLinks = $this->msg( 'parentheses' )->rawParams( $difftext . $this->messages['pipe-separator'] . $histlink )->escaped(); + $ret = "{$del}{$d} {$diffHistLinks}{$chardiff}{$nflag}{$mflag} {$link}{$userlink} {$comment} {$topmarktext}"; - # Denote if username is redacted for this edit - if ( $rev->isDeleted( Revision::DELETED_USER ) ) { - $ret .= " <strong>" . $this->msg( 'rev-deleted-user-contribs' )->escaped() . "</strong>"; - } + # Denote if username is redacted for this edit + if ( $rev->isDeleted( Revision::DELETED_USER ) ) { + $ret .= " <strong>" . $this->msg( 'rev-deleted-user-contribs' )->escaped() . "</strong>"; + } - # Tags, if any. - list( $tagSummary, $newClasses ) = ChangeTags::formatSummaryRow( $row->ts_tags, 'contributions' ); - $classes = array_merge( $classes, $newClasses ); - $ret .= " $tagSummary"; + # Tags, if any. + list( $tagSummary, $newClasses ) = ChangeTags::formatSummaryRow( $row->ts_tags, 'contributions' ); + $classes = array_merge( $classes, $newClasses ); + $ret .= " $tagSummary"; + } // Let extensions add data - wfRunHooks( 'ContributionsLineEnding', array( &$this, &$ret, $row ) ); + wfRunHooks( 'ContributionsLineEnding', array( $this, &$ret, $row, &$classes ) ); $classes = implode( ' ', $classes ); $ret = "<li class=\"$classes\">$ret</li>\n"; + wfProfileOut( __METHOD__ ); return $ret; } /** - * Get the Database object in use - * - * @return DatabaseBase - */ - public function getDatabase() { - return $this->mDb; - } - - /** * Overwrite Pager function and return a helpful comment + * @return string */ function getSqlComment() { if ( $this->namespace || $this->deletedOnly ) { @@ -895,6 +973,9 @@ class ContribsPager extends ReverseChronologicalPager { $this->preventClickjacking = true; } + /** + * @return bool + */ public function getPreventClickjacking() { return $this->preventClickjacking; } diff --git a/includes/specials/SpecialDeadendpages.php b/includes/specials/SpecialDeadendpages.php index 1266a0ce..f4904a50 100644 --- a/includes/specials/SpecialDeadendpages.php +++ b/includes/specials/SpecialDeadendpages.php @@ -39,7 +39,7 @@ class DeadendPagesPage extends PageQueryPage { /** * LEFT JOIN is expensive * - * @return true + * @return bool */ function isExpensive() { return true; @@ -50,7 +50,7 @@ class DeadendPagesPage extends PageQueryPage { } /** - * @return false + * @return bool */ function sortDescending() { return false; @@ -59,9 +59,9 @@ class DeadendPagesPage extends PageQueryPage { function getQueryInfo() { return array( 'tables' => array( 'page', 'pagelinks' ), - 'fields' => array( 'page_namespace AS namespace', - 'page_title AS title', - 'page_title AS value' + 'fields' => array( 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'page_title' ), 'conds' => array( 'pl_from IS NULL', 'page_namespace' => MWNamespace::getContentNamespaces(), diff --git a/includes/specials/SpecialDeletedContributions.php b/includes/specials/SpecialDeletedContributions.php index 3498a16d..c880b617 100644 --- a/includes/specials/SpecialDeletedContributions.php +++ b/includes/specials/SpecialDeletedContributions.php @@ -25,7 +25,6 @@ * Implements Special:DeletedContributions to display archived revisions * @ingroup SpecialPage */ - class DeletedContribsPager extends IndexPager { public $mDefaultDirection = true; var $messages, $target; @@ -54,9 +53,9 @@ class DeletedContribsPager extends IndexPager { $user = $this->getUser(); // Paranoia: avoid brute force searches (bug 17792) if( !$user->isAllowed( 'deletedhistory' ) ) { - $conds[] = $this->mDb->bitAnd('ar_deleted',Revision::DELETED_USER) . ' = 0'; + $conds[] = $this->mDb->bitAnd( 'ar_deleted', Revision::DELETED_USER ) . ' = 0'; } elseif( !$user->isAllowed( 'suppressrevision' ) ) { - $conds[] = $this->mDb->bitAnd('ar_deleted',Revision::SUPPRESSED_USER) . + $conds[] = $this->mDb->bitAnd( 'ar_deleted', Revision::SUPPRESSED_USER ) . ' != ' . Revision::SUPPRESSED_USER; } return array( @@ -95,17 +94,17 @@ class DeletedContribsPager extends IndexPager { if ( isset( $this->mNavigationBar ) ) { return $this->mNavigationBar; } - $lang = $this->getLanguage(); - $fmtLimit = $lang->formatNum( $this->mLimit ); + $linkTexts = array( - 'prev' => $this->msg( 'pager-newer-n', $fmtLimit )->escaped(), - 'next' => $this->msg( 'pager-older-n', $fmtLimit )->escaped(), + 'prev' => $this->msg( 'pager-newer-n' )->numParams( $this->mLimit )->escaped(), + 'next' => $this->msg( 'pager-older-n' )->numParams( $this->mLimit )->escaped(), 'first' => $this->msg( 'histlast' )->escaped(), 'last' => $this->msg( 'histfirst' )->escaped() ); $pagingLinks = $this->getPagingLinks( $linkTexts ); $limitLinks = $this->getLimitLinks(); + $lang = $this->getLanguage(); $limits = $lang->pipeList( $limitLinks ); $this->mNavigationBar = "(" . $lang->pipeList( array( $pagingLinks['first'], $pagingLinks['last'] ) ) . ") " . @@ -130,6 +129,8 @@ class DeletedContribsPager extends IndexPager { * written by the target user. * * @todo This would probably look a lot nicer in a table. + * @param $row + * @return string */ function formatRow( $row ) { wfProfileIn( __METHOD__ ); @@ -190,7 +191,7 @@ class DeletedContribsPager extends IndexPager { $link = Linker::linkKnown( $undelete, $date, - array(), + array( 'class' => 'mw-changeslist-date' ), array( 'target' => $page->getPrefixedText(), 'timestamp' => $rev->getTimestamp() @@ -202,7 +203,11 @@ class DeletedContribsPager extends IndexPager { $link = '<span class="history-deleted">' . $link . '</span>'; } - $pagelink = Linker::link( $page ); + $pagelink = Linker::link( + $page, + null, + array( 'class' => 'mw-changeslist-title' ) + ); if( $rev->isMinor() ) { $mflag = ChangesList::flag( 'minor' ); @@ -221,7 +226,8 @@ class DeletedContribsPager extends IndexPager { array( $last, $dellog, $reviewlink ) ) )->escaped() ); - $ret = "{$del}{$link} {$tools} . . {$mflag} {$pagelink} {$comment}"; + $separator = '<span class="mw-changeslist-separator">. .</span>'; + $ret = "{$del}{$link} {$tools} {$separator} {$mflag} {$pagelink} {$comment}"; # Denote if username is redacted for this edit if( $rev->isDeleted( Revision::DELETED_USER ) ) { @@ -237,7 +243,7 @@ class DeletedContribsPager extends IndexPager { /** * Get the Database object in use * - * @return Database + * @return DatabaseBase */ public function getDatabase() { return $this->mDb; @@ -254,12 +260,12 @@ class DeletedContributionsPage extends SpecialPage { * Special page "deleted user contributions". * Shows a list of the deleted contributions of a user. * - * @return none * @param $par String: (optional) user name of the user for which to show the contributions */ function execute( $par ) { global $wgQueryPageDefaultLimit; $this->setHeaders(); + $this->outputHeader(); $user = $this->getUser(); @@ -293,6 +299,7 @@ class DeletedContributionsPage extends SpecialPage { $out->addHTML( $this->getForm( '' ) ); return; } + $this->getSkin()->setRelevantUser( $userObj ); $target = $userObj->getName(); $out->addSubtitle( $this->getSubTitle( $userObj ) ); @@ -346,6 +353,7 @@ class DeletedContributionsPage extends SpecialPage { } else { $user = Linker::link( $userObj->getUserPage(), htmlspecialchars( $userObj->getName() ) ); } + $links = ''; $nt = $userObj->getUserPage(); $id = $userObj->getID(); $talk = $nt->getTalkPage(); @@ -387,6 +395,13 @@ class DeletedContributionsPage extends SpecialPage { ) ); } + + # Uploads + $tools[] = Linker::linkKnown( + SpecialPage::getTitleFor( 'Listfiles', $userObj->getName() ), + $this->msg( 'sp-contributions-uploads' )->escaped() + ); + # Other logs link $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Log' ), @@ -403,7 +418,7 @@ class DeletedContributionsPage extends SpecialPage { # Add a link to change user rights for privileged users $userrightsPage = new UserrightsPage(); $userrightsPage->setContext( $this->getContext() ); - if( $id !== null && $userrightsPage->userCanChangeRights( User::newFromId( $id ) ) ) { + if( $userrightsPage->userCanChangeRights( $userObj ) ) { $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Userrights', $nt->getDBkey() ), $this->msg( 'sp-contributions-userrights' )->escaped() @@ -450,6 +465,7 @@ class DeletedContributionsPage extends SpecialPage { /** * Generates the namespace selector form with hidden attributes. * @param $options Array: the options to be included. + * @return string */ function getForm( $options ) { global $wgScript; @@ -489,8 +505,17 @@ class DeletedContributionsPage extends SpecialPage { 'size' => '20', 'required' => '' ) + ( $options['target'] ? array() : array( 'autofocus' ) ) ) . ' '. - Xml::label( $this->msg( 'namespace' )->text(), 'namespace' ) . ' ' . - Xml::namespaceSelector( $options['namespace'], '' ) . ' ' . + Html::namespaceSelector( + array( + 'selected' => $options['namespace'], + 'all' => '', + 'label' => $this->msg( 'namespace' )->text() + ), array( + 'name' => 'namespace', + 'id' => 'namespace', + 'class' => 'namespaceselector', + ) + ) . ' ' . Xml::submitButton( $this->msg( 'sp-contributions-submit' )->text() ) . Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' ); diff --git a/includes/specials/SpecialDisambiguations.php b/includes/specials/SpecialDisambiguations.php index 2b05fb6b..48180a77 100644 --- a/includes/specials/SpecialDisambiguations.php +++ b/includes/specials/SpecialDisambiguations.php @@ -26,27 +26,35 @@ * * @ingroup SpecialPage */ -class DisambiguationsPage extends PageQueryPage { +class DisambiguationsPage extends QueryPage { function __construct( $name = 'Disambiguations' ) { parent::__construct( $name ); } - function isExpensive() { return true; } - function isSyndicated() { return false; } + function isExpensive() { + return true; + } + + function isSyndicated() { + return false; + } function getPageHeader() { return $this->msg( 'disambiguations-text' )->parseAsBlock(); } - function getQueryInfo() { + /** + * @return string|bool False on failure + */ + function getQueryFromLinkBatch() { $dbr = wfGetDB( DB_SLAVE ); $dMsgText = $this->msg( 'disambiguationspage' )->inContentLanguage()->text(); $linkBatch = new LinkBatch; # If the text can be treated as a title, use it verbatim. # Otherwise, pull the titles from the links table - $dp = Title::newFromText($dMsgText); + $dp = Title::newFromText( $dMsgText ); if( $dp ) { if( $dp->getNamespace() != NS_TEMPLATE ) { # @todo FIXME: We assume the disambiguation message is a template but @@ -71,25 +79,38 @@ class DisambiguationsPage extends PageQueryPage { } } $set = $linkBatch->constructSet( 'tl', $dbr ); + if( $set === false ) { # We must always return a valid SQL query, but this way # the DB will always quickly return an empty result $set = 'FALSE'; - wfDebug("Mediawiki:disambiguationspage message does not link to any templates!\n"); + wfDebug( "Mediawiki:disambiguationspage message does not link to any templates!\n" ); } + return $set; + } + function getQueryInfo() { // @todo FIXME: What are pagelinks and p2 doing here? return array ( - 'tables' => array( 'templatelinks', 'p1' => 'page', 'pagelinks', 'p2' => 'page' ), - 'fields' => array( 'p1.page_namespace AS namespace', - 'p1.page_title AS title', - 'pl_from AS value' ), - 'conds' => array( $set, - 'p1.page_id = tl_from', - 'pl_namespace = p1.page_namespace', - 'pl_title = p1.page_title', - 'p2.page_id = pl_from', - 'p2.page_namespace' => MWNamespace::getContentNamespaces() ) + 'tables' => array( + 'templatelinks', + 'p1' => 'page', + 'pagelinks', + 'p2' => 'page' + ), + 'fields' => array( + 'namespace' => 'p1.page_namespace', + 'title' => 'p1.page_title', + 'value' => 'pl_from' + ), + 'conds' => array( + $this->getQueryFromLinkBatch(), + 'p1.page_id = tl_from', + 'pl_namespace = p1.page_namespace', + 'pl_title = p1.page_title', + 'p2.page_id = pl_from', + 'p2.page_namespace' => MWNamespace::getContentNamespaces() + ) ); } @@ -108,17 +129,17 @@ class DisambiguationsPage extends PageQueryPage { * @param $res */ function preprocessResults( $db, $res ) { + if ( !$res->numRows() ) { + return; + } + $batch = new LinkBatch; foreach ( $res as $row ) { $batch->add( $row->namespace, $row->title ); } $batch->execute(); - // Back to start for display - if ( $db->numRows( $res ) > 0 ) { - // If there are no rows we get an error seeking. - $db->dataSeek( $res, 0 ); - } + $res->seek( 0 ); } function formatResult( $skin, $result ) { @@ -126,10 +147,14 @@ class DisambiguationsPage extends PageQueryPage { $dp = Title::makeTitle( $result->namespace, $result->title ); $from = Linker::link( $title ); - $edit = Linker::link( $title, $this->msg( 'parentheses', $this->msg( 'editlink' )->text() )->escaped(), - array(), array( 'redirect' => 'no', 'action' => 'edit' ) ); - $arr = $this->getLanguage()->getArrow(); - $to = Linker::link( $dp ); + $edit = Linker::link( + $title, + $this->msg( 'parentheses', $this->msg( 'editlink' )->text() )->escaped(), + array(), + array( 'redirect' => 'no', 'action' => 'edit' ) + ); + $arr = $this->getLanguage()->getArrow(); + $to = Linker::link( $dp ); return "$from $edit $arr $to"; } diff --git a/includes/specials/SpecialDoubleRedirects.php b/includes/specials/SpecialDoubleRedirects.php index a6df66f6..5864ca9f 100644 --- a/includes/specials/SpecialDoubleRedirects.php +++ b/includes/specials/SpecialDoubleRedirects.php @@ -27,7 +27,7 @@ * * @ingroup SpecialPage */ -class DoubleRedirectsPage extends PageQueryPage { +class DoubleRedirectsPage extends QueryPage { function __construct( $name = 'DoubleRedirects' ) { parent::__construct( $name ); @@ -47,13 +47,13 @@ class DoubleRedirectsPage extends PageQueryPage { 'tables' => array ( 'ra' => 'redirect', 'rb' => 'redirect', 'pa' => 'page', 'pb' => 'page', 'pc' => 'page' ), - 'fields' => array ( 'pa.page_namespace AS namespace', - 'pa.page_title AS title', - 'pa.page_title AS value', - 'pb.page_namespace AS nsb', - 'pb.page_title AS tb', - 'pc.page_namespace AS nsc', - 'pc.page_title AS tc' ), + 'fields' => array ( 'namespace' => 'pa.page_namespace', + 'title' => 'pa.page_title', + 'value' => 'pa.page_title', + 'nsb' => 'pb.page_namespace', + 'tb' => 'pb.page_title', + 'nsc' => 'pc.page_namespace', + 'tc' => 'pc.page_title' ), 'conds' => array ( 'ra.rd_from = pa.page_id', 'pb.page_namespace = ra.rd_namespace', 'pb.page_title = ra.rd_title', diff --git a/includes/specials/SpecialEditWatchlist.php b/includes/specials/SpecialEditWatchlist.php index 9c9689ae..23cd9aa6 100644 --- a/includes/specials/SpecialEditWatchlist.php +++ b/includes/specials/SpecialEditWatchlist.php @@ -1,9 +1,36 @@ <?php +/** + * @defgroup Watchlist Users watchlist handling + */ + +/** + * Implements Special:EditWatchlist + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + * @ingroup SpecialPage + * @ingroup Watchlist + */ /** * Provides the UI through which users can perform editing * operations on their watchlist * + * @ingroup SpecialPage * @ingroup Watchlist * @author Rob Church <robchur@gmail.com> */ @@ -76,7 +103,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { $form = $this->getRawForm(); if( $form->show() ){ $out->addHTML( $this->successMessage ); - $out->returnToMain(); + $out->addReturnTo( SpecialPage::getTitleFor( 'Watchlist' ) ); } break; @@ -86,7 +113,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { $form = $this->getNormalForm(); if( $form->show() ){ $out->addHTML( $this->successMessage ); - $out->returnToMain(); + $out->addReturnTo( SpecialPage::getTitleFor( 'Watchlist' ) ); } elseif ( $this->toc !== false ) { $out->prependHTML( $this->toc ); } @@ -102,21 +129,28 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { * @return array */ private function extractTitles( $list ) { - $titles = array(); $list = explode( "\n", trim( $list ) ); if( !is_array( $list ) ) { return array(); } + $titles = array(); foreach( $list as $text ) { $text = trim( $text ); if( strlen( $text ) > 0 ) { $title = Title::newFromText( $text ); if( $title instanceof Title && $title->isWatchable() ) { - $titles[] = $title->getPrefixedText(); + $titles[] = $title; } } } - return array_unique( $titles ); + + GenderCache::singleton()->doTitlesArray( $titles ); + + $list = array(); + foreach( $titles as $title ) { + $list[] = $title->getPrefixedText(); + } + return array_unique( $list ); } public function submitRaw( $data ){ @@ -214,22 +248,30 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { $dbr = wfGetDB( DB_MASTER ); $res = $dbr->select( 'watchlist', - '*', array( + 'wl_namespace', 'wl_title' + ), array( 'wl_user' => $this->getUser()->getId(), ), __METHOD__ ); 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() ) { - $list[] = $title->getPrefixedText(); + $titles[] = $title; } } $res->free(); + + GenderCache::singleton()->doTitlesArray( $titles ); + + foreach( $titles as $title ) { + $list[] = $title->getPrefixedText(); + } } $this->cleanupWatchlist(); return $list; @@ -250,7 +292,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { array( 'wl_namespace', 'wl_title' ), array( 'wl_user' => $this->getUser()->getId() ), __METHOD__, - array( 'ORDER BY' => 'wl_namespace, wl_title' ) + array( 'ORDER BY' => array( 'wl_namespace', 'wl_title' ) ) ); $lb = new LinkBatch(); @@ -270,7 +312,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 ) { @@ -294,18 +336,20 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { * Attempts to clean up broken items */ private function cleanupWatchlist() { - if ( count( $this->badItems ) ) { - $dbw = wfGetDB( DB_MASTER ); + 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 {$this->getUser()} has broken watchlist item ns($namespace):$dbKey, " + wfDebug( "User {$user->getName()} has broken watchlist item ns($namespace):$dbKey, " . ( $title ? 'cleaning up' : 'deleting' ) . ".\n" ); $dbw->delete( 'watchlist', array( - 'wl_user' => $this->getUser()->getId(), + 'wl_user' => $user->getId(), 'wl_namespace' => $namespace, 'wl_title' => $dbKey, ), @@ -314,7 +358,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { // Can't just do an UPDATE instead of DELETE/INSERT due to unique index if ( $title ) { - $this->getUser()->addWatch( $title ); + $user->addWatch( $title ); } } } @@ -408,7 +452,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { foreach( $data as $titles ) { $this->unwatchTitles( $titles ); - $removed += $titles; + $removed = array_merge( $removed, $titles ); } if( count( $removed ) > 0 ) { @@ -445,7 +489,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { $title = Title::makeTitleSafe( $namespace, $dbkey ); if ( $this->checkTitle( $title, $namespace, $dbkey ) ) { $text = $this->buildRemoveLine( $title ); - $fields['TitlesNs'.$namespace]['options'][$text] = $title->getEscapedText(); + $fields['TitlesNs'.$namespace]['options'][$text] = htmlspecialchars( $title->getPrefixedText() ); $count++; } } @@ -455,7 +499,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { if ( count( $fields ) > 1 && $count > 30 ) { $this->toc = Linker::tocIndent(); $tocLength = 0; - foreach( $fields as $key => $data ) { + foreach( $fields as $data ) { # strip out the 'ns' prefix from the section name: $ns = substr( $data['section'], 2 ); @@ -572,7 +616,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { * Build a set of links for convenient navigation * between watchlist viewing and editing modes * - * @param $unused Unused + * @param $unused * @return string */ public static function buildTools( $unused ) { @@ -588,12 +632,12 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { // can use messages 'watchlisttools-view', 'watchlisttools-edit', 'watchlisttools-raw' $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( $arr[0], $arr[1] ), - wfMsgHtml( "watchlisttools-{$mode}" ) + wfMessage( "watchlisttools-{$mode}" )->escaped() ); } return Html::rawElement( 'span', array( 'class' => 'mw-watchlist-toollinks' ), - wfMsg( 'parentheses', $wgLang->pipeList( $tools ) ) ); + wfMessage( 'parentheses', $wgLang->pipeList( $tools ) )->text() ); } } diff --git a/includes/specials/SpecialEmailuser.php b/includes/specials/SpecialEmailuser.php index 314da727..4d875e6e 100644 --- a/includes/specials/SpecialEmailuser.php +++ b/includes/specials/SpecialEmailuser.php @@ -33,6 +33,15 @@ class SpecialEmailUser extends UnlistedSpecialPage { parent::__construct( 'Emailuser' ); } + public function getDescription() { + $target = self::getTarget( $this->mTarget ); + if( !$target instanceof User ) { + return $this->msg( 'emailuser-title-notarget' )->text(); + } + + return $this->msg( 'emailuser-title-target', $target->getName() )->text(); + } + protected function getFormFields() { return array( 'From' => array( @@ -61,18 +70,19 @@ class SpecialEmailUser extends UnlistedSpecialPage { ), 'Subject' => array( 'type' => 'text', - 'default' => wfMsgExt( 'defemailsubject', array( 'content', 'parsemag' ), $this->getUser()->getName() ), + 'default' => $this->msg( 'defemailsubject', + $this->getUser()->getName() )->inContentLanguage()->text(), 'label-message' => 'emailsubject', 'maxlength' => 200, 'size' => 60, - 'required' => 1, + 'required' => true, ), 'Text' => array( 'type' => 'textarea', 'rows' => 20, 'cols' => 80, 'label-message' => 'emailmessage', - 'required' => 1, + 'required' => true, ), 'CCMe' => array( 'type' => 'check', @@ -83,13 +93,18 @@ class SpecialEmailUser extends UnlistedSpecialPage { } public function execute( $par ) { - $this->setHeaders(); - $this->outputHeader(); $out = $this->getOutput(); $out->addModuleStyles( 'mediawiki.special' ); + $this->mTarget = is_null( $par ) ? $this->getRequest()->getVal( 'wpTarget', $this->getRequest()->getVal( 'target', '' ) ) : $par; + + // This needs to be below assignment of $this->mTarget because + // getDescription() needs it to determine the correct page title. + $this->setHeaders(); + $this->outputHeader(); + // error out if sending user cannot do this $error = self::getPermissionsError( $this->getUser(), $this->getRequest()->getVal( 'wpEditToken' ) ); switch ( $error ) { @@ -124,18 +139,17 @@ class SpecialEmailUser extends UnlistedSpecialPage { $this->mTargetObj = $ret; $form = new HTMLForm( $this->getFormFields(), $this->getContext() ); - $form->addPreText( wfMsgExt( 'emailpagetext', 'parseinline' ) ); - $form->setSubmitText( wfMsg( 'emailsend' ) ); + $form->addPreText( $this->msg( 'emailpagetext' )->parse() ); + $form->setSubmitTextMsg( 'emailsend' ); $form->setTitle( $this->getTitle() ); - $form->setSubmitCallback( array( __CLASS__, 'submit' ) ); - $form->setWrapperLegend( wfMsgExt( 'email-legend', 'parsemag' ) ); + $form->setSubmitCallback( array( __CLASS__, 'uiSubmit' ) ); + $form->setWrapperLegendMsg( 'email-legend' ); $form->loadData(); if( !wfRunHooks( 'EmailUserForm', array( &$form ) ) ) { return false; } - $out->setPageTitle( $this->msg( 'emailpage' ) ); $result = $form->show(); if( $result === true || ( $result instanceof Status && $result->isGood() ) ) { @@ -224,15 +238,27 @@ class SpecialEmailUser extends UnlistedSpecialPage { $string = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'askusername' ) ) . Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . Xml::openElement( 'fieldset' ) . - Html::rawElement( 'legend', null, wfMessage( 'emailtarget' )->parse() ) . - Xml::inputLabel( wfMessage( 'emailusername' )->text(), 'target', 'emailusertarget', 30, $name ) . ' ' . - Xml::submitButton( wfMessage( 'emailusernamesubmit' )->text() ) . + Html::rawElement( 'legend', null, $this->msg( 'emailtarget' )->parse() ) . + Xml::inputLabel( $this->msg( 'emailusername' )->text(), 'target', 'emailusertarget', 30, $name ) . ' ' . + Xml::submitButton( $this->msg( 'emailusernamesubmit' )->text() ) . Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' ) . "\n"; return $string; } /** + * Submit callback for an HTMLForm object, will simply call submit(). + * + * @since 1.20 + * @param $data array + * @param $form HTMLForm object + * @return Status|string|bool + */ + public static function uiSubmit( array $data, HTMLForm $form ) { + return self::submit( $data, $form->getContext() ); + } + + /** * Really send a mail. Permissions should have been checked using * getPermissionsError(). It is probably also a good * idea to check the edit token and ping limiter in advance. @@ -240,25 +266,22 @@ class SpecialEmailUser extends UnlistedSpecialPage { * @return Mixed: Status object, or potentially a String on error * or maybe even true on success if anything uses the EmailUser hook. */ - public static function submit( $data ) { - global $wgUser, $wgUserEmailUseReplyTo; + public static function submit( array $data, IContextSource $context ) { + global $wgUserEmailUseReplyTo; $target = self::getTarget( $data['Target'] ); if( !$target instanceof User ) { - return wfMsgExt( $target . 'text', 'parse' ); + return $context->msg( $target . 'text' )->parseAsBlock(); } $to = new MailAddress( $target ); - $from = new MailAddress( $wgUser ); + $from = new MailAddress( $context->getUser() ); $subject = $data['Subject']; $text = $data['Text']; // Add a standard footer and trim up trailing newlines $text = rtrim( $text ) . "\n\n-- \n"; - $text .= wfMsgExt( - 'emailuserfooter', - array( 'content', 'parsemag' ), - array( $from->name, $to->name ) - ); + $text .= $context->msg( 'emailuserfooter', + $from->name, $to->name )->inContentLanguage()->text(); $error = ''; if( !wfRunHooks( 'EmailUser', array( &$to, &$from, &$subject, &$text, &$error ) ) ) { @@ -302,11 +325,8 @@ class SpecialEmailUser extends UnlistedSpecialPage { // unless they are emailing themselves, in which case one // copy of the message is sufficient. if ( $data['CCMe'] && $to != $from ) { - $cc_subject = wfMsg( - 'emailccsubject', - $target->getName(), - $subject - ); + $cc_subject = $context->msg( 'emailccsubject' )->rawParams( + $target->getName(), $subject )->text(); wfRunHooks( 'EmailUserCC', array( &$from, &$from, &$cc_subject, &$text ) ); $ccStatus = UserMailer::send( $from, $from, $cc_subject, $text ); $status->merge( $ccStatus ); diff --git a/includes/specials/SpecialExport.php b/includes/specials/SpecialExport.php index d061389e..b4294b32 100644 --- a/includes/specials/SpecialExport.php +++ b/includes/specials/SpecialExport.php @@ -93,6 +93,13 @@ class SpecialExport extends SpecialPage { elseif( $request->getCheck( 'exportall' ) && $wgExportAllowAll ) { $this->doExport = true; $exportall = true; + + /* Although $page and $history are not used later on, we + nevertheless set them to avoid that PHP notices about using + undefined variables foul up our XML output (see call to + doExport(...) further down) */ + $page = ''; + $history = ''; } elseif( $request->wasPosted() && $par == '' ) { $page = $request->getText( 'pages' ); @@ -181,17 +188,26 @@ class SpecialExport extends SpecialPage { $form = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalUrl( 'action=submit' ) ) ); - $form .= Xml::inputLabel( wfMsg( 'export-addcattext' ) , 'catname', 'catname', 40 ) . ' '; - $form .= Xml::submitButton( wfMsg( 'export-addcat' ), array( 'name' => 'addcat' ) ) . '<br />'; + $form .= Xml::inputLabel( $this->msg( 'export-addcattext' )->text(), 'catname', 'catname', 40 ) . ' '; + $form .= Xml::submitButton( $this->msg( 'export-addcat' )->text(), array( 'name' => 'addcat' ) ) . '<br />'; if ( $wgExportFromNamespaces ) { - $form .= Xml::namespaceSelector( $nsindex, null, 'nsindex', wfMsg( 'export-addnstext' ) ) . ' '; - $form .= Xml::submitButton( wfMsg( 'export-addns' ), array( 'name' => 'addns' ) ) . '<br />'; + $form .= Html::namespaceSelector( + array( + 'selected' => $nsindex, + 'label' => $this->msg( 'export-addnstext' )->text() + ), array( + 'name' => 'nsindex', + 'id' => 'namespace', + 'class' => 'namespaceselector', + ) + ) . ' '; + $form .= Xml::submitButton( $this->msg( 'export-addns' )->text(), array( 'name' => 'addns' ) ) . '<br />'; } if ( $wgExportAllowAll ) { $form .= Xml::checkLabel( - wfMsg( 'exportall' ), + $this->msg( 'exportall' )->text(), 'exportall', 'exportall', $request->wasPosted() ? $request->getCheck( 'exportall' ) : false @@ -203,29 +219,29 @@ class SpecialExport extends SpecialPage { if( $wgExportAllowHistory ) { $form .= Xml::checkLabel( - wfMsg( 'exportcuronly' ), + $this->msg( 'exportcuronly' )->text(), 'curonly', 'curonly', $request->wasPosted() ? $request->getCheck( 'curonly' ) : true ) . '<br />'; } else { - $out->addHTML( wfMsgExt( 'exportnohistory', 'parse' ) ); + $out->addWikiMsg( 'exportnohistory' ); } $form .= Xml::checkLabel( - wfMsg( 'export-templates' ), + $this->msg( 'export-templates' )->text(), 'templates', 'wpExportTemplates', $request->wasPosted() ? $request->getCheck( 'templates' ) : false ) . '<br />'; if( $wgExportMaxLinkDepth || $this->userCanOverrideExportDepth() ) { - $form .= Xml::inputLabel( wfMsg( 'export-pagelinks' ), 'pagelink-depth', 'pagelink-depth', 20, 0 ) . '<br />'; + $form .= Xml::inputLabel( $this->msg( 'export-pagelinks' )->text(), 'pagelink-depth', 'pagelink-depth', 20, 0 ) . '<br />'; } // Enable this when we can do something useful exporting/importing image information. :) - //$form .= Xml::checkLabel( wfMsg( 'export-images' ), 'images', 'wpExportImages', false ) . '<br />'; + //$form .= Xml::checkLabel( $this->msg( 'export-images' )->text(), 'images', 'wpExportImages', false ) . '<br />'; $form .= Xml::checkLabel( - wfMsg( 'export-download' ), + $this->msg( 'export-download' )->text(), 'wpDownload', 'wpDownload', $request->wasPosted() ? $request->getCheck( 'wpDownload' ) : true @@ -233,14 +249,14 @@ class SpecialExport extends SpecialPage { if ( $wgExportAllowListContributors ) { $form .= Xml::checkLabel( - wfMsg( 'exportlistauthors' ), + $this->msg( 'exportlistauthors' )->text(), 'listauthors', 'listauthors', $request->wasPosted() ? $request->getCheck( 'listauthors' ) : false ) . '<br />'; } - $form .= Xml::submitButton( wfMsg( 'export-submit' ), Linker::tooltipAndAccesskeyAttribs( 'export' ) ); + $form .= Xml::submitButton( $this->msg( 'export-submit' )->text(), Linker::tooltipAndAccesskeyAttribs( 'export' ) ); $form .= Xml::closeElement( 'form' ); $out->addHTML( $form ); @@ -439,7 +455,7 @@ class SpecialExport extends SpecialPage { private function getTemplates( $inputPages, $pageSet ) { return $this->getLinks( $inputPages, $pageSet, 'templatelinks', - array( 'tl_namespace AS namespace', 'tl_title AS title' ), + array( 'namespace' => 'tl_namespace', 'title' => 'tl_title' ), array( 'page_id=tl_from' ) ); } @@ -481,7 +497,7 @@ class SpecialExport extends SpecialPage { for( ; $depth > 0; --$depth ) { $pageSet = $this->getLinks( $inputPages, $pageSet, 'pagelinks', - array( 'pl_namespace AS namespace', 'pl_title AS title' ), + array( 'namespace' => 'pl_namespace', 'title' => 'pl_title' ), array( 'page_id=pl_from' ) ); $inputPages = array_keys( $pageSet ); @@ -503,13 +519,14 @@ class SpecialExport extends SpecialPage { $inputPages, $pageSet, 'imagelinks', - array( NS_FILE . ' AS namespace', 'il_to AS title' ), + array( 'namespace' => NS_FILE, 'title' => 'il_to' ), array( 'page_id=il_from' ) ); } /** * Expand a list of pages to include items used in those pages. + * @return array */ private function getLinks( $inputPages, $pageSet, $table, $fields, $join ) { $dbr = wfGetDB( DB_SLAVE ); diff --git a/includes/specials/SpecialFewestrevisions.php b/includes/specials/SpecialFewestrevisions.php index 27d17f63..7e4bc9ce 100644 --- a/includes/specials/SpecialFewestrevisions.php +++ b/includes/specials/SpecialFewestrevisions.php @@ -44,10 +44,10 @@ class FewestrevisionsPage extends QueryPage { function getQueryInfo() { return array ( 'tables' => array ( 'revision', 'page' ), - 'fields' => array ( 'page_namespace AS namespace', - 'page_title AS title', - 'COUNT(*) AS value', - 'page_is_redirect AS redirect' ), + 'fields' => array ( 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'COUNT(*)', + 'redirect' => 'page_is_redirect' ), 'conds' => array ( 'page_namespace' => MWNamespace::getContentNamespaces(), 'page_id = rev_page' ), 'options' => array ( 'HAVING' => 'COUNT(*) > 1', @@ -56,7 +56,7 @@ class FewestrevisionsPage extends QueryPage { // useful to remove this. People _do_ create pages // and never revise them, they aren't necessarily // redirects. - 'GROUP BY' => 'page_namespace, page_title, page_is_redirect' ) + 'GROUP BY' => array( 'page_namespace', 'page_title', 'page_is_redirect' ) ) ); } @@ -68,13 +68,15 @@ class FewestrevisionsPage extends QueryPage { /** * @param $skin Skin object * @param $result Object: database row + * @return String */ function formatResult( $skin, $result ) { global $wgContLang; $nt = Title::makeTitleSafe( $result->namespace, $result->title ); if( !$nt ) { - return '<!-- bad title -->'; + return Html::element( 'span', array( 'class' => 'mw-invalidtitle' ), + Linker::getInvalidTitleDescription( $this->getContext(), $result->namespace, $result->title ) ); } $text = htmlspecialchars( $wgContLang->convert( $nt->getPrefixedText() ) ); @@ -82,7 +84,7 @@ class FewestrevisionsPage extends QueryPage { $nl = $this->msg( 'nrevisions' )->numParams( $result->value )->escaped(); $redirect = isset( $result->redirect ) && $result->redirect ? - ' - ' . wfMsgHtml( 'isredirect' ) : ''; + ' - ' . $this->msg( 'isredirect' )->escaped() : ''; $nlink = Linker::linkKnown( $nt, $nl, diff --git a/includes/specials/SpecialFileDuplicateSearch.php b/includes/specials/SpecialFileDuplicateSearch.php index 18d19db8..ccf8ba17 100644 --- a/includes/specials/SpecialFileDuplicateSearch.php +++ b/includes/specials/SpecialFileDuplicateSearch.php @@ -78,8 +78,8 @@ class FileDuplicateSearchPage extends QueryPage { return array( 'tables' => array( 'image' ), 'fields' => array( - 'img_name AS title', - 'img_sha1 AS value', + 'title' => 'img_name', + 'value' => 'img_sha1', 'img_user_text', 'img_timestamp' ), @@ -157,10 +157,24 @@ class FileDuplicateSearchPage extends QueryPage { ); } + $this->doBatchLookups( $dupes ); $this->showList( $dupes ); } } + function doBatchLookups( $list ) { + $batch = new LinkBatch(); + foreach( $list as $file ) { + $batch->addObj( $file->getTitle() ); + if( $file->isLocal() ) { + $userName = $file->getUser( 'text' ); + $batch->add( NS_USER, $userName ); + $batch->add( NS_USER_TALK, $userName ); + } + } + $batch->execute(); + } + /** * * @param Skin $skin @@ -178,7 +192,17 @@ class FileDuplicateSearchPage extends QueryPage { ); $userText = $result->getUser( 'text' ); - $user = Linker::link( Title::makeTitle( NS_USER, $userText ), $userText ); + if ( $result->isLocal() ) { + $userId = $result->getUser( 'id' ); + $user = Linker::userLink( $userId, $userText ); + $user .= $this->getContext()->msg( 'word-separator' )->plain(); + $user .= '<span style="white-space: nowrap;">'; + $user .= Linker::userToolLinks( $userId, $userText ); + $user .= '</span>'; + } else { + $user = htmlspecialchars( $userText ); + } + $time = $this->getLanguage()->userTimeAndDate( $result->getTimestamp(), $this->getUser() ); return "$plink . . $user . . $time"; diff --git a/includes/specials/SpecialFilepath.php b/includes/specials/SpecialFilepath.php index 101a33f4..e0866504 100644 --- a/includes/specials/SpecialFilepath.php +++ b/includes/specials/SpecialFilepath.php @@ -78,10 +78,10 @@ class SpecialFilepath extends SpecialPage { $this->getOutput()->addHTML( Html::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'specialfilepath' ) ) . Html::openElement( 'fieldset' ) . - Html::element( 'legend', null, wfMsg( 'filepath' ) ) . + Html::element( 'legend', null, $this->msg( 'filepath' )->text() ) . Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . - Xml::inputLabel( wfMsg( 'filepath-page' ), 'file', 'file', 25, is_object( $title ) ? $title->getText() : '' ) . ' ' . - Xml::submitButton( wfMsg( 'filepath-submit' ) ) . "\n" . + Xml::inputLabel( $this->msg( 'filepath-page' )->text(), 'file', 'file', 25, is_object( $title ) ? $title->getText() : '' ) . ' ' . + Xml::submitButton( $this->msg( 'filepath-submit' )->text() ) . "\n" . Html::closeElement( 'fieldset' ) . Html::closeElement( 'form' ) ); diff --git a/includes/specials/SpecialImport.php b/includes/specials/SpecialImport.php index a2380fbe..362fc5cf 100644 --- a/includes/specials/SpecialImport.php +++ b/includes/specials/SpecialImport.php @@ -33,6 +33,7 @@ class SpecialImport extends SpecialPage { private $interwiki = false; private $namespace; + private $rootpage = ''; private $frompage = ''; private $logcomment= false; private $history = true; @@ -100,6 +101,7 @@ class SpecialImport extends SpecialPage { $this->logcomment = $request->getText( 'log-comment' ); $this->pageLinkDepth = $wgExportMaxLinkDepth == 0 ? 0 : $request->getIntOrNull( 'pagelink-depth' ); + $this->rootpage = $request->getText( 'rootpage' );
$user = $this->getUser(); if ( !$user->matchEditToken( $request->getVal( 'editToken' ) ) ) { @@ -137,12 +139,20 @@ class SpecialImport extends SpecialPage { if( !$source->isGood() ) { $out->wrapWikiMsg( "<p class=\"error\">\n$1\n</p>", array( 'importfailed', $source->getWikiText() ) ); } else { - $out->addWikiMsg( "importstart" ); - $importer = new WikiImporter( $source->value ); if( !is_null( $this->namespace ) ) { $importer->setTargetNamespace( $this->namespace ); } + if( !is_null( $this->rootpage ) ) { + $statusRootPage = $importer->setTargetRootPage( $this->rootpage ); + if( !$statusRootPage->isGood() ) { + $out->wrapWikiMsg( "<p class=\"error\">\n$1\n</p>", array( 'import-options-wrong', $statusRootPage->getWikiText(), count( $statusRootPage->getErrorsArray() ) ) ); + return; + } + } + + $out->addWikiMsg( "importstart" ); + $reporter = new ImportReporter( $importer, $isUpload, $this->interwiki , $this->logcomment); $reporter->setContext( $this->getContext() ); $exception = false; @@ -177,18 +187,18 @@ class SpecialImport extends SpecialPage { $out = $this->getOutput(); if( $user->isAllowed( 'importupload' ) ) { - $out->addWikiMsg( "importtext" ); $out->addHTML( - Xml::fieldset( wfMsg( 'import-upload' ) ). + Xml::fieldset( $this->msg( 'import-upload' )->text() ). Xml::openElement( 'form', array( 'enctype' => 'multipart/form-data', 'method' => 'post', 'action' => $action, 'id' => 'mw-import-upload-form' ) ) . + $this->msg( 'importtext' )->parseAsBlock() . Html::hidden( 'action', 'submit' ) . Html::hidden( 'source', 'upload' ) . Xml::openElement( 'table', array( 'id' => 'mw-import-table' ) ) . "<tr> <td class='mw-label'>" . - Xml::label( wfMsg( 'import-upload-filename' ), 'xmlimport' ) . + Xml::label( $this->msg( 'import-upload-filename' )->text(), 'xmlimport' ) . "</td> <td class='mw-input'>" . Xml::input( 'xmlimport', 50, '', array( 'type' => 'file' ) ) . ' ' . @@ -196,7 +206,7 @@ class SpecialImport extends SpecialPage { </tr> <tr> <td class='mw-label'>" . - Xml::label( wfMsg( 'import-comment' ), 'mw-import-comment' ) . + Xml::label( $this->msg( 'import-comment' )->text(), 'mw-import-comment' ) . "</td> <td class='mw-input'>" . Xml::input( 'log-comment', 50, '', @@ -204,9 +214,18 @@ class SpecialImport extends SpecialPage { "</td> </tr> <tr> + <td class='mw-label'>" . + Xml::label( $this->msg( 'import-interwiki-rootpage' )->text(), 'mw-interwiki-rootpage' ) . + "</td> + <td class='mw-input'>" . + Xml::input( 'rootpage', 50, $this->rootpage, + array( 'id' => 'mw-interwiki-rootpage', 'type' => 'text' ) ) . ' ' . + "</td> + </tr> + <tr> <td></td> <td class='mw-submit'>" . - Xml::submitButton( wfMsg( 'uploadbtn' ) ) . + Xml::submitButton( $this->msg( 'uploadbtn' )->text() ) . "</td> </tr>" . Xml::closeElement( 'table' ). @@ -226,7 +245,7 @@ class SpecialImport extends SpecialPage { if( $wgExportMaxLinkDepth > 0 ) { $importDepth = "<tr> <td class='mw-label'>" . - wfMsgExt( 'export-pagelinks', 'parseinline' ) . + $this->msg( 'export-pagelinks' )->parse() . "</td> <td class='mw-input'>" . Xml::input( 'pagelink-depth', 3, 0 ) . @@ -235,16 +254,16 @@ class SpecialImport extends SpecialPage { } $out->addHTML( - Xml::fieldset( wfMsg( 'importinterwiki' ) ) . + Xml::fieldset( $this->msg( 'importinterwiki' )->text() ) . Xml::openElement( 'form', array( 'method' => 'post', 'action' => $action, 'id' => 'mw-import-interwiki-form' ) ) . - wfMsgExt( 'import-interwiki-text', array( 'parse' ) ) . + $this->msg( 'import-interwiki-text' )->parseAsBlock() . Html::hidden( 'action', 'submit' ) . Html::hidden( 'source', 'interwiki' ) . Html::hidden( 'editToken', $user->getEditToken() ) . Xml::openElement( 'table', array( 'id' => 'mw-import-table' ) ) . "<tr> <td class='mw-label'>" . - Xml::label( wfMsg( 'import-interwiki-source' ), 'interwiki' ) . + Xml::label( $this->msg( 'import-interwiki-source' )->text(), 'interwiki' ) . "</td> <td class='mw-input'>" . Xml::openElement( 'select', array( 'name' => 'interwiki' ) ) @@ -263,28 +282,37 @@ class SpecialImport extends SpecialPage { <td> </td> <td class='mw-input'>" . - Xml::checkLabel( wfMsg( 'import-interwiki-history' ), 'interwikiHistory', 'interwikiHistory', $this->history ) . + Xml::checkLabel( $this->msg( 'import-interwiki-history' )->text(), 'interwikiHistory', 'interwikiHistory', $this->history ) . "</td> </tr> <tr> <td> </td> <td class='mw-input'>" . - Xml::checkLabel( wfMsg( 'import-interwiki-templates' ), 'interwikiTemplates', 'interwikiTemplates', $this->includeTemplates ) . + Xml::checkLabel( $this->msg( 'import-interwiki-templates' )->text(), 'interwikiTemplates', 'interwikiTemplates', $this->includeTemplates ) . "</td> </tr> $importDepth <tr> <td class='mw-label'>" . - Xml::label( wfMsg( 'import-interwiki-namespace' ), 'namespace' ) . + Xml::label( $this->msg( 'import-interwiki-namespace' )->text(), 'namespace' ) . "</td> <td class='mw-input'>" . - Xml::namespaceSelector( $this->namespace, '' ) . + Html::namespaceSelector( + array( + 'selected' => $this->namespace, + 'all' => '', + ), array( + 'name' => 'namespace', + 'id' => 'namespace', + 'class' => 'namespaceselector', + ) + ) . "</td> </tr> <tr> <td class='mw-label'>" . - Xml::label( wfMsg( 'import-comment' ), 'mw-interwiki-comment' ) . + Xml::label( $this->msg( 'import-comment' )->text(), 'mw-interwiki-comment' ) . "</td> <td class='mw-input'>" . Xml::input( 'log-comment', 50, '', @@ -292,10 +320,19 @@ class SpecialImport extends SpecialPage { "</td> </tr> <tr> + <td class='mw-label'>" . + Xml::label( $this->msg( 'import-interwiki-rootpage' )->text(), 'mw-interwiki-rootpage' ) . + "</td> + <td class='mw-input'>" . + Xml::input( 'rootpage', 50, $this->rootpage, + array( 'id' => 'mw-interwiki-rootpage', 'type' => 'text' ) ) . ' ' . + "</td> + </tr> + <tr> <td> </td> <td class='mw-submit'>" . - Xml::submitButton( wfMsg( 'import-interwiki-submit' ), Linker::tooltipAndAccesskeyAttribs( 'import' ) ) . + Xml::submitButton( $this->msg( 'import-interwiki-submit' )->text(), Linker::tooltipAndAccesskeyAttribs( 'import' ) ) . "</td> </tr>" . Xml::closeElement( 'table' ). @@ -352,8 +389,6 @@ class ImportReporter extends ContextSource { * @return void */ function reportPage( $title, $origTitle, $revisionCount, $successCount, $pageInfo ) { - global $wgContLang; - $args = func_get_args(); call_user_func_array( $this->mOriginalPageOutCallback, $args ); @@ -364,30 +399,27 @@ class ImportReporter extends ContextSource { $this->mPageCount++; - $localCount = $this->getLanguage()->formatNum( $successCount ); - $contentCount = $wgContLang->formatNum( $successCount ); - if( $successCount > 0 ) { $this->getOutput()->addHTML( "<li>" . Linker::linkKnown( $title ) . " " . - wfMsgExt( 'import-revision-count', array( 'parsemag', 'escape' ), $localCount ) . + $this->msg( 'import-revision-count' )->numParams( $successCount )->escaped() . "</li>\n" ); $log = new LogPage( 'import' ); if( $this->mIsUpload ) { - $detail = wfMsgExt( 'import-logentry-upload-detail', array( 'content', 'parsemag' ), - $contentCount ); + $detail = $this->msg( 'import-logentry-upload-detail' )->numParams( + $successCount )->inContentLanguage()->text(); if ( $this->reason ) { - $detail .= wfMsgForContent( 'colon-separator' ) . $this->reason; + $detail .= $this->msg( 'colon-separator' )->inContentLanguage()->text() . $this->reason; } $log->addEntry( 'upload', $title, $detail ); } else { $interwiki = '[[:' . $this->mInterwiki . ':' . $origTitle->getPrefixedText() . ']]'; - $detail = wfMsgExt( 'import-logentry-interwiki-detail', array( 'content', 'parsemag' ), - $contentCount, $interwiki ); + $detail = $this->msg( 'import-logentry-interwiki-detail' )->numParams( + $successCount )->params( $interwiki )->inContentLanguage()->text(); if ( $this->reason ) { - $detail .= wfMsgForContent( 'colon-separator' ) . $this->reason; + $detail .= $this->msg( 'colon-separator' )->inContentLanguage()->text() . $this->reason; } $log->addEntry( 'interwiki', $title, $detail ); } @@ -395,7 +427,7 @@ class ImportReporter extends ContextSource { $comment = $detail; // quick $dbw = wfGetDB( DB_MASTER ); $latest = $title->getLatestRevID(); - $nullRevision = Revision::newNullRevision( $dbw, $title->getArticleId(), $comment, true ); + $nullRevision = Revision::newNullRevision( $dbw, $title->getArticleID(), $comment, true ); if (!is_null($nullRevision)) { $nullRevision->insertOn( $dbw ); $page = WikiPage::factory( $title ); @@ -405,15 +437,14 @@ class ImportReporter extends ContextSource { } } else { $this->getOutput()->addHTML( "<li>" . Linker::linkKnown( $title ) . " " . - wfMsgHtml( 'import-nonewrevisions' ) . "</li>\n" ); + $this->msg( 'import-nonewrevisions' )->escaped() . "</li>\n" ); } } function close() { $out = $this->getOutput(); if ( $this->mLogItemCount > 0 ) { - $msg = wfMsgExt( 'imported-log-entries', 'parseinline', - $this->getLanguage()->formatNum( $this->mLogItemCount ) ); + $msg = $this->msg( 'imported-log-entries' )->numParams( $this->mLogItemCount )->parse(); $out->addHTML( Xml::tags( 'li', null, $msg ) ); } elseif( $this->mPageCount == 0 && $this->mLogItemCount == 0 ) { $out->addHTML( "</ul>\n" ); diff --git a/includes/specials/SpecialJavaScriptTest.php b/includes/specials/SpecialJavaScriptTest.php index d7e1655f..c217eccb 100644 --- a/includes/specials/SpecialJavaScriptTest.php +++ b/includes/specials/SpecialJavaScriptTest.php @@ -1,5 +1,29 @@ <?php - +/** + * Implements Special:JavaScriptTest + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + * @ingroup SpecialPage + */ + +/** + * @ingroup SpecialPage + */ class SpecialJavaScriptTest extends SpecialPage { /** @@ -37,26 +61,24 @@ class SpecialJavaScriptTest extends SpecialPage { // No framework specified if ( $par == '' ) { - $out->setPagetitle( wfMsgHtml( 'javascripttest' ) ); + $out->setPageTitle( $this->msg( 'javascripttest' ) ); $summary = $this->wrapSummaryHtml( - wfMsgHtml( 'javascripttest-pagetext-noframework' ) . $this->getFrameworkListHtml(), + $this->msg( 'javascripttest-pagetext-noframework' )->escaped() . $this->getFrameworkListHtml(), 'noframework' ); $out->addHtml( $summary ); // Matched! Display proper title and initialize the framework } elseif ( isset( self::$frameworks[$framework] ) ) { - $out->setPagetitle( wfMsgHtml( 'javascripttest-title', wfMsgHtml( "javascripttest-$framework-name" ) ) ); - $out->setSubtitle( - wfMessage( 'javascripttest-backlink' )->rawParams( Linker::linkKnown( $this->getTitle() ) )->escaped() - ); + $out->setPageTitle( $this->msg( 'javascripttest-title', $this->msg( "javascripttest-$framework-name" )->plain() ) ); + $out->setSubtitle( $this->msg( 'javascripttest-backlink' )->rawParams( Linker::linkKnown( $this->getTitle() ) ) ); $this->{self::$frameworks[$framework]}(); // Framework not found, display error } else { - $out->setPagetitle( wfMsgHtml( 'javascripttest' ) ); + $out->setPageTitle( $this->msg( 'javascripttest' ) ); $summary = $this->wrapSummaryHtml( '<p class="error">' - . wfMsgHtml( 'javascripttest-pagetext-unknownframework', $par ) + . $this->msg( 'javascripttest-pagetext-unknownframework', $par )->escaped() . '</p>' . $this->getFrameworkListHtml(), 'unknownframework' @@ -75,11 +97,11 @@ class SpecialJavaScriptTest extends SpecialPage { $list .= Html::rawElement( 'li', array(), - Linker::link( $this->getTitle( $framework ), wfMsgHtml( "javascripttest-$framework-name" ) ) + Linker::link( $this->getTitle( $framework ), $this->msg( "javascripttest-$framework-name" )->escaped() ) ); } $list .= '</ul>'; - $msg = wfMessage( 'javascripttest-pagetext-frameworks' )->rawParams( $list )->parseAsBlock(); + $msg = $this->msg( 'javascripttest-pagetext-frameworks' )->rawParams( $list )->parseAsBlock(); return $msg; } @@ -90,6 +112,7 @@ class SpecialJavaScriptTest extends SpecialPage { * be thrown. * @param $html String: The raw HTML. * @param $state String: State, one of 'noframework', 'unknownframework' or 'frameworkfound' + * @return string */ private function wrapSummaryHtml( $html, $state ) { $validStates = array( 'noframework', 'unknownframework', 'frameworkfound' ); @@ -106,7 +129,7 @@ class SpecialJavaScriptTest extends SpecialPage { * Initialize the page for QUnit. */ private function initQUnitTesting() { - global $wgJavaScriptTestConfig, $wgLang; + global $wgJavaScriptTestConfig; $out = $this->getOutput(); @@ -114,11 +137,11 @@ class SpecialJavaScriptTest extends SpecialPage { $qunitTestModules = $out->getResourceLoader()->getTestModuleNames( 'qunit' ); $out->addModules( $qunitTestModules ); - $summary = wfMessage( 'javascripttest-qunit-intro' ) + $summary = $this->msg( 'javascripttest-qunit-intro' ) ->params( $wgJavaScriptTestConfig['qunit']['documentation'] ) ->parseAsBlock(); - $header = wfMessage( 'javascripttest-qunit-heading' )->escaped(); - $userDir = $wgLang->getDir(); + $header = $this->msg( 'javascripttest-qunit-heading' )->escaped(); + $userDir = $this->getLanguage()->getDir(); $baseHtml = <<<HTML <div class="mw-content-ltr"> @@ -132,6 +155,14 @@ class SpecialJavaScriptTest extends SpecialPage { HTML; $out->addHtml( $this->wrapSummaryHtml( $summary, 'frameworkfound' ) . $baseHtml ); + // This special page is disabled by default ($wgEnableJavaScriptTest), and contains + // no sensitive data. In order to allow TestSwarm to embed it into a test client window, + // we need to allow iframing of this page. + $out->allowClickjacking(); + + // Used in ./tests/qunit/data/testrunner.js, see also documentation of + // $wgJavaScriptTestConfig in DefaultSettings.php + $out->addJsConfigVars( 'QUnitTestSwarmInjectJSPath', $wgJavaScriptTestConfig['qunit']['testswarm-injectjs'] ); } public function isListed(){ diff --git a/includes/specials/SpecialLinkSearch.php b/includes/specials/SpecialLinkSearch.php index d3ab2f04..0810ee77 100644 --- a/includes/specials/SpecialLinkSearch.php +++ b/includes/specials/SpecialLinkSearch.php @@ -88,13 +88,22 @@ class LinkSearchPage extends QueryPage { $s = Xml::openElement( 'form', array( 'id' => 'mw-linksearch-form', 'method' => 'get', 'action' => $GLOBALS['wgScript'] ) ) . Html::hidden( 'title', $this->getTitle()->getPrefixedDbKey() ) . '<fieldset>' . - Xml::element( 'legend', array(), wfMsg( 'linksearch' ) ) . - Xml::inputLabel( wfMsg( 'linksearch-pat' ), 'target', 'target', 50, $target ) . ' '; + Xml::element( 'legend', array(), $this->msg( 'linksearch' )->text() ) . + Xml::inputLabel( $this->msg( 'linksearch-pat' )->text(), 'target', 'target', 50, $target ) . ' '; if ( !$wgMiserMode ) { - $s .= Xml::label( wfMsg( 'linksearch-ns' ), 'namespace' ) . ' ' . - Xml::namespaceSelector( $namespace, '' ); + $s .= Html::namespaceSelector( + array( + 'selected' => $namespace, + 'all' => '', + 'label' => $this->msg( 'linksearch-ns' )->text() + ), array( + 'name' => 'namespace', + 'id' => 'namespace', + 'class' => 'namespaceselector', + ) + ); } - $s .= Xml::submitButton( wfMsg( 'linksearch-ok' ) ) . + $s .= Xml::submitButton( $this->msg( 'linksearch-ok' )->text() ) . '</fieldset>' . Xml::closeElement( 'form' ); $out->addHTML( $s ); @@ -112,6 +121,7 @@ class LinkSearchPage extends QueryPage { /** * Disable RSS/Atom feeds + * @return bool */ function isSyndicated() { return false; @@ -161,9 +171,9 @@ class LinkSearchPage extends QueryPage { $like = $dbr->buildLike( $stripped ); $retval = array ( 'tables' => array ( 'page', 'externallinks' ), - 'fields' => array ( 'page_namespace AS namespace', - 'page_title AS title', - 'el_index AS value', 'el_to AS url' ), + 'fields' => array ( 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'el_index', 'url' => 'el_to' ), 'conds' => array ( 'page_id = el_from', "$clause $like" ), 'options' => array( 'USE INDEX' => $clause ) @@ -180,7 +190,7 @@ class LinkSearchPage extends QueryPage { $pageLink = Linker::linkKnown( $title ); $urlLink = Linker::makeExternalLink( $url, $url ); - return wfMsgHtml( 'linksearch-line', $urlLink, $pageLink ); + return $this->msg( 'linksearch-line' )->rawParams( $urlLink, $pageLink )->escaped(); } /** @@ -203,6 +213,7 @@ class LinkSearchPage extends QueryPage { * We do a truncated index search, so the optimizer won't trust * it as good enough for optimizing sort. The implicit ordering * from the scan will usually do well enough for our needs. + * @return array */ function getOrderFields() { return array(); diff --git a/includes/specials/SpecialListfiles.php b/includes/specials/SpecialListfiles.php index b5754991..cc055221 100644 --- a/includes/specials/SpecialListfiles.php +++ b/includes/specials/SpecialListfiles.php @@ -107,15 +107,15 @@ class ImageListPager extends TablePager { if ( !$this->mFieldNames ) { global $wgMiserMode; $this->mFieldNames = array( - 'img_timestamp' => wfMsg( 'listfiles_date' ), - 'img_name' => wfMsg( 'listfiles_name' ), - 'thumb' => wfMsg( 'listfiles_thumb' ), - 'img_size' => wfMsg( 'listfiles_size' ), - 'img_user_text' => wfMsg( 'listfiles_user' ), - 'img_description' => wfMsg( 'listfiles_description' ), + 'img_timestamp' => $this->msg( 'listfiles_date' )->text(), + 'img_name' => $this->msg( 'listfiles_name' )->text(), + 'thumb' => $this->msg( 'listfiles_thumb' )->text(), + 'img_size' => $this->msg( 'listfiles_size' )->text(), + 'img_user_text' => $this->msg( 'listfiles_user' )->text(), + 'img_description' => $this->msg( 'listfiles_description' )->text(), ); if( !$wgMiserMode ) { - $this->mFieldNames['count'] = wfMsg( 'listfiles_count' ); + $this->mFieldNames['count'] = $this->msg( 'listfiles_count' )->text(); } } return $this->mFieldNames; @@ -156,9 +156,8 @@ class ImageListPager extends TablePager { if( $dbr->implicitGroupby() ) { $options = array( 'GROUP BY' => 'img_name' ); } else { - $columnlist = implode( ',', - preg_grep( '/^img/', array_keys( $this->getFieldNames() ) ) ); - $options = array( 'GROUP BY' => "img_user, $columnlist" ); + $columnlist = preg_grep( '/^img/', array_keys( $this->getFieldNames() ) ); + $options = array( 'GROUP BY' => array_merge( array( 'img_user' ), $columnlist ) ); } $join_conds = array( 'oldimage' => array( 'LEFT JOIN', 'oi_name = img_name' ) ); } @@ -175,20 +174,14 @@ class ImageListPager extends TablePager { return 'img_timestamp'; } - function getStartBody() { - # Do a link batch query for user pages - if ( $this->mResult->numRows() ) { - $lb = new LinkBatch; - $this->mResult->seek( 0 ); - foreach ( $this->mResult as $row ) { - if ( $row->img_user ) { - $lb->add( NS_USER, str_replace( ' ', '_', $row->img_user_text ) ); - } - } - $lb->execute(); + function doBatchLookups() { + $userIds = array(); + $this->mResult->seek( 0 ); + foreach ( $this->mResult as $row ) { + $userIds[] = $row->img_user; } - - return parent::getStartBody(); + # Do a link batch query for names and userpages + UserCache::singleton()->doQuery( $userIds, array( 'userpage' ), __METHOD__ ); } function formatValue( $field, $value ) { @@ -198,10 +191,10 @@ class ImageListPager extends TablePager { $thumb = $file->transform( array( 'width' => 180, 'height' => 360 ) ); return $thumb->toHtml( array( 'desc-link' => true ) ); case 'img_timestamp': - return htmlspecialchars( $this->getLanguage()->timeanddate( $value, true ) ); + return htmlspecialchars( $this->getLanguage()->userTimeAndDate( $value, $this->getUser() ) ); case 'img_name': static $imgfile = null; - if ( $imgfile === null ) $imgfile = wfMsg( 'imgfile' ); + if ( $imgfile === null ) $imgfile = $this->msg( 'imgfile' )->text(); // Weird files can maybe exist? Bug 22227 $filePage = Title::makeTitleSafe( NS_FILE, $value ); @@ -211,15 +204,17 @@ class ImageListPager extends TablePager { array( 'href' => wfLocalFile( $filePage )->getURL() ), $imgfile ); - return "$link ($download)"; + $download = $this->msg( 'parentheses' )->rawParams( $download )->escaped(); + return "$link $download"; } else { return htmlspecialchars( $value ); } case 'img_user_text': if ( $this->mCurrentRow->img_user ) { + $name = User::whoIs( $this->mCurrentRow->img_user ); $link = Linker::link( - Title::makeTitle( NS_USER, $value ), - htmlspecialchars( $value ) + Title::makeTitle( NS_USER, $name ), + htmlspecialchars( $name ) ); } else { $link = htmlspecialchars( $value ); @@ -253,9 +248,10 @@ class ImageListPager extends TablePager { ) ); return Html::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'mw-listfiles-form' ) ) . - Xml::fieldset( wfMsg( 'listfiles' ) ) . + Xml::fieldset( $this->msg( 'listfiles' )->text() ) . + Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . Xml::buildForm( $inputForm, 'table_pager_limit_submit' ) . - $this->getHiddenFields( array( 'limit', 'ilsearch', 'user' ) ) . + $this->getHiddenFields( array( 'limit', 'ilsearch', 'user', 'title' ) ) . Html::closeElement( 'fieldset' ) . Html::closeElement( 'form' ) . "\n"; } @@ -290,4 +286,8 @@ class ImageListPager extends TablePager { } return $queries; } + + function getTitle() { + return SpecialPage::getTitleFor( 'Listfiles' ); + } } diff --git a/includes/specials/SpecialListgrouprights.php b/includes/specials/SpecialListgrouprights.php index 91d8ed87..1f95c225 100644 --- a/includes/specials/SpecialListgrouprights.php +++ b/includes/specials/SpecialListgrouprights.php @@ -54,8 +54,8 @@ class SpecialListGroupRights extends SpecialPage { $out->addHTML( Xml::openElement( 'table', array( 'class' => 'wikitable mw-listgrouprights-table' ) ) . '<tr>' . - Xml::element( 'th', null, wfMsg( 'listgrouprights-group' ) ) . - Xml::element( 'th', null, wfMsg( 'listgrouprights-rights' ) ) . + Xml::element( 'th', null, $this->msg( 'listgrouprights-group' )->text() ) . + Xml::element( 'th', null, $this->msg( 'listgrouprights-rights' )->text() ) . '</tr>' ); @@ -77,10 +77,10 @@ class SpecialListGroupRights extends SpecialPage { ? 'all' : $group; - $msg = wfMessage( 'group-' . $groupname ); + $msg = $this->msg( 'group-' . $groupname ); $groupnameLocalized = !$msg->isBlank() ? $msg->text() : $groupname; - $msg = wfMessage( 'grouppage-' . $groupname )->inContentLanguage(); + $msg = $this->msg( 'grouppage-' . $groupname )->inContentLanguage(); $grouppageLocalized = !$msg->isBlank() ? $msg->text() : MWNamespace::getCanonicalName( NS_PROJECT ) . ':' . $groupname; @@ -99,12 +99,12 @@ class SpecialListGroupRights extends SpecialPage { // Link to Special:listusers for implicit group 'user' $grouplink = '<br />' . Linker::linkKnown( SpecialPage::getTitleFor( 'Listusers' ), - wfMsgHtml( 'listgrouprights-members' ) + $this->msg( 'listgrouprights-members' )->escaped() ); } elseif ( !in_array( $group, $wgImplicitGroups ) ) { $grouplink = '<br />' . Linker::linkKnown( SpecialPage::getTitleFor( 'Listusers' ), - wfMsgHtml( 'listgrouprights-members' ), + $this->msg( 'listgrouprights-members' )->escaped(), array(), array( 'group' => $group ) ); @@ -152,59 +152,59 @@ class SpecialListGroupRights extends SpecialPage { foreach( $permissions as $permission => $granted ) { //show as granted only if it isn't revoked to prevent duplicate display of permissions if( $granted && ( !isset( $revoke[$permission] ) || !$revoke[$permission] ) ) { - $description = wfMsgExt( 'listgrouprights-right-display', array( 'parseinline' ), + $description = $this->msg( 'listgrouprights-right-display', User::getRightDescription( $permission ), '<span class="mw-listgrouprights-right-name">' . $permission . '</span>' - ); + )->parse(); $r[] = $description; } } foreach( $revoke as $permission => $revoked ) { if( $revoked ) { - $description = wfMsgExt( 'listgrouprights-right-revoked', array( 'parseinline' ), + $description = $this->msg( 'listgrouprights-right-revoked', User::getRightDescription( $permission ), '<span class="mw-listgrouprights-right-name">' . $permission . '</span>' - ); + )->parse(); $r[] = $description; } } sort( $r ); $lang = $this->getLanguage(); if( $add === true ){ - $r[] = wfMsgExt( 'listgrouprights-addgroup-all', array( 'escape' ) ); + $r[] = $this->msg( 'listgrouprights-addgroup-all' )->escaped(); } elseif( is_array( $add ) && count( $add ) ) { $add = array_values( array_unique( $add ) ); - $r[] = wfMsgExt( 'listgrouprights-addgroup', array( 'parseinline' ), + $r[] = $this->msg( 'listgrouprights-addgroup', $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $add ) ), count( $add ) - ); + )->parse(); } if( $remove === true ){ - $r[] = wfMsgExt( 'listgrouprights-removegroup-all', array( 'escape' ) ); + $r[] = $this->msg( 'listgrouprights-removegroup-all' )->escaped(); } elseif( is_array( $remove ) && count( $remove ) ) { $remove = array_values( array_unique( $remove ) ); - $r[] = wfMsgExt( 'listgrouprights-removegroup', array( 'parseinline' ), + $r[] = $this->msg( 'listgrouprights-removegroup', $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $remove ) ), count( $remove ) - ); + )->parse(); } if( $addSelf === true ){ - $r[] = wfMsgExt( 'listgrouprights-addgroup-self-all', array( 'escape' ) ); + $r[] = $this->msg( 'listgrouprights-addgroup-self-all' )->escaped(); } elseif( is_array( $addSelf ) && count( $addSelf ) ) { $addSelf = array_values( array_unique( $addSelf ) ); - $r[] = wfMsgExt( 'listgrouprights-addgroup-self', array( 'parseinline' ), + $r[] = $this->msg( 'listgrouprights-addgroup-self', $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $addSelf ) ), count( $addSelf ) - ); + )->parse(); } if( $removeSelf === true ){ - $r[] = wfMsgExt( 'listgrouprights-removegroup-self-all', array( 'escape' ) ); + $r[] = $this->msg( 'listgrouprights-removegroup-self-all' )->parse(); } elseif( is_array( $removeSelf ) && count( $removeSelf ) ) { $removeSelf = array_values( array_unique( $removeSelf ) ); - $r[] = wfMsgExt( 'listgrouprights-removegroup-self', array( 'parseinline' ), + $r[] = $this->msg( 'listgrouprights-removegroup-self', $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $removeSelf ) ), count( $removeSelf ) - ); + )->parse(); } if( empty( $r ) ) { return ''; diff --git a/includes/specials/SpecialListredirects.php b/includes/specials/SpecialListredirects.php index f9cf3e6e..fe338a08 100644 --- a/includes/specials/SpecialListredirects.php +++ b/includes/specials/SpecialListredirects.php @@ -41,14 +41,14 @@ class ListredirectsPage extends QueryPage { function getQueryInfo() { return array( 'tables' => array( 'p1' => 'page', 'redirect', 'p2' => 'page' ), - 'fields' => array( 'p1.page_namespace AS namespace', - 'p1.page_title AS title', - 'p1.page_title AS value', + 'fields' => array( 'namespace' => 'p1.page_namespace', + 'title' => 'p1.page_title', + 'value' => 'p1.page_title', 'rd_namespace', 'rd_title', 'rd_fragment', 'rd_interwiki', - 'p2.page_id AS redirid' ), + 'redirid' => 'p2.page_id' ), 'conds' => array( 'p1.page_is_redirect' => 1 ), 'join_conds' => array( 'redirect' => array( 'LEFT JOIN', 'rd_from=p1.page_id' ), diff --git a/includes/specials/SpecialListusers.php b/includes/specials/SpecialListusers.php index d743712d..1089fbbe 100644 --- a/includes/specials/SpecialListusers.php +++ b/includes/specials/SpecialListusers.php @@ -34,7 +34,11 @@ */ class UsersPager extends AlphabeticPager { - function __construct( IContextSource $context = null, $par = null ) { + /** + * @param $context IContextSource + * @param $par null|array + */ + function __construct( IContextSource $context = null, $par = null, $including = null ) { if ( $context ) { $this->setContext( $context ); } @@ -58,6 +62,7 @@ class UsersPager extends AlphabeticPager { } $this->editsOnly = $request->getBool( 'editsOnly' ); $this->creationSort = $request->getBool( 'creationSort' ); + $this->including = $including; $this->requestedUser = ''; if ( $un != '' ) { @@ -69,15 +74,21 @@ class UsersPager extends AlphabeticPager { parent::__construct(); } + /** + * @return string + */ function getIndexField() { return $this->creationSort ? 'user_id' : 'user_name'; } + /** + * @return Array + */ function getQueryInfo() { $dbr = wfGetDB( DB_SLAVE ); $conds = array(); // Don't show hidden names - if( !$this->getUser()->isAllowed('hideuser') ) { + if( !$this->getUser()->isAllowed( 'hideuser' ) ) { $conds[] = 'ipb_deleted IS NULL'; } @@ -105,18 +116,22 @@ class UsersPager extends AlphabeticPager { $query = array( 'tables' => array( 'user', 'user_groups', 'ipblocks'), 'fields' => array( - $this->creationSort ? 'MAX(user_name) AS user_name' : 'user_name', - $this->creationSort ? 'user_id' : 'MAX(user_id) AS user_id', - 'MAX(user_editcount) AS edits', - 'COUNT(ug_group) AS numgroups', - 'MAX(ug_group) AS singlegroup', // the usergroup if there is only one - 'MIN(user_registration) AS creation', - 'MAX(ipb_deleted) AS ipb_deleted' // block/hide status + 'user_name' => $this->creationSort ? 'MAX(user_name)' : 'user_name', + 'user_id' => $this->creationSort ? 'user_id' : 'MAX(user_id)', + 'edits' => 'MAX(user_editcount)', + 'numgroups' => 'COUNT(ug_group)', + 'singlegroup' => 'MAX(ug_group)', // the usergroup if there is only one + 'creation' => 'MIN(user_registration)', + 'ipb_deleted' => 'MAX(ipb_deleted)' // block/hide status ), 'options' => $options, 'join_conds' => array( 'user_groups' => array( 'LEFT JOIN', 'user_id=ug_user' ), - 'ipblocks' => array( 'LEFT JOIN', 'user_id=ipb_user AND ipb_deleted=1 AND ipb_auto=0' ), + 'ipblocks' => array( 'LEFT JOIN', array( + 'user_id=ipb_user', + 'ipb_deleted' => 1, + 'ipb_auto' => 0 + )), ), 'conds' => $conds ); @@ -125,95 +140,101 @@ class UsersPager extends AlphabeticPager { return $query; } + /** + * @param $row Object + * @return String + */ function formatRow( $row ) { - if ($row->user_id == 0) #Bug 16487 + if ( $row->user_id == 0 ) { #Bug 16487 return ''; + } - $userPage = Title::makeTitle( NS_USER, $row->user_name ); - $name = Linker::link( $userPage, htmlspecialchars( $userPage->getText() ) ); + $userName = $row->user_name; + + $ulinks = Linker::userLink( $row->user_id, $userName ); + $ulinks .= Linker::userToolLinks( $row->user_id, $userName ); $lang = $this->getLanguage(); + $groups = ''; $groups_list = self::getGroups( $row->user_id ); - if( count( $groups_list ) > 0 ) { + if( !$this->including && count( $groups_list ) > 0 ) { $list = array(); foreach( $groups_list as $group ) - $list[] = self::buildGroupLink( $group, $userPage->getText() ); + $list[] = self::buildGroupLink( $group, $userName ); $groups = $lang->commaList( $list ); - } else { - $groups = ''; } - $item = $lang->specialList( $name, $groups ); + $item = $lang->specialList( $ulinks, $groups ); if( $row->ipb_deleted ) { $item = "<span class=\"deleted\">$item</span>"; } + $edits = ''; global $wgEdititis; - if ( $wgEdititis ) { - $editCount = $lang->formatNum( $row->edits ); - $edits = ' [' . wfMsgExt( 'usereditcount', array( 'parsemag', 'escape' ), $editCount ) . ']'; - } else { - $edits = ''; + if ( !$this->including && $wgEdititis ) { + $edits = ' [' . $this->msg( 'usereditcount' )->numParams( $row->edits )->escaped() . ']'; } $created = ''; # Some rows may be NULL - if( $row->creation ) { - $d = $lang->date( wfTimestamp( TS_MW, $row->creation ), true ); - $t = $lang->time( wfTimestamp( TS_MW, $row->creation ), true ); - $created = ' (' . wfMsgExt( 'usercreated', array( 'parsemag', 'escape' ), $d, $t, $row->user_name ) . ')'; + if( !$this->including && $row->creation ) { + $user = $this->getUser(); + $d = $lang->userDate( $row->creation, $user ); + $t = $lang->userTime( $row->creation, $user ); + $created = $this->msg( 'usercreated', $d, $t, $row->user_name )->escaped(); + $created = ' ' . $this->msg( 'parentheses' )->rawParams( $created )->escaped(); } wfRunHooks( 'SpecialListusersFormatRow', array( &$item, $row ) ); - return "<li>{$item}{$edits}{$created}</li>"; + return Html::rawElement( 'li', array(), "{$item}{$edits}{$created}" ); } - function getBody() { - if( !$this->mQueryDone ) { - $this->doQuery(); - } - $this->mResult->rewind(); - $batch = new LinkBatch; + function doBatchLookups() { + $batch = new LinkBatch(); + # Give some pointers to make user links foreach ( $this->mResult as $row ) { - $batch->addObj( Title::makeTitleSafe( NS_USER, $row->user_name ) ); + $batch->add( NS_USER, $row->user_name ); + $batch->add( NS_USER_TALK, $row->user_name ); } $batch->execute(); $this->mResult->rewind(); - return parent::getBody(); } + /** + * @return string + */ function getPageHeader( ) { global $wgScript; - // @todo Add a PrefixedBaseDBKey + list( $self ) = explode( '/', $this->getTitle()->getPrefixedDBkey() ); # Form tag $out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'mw-listusers-form' ) ) . - Xml::fieldset( wfMsg( 'listusers' ) ) . + Xml::fieldset( $this->msg( 'listusers' )->text() ) . Html::hidden( 'title', $self ); # Username field - $out .= Xml::label( wfMsg( 'listusersfrom' ), 'offset' ) . ' ' . + $out .= Xml::label( $this->msg( 'listusersfrom' )->text(), 'offset' ) . ' ' . Xml::input( 'username', 20, $this->requestedUser, array( 'id' => 'offset' ) ) . ' '; # Group drop-down list - $out .= Xml::label( wfMsg( 'group' ), 'group' ) . ' ' . + $out .= Xml::label( $this->msg( 'group' )->text(), 'group' ) . ' ' . Xml::openElement('select', array( 'name' => 'group', 'id' => 'group' ) ) . - Xml::option( wfMsg( 'group-all' ), '' ); + Xml::option( $this->msg( 'group-all' )->text(), '' ); foreach( $this->getAllGroups() as $group => $groupText ) $out .= Xml::option( $groupText, $group, $group == $this->requestedGroup ); $out .= Xml::closeElement( 'select' ) . '<br />'; - $out .= Xml::checkLabel( wfMsg('listusers-editsonly'), 'editsOnly', 'editsOnly', $this->editsOnly ); + $out .= Xml::checkLabel( $this->msg( 'listusers-editsonly' )->text(), 'editsOnly', 'editsOnly', $this->editsOnly ); $out .= ' '; - $out .= Xml::checkLabel( wfMsg('listusers-creationsort'), 'creationSort', 'creationSort', $this->creationSort ); + $out .= Xml::checkLabel( $this->msg( 'listusers-creationsort' )->text(), 'creationSort', 'creationSort', $this->creationSort ); $out .= '<br />'; wfRunHooks( 'SpecialListusersHeaderForm', array( $this, &$out ) ); # Submit button and form bottom $out .= Html::hidden( 'limit', $this->mLimit ); - $out .= Xml::submitButton( wfMsg( 'allpagessubmit' ) ); + $out .= Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ); wfRunHooks( 'SpecialListusersHeader', array( $this, &$out ) ); $out .= Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' ); @@ -240,10 +261,12 @@ class UsersPager extends AlphabeticPager { */ function getDefaultQuery() { $query = parent::getDefaultQuery(); - if( $this->requestedGroup != '' ) + if( $this->requestedGroup != '' ) { $query['group'] = $this->requestedGroup; - if( $this->requestedUser != '' ) + } + if( $this->requestedUser != '' ) { $query['username'] = $this->requestedUser; + } wfRunHooks( 'SpecialListusersDefaultQuery', array( $this, &$query ) ); return $query; } @@ -282,6 +305,7 @@ class SpecialListUsers extends SpecialPage { */ public function __construct() { parent::__construct( 'Listusers' ); + $this->mIncludable = true; } /** @@ -293,18 +317,22 @@ class SpecialListUsers extends SpecialPage { $this->setHeaders(); $this->outputHeader(); - $up = new UsersPager( $this->getContext(), $par ); + $up = new UsersPager( $this->getContext(), $par, $this->including() ); # getBody() first to check, if empty $usersbody = $up->getBody(); - $s = $up->getPageHeader(); + $s = ''; + if ( !$this->including() ) { + $s = $up->getPageHeader(); + } + if( $usersbody ) { $s .= $up->getNavigationBar(); $s .= Html::rawElement( 'ul', array(), $usersbody ); $s .= $up->getNavigationBar(); } else { - $s .= wfMessage( 'listusers-noresult' )->parseAsBlock(); + $s .= $this->msg( 'listusers-noresult' )->parseAsBlock(); } $this->getOutput()->addHTML( $s ); diff --git a/includes/specials/SpecialLockdb.php b/includes/specials/SpecialLockdb.php index c1453518..d71ac6e1 100644 --- a/includes/specials/SpecialLockdb.php +++ b/includes/specials/SpecialLockdb.php @@ -87,13 +87,11 @@ class SpecialLockdb extends FormSpecialPage { } fwrite( $fp, $data['Reason'] ); $timestamp = wfTimestampNow(); - fwrite( $fp, "\n<p>" . wfMsgExt( - 'lockedbyandtime', - array( 'content', 'parsemag' ), + fwrite( $fp, "\n<p>" . $this->msg( 'lockedbyandtime', $this->getUser()->getName(), - $wgContLang->date( $timestamp ), - $wgContLang->time( $timestamp ) - ) . "</p>\n" ); + $wgContLang->date( $timestamp, false, false ), + $wgContLang->time( $timestamp, false, false ) + )->inContentLanguage()->text() . "</p>\n" ); fclose( $fp ); return Status::newGood(); diff --git a/includes/specials/SpecialLog.php b/includes/specials/SpecialLog.php index 64190df1..7800e566 100644 --- a/includes/specials/SpecialLog.php +++ b/includes/specials/SpecialLog.php @@ -33,7 +33,7 @@ class SpecialLog extends SpecialPage { /** * List log type for which the target is a user * Thus if the given target is in NS_MAIN we can alter it to be an NS_USER - * Title user instead. + * Title user instead. */ private $typeOnUser = array( 'block', @@ -47,7 +47,7 @@ class SpecialLog extends SpecialPage { public function execute( $par ) { global $wgLogRestrictions; - + $this->setHeaders(); $this->outputHeader(); @@ -65,7 +65,7 @@ class SpecialLog extends SpecialPage { // Set values $opts->fetchValuesFromRequest( $this->getRequest() ); - if ( $par ) { + if ( $par !== null ) { $this->parseParams( $opts, (string)$par ); } @@ -131,7 +131,7 @@ class SpecialLog extends SpecialPage { private function show( FormOptions $opts, array $extraConds ) { # Create a LogPager item to get the results and a LogEventsList item to format them... - $loglist = new LogEventsList( $this->getSkin(), $this->getOutput(), 0 ); + $loglist = new LogEventsList( $this->getContext(), null, LogEventsList::USE_REVDEL_CHECKBOXES ); $pager = new LogPager( $loglist, $opts->getValue( 'type' ), $opts->getValue( 'user' ), $opts->getValue( 'page' ), $opts->getValue( 'pattern' ), $extraConds, $opts->getValue( 'year' ), $opts->getValue( 'month' ), $opts->getValue( 'tagfilter' ) ); @@ -152,9 +152,7 @@ class SpecialLog extends SpecialPage { if ( $logBody ) { $this->getOutput()->addHTML( $pager->getNavigationBar() . - $loglist->beginLogEventsList() . - $logBody . - $loglist->endLogEventsList() . + $this->getRevisionButton( $loglist->beginLogEventsList() . $logBody . $loglist->endLogEventsList() ) . $pager->getNavigationBar() ); } else { @@ -162,6 +160,29 @@ class SpecialLog extends SpecialPage { } } + private function getRevisionButton( $formcontents ) { + # If the user doesn't have the ability to delete log entries, don't bother showing him/her the button. + if ( !$this->getUser()->isAllowedAll( 'deletedhistory', 'deletelogentry' ) ) { + return $formcontents; + } + + # Show button to hide log entries + global $wgScript; + $s = Html::openElement( 'form', array( 'action' => $wgScript, 'id' => 'mw-log-deleterevision-submit' ) ) . "\n"; + $s .= Html::hidden( 'title', SpecialPage::getTitleFor( 'Revisiondelete' ) ) . "\n"; + $s .= Html::hidden( 'target', SpecialPage::getTitleFor( 'Log' ) ) . "\n"; + $s .= Html::hidden( 'type', 'logging' ) . "\n"; + $button = Html::element( 'button', + array( 'type' => 'submit', 'class' => "deleterevision-log-submit mw-log-deleterevision-button" ), + $this->msg( 'showhideselectedlogentries' )->text() + ) . "\n"; + $s .= $button . $formcontents . $button; + $s .= Html::closeElement( 'form' ); + + return $s; + } + + /** * Set page title and show header for this log type * @param $type string diff --git a/includes/specials/SpecialLonelypages.php b/includes/specials/SpecialLonelypages.php index 0800e43c..763bbdb1 100644 --- a/includes/specials/SpecialLonelypages.php +++ b/includes/specials/SpecialLonelypages.php @@ -34,7 +34,7 @@ class LonelyPagesPage extends PageQueryPage { } function getPageHeader() { - return wfMsgExt( 'lonelypagestext', array( 'parse' ) ); + return $this->msg( 'lonelypagestext' )->parseAsBlock(); } function sortDescending() { @@ -50,9 +50,9 @@ class LonelyPagesPage extends PageQueryPage { return array ( 'tables' => array ( 'page', 'pagelinks', 'templatelinks' ), - 'fields' => array ( 'page_namespace AS namespace', - 'page_title AS title', - 'page_title AS value' ), + 'fields' => array ( 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'page_title' ), 'conds' => array ( 'pl_namespace IS NULL', 'page_namespace' => MWNamespace::getContentNamespaces(), 'page_is_redirect' => 0, diff --git a/includes/specials/SpecialMIMEsearch.php b/includes/specials/SpecialMIMEsearch.php index 2213ffa4..104c653f 100644 --- a/includes/specials/SpecialMIMEsearch.php +++ b/includes/specials/SpecialMIMEsearch.php @@ -45,9 +45,9 @@ class MIMEsearchPage extends QueryPage { public function getQueryInfo() { return array( 'tables' => array( 'image' ), - 'fields' => array( "'" . NS_FILE . "' AS namespace", - 'img_name AS title', - 'img_major_mime AS value', + 'fields' => array( 'namespace' => NS_FILE, + 'title' => 'img_name', + 'value' => 'img_major_mime', 'img_size', 'img_width', 'img_height', @@ -59,17 +59,19 @@ class MIMEsearchPage extends QueryPage { } function execute( $par ) { + global $wgScript; + $mime = $par ? $par : $this->getRequest()->getText( 'mime' ); $this->setHeaders(); $this->outputHeader(); $this->getOutput()->addHTML( - Xml::openElement( 'form', array( 'id' => 'specialmimesearch', 'method' => 'get', 'action' => SpecialPage::getTitleFor( 'MIMEsearch' )->getLocalUrl() ) ) . + Xml::openElement( 'form', array( 'id' => 'specialmimesearch', 'method' => 'get', 'action' => $wgScript ) ) . Xml::openElement( 'fieldset' ) . - Html::hidden( 'title', SpecialPage::getTitleFor( 'MIMEsearch' )->getPrefixedText() ) . - Xml::element( 'legend', null, wfMsg( 'mimesearch' ) ) . - Xml::inputLabel( wfMsg( 'mimetype' ), 'mime', 'mime', 20, $mime ) . ' ' . - Xml::submitButton( wfMsg( 'ilsubmit' ) ) . + Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . + Xml::element( 'legend', null, $this->msg( 'mimesearch' )->text() ) . + Xml::inputLabel( $this->msg( 'mimetype' )->text(), 'mime', 'mime', 20, $mime ) . ' ' . + Xml::submitButton( $this->msg( 'ilsubmit' )->text() ) . Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' ) ); @@ -93,17 +95,16 @@ class MIMEsearchPage extends QueryPage { htmlspecialchars( $text ) ); - $download = Linker::makeMediaLinkObj( $nt, wfMsgHtml( 'download' ) ); + $download = Linker::makeMediaLinkObj( $nt, $this->msg( 'download' )->escaped() ); + $download = $this->msg( 'parentheses' )->rawParams( $download )->escaped(); $lang = $this->getLanguage(); $bytes = htmlspecialchars( $lang->formatSize( $result->img_size ) ); - $dimensions = htmlspecialchars( wfMsg( 'widthheight', - $lang->formatNum( $result->img_width ), - $lang->formatNum( $result->img_height ) - ) ); + $dimensions = $this->msg( 'widthheight' )->numParams( $result->img_width, + $result->img_height )->escaped(); $user = Linker::link( Title::makeTitle( NS_USER, $result->img_user_text ), htmlspecialchars( $result->img_user_text ) ); - $time = htmlspecialchars( $lang->timeanddate( $result->img_timestamp ) ); + $time = htmlspecialchars( $lang->userTimeAndDate( $result->img_timestamp, $this->getUser() ) ); - return "($download) $plink . . $dimensions . . $bytes . . $user . . $time"; + return "$download $plink . . $dimensions . . $bytes . . $user . . $time"; } /** diff --git a/includes/specials/SpecialMergeHistory.php b/includes/specials/SpecialMergeHistory.php index 19650da9..1f057499 100644 --- a/includes/specials/SpecialMergeHistory.php +++ b/includes/specials/SpecialMergeHistory.php @@ -76,7 +76,7 @@ class SpecialMergeHistory extends SpecialPage { function preCacheMessages() { // Precache various messages if( !isset( $this->message ) ) { - $this->message['last'] = wfMsgExt( 'last', array( 'escape' ) ); + $this->message['last'] = $this->msg( 'last' )->escaped(); } } @@ -90,7 +90,8 @@ class SpecialMergeHistory extends SpecialPage { $this->outputHeader(); if( $this->mTargetID && $this->mDestID && $this->mAction == 'submit' && $this->mMerge ) { - return $this->merge(); + $this->merge(); + return; } if ( !$this->mSubmitted ) { @@ -100,23 +101,23 @@ class SpecialMergeHistory extends SpecialPage { $errors = array(); if ( !$this->mTargetObj instanceof Title ) { - $errors[] = wfMsgExt( 'mergehistory-invalid-source', array( 'parse' ) ); + $errors[] = $this->msg( 'mergehistory-invalid-source' )->parseAsBlock(); } elseif( !$this->mTargetObj->exists() ) { - $errors[] = wfMsgExt( 'mergehistory-no-source', array( 'parse' ), + $errors[] = $this->msg( 'mergehistory-no-source', array( 'parse' ), wfEscapeWikiText( $this->mTargetObj->getPrefixedText() ) - ); + )->parseAsBlock(); } if ( !$this->mDestObj instanceof Title ) { - $errors[] = wfMsgExt( 'mergehistory-invalid-destination', array( 'parse' ) ); + $errors[] = $this->msg( 'mergehistory-invalid-destination' )->parseAsBlock(); } elseif( !$this->mDestObj->exists() ) { - $errors[] = wfMsgExt( 'mergehistory-no-destination', array( 'parse' ), + $errors[] = $this->msg( 'mergehistory-no-destination', array( 'parse' ), wfEscapeWikiText( $this->mDestObj->getPrefixedText() ) - ); + )->parseAsBlock(); } if ( $this->mTargetObj && $this->mDestObj && $this->mTargetObj->equals( $this->mDestObj ) ) { - $errors[] = wfMsgExt( 'mergehistory-same-destination', array( 'parse' ) ); + $errors[] = $this->msg( 'mergehistory-same-destination' )->parseAsBlock(); } if ( count( $errors ) ) { @@ -139,19 +140,19 @@ class SpecialMergeHistory extends SpecialPage { 'action' => $wgScript ) ) . '<fieldset>' . Xml::element( 'legend', array(), - wfMsg( 'mergehistory-box' ) ) . + $this->msg( 'mergehistory-box' )->text() ) . Html::hidden( 'title', $this->getTitle()->getPrefixedDbKey() ) . Html::hidden( 'submitted', '1' ) . Html::hidden( 'mergepoint', $this->mTimestamp ) . Xml::openElement( 'table' ) . '<tr> - <td>' . Xml::label( wfMsg( 'mergehistory-from' ), 'target' ) . '</td> + <td>' . Xml::label( $this->msg( 'mergehistory-from' )->text(), 'target' ) . '</td> <td>' . Xml::input( 'target', 30, $this->mTarget, array( 'id' => 'target' ) ) . '</td> </tr><tr> - <td>' . Xml::label( wfMsg( 'mergehistory-into' ), 'dest' ) . '</td> + <td>' . Xml::label( $this->msg( 'mergehistory-into' )->text(), 'dest' ) . '</td> <td>' . Xml::input( 'dest', 30, $this->mDest, array( 'id' => 'dest' ) ) . '</td> </tr><tr><td>' . - Xml::submitButton( wfMsg( 'mergehistory-go' ) ) . + Xml::submitButton( $this->msg( 'mergehistory-go' )->text() ) . '</td></tr>' . Xml::closeElement( 'table' ) . '</fieldset>' . @@ -187,12 +188,12 @@ class SpecialMergeHistory extends SpecialPage { # in a nice little table $table = Xml::openElement( 'fieldset' ) . - wfMsgExt( 'mergehistory-merge', array( 'parseinline' ), - $this->mTargetObj->getPrefixedText(), $this->mDestObj->getPrefixedText() ) . + $this->msg( 'mergehistory-merge', $this->mTargetObj->getPrefixedText(), + $this->mDestObj->getPrefixedText() )->parse() . Xml::openElement( 'table', array( 'id' => 'mw-mergehistory-table' ) ) . '<tr> <td class="mw-label">' . - Xml::label( wfMsg( 'mergehistory-reason' ), 'wpComment' ) . + Xml::label( $this->msg( 'mergehistory-reason' )->text(), 'wpComment' ) . '</td> <td class="mw-input">' . Xml::input( 'wpComment', 50, $this->mComment, array( 'id' => 'wpComment' ) ) . @@ -201,7 +202,7 @@ class SpecialMergeHistory extends SpecialPage { <tr> <td> </td> <td class="mw-submit">' . - Xml::submitButton( wfMsg( 'mergehistory-submit' ), array( 'name' => 'merge', 'id' => 'mw-merge-submit' ) ) . + Xml::submitButton( $this->msg( 'mergehistory-submit' )->text(), array( 'name' => 'merge', 'id' => 'mw-merge-submit' ) ) . '</td> </tr>' . Xml::closeElement( 'table' ) . @@ -212,7 +213,7 @@ class SpecialMergeHistory extends SpecialPage { $out->addHTML( '<h2 id="mw-mergehistory">' . - wfMsgHtml( 'mergehistory-list' ) . "</h2>\n" + $this->msg( 'mergehistory-list' )->escaped() . "</h2>\n" ); if( $haveRevisions ) { @@ -225,8 +226,9 @@ class SpecialMergeHistory extends SpecialPage { $out->addWikiMsg( 'mergehistory-empty' ); } - # Show relevant lines from the deletion log: - $out->addHTML( '<h2>' . htmlspecialchars( LogPage::logName( 'merge' ) ) . "</h2>\n" ); + # Show relevant lines from the merge log: + $mergeLogPage = new LogPage( 'merge' ); + $out->addHTML( '<h2>' . $mergeLogPage->getName()->escaped() . "</h2>\n" ); LogEventsList::showLogExtract( $out, 'merge', $this->mTargetObj ); # When we submit, go by page ID to avoid some nasty but unlikely collisions. @@ -251,9 +253,11 @@ class SpecialMergeHistory extends SpecialPage { $ts = wfTimestamp( TS_MW, $row->rev_timestamp ); $checkBox = Xml::radio( 'mergepoint', $ts, false ); + $user = $this->getUser(); + $pageLink = Linker::linkKnown( $rev->getTitle(), - htmlspecialchars( $this->getLanguage()->timeanddate( $ts ) ), + htmlspecialchars( $this->getLanguage()->userTimeAndDate( $ts, $user ) ), array(), array( 'oldid' => $rev->getId() ) ); @@ -262,7 +266,7 @@ class SpecialMergeHistory extends SpecialPage { } # Last link - if( !$rev->userCan( Revision::DELETED_TEXT, $this->getUser() ) ) { + if( !$rev->userCan( Revision::DELETED_TEXT, $user ) ) { $last = $this->message['last']; } elseif( isset( $this->prevId[$row->rev_id] ) ) { $last = Linker::linkKnown( @@ -284,7 +288,8 @@ class SpecialMergeHistory extends SpecialPage { } $comment = Linker::revComment( $rev ); - return "<li>$checkBox ($last) $pageLink . . $userLink $stxt $comment</li>"; + return Html::rawElement( 'li', array(), + $this->msg( 'mergehistory-revisionrow' )->rawParams( $checkBox, $last, $pageLink, $userLink, $stxt, $comment )->escaped() ); } function merge() { @@ -296,7 +301,7 @@ class SpecialMergeHistory extends SpecialPage { if( is_null( $targetTitle ) || is_null( $destTitle ) ) { return false; // validate these } - if( $targetTitle->getArticleId() == $destTitle->getArticleId() ) { + if( $targetTitle->getArticleID() == $destTitle->getArticleID() ) { return false; } # Verify that this timestamp is valid @@ -355,18 +360,18 @@ class SpecialMergeHistory extends SpecialPage { ); if( !$haveRevisions ) { if( $this->mComment ) { - $comment = wfMsgForContent( + $comment = $this->msg( 'mergehistory-comment', $targetTitle->getPrefixedText(), $destTitle->getPrefixedText(), $this->mComment - ); + )->inContentLanguage()->text(); } else { - $comment = wfMsgForContent( + $comment = $this->msg( 'mergehistory-autocomment', $targetTitle->getPrefixedText(), $destTitle->getPrefixedText() - ); + )->inContentLanguage()->text(); } $mwRedir = MagicWord::get( 'redirect' ); $redirectText = $mwRedir->getSynonym( 0 ) . ' [[' . $destTitle->getPrefixedText() . "]]\n"; @@ -404,9 +409,8 @@ class SpecialMergeHistory extends SpecialPage { array( $destTitle->getPrefixedText(), $timestampLimit ) ); - $this->getOutput()->addHTML( - wfMsgExt( 'mergehistory-success', array('parseinline'), - $targetTitle->getPrefixedText(), $destTitle->getPrefixedText(), $count ) ); + $this->getOutput()->addWikiMsg( 'mergehistory-success', + $targetTitle->getPrefixedText(), $destTitle->getPrefixedText(), $count ); wfRunHooks( 'ArticleMergeComplete', array( $targetTitle, $destTitle ) ); diff --git a/includes/specials/SpecialMostcategories.php b/includes/specials/SpecialMostcategories.php index 98b73675..3f0bafa3 100644 --- a/includes/specials/SpecialMostcategories.php +++ b/includes/specials/SpecialMostcategories.php @@ -41,27 +41,57 @@ class MostcategoriesPage extends QueryPage { function getQueryInfo() { return array ( 'tables' => array ( 'categorylinks', 'page' ), - 'fields' => array ( 'page_namespace AS namespace', - 'page_title AS title', - 'COUNT(*) AS value' ), + 'fields' => array ( 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'COUNT(*)' ), 'conds' => array ( 'page_namespace' => MWNamespace::getContentNamespaces() ), 'options' => array ( 'HAVING' => 'COUNT(*) > 1', - 'GROUP BY' => 'page_namespace, page_title' ), + 'GROUP BY' => array( 'page_namespace', 'page_title' ) ), 'join_conds' => array ( 'page' => array ( 'LEFT JOIN', 'page_id = cl_from' ) ) ); } /** + * @param $db DatabaseBase + * @param $res + */ + function preprocessResults( $db, $res ) { + # There's no point doing a batch check if we aren't caching results; + # the page must exist for it to have been pulled out of the table + if ( !$this->isCached() || !$res->numRows() ) { + return; + } + + $batch = new LinkBatch(); + foreach ( $res as $row ) { + $batch->add( $row->namespace, $row->title ); + } + $batch->execute(); + + $res->seek( 0 ); + } + + /** * @param $skin Skin * @param $result * @return string */ function formatResult( $skin, $result ) { $title = Title::makeTitleSafe( $result->namespace, $result->title ); + if ( !$title ) { + return Html::element( 'span', array( 'class' => 'mw-invalidtitle' ), + Linker::getInvalidTitleDescription( $this->getContext(), $result->namespace, $result->title ) ); + } + + if ( $this->isCached() ) { + $link = Linker::link( $title ); + } else { + $link = Linker::linkKnown( $title ); + } $count = $this->msg( 'ncategories' )->numParams( $result->value )->escaped(); - $link = Linker::link( $title ); + return $this->getLanguage()->specialList( $link, $count ); } } diff --git a/includes/specials/SpecialMostimages.php b/includes/specials/SpecialMostimages.php index 7805e53e..3d797908 100644 --- a/includes/specials/SpecialMostimages.php +++ b/includes/specials/SpecialMostimages.php @@ -41,9 +41,9 @@ class MostimagesPage extends ImageQueryPage { function getQueryInfo() { return array ( 'tables' => array ( 'imagelinks' ), - 'fields' => array ( "'" . NS_FILE . "' AS namespace", - 'il_to AS title', - 'COUNT(*) AS value' ), + 'fields' => array ( 'namespace' => NS_FILE, + 'title' => 'il_to', + 'value' => 'COUNT(*)' ), 'options' => array ( 'GROUP BY' => 'il_to', 'HAVING' => 'COUNT(*) > 1' ) ); diff --git a/includes/specials/SpecialMostinterwikis.php b/includes/specials/SpecialMostinterwikis.php new file mode 100644 index 00000000..894d697b --- /dev/null +++ b/includes/specials/SpecialMostinterwikis.php @@ -0,0 +1,112 @@ +<?php +/** + * Implements Special:Mostinterwikis + * + * Copyright © 2012 Umherirrender + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + * @ingroup SpecialPage + * @author Umherirrender + */ + +/** + * A special page that listed pages that have highest interwiki count + * + * @ingroup SpecialPage + */ +class MostinterwikisPage extends QueryPage { + + function __construct( $name = 'Mostinterwikis' ) { + parent::__construct( $name ); + } + + function isExpensive() { return true; } + function isSyndicated() { return false; } + + function getQueryInfo() { + return array ( + 'tables' => array ( + 'langlinks', + 'page' + ), 'fields' => array ( + 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'COUNT(*)' + ), 'conds' => array ( + 'page_namespace' => MWNamespace::getContentNamespaces() + ), 'options' => array ( + 'HAVING' => 'COUNT(*) > 1', + 'GROUP BY' => array ( + 'page_namespace', + 'page_title' + ) + ), 'join_conds' => array ( + 'page' => array ( + 'LEFT JOIN', + 'page_id = ll_from' + ) + ) + ); + } + + /** + * Pre-fill the link cache + * + * @param $db DatabaseBase + * @param $res + */ + function preprocessResults( $db, $res ) { + # There's no point doing a batch check if we aren't caching results; + # the page must exist for it to have been pulled out of the table + if ( !$this->isCached() || !$res->numRows() ) { + return; + } + + $batch = new LinkBatch; + foreach ( $res as $row ) { + $batch->add( $row->namespace, $row->title ); + } + $batch->execute(); + + // Back to start for display + $res->seek( 0 ); + } + + /** + * @param $skin Skin + * @param $result + * @return string + */ + function formatResult( $skin, $result ) { + $title = Title::makeTitleSafe( $result->namespace, $result->title ); + if ( !$title ) { + return Html::element( 'span', array( 'class' => 'mw-invalidtitle' ), + Linker::getInvalidTitleDescription( $this->getContext(), $result->namespace, $result->title ) ); + } + + if ( $this->isCached() ) { + $link = Linker::link( $title ); + } else { + $link = Linker::linkKnown( $title ); + } + + $count = $this->msg( 'ninterwikis' )->numParams( $result->value )->escaped(); + + return $this->getLanguage()->specialList( $link, $count ); + } +} diff --git a/includes/specials/SpecialMostlinked.php b/includes/specials/SpecialMostlinked.php index a16f0872..89c43509 100644 --- a/includes/specials/SpecialMostlinked.php +++ b/includes/specials/SpecialMostlinked.php @@ -42,13 +42,13 @@ class MostlinkedPage extends QueryPage { function getQueryInfo() { return array ( 'tables' => array ( 'pagelinks', 'page' ), - 'fields' => array ( 'pl_namespace AS namespace', - 'pl_title AS title', - 'COUNT(*) AS value', + 'fields' => array ( 'namespace' => 'pl_namespace', + 'title' => 'pl_title', + 'value' => 'COUNT(*)', 'page_namespace' ), 'options' => array ( 'HAVING' => 'COUNT(*) > 1', - 'GROUP BY' => 'pl_namespace, pl_title, '. - 'page_namespace' ), + 'GROUP BY' => array( 'pl_namespace', 'pl_title', + 'page_namespace' ) ), 'join_conds' => array ( 'page' => array ( 'LEFT JOIN', array ( 'page_namespace = pl_namespace', 'page_title = pl_title' ) ) ) @@ -62,12 +62,12 @@ class MostlinkedPage extends QueryPage { * @param $res */ function preprocessResults( $db, $res ) { - if( $db->numRows( $res ) > 0 ) { + if ( $res->numRows() > 0 ) { $linkBatch = new LinkBatch(); foreach ( $res as $row ) { $linkBatch->add( $row->namespace, $row->title ); } - $db->dataSeek( $res, 0 ); + $res->seek( 0 ); $linkBatch->execute(); } } @@ -94,7 +94,8 @@ class MostlinkedPage extends QueryPage { function formatResult( $skin, $result ) { $title = Title::makeTitleSafe( $result->namespace, $result->title ); if ( !$title ) { - return '<!-- ' . htmlspecialchars( "Invalid title: [[$title]]" ) . ' -->'; + return Html::element( 'span', array( 'class' => 'mw-invalidtitle' ), + Linker::getInvalidTitleDescription( $this->getContext(), $result->namespace, $result->title ) ); } $link = Linker::link( $title ); $wlh = $this->makeWlhLink( $title, diff --git a/includes/specials/SpecialMostlinkedcategories.php b/includes/specials/SpecialMostlinkedcategories.php index 7fb9dea9..dadef8bf 100644 --- a/includes/specials/SpecialMostlinkedcategories.php +++ b/includes/specials/SpecialMostlinkedcategories.php @@ -40,9 +40,9 @@ class MostlinkedCategoriesPage extends QueryPage { function getQueryInfo() { return array ( 'tables' => array ( 'category' ), - 'fields' => array ( 'cat_title AS title', - NS_CATEGORY . ' AS namespace', - 'cat_pages AS value' ), + 'fields' => array ( 'title' => 'cat_title', + 'namespace' => NS_CATEGORY, + 'value' => 'cat_pages' ), ); } @@ -55,6 +55,10 @@ class MostlinkedCategoriesPage extends QueryPage { * @param $res DatabaseResult */ function preprocessResults( $db, $res ) { + if ( !$res->numRows() ) { + return; + } + $batch = new LinkBatch; foreach ( $res as $row ) { $batch->add( NS_CATEGORY, $row->title ); @@ -62,10 +66,7 @@ class MostlinkedCategoriesPage extends QueryPage { $batch->execute(); // Back to start for display - if ( $db->numRows( $res ) > 0 ) { - // If there are no rows we get an error seeking. - $db->dataSeek( $res, 0 ); - } + $res->seek( 0 ); } /** @@ -76,7 +77,12 @@ class MostlinkedCategoriesPage extends QueryPage { function formatResult( $skin, $result ) { global $wgContLang; - $nt = Title::makeTitle( NS_CATEGORY, $result->title ); + $nt = Title::makeTitleSafe( NS_CATEGORY, $result->title ); + if ( !$nt ) { + return Html::element( 'span', array( 'class' => 'mw-invalidtitle' ), + Linker::getInvalidTitleDescription( $this->getContext(), NS_CATEGORY, $result->title ) ); + } + $text = $wgContLang->convert( $nt->getText() ); $plink = Linker::link( $nt, htmlspecialchars( $text ) ); diff --git a/includes/specials/SpecialMostlinkedtemplates.php b/includes/specials/SpecialMostlinkedtemplates.php index 6fb09426..22932e5c 100644 --- a/includes/specials/SpecialMostlinkedtemplates.php +++ b/includes/specials/SpecialMostlinkedtemplates.php @@ -64,28 +64,32 @@ class MostlinkedTemplatesPage extends QueryPage { public function getQueryInfo() { return array ( 'tables' => array ( 'templatelinks' ), - 'fields' => array ( 'tl_namespace AS namespace', - 'tl_title AS title', - 'COUNT(*) AS value' ), + 'fields' => array ( 'namespace' => 'tl_namespace', + 'title' => 'tl_title', + 'value' => 'COUNT(*)' ), 'conds' => array ( 'tl_namespace' => NS_TEMPLATE ), - 'options' => array( 'GROUP BY' => 'tl_namespace, tl_title' ) + 'options' => array( 'GROUP BY' => array( 'tl_namespace', 'tl_title' ) ) ); } /** * Pre-cache page existence to speed up link generation * - * @param $db Database connection + * @param $db DatabaseBase connection * @param $res ResultWrapper */ public function preprocessResults( $db, $res ) { + if ( !$res->numRows() ) { + return; + } + $batch = new LinkBatch(); foreach ( $res as $row ) { $batch->add( $row->namespace, $row->title ); } $batch->execute(); - if( $db->numRows( $res ) > 0 ) - $db->dataSeek( $res, 0 ); + + $res->seek( 0 ); } /** @@ -96,7 +100,11 @@ class MostlinkedTemplatesPage extends QueryPage { * @return String */ public function formatResult( $skin, $result ) { - $title = Title::makeTitle( $result->namespace, $result->title ); + $title = Title::makeTitleSafe( $result->namespace, $result->title ); + if ( !$title ) { + return Html::element( 'span', array( 'class' => 'mw-invalidtitle' ), + Linker::getInvalidTitleDescription( $this->getContext(), $result->namespace, $result->title ) ); + } return $this->getLanguage()->specialList( Linker::link( $title ), diff --git a/includes/specials/SpecialMovepage.php b/includes/specials/SpecialMovepage.php index 5536fbc9..af3dbf3e 100644 --- a/includes/specials/SpecialMovepage.php +++ b/includes/specials/SpecialMovepage.php @@ -141,13 +141,13 @@ class MovePageForm extends UnlistedSpecialPage { && $newTitle->quickUserCan( 'delete', $user ) ) { $out->addWikiMsg( 'delete_and_move_text', $newTitle->getPrefixedText() ); - $movepagebtn = wfMsg( 'delete_and_move' ); + $movepagebtn = $this->msg( 'delete_and_move' )->text(); $submitVar = 'wpDeleteAndMove'; $confirm = " <tr> <td></td> <td class='mw-input'>" . - Xml::checkLabel( wfMsg( 'delete_and_move_confirm' ), 'wpConfirm', 'wpConfirm' ) . + Xml::checkLabel( $this->msg( 'delete_and_move_confirm' )->text(), 'wpConfirm', 'wpConfirm' ) . "</td> </tr>"; $err = array(); @@ -157,7 +157,7 @@ class MovePageForm extends UnlistedSpecialPage { } $out->addWikiMsg( $wgFixDoubleRedirects ? 'movepagetext' : 'movepagetext-noredirectfixer' ); - $movepagebtn = wfMsg( 'movepagebtn' ); + $movepagebtn = $this->msg( 'movepagebtn' )->text(); $submitVar = 'wpMove'; $confirm = false; } @@ -246,14 +246,22 @@ class MovePageForm extends UnlistedSpecialPage { // Byte limit (not string length limit) for wpReason and wpNewTitleMain // is enforced in the mediawiki.special.movePage module + $immovableNamespaces = array(); + + foreach ( array_keys( $this->getLanguage()->getNamespaces() ) as $nsId ) { + if ( !MWNamespace::isMovable( $nsId ) ) { + $immovableNamespaces[] = $nsId; + } + } + $out->addHTML( Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalURL( 'action=submit' ), 'id' => 'movepage' ) ) . Xml::openElement( 'fieldset' ) . - Xml::element( 'legend', null, wfMsg( 'move-page-legend' ) ) . - Xml::openElement( 'table', array( 'border' => '0', 'id' => 'mw-movepage-table' ) ) . + Xml::element( 'legend', null, $this->msg( 'move-page-legend' )->text() ) . + Xml::openElement( 'table', array( 'id' => 'mw-movepage-table' ) ) . "<tr> <td class='mw-label'>" . - wfMsgHtml( 'movearticle' ) . + $this->msg( 'movearticle' )->escaped() . "</td> <td class='mw-input'> <strong>{$oldTitleLink}</strong> @@ -261,11 +269,14 @@ class MovePageForm extends UnlistedSpecialPage { </tr> <tr> <td class='mw-label'>" . - Xml::label( wfMsg( 'newtitle' ), 'wpNewTitleMain' ) . + Xml::label( $this->msg( 'newtitle' )->text(), 'wpNewTitleMain' ) . "</td> <td class='mw-input'>" . Html::namespaceSelector( - array( 'selected' => $newTitle->getNamespace() ), + array( + 'selected' => $newTitle->getNamespace(), + 'exclude' => $immovableNamespaces + ), array( 'name' => 'wpNewTitleNs', 'id' => 'wpNewTitleNs' ) ) . Xml::input( 'wpNewTitleMain', 60, $wgContLang->recodeForEdit( $newTitle->getText() ), array( @@ -278,7 +289,7 @@ class MovePageForm extends UnlistedSpecialPage { </tr> <tr> <td class='mw-label'>" . - Xml::label( wfMsg( 'movereason' ), 'wpReason' ) . + Xml::label( $this->msg( 'movereason' )->text(), 'wpReason' ) . "</td> <td class='mw-input'>" . Html::element( 'textarea', array( 'name' => 'wpReason', 'id' => 'wpReason', 'cols' => 60, 'rows' => 2, @@ -292,7 +303,7 @@ class MovePageForm extends UnlistedSpecialPage { <tr> <td></td> <td class='mw-input'>" . - Xml::checkLabel( wfMsg( 'movetalk' ), 'wpMovetalk', 'wpMovetalk', $this->moveTalk ) . + Xml::checkLabel( $this->msg( 'movetalk' )->text(), 'wpMovetalk', 'wpMovetalk', $this->moveTalk ) . "</td> </tr>" ); @@ -303,7 +314,7 @@ class MovePageForm extends UnlistedSpecialPage { <tr> <td></td> <td class='mw-input' >" . - Xml::checkLabel( wfMsg( 'move-leave-redirect' ), 'wpLeaveRedirect', + Xml::checkLabel( $this->msg( 'move-leave-redirect' )->text(), 'wpLeaveRedirect', 'wpLeaveRedirect', $this->leaveRedirect ) . "</td> </tr>" @@ -315,7 +326,7 @@ class MovePageForm extends UnlistedSpecialPage { <tr> <td></td> <td class='mw-input' >" . - Xml::checkLabel( wfMsg( 'fix-double-redirects' ), 'wpFixRedirects', + Xml::checkLabel( $this->msg( 'fix-double-redirects' )->text(), 'wpFixRedirects', 'wpFixRedirects', $this->fixRedirects ) . "</td> </tr>" @@ -335,15 +346,11 @@ class MovePageForm extends UnlistedSpecialPage { array( 'id' => 'wpMovesubpages' ) ) . ' ' . Xml::tags( 'label', array( 'for' => 'wpMovesubpages' ), - wfMsgExt( + $this->msg( ( $this->oldTitle->hasSubpages() ? 'move-subpages' - : 'move-talk-subpages' ), - array( 'parseinline' ), - $this->getLanguage()->formatNum( $wgMaximumMovedPages ), - # $2 to allow use of PLURAL in message. - $wgMaximumMovedPages - ) + : 'move-talk-subpages' ) + )->numParams( $wgMaximumMovedPages )->params( $wgMaximumMovedPages )->parse() ) . "</td> </tr>" @@ -351,14 +358,14 @@ 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( " <tr> <td></td> <td class='mw-input'>" . - Xml::checkLabel( wfMsg( 'move-watch' ), 'wpWatch', 'watch', $watchChecked ) . + Xml::checkLabel( $this->msg( 'move-watch' )->text(), 'wpWatch', 'watch', $watchChecked ) . "</td> </tr>"); } @@ -384,7 +391,7 @@ class MovePageForm extends UnlistedSpecialPage { } function doSubmit() { - global $wgMaximumMovedPages, $wgFixDoubleRedirects, $wgDeleteRevisionsLimit; + global $wgMaximumMovedPages, $wgFixDoubleRedirects; $user = $this->getUser(); @@ -421,7 +428,7 @@ class MovePageForm extends UnlistedSpecialPage { return; } - $reason = wfMessage( 'delete_and_move_reason', $ot )->inContentLanguage()->text(); + $reason = $this->msg( 'delete_and_move_reason', $ot )->inContentLanguage()->text(); // Delete an associated image if there is if ( $nt->getNamespace() == NS_FILE ) { @@ -433,8 +440,9 @@ class MovePageForm extends UnlistedSpecialPage { $error = ''; // passed by ref $page = WikiPage::factory( $nt ); - if ( !$page->doDeleteArticle( $reason, false, 0, true, $error, $user ) ) { - $this->showForm( array( array( 'cannotdelete', wfEscapeWikiText( $nt->getPrefixedText() ) ) ) ); + $deleteStatus = $page->doDeleteArticleReal( $reason, false, 0, true, $error, $user ); + if ( !$deleteStatus->isGood() ) { + $this->showForm( $deleteStatus->getErrorsArray() ); return; } } @@ -459,7 +467,7 @@ class MovePageForm extends UnlistedSpecialPage { wfRunHooks( 'SpecialMovepageAfterMove', array( &$this, &$ot, &$nt ) ); $out = $this->getOutput(); - $out->setPagetitle( wfMsg( 'pagemovedsub' ) ); + $out->setPageTitle( $this->msg( 'pagemovedsub' ) ); $oldLink = Linker::link( $ot, @@ -472,7 +480,7 @@ class MovePageForm extends UnlistedSpecialPage { $newText = $nt->getPrefixedText(); $msgName = $createRedirect ? 'movepage-moved-redirect' : 'movepage-moved-noredirect'; - $out->addHTML( wfMessage( 'movepage-moved' )->rawParams( $oldLink, + $out->addHTML( $this->msg( 'movepage-moved' )->rawParams( $oldLink, $newLink )->params( $oldText, $newText )->parseAsBlock() ); $out->addWikiMsg( $msgName ); @@ -562,15 +570,15 @@ class MovePageForm extends UnlistedSpecialPage { $newSubpage = Title::makeTitleSafe( $newNs, $newPageName ); if( !$newSubpage ) { $oldLink = Linker::linkKnown( $oldSubpage ); - $extraOutput []= wfMsgHtml( 'movepage-page-unmoved', $oldLink, - htmlspecialchars(Title::makeName( $newNs, $newPageName ))); + $extraOutput []= $this->msg( 'movepage-page-unmoved' )->rawParams( $oldLink + )->params( Title::makeName( $newNs, $newPageName ) )->escaped(); continue; } # This was copy-pasted from Renameuser, bleh. if ( $newSubpage->exists() && !$oldSubpage->isValidMoveTarget( $newSubpage ) ) { $link = Linker::linkKnown( $newSubpage ); - $extraOutput []= wfMsgHtml( 'movepage-page-exists', $link ); + $extraOutput []= $this->msg( 'movepage-page-exists' )->rawParams( $link )->escaped(); } else { $success = $oldSubpage->moveTo( $newSubpage, true, $this->reason, $createRedirect ); if( $success === true ) { @@ -584,16 +592,16 @@ class MovePageForm extends UnlistedSpecialPage { array( 'redirect' => 'no' ) ); $newLink = Linker::linkKnown( $newSubpage ); - $extraOutput []= wfMsgHtml( 'movepage-page-moved', $oldLink, $newLink ); + $extraOutput []= $this->msg( 'movepage-page-moved' )->rawParams( $oldLink, $newLink )->escaped(); ++$count; if( $count >= $wgMaximumMovedPages ) { - $extraOutput []= wfMsgExt( 'movepage-max-pages', array( 'parsemag', 'escape' ), $this->getLanguage()->formatNum( $wgMaximumMovedPages ) ); + $extraOutput []= $this->msg( 'movepage-max-pages' )->numParams( $wgMaximumMovedPages )->escaped(); break; } } else { $oldLink = Linker::linkKnown( $oldSubpage ); $newLink = Linker::link( $newSubpage ); - $extraOutput []= wfMsgHtml( 'movepage-page-unmoved', $oldLink, $newLink ); + $extraOutput []= $this->msg( 'movepage-page-unmoved' )->rawParams( $oldLink, $newLink )->escaped(); } } @@ -621,8 +629,9 @@ class MovePageForm extends UnlistedSpecialPage { } function showLogFragment( $title ) { + $moveLogPage = new LogPage( 'move' ); $out = $this->getOutput(); - $out->addHTML( Xml::element( 'h2', null, LogPage::logName( 'move' ) ) ); + $out->addHTML( Xml::element( 'h2', null, $moveLogPage->getName()->text() ) ); LogEventsList::showLogExtract( $out, 'move', $title ); } diff --git a/includes/specials/SpecialNewimages.php b/includes/specials/SpecialNewimages.php index b88123dc..350aac63 100644 --- a/includes/specials/SpecialNewimages.php +++ b/includes/specials/SpecialNewimages.php @@ -58,6 +58,9 @@ class NewFilesPager extends ReverseChronologicalPager { function __construct( IContextSource $context, $par = null ) { $this->like = $context->getRequest()->getText( 'like' ); $this->showbots = $context->getRequest()->getBool( 'showbots' , 0 ); + if ( is_numeric( $par ) ) { + $this->setLimit( $par ); + } parent::__construct( $context ); } @@ -68,15 +71,18 @@ class NewFilesPager extends ReverseChronologicalPager { $tables = array( 'image' ); if( !$this->showbots ) { - $tables[] = 'user_groups'; - $conds[] = 'ug_group IS NULL'; - $jconds['user_groups'] = array( - 'LEFT JOIN', - array( - 'ug_group' => User::getGroupsWithPermission( 'bot' ), - 'ug_user = img_user' - ) - ); + $groupsWithBotPermission = User::getGroupsWithPermission( 'bot' ); + if( count( $groupsWithBotPermission ) ) { + $tables[] = 'user_groups'; + $conds[] = 'ug_group IS NULL'; + $jconds['user_groups'] = array( + 'LEFT JOIN', + array( + 'ug_group' => $groupsWithBotPermission, + 'ug_user = img_user' + ) + ); + } } if( !$wgMiserMode && $this->like !== null ){ @@ -123,7 +129,7 @@ class NewFilesPager extends ReverseChronologicalPager { $this->gallery->add( $title, "$ul<br />\n<i>" - . htmlspecialchars( $this->getLanguage()->timeanddate( $row->img_timestamp, true ) ) + . htmlspecialchars( $this->getLanguage()->userTimeAndDate( $row->img_timestamp, $this->getUser() ) ) . "</i><br />\n" ); } @@ -139,13 +145,13 @@ class NewFilesPager extends ReverseChronologicalPager { ), 'showbots' => array( 'type' => 'check', - 'label' => wfMessage( 'showhidebots', wfMsg( 'show' ) ), + 'label' => $this->msg( 'showhidebots', $this->msg( 'show' )->plain() )->escaped(), 'name' => 'showbots', # 'default' => $this->getRequest()->getBool( 'showbots', 0 ), ), 'limit' => array( 'type' => 'hidden', - 'default' => $this->getRequest()->getText( 'limit' ), + 'default' => $this->mLimit, 'name' => 'limit', ), 'offset' => array( @@ -161,9 +167,9 @@ class NewFilesPager extends ReverseChronologicalPager { $form = new HTMLForm( $fields, $this->getContext() ); $form->setTitle( $this->getTitle() ); - $form->setSubmitText( wfMsg( 'ilsubmit' ) ); + $form->setSubmitTextMsg( 'ilsubmit' ); $form->setMethod( 'get' ); - $form->setWrapperLegend( wfMsg( 'newimages-legend' ) ); + $form->setWrapperLegendMsg( 'newimages-legend' ); return $form; } diff --git a/includes/specials/SpecialNewpages.php b/includes/specials/SpecialNewpages.php index 54bcb97f..8e15d554 100644 --- a/includes/specials/SpecialNewpages.php +++ b/includes/specials/SpecialNewpages.php @@ -143,7 +143,9 @@ class SpecialNewpages extends IncludableSpecialPage { return $this->feed( $feedType ); } - $out->setFeedAppendQuery( wfArrayToCGI( $this->opts->getAllValues() ) ); + $allValues = $this->opts->getAllValues(); + unset( $allValues['feed'] ); + $out->setFeedAppendQuery( wfArrayToCGI( $allValues ) ); } $pager = new NewPagesPager( $this, $this->opts ); @@ -165,7 +167,7 @@ class SpecialNewpages extends IncludableSpecialPage { global $wgGroupPermissions; // show/hide links - $showhide = array( wfMsgHtml( 'show' ), wfMsgHtml( 'hide' ) ); + $showhide = array( $this->msg( 'show' )->escaped(), $this->msg( 'hide' )->escaped() ); // Option value -> message mapping $filters = array( @@ -197,7 +199,7 @@ class SpecialNewpages extends IncludableSpecialPage { $link = Linker::link( $self, $showhide[$onoff], array(), array( $key => $onoff ) + $changed ); - $links[$key] = wfMsgHtml( $msg, $link ); + $links[$key] = $this->msg( $msg )->rawParams( $link )->escaped(); } return $this->getLanguage()->pipeList( $links ); @@ -230,14 +232,23 @@ class SpecialNewpages extends IncludableSpecialPage { $form = Xml::openElement( 'form', array( 'action' => $wgScript ) ) . Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) . - Xml::fieldset( wfMsg( 'newpages' ) ) . + Xml::fieldset( $this->msg( 'newpages' )->text() ) . Xml::openElement( 'table', array( 'id' => 'mw-newpages-table' ) ) . '<tr> <td class="mw-label">' . - Xml::label( wfMsg( 'namespace' ), 'namespace' ) . + Xml::label( $this->msg( 'namespace' )->text(), 'namespace' ) . '</td> <td class="mw-input">' . - Xml::namespaceSelector( $namespace, 'all' ) . + Html::namespaceSelector( + array( + 'selected' => $namespace, + 'all' => 'all', + ), array( + 'name' => 'namespace', + 'id' => 'namespace', + 'class' => 'namespaceselector', + ) + ) . '</td> </tr>' . ( $tagFilter ? ( '<tr> @@ -251,7 +262,7 @@ class SpecialNewpages extends IncludableSpecialPage { ( $wgEnableNewpagesUserFilter ? '<tr> <td class="mw-label">' . - Xml::label( wfMsg( 'newpages-username' ), 'mw-np-username' ) . + Xml::label( $this->msg( 'newpages-username' )->text(), 'mw-np-username' ) . '</td> <td class="mw-input">' . Xml::input( 'username', 30, $userText, array( 'id' => 'mw-np-username' ) ) . @@ -259,7 +270,7 @@ class SpecialNewpages extends IncludableSpecialPage { </tr>' : '' ) . '<tr> <td></td> <td class="mw-submit">' . - Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . + Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . '</td> </tr>' . '<tr> @@ -283,6 +294,8 @@ class SpecialNewpages extends IncludableSpecialPage { * @return String */ public function formatRow( $result ) { + $title = Title::newFromRow( $result ); + # Revision deletion works on revisions, so we should cast one $row = array( 'comment' => $result->rc_comment, @@ -291,15 +304,15 @@ class SpecialNewpages extends IncludableSpecialPage { 'user' => $result->rc_user, ); $rev = new Revision( $row ); + $rev->setTitle( $title ); $classes = array(); $lang = $this->getLanguage(); $dm = $lang->getDirMark(); - $title = Title::newFromRow( $result ); $spanTime = Html::element( 'span', array( 'class' => 'mw-newpages-time' ), - $lang->timeanddate( $result->rc_timestamp, true ) + $lang->userTimeAndDate( $result->rc_timestamp, $this->getUser() ) ); $time = Linker::linkKnown( $title, @@ -324,14 +337,15 @@ class SpecialNewpages extends IncludableSpecialPage { ); $histLink = Linker::linkKnown( $title, - wfMsgHtml( 'hist' ), + $this->msg( 'hist' )->escaped(), array(), array( 'action' => 'history' ) ); - $hist = Html::rawElement( 'span', array( 'class' => 'mw-newpages-history' ), wfMsg( 'parentheses', $histLink ) ); + $hist = Html::rawElement( 'span', array( 'class' => 'mw-newpages-history' ), + $this->msg( 'parentheses' )->rawParams( $histLink )->escaped() ); $length = Html::element( 'span', array( 'class' => 'mw-newpages-length' ), - '[' . $this->msg( 'nbytes' )->numParams( $result->length )->text() . ']' + $this->msg( 'brackets' )->params( $this->msg( 'nbytes' )->numParams( $result->length )->text() ) ); $ulink = Linker::revUserTools( $rev ); @@ -346,8 +360,8 @@ class SpecialNewpages extends IncludableSpecialPage { $classes[] = 'mw-newpages-zero-byte-page'; } - # Tags, if any. check for including due to bug 23293 - if ( !$this->including() ) { + # Tags, if any. + if( isset( $result->ts_tags ) ) { list( $tagDisplay, $newClasses ) = ChangeTags::formatSummaryRow( $result->ts_tags, 'newpages' ); $classes = array_merge( $classes, $newClasses ); } else { @@ -356,11 +370,11 @@ class SpecialNewpages extends IncludableSpecialPage { $css = count( $classes ) ? ' class="' . implode( ' ', $classes ) . '"' : ''; - # Display the old title if the namespace has been changed + # Display the old title if the namespace/title has been changed $oldTitleText = ''; - if ( $result->page_namespace !== $result->rc_namespace ) { - $oldTitleText = wfMessage( 'rc-old-title' )->params( Title::makeTitle( $result->rc_namespace, $result->rc_title ) - ->getPrefixedText() )->escaped(); + $oldTitle = Title::makeTitle( $result->rc_namespace, $result->rc_title ); + if ( !$title->equals( $oldTitle ) ) { + $oldTitleText = $this->msg( 'rc-old-title' )->params( $oldTitle->getPrefixedText() )->escaped(); } return "<li{$css}>{$time} {$dm}{$plink} {$hist} {$dm}{$length} {$dm}{$ulink} {$comment} {$tagDisplay} {$oldTitleText}</li>\n"; @@ -396,7 +410,7 @@ class SpecialNewpages extends IncludableSpecialPage { $feed = new $wgFeedClasses[$type]( $this->feedTitle(), - wfMsgExt( 'tagline', 'parsemag' ), + $this->msg( 'tagline' )->text(), $this->getTitle()->getFullUrl() ); @@ -420,7 +434,7 @@ class SpecialNewpages extends IncludableSpecialPage { } protected function feedItem( $row ) { - $title = Title::MakeTitle( intval( $row->rc_namespace ), $row->rc_title ); + $title = Title::makeTitle( intval( $row->rc_namespace ), $row->rc_title ); if( $title ) { $date = $row->rc_timestamp; $comments = $title->getTalkPage()->getFullURL(); @@ -445,7 +459,8 @@ class SpecialNewpages extends IncludableSpecialPage { protected function feedItemDesc( $row ) { $revision = Revision::newFromId( $row->rev_id ); if( $revision ) { - return '<p>' . htmlspecialchars( $revision->getUserText() ) . wfMsgForContent( 'colon-separator' ) . + return '<p>' . htmlspecialchars( $revision->getUserText() ) . + $this->msg( 'colon-separator' )->inContentLanguage()->escaped() . htmlspecialchars( FeedItem::stripComment( $revision->getComment() ) ) . "</p>\n<hr />\n<div>" . nl2br( htmlspecialchars( $revision->getText() ) ) . "</div>"; @@ -515,7 +530,7 @@ class NewPagesPager extends ReverseChronologicalPager { $fields = array( 'rc_namespace', 'rc_title', 'rc_cur_id', 'rc_user', 'rc_user_text', 'rc_comment', 'rc_timestamp', 'rc_patrolled','rc_id', 'rc_deleted', - 'page_len AS length', 'page_latest AS rev_id', 'ts_tags', 'rc_this_oldid', + 'length' => 'page_len', 'rev_id' => 'page_latest', 'rc_this_oldid', 'page_namespace', 'page_title' ); $join_conds = array( 'page' => array( 'INNER JOIN', 'page_id=rc_cur_id' ) ); @@ -531,13 +546,10 @@ class NewPagesPager extends ReverseChronologicalPager { 'join_conds' => $join_conds ); - // Empty array for fields, it'll be set by us anyway. - $fields = array(); - // Modify query for tags ChangeTags::modifyDisplayQuery( $info['tables'], - $fields, + $info['fields'], $info['conds'], $info['join_conds'], $info['options'], diff --git a/includes/specials/SpecialPasswordReset.php b/includes/specials/SpecialPasswordReset.php index 62731e98..efb57657 100644 --- a/includes/specials/SpecialPasswordReset.php +++ b/includes/specials/SpecialPasswordReset.php @@ -65,6 +65,9 @@ class SpecialPasswordReset extends FormSpecialPage { 'type' => 'text', 'label-message' => 'passwordreset-username', ); + if( $this->getUser()->isLoggedIn() ) { + $a['Username']['default'] = $this->getUser()->getName(); + } } if ( isset( $wgPasswordResetRoutes['email'] ) && $wgPasswordResetRoutes['email'] ) { @@ -95,7 +98,7 @@ class SpecialPasswordReset extends FormSpecialPage { } public function alterForm( HTMLForm $form ) { - $form->setSubmitText( wfMessage( "mailmypassword" ) ); + $form->setSubmitTextMsg( 'mailmypassword' ); } protected function preText() { @@ -110,7 +113,7 @@ class SpecialPasswordReset extends FormSpecialPage { if ( isset( $wgPasswordResetRoutes['domain'] ) && $wgPasswordResetRoutes['domain'] ) { $i++; } - return wfMessage( 'passwordreset-pretext', $i )->parseAsBlock(); + return $this->msg( 'passwordreset-pretext', $i )->parseAsBlock(); } /** @@ -151,7 +154,7 @@ class SpecialPasswordReset extends FormSpecialPage { $method = 'email'; $res = wfGetDB( DB_SLAVE )->select( 'user', - '*', + User::selectFields(), array( 'user_email' => $data['Email'] ), __METHOD__ ); @@ -234,12 +237,12 @@ class SpecialPasswordReset extends FormSpecialPage { $password = $user->randomPassword(); $user->setNewpassword( $password ); $user->saveSettings(); - $passwords[] = wfMessage( 'passwordreset-emailelement', $user->getName(), $password - )->inLanguage( $userLanguage )->plain(); // We'll escape the whole thing later + $passwords[] = $this->msg( 'passwordreset-emailelement', $user->getName(), $password + )->inLanguage( $userLanguage )->text(); // We'll escape the whole thing later } $passwordBlock = implode( "\n\n", $passwords ); - $this->email = wfMessage( $msg )->inLanguage( $userLanguage ); + $this->email = $this->msg( $msg )->inLanguage( $userLanguage ); $this->email->params( $username, $passwordBlock, @@ -248,7 +251,7 @@ class SpecialPasswordReset extends FormSpecialPage { round( $wgNewPasswordExpiry / 86400 ) ); - $title = wfMessage( 'passwordreset-emailtitle' ); + $title = $this->msg( 'passwordreset-emailtitle' ); $this->result = $firstUser->sendMail( $title->escaped(), $this->email->escaped() ); diff --git a/includes/specials/SpecialPopularpages.php b/includes/specials/SpecialPopularpages.php index 803f03e7..448d1799 100644 --- a/includes/specials/SpecialPopularpages.php +++ b/includes/specials/SpecialPopularpages.php @@ -42,9 +42,9 @@ class PopularPagesPage extends QueryPage { function getQueryInfo() { return array ( 'tables' => array( 'page' ), - 'fields' => array( 'page_namespace AS namespace', - 'page_title AS title', - 'page_counter AS value'), + 'fields' => array( 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'page_counter'), 'conds' => array( 'page_is_redirect' => 0, 'page_namespace' => MWNamespace::getContentNamespaces() ) ); } @@ -56,7 +56,13 @@ class PopularPagesPage extends QueryPage { */ function formatResult( $skin, $result ) { global $wgContLang; - $title = Title::makeTitle( $result->namespace, $result->title ); + + $title = Title::makeTitleSafe( $result->namespace, $result->title ); + if( !$title ) { + return Html::element( 'span', array( 'class' => 'mw-invalidtitle' ), + Linker::getInvalidTitleDescription( $this->getContext(), $result->namespace, $result->title ) ); + } + $link = Linker::linkKnown( $title, htmlspecialchars( $wgContLang->convert( $title->getPrefixedText() ) ) diff --git a/includes/specials/SpecialPreferences.php b/includes/specials/SpecialPreferences.php index 946112bf..c6b2bb6b 100644 --- a/includes/specials/SpecialPreferences.php +++ b/includes/specials/SpecialPreferences.php @@ -39,8 +39,7 @@ class SpecialPreferences extends SpecialPage { $user = $this->getUser(); if ( $user->isAnon() ) { - $out->showErrorPage( 'prefsnologin', 'prefsnologintext', array( $this->getTitle()->getPrefixedDBkey() ) ); - return; + throw new ErrorPageError( 'prefsnologin', 'prefsnologintext', array( $this->getTitle()->getPrefixedDBkey() ) ); } $this->checkReadOnly(); @@ -69,7 +68,7 @@ class SpecialPreferences extends SpecialPage { $htmlForm = new HTMLForm( array(), $this->getContext(), 'prefs-restore' ); - $htmlForm->setSubmitText( wfMsg( 'restoreprefs' ) ); + $htmlForm->setSubmitTextMsg( 'restoreprefs' ); $htmlForm->setTitle( $this->getTitle( 'reset' ) ); $htmlForm->setSubmitCallback( array( $this, 'submitReset' ) ); $htmlForm->suppressReset(); @@ -82,7 +81,7 @@ class SpecialPreferences extends SpecialPage { $user->resetOptions(); $user->saveSettings(); - $url = SpecialPage::getTitleFor( 'Preferences' )->getFullURL( 'success' ); + $url = $this->getTitle()->getFullURL( 'success' ); $this->getOutput()->redirect( $url ); diff --git a/includes/specials/SpecialPrefixindex.php b/includes/specials/SpecialPrefixindex.php index 495f15f7..7740b320 100644 --- a/includes/specials/SpecialPrefixindex.php +++ b/includes/specials/SpecialPrefixindex.php @@ -52,6 +52,7 @@ class SpecialPrefixindex extends SpecialAllpages { $prefix = $request->getVal( 'prefix', '' ); $ns = $request->getIntOrNull( 'namespace' ); $namespace = (int)$ns; // if no namespace given, use 0 (NS_MAIN). + $hideredirects = $request->getBool( 'hideredirects', false ); $namespaces = $wgContLang->getNamespaces(); $out->setPageTitle( @@ -73,29 +74,31 @@ class SpecialPrefixindex extends SpecialAllpages { // Bug 27864: if transcluded, show all pages instead of the form. if ( $this->including() || $showme != '' || $ns !== null ) { - $this->showPrefixChunk( $namespace, $showme, $from ); + $this->showPrefixChunk( $namespace, $showme, $from, $hideredirects ); } else { - $out->addHTML( $this->namespacePrefixForm( $namespace, null ) ); + $out->addHTML( $this->namespacePrefixForm( $namespace, null, $hideredirects ) ); } } /** - * HTML for the top form - * @param $namespace Integer: a namespace constant (default NS_MAIN). - * @param $from String: dbKey we are starting listing at. - */ - function namespacePrefixForm( $namespace = NS_MAIN, $from = '' ) { + * HTML for the top form + * @param $namespace Integer: a namespace constant (default NS_MAIN). + * @param $from String: dbKey we are starting listing at. + * @param $hideredirects Bool: hide redirects (default FALSE) + * @return string + */ + function namespacePrefixForm( $namespace = NS_MAIN, $from = '', $hideredirects = false ) { global $wgScript; $out = Xml::openElement( 'div', array( 'class' => 'namespaceoptions' ) ); $out .= Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ); $out .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ); $out .= Xml::openElement( 'fieldset' ); - $out .= Xml::element( 'legend', null, wfMsg( 'allpages' ) ); + $out .= Xml::element( 'legend', null, $this->msg( 'allpages' )->text() ); $out .= Xml::openElement( 'table', array( 'id' => 'nsselect', 'class' => 'allpages' ) ); $out .= "<tr> <td class='mw-label'>" . - Xml::label( wfMsg( 'allpagesprefix' ), 'nsfrom' ) . + Xml::label( $this->msg( 'allpagesprefix' )->text(), 'nsfrom' ) . "</td> <td class='mw-input'>" . Xml::input( 'prefix', 30, str_replace('_',' ',$from), array( 'id' => 'nsfrom' ) ) . @@ -103,13 +106,25 @@ class SpecialPrefixindex extends SpecialAllpages { </tr> <tr> <td class='mw-label'>" . - Xml::label( wfMsg( 'namespace' ), 'namespace' ) . + Xml::label( $this->msg( 'namespace' )->text(), 'namespace' ) . "</td> <td class='mw-input'>" . - Xml::namespaceSelector( $namespace, null ) . ' ' . - Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . + Html::namespaceSelector( array( + 'selected' => $namespace, + ), array( + 'name' => 'namespace', + 'id' => 'namespace', + 'class' => 'namespaceselector', + ) ) . + Xml::checkLabel( + $this->msg( 'allpages-hide-redirects' )->text(), + 'hideredirects', + 'hideredirects', + $hideredirects + ) . ' ' . + Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . "</td> - </tr>"; + </tr>"; $out .= Xml::closeElement( 'table' ); $out .= Xml::closeElement( 'fieldset' ); $out .= Xml::closeElement( 'form' ); @@ -121,8 +136,9 @@ class SpecialPrefixindex extends SpecialAllpages { * @param $namespace Integer, default NS_MAIN * @param $prefix String * @param $from String: list all pages from this name (default FALSE) + * @param $hideredirects Bool: hide redirects (default FALSE) */ - function showPrefixChunk( $namespace = NS_MAIN, $prefix, $from = null ) { + function showPrefixChunk( $namespace = NS_MAIN, $prefix, $from = null, $hideredirects = false ) { global $wgContLang; if ( $from === null ) { @@ -134,10 +150,10 @@ class SpecialPrefixindex extends SpecialAllpages { $namespaces = $wgContLang->getNamespaces(); if ( !$prefixList || !$fromList ) { - $out = wfMsgExt( 'allpagesbadtitle', 'parse' ); + $out = $this->msg( 'allpagesbadtitle' )->parseAsBlock(); } elseif ( !in_array( $namespace, array_keys( $namespaces ) ) ) { // Show errormessage and reset to NS_MAIN - $out = wfMsgExt( 'allpages-bad-ns', array( 'parseinline' ), $namespace ); + $out = $this->msg( 'allpages-bad-ns', $namespace )->parse(); $namespace = NS_MAIN; } else { list( $namespace, $prefixKey, $prefix ) = $prefixList; @@ -147,13 +163,19 @@ class SpecialPrefixindex extends SpecialAllpages { $dbr = wfGetDB( DB_SLAVE ); + $conds = array( + 'page_namespace' => $namespace, + 'page_title' . $dbr->buildLike( $prefixKey, $dbr->anyString() ), + 'page_title >= ' . $dbr->addQuotes( $fromKey ), + ); + + if ( $hideredirects ) { + $conds['page_is_redirect'] = 0; + } + $res = $dbr->select( 'page', array( 'page_namespace', 'page_title', 'page_is_redirect' ), - array( - 'page_namespace' => $namespace, - 'page_title' . $dbr->buildLike( $prefixKey, $dbr->anyString() ), - 'page_title >= ' . $dbr->addQuotes( $fromKey ), - ), + $conds, __METHOD__, array( 'ORDER BY' => 'page_title', @@ -166,7 +188,7 @@ class SpecialPrefixindex extends SpecialAllpages { $n = 0; if( $res->numRows() > 0 ) { - $out = Xml::openElement( 'table', array( 'border' => '0', 'id' => 'mw-prefixindex-list-table' ) ); + $out = Xml::openElement( 'table', array( 'id' => 'mw-prefixindex-list-table' ) ); while( ( $n < $this->maxPerPage ) && ( $s = $res->fetchObject() ) ) { $t = Title::makeTitle( $s->page_namespace, $s->page_title ); @@ -174,7 +196,8 @@ class SpecialPrefixindex extends SpecialAllpages { $link = ($s->page_is_redirect ? '<div class="allpagesredirect">' : '' ) . Linker::linkKnown( $t, - htmlspecialchars( $t->getText() ) + htmlspecialchars( $t->getText() ), + $s->page_is_redirect ? array( 'class' => 'mw-redirect' ) : array() ) . ($s->page_is_redirect ? '</div>' : '' ); } else { @@ -202,9 +225,9 @@ class SpecialPrefixindex extends SpecialAllpages { if ( $this->including() ) { $out2 = ''; } else { - $nsForm = $this->namespacePrefixForm( $namespace, $prefix ); + $nsForm = $this->namespacePrefixForm( $namespace, $prefix, $hideredirects ); $self = $this->getTitle(); - $out2 = Xml::openElement( 'table', array( 'border' => '0', 'id' => 'mw-prefixindex-nav-table' ) ) . + $out2 = Xml::openElement( 'table', array( 'id' => 'mw-prefixindex-nav-table' ) ) . '<tr> <td>' . $nsForm . @@ -214,7 +237,8 @@ class SpecialPrefixindex extends SpecialAllpages { if( isset( $res ) && $res && ( $n == $this->maxPerPage ) && ( $s = $res->fetchObject() ) ) { $query = array( 'from' => $s->page_title, - 'prefix' => $prefix + 'prefix' => $prefix, + 'hideredirects' => $hideredirects, ); if( $namespace || ($prefix == '')) { @@ -224,7 +248,7 @@ class SpecialPrefixindex extends SpecialAllpages { } $nextLink = Linker::linkKnown( $self, - wfMsgHtml( 'nextpage', str_replace( '_',' ', htmlspecialchars( $s->page_title ) ) ), + $this->msg( 'nextpage', str_replace( '_',' ', $s->page_title ) )->escaped(), array(), $query ); diff --git a/includes/specials/SpecialProtectedpages.php b/includes/specials/SpecialProtectedpages.php index eec974fe..74ed5378 100644 --- a/includes/specials/SpecialProtectedpages.php +++ b/includes/specials/SpecialProtectedpages.php @@ -58,21 +58,20 @@ class SpecialProtectedpages extends SpecialPage { $this->getOutput()->addHTML( $this->showOptions( $NS, $type, $level, $sizetype, $size, $indefOnly, $cascadeOnly ) ); if( $pager->getNumRows() ) { - $s = $pager->getNavigationBar(); - $s .= "<ul>" . - $pager->getBody() . - "</ul>"; - $s .= $pager->getNavigationBar(); + $this->getOutput()->addHTML( + $pager->getNavigationBar() . + '<ul>' . $pager->getBody() . '</ul>' . + $pager->getNavigationBar() + ); } else { - $s = '<p>' . wfMsgHtml( 'protectedpagesempty' ) . '</p>'; + $this->getOutput()->addWikiMsg( 'protectedpagesempty' ); } - $this->getOutput()->addHTML( $s ); } /** * Callback function to output a restriction - * @param $row object Protected title - * @return string Formatted <li> element + * @param Title $row Protected title + * @return string Formatted "<li>" element */ public function formatRow( $row ) { wfProfileIn( __METHOD__ ); @@ -88,12 +87,12 @@ class SpecialProtectedpages extends SpecialPage { $description_items = array (); - $protType = wfMsgHtml( 'restriction-level-' . $row->pr_level ); + $protType = $this->msg( 'restriction-level-' . $row->pr_level )->escaped(); $description_items[] = $protType; if( $row->pr_cascade ) { - $description_items[] = wfMsg( 'protect-summary-cascade' ); + $description_items[] = $this->msg( 'protect-summary-cascade' )->text(); } $stxt = ''; @@ -101,15 +100,13 @@ class SpecialProtectedpages extends SpecialPage { $expiry = $lang->formatExpiry( $row->pr_expiry, TS_MW ); if( $expiry != $infinity ) { - - $expiry_description = wfMsg( + $user = $this->getUser(); + $description_items[] = $this->msg( 'protect-expiring-local', - $lang->timeanddate( $expiry, true ), - $lang->date( $expiry, true ), - $lang->time( $expiry, true ) - ); - - $description_items[] = htmlspecialchars($expiry_description); + $lang->userTimeAndDate( $expiry, $user ), + $lang->userDate( $expiry, $user ), + $lang->userTime( $expiry, $user ) + )->escaped(); } if(!is_null($size = $row->page_len)) { @@ -118,25 +115,27 @@ class SpecialProtectedpages extends SpecialPage { # Show a link to the change protection form for allowed users otherwise a link to the protection log if( $this->getUser()->isAllowed( 'protect' ) ) { - $changeProtection = ' (' . Linker::linkKnown( + $changeProtection = Linker::linkKnown( $title, - wfMsgHtml( 'protect_change' ), + $this->msg( 'protect_change' )->escaped(), array(), array( 'action' => 'unprotect' ) - ) . ')'; + ); } else { $ltitle = SpecialPage::getTitleFor( 'Log' ); - $changeProtection = ' (' . Linker::linkKnown( + $changeProtection = Linker::linkKnown( $ltitle, - wfMsgHtml( 'protectlogpage' ), + $this->msg( 'protectlogpage' )->escaped(), array(), array( 'type' => 'protect', 'page' => $title->getPrefixedText() ) - ) . ')'; + ); } + $changeProtection = ' ' . $this->msg( 'parentheses' )->rawParams( $changeProtection )->escaped(); + wfProfileOut( __METHOD__ ); return Html::rawElement( @@ -160,7 +159,7 @@ class SpecialProtectedpages extends SpecialPage { $title = $this->getTitle(); return Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) . Xml::openElement( 'fieldset' ) . - Xml::element( 'legend', array(), wfMsg( 'protectedpages' ) ) . + Xml::element( 'legend', array(), $this->msg( 'protectedpages' )->text() ) . Html::hidden( 'title', $title->getPrefixedDBkey() ) . "\n" . $this->getNamespaceMenu( $namespace ) . " \n" . $this->getTypeMenu( $type ) . " \n" . @@ -171,7 +170,7 @@ class SpecialProtectedpages extends SpecialPage { "</span><br /><span style='white-space: nowrap'>" . $this->getSizeLimit( $sizetype, $size ) . " \n" . "</span>" . - " " . Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" . + " " . Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . "\n" . Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' ); } @@ -184,9 +183,19 @@ class SpecialProtectedpages extends SpecialPage { * @return String */ protected function getNamespaceMenu( $namespace = null ) { - return "<span style='white-space: nowrap'>" . - Xml::label( wfMsg( 'namespace' ), 'namespace' ) . ' ' - . Xml::namespaceSelector( $namespace, '' ) . "</span>"; + return Html::rawElement( 'span', array( 'style' => 'white-space: nowrap;' ), + Html::namespaceSelector( + array( + 'selected' => $namespace, + 'all' => '', + 'label' => $this->msg( 'namespace' )->text() + ), array( + 'name' => 'namespace', + 'id' => 'namespace', + 'class' => 'namespaceselector', + ) + ) + ); } /** @@ -194,7 +203,7 @@ class SpecialProtectedpages extends SpecialPage { */ protected function getExpiryCheck( $indefOnly ) { return - Xml::checkLabel( wfMsg('protectedpages-indef'), 'indefonly', 'indefonly', $indefOnly ) . "\n"; + Xml::checkLabel( $this->msg( 'protectedpages-indef' )->text(), 'indefonly', 'indefonly', $indefOnly ) . "\n"; } /** @@ -202,7 +211,7 @@ class SpecialProtectedpages extends SpecialPage { */ protected function getCascadeCheck( $cascadeOnly ) { return - Xml::checkLabel( wfMsg('protectedpages-cascade'), 'cascadeonly', 'cascadeonly', $cascadeOnly ) . "\n"; + Xml::checkLabel( $this->msg( 'protectedpages-cascade' )->text(), 'cascadeonly', 'cascadeonly', $cascadeOnly ) . "\n"; } /** @@ -212,13 +221,13 @@ class SpecialProtectedpages extends SpecialPage { $max = $sizetype === 'max'; return - Xml::radioLabel( wfMsg('minimum-size'), 'sizetype', 'min', 'wpmin', !$max ) . + Xml::radioLabel( $this->msg( 'minimum-size' )->text(), 'sizetype', 'min', 'wpmin', !$max ) . ' ' . - Xml::radioLabel( wfMsg('maximum-size'), 'sizetype', 'max', 'wpmax', $max ) . + Xml::radioLabel( $this->msg( 'maximum-size' )->text(), 'sizetype', 'max', 'wpmax', $max ) . ' ' . Xml::input( 'size', 9, $size, array( 'id' => 'wpsize' ) ) . ' ' . - Xml::label( wfMsg('pagesize'), 'wpsize' ); + Xml::label( $this->msg( 'pagesize' )->text(), 'wpsize' ); } /** @@ -232,7 +241,7 @@ class SpecialProtectedpages extends SpecialPage { // First pass to load the log names foreach( Title::getFilteredRestrictionTypes( true ) as $type ) { - $text = wfMsg("restriction-$type"); + $text = $this->msg( "restriction-$type" )->text(); $m[$text] = $type; } @@ -243,7 +252,7 @@ class SpecialProtectedpages extends SpecialPage { } return "<span style='white-space: nowrap'>" . - Xml::label( wfMsg('restriction-type') , $this->IdType ) . ' ' . + Xml::label( $this->msg( 'restriction-type' )->text(), $this->IdType ) . ' ' . Xml::tags( 'select', array( 'id' => $this->IdType, 'name' => $this->IdType ), implode( "\n", $options ) ) . "</span>"; @@ -257,14 +266,14 @@ class SpecialProtectedpages extends SpecialPage { protected function getLevelMenu( $pr_level ) { global $wgRestrictionLevels; - $m = array( wfMsg('restriction-level-all') => 0 ); // Temporary array + $m = array( $this->msg( 'restriction-level-all' )->text() => 0 ); // Temporary array $options = array(); // First pass to load the log names foreach( $wgRestrictionLevels as $type ) { // Messages used can be 'restriction-level-sysop' and 'restriction-level-autoconfirmed' if( $type !='' && $type !='*') { - $text = wfMsg("restriction-level-$type"); + $text = $this->msg( "restriction-level-$type" )->text(); $m[$text] = $type; } } @@ -276,7 +285,7 @@ class SpecialProtectedpages extends SpecialPage { } return "<span style='white-space: nowrap'>" . - Xml::label( wfMsg( 'restriction-level' ) , $this->IdLevel ) . ' ' . + Xml::label( $this->msg( 'restriction-level' )->text(), $this->IdLevel ) . ' ' . Xml::tags( 'select', array( 'id' => $this->IdLevel, 'name' => $this->IdLevel ), implode( "\n", $options ) ) . "</span>"; diff --git a/includes/specials/SpecialProtectedtitles.php b/includes/specials/SpecialProtectedtitles.php index 982feb66..a80f0d0a 100644 --- a/includes/specials/SpecialProtectedtitles.php +++ b/includes/specials/SpecialProtectedtitles.php @@ -56,15 +56,14 @@ class SpecialProtectedtitles extends SpecialPage { $this->getOutput()->addHTML( $this->showOptions( $NS, $type, $level ) ); if ( $pager->getNumRows() ) { - $s = $pager->getNavigationBar(); - $s .= "<ul>" . - $pager->getBody() . - "</ul>"; - $s .= $pager->getNavigationBar(); + $this->getOutput()->addHTML( + $pager->getNavigationBar() . + '<ul>' . $pager->getBody() . '</ul>' . + $pager->getNavigationBar() + ); } else { - $s = '<p>' . wfMsgHtml( 'protectedtitlesempty' ) . '</p>'; + $this->getOutput()->addWikiMsg( 'protectedtitlesempty' ); } - $this->getOutput()->addHTML( $s ); } /** @@ -86,21 +85,20 @@ class SpecialProtectedtitles extends SpecialPage { $description_items = array (); - $protType = wfMsgHtml( 'restriction-level-' . $row->pt_create_perm ); + $protType = $this->msg( 'restriction-level-' . $row->pt_create_perm )->escaped(); $description_items[] = $protType; $lang = $this->getLanguage(); $expiry = strlen( $row->pt_expiry ) ? $lang->formatExpiry( $row->pt_expiry, TS_MW ) : $infinity; if( $expiry != $infinity ) { - $expiry_description = wfMsg( + $user = $this->getUser(); + $description_items[] = $this->msg( 'protect-expiring-local', - $lang->timeanddate( $expiry, true ), - $lang->date( $expiry, true ), - $lang->time( $expiry, true ) - ); - - $description_items[] = htmlspecialchars($expiry_description); + $lang->userTimeAndDate( $expiry, $user ), + $lang->userDate( $expiry, $user ), + $lang->userTime( $expiry, $user ) + )->escaped(); } wfProfileOut( __METHOD__ ); @@ -112,6 +110,7 @@ class SpecialProtectedtitles extends SpecialPage { * @param $namespace Integer: * @param $type string * @param $level string + * @return string * @private */ function showOptions( $namespace, $type='edit', $level ) { @@ -121,11 +120,11 @@ class SpecialProtectedtitles extends SpecialPage { $special = htmlspecialchars( $title->getPrefixedDBkey() ); return "<form action=\"$action\" method=\"get\">\n" . '<fieldset>' . - Xml::element( 'legend', array(), wfMsg( 'protectedtitles' ) ) . + Xml::element( 'legend', array(), $this->msg( 'protectedtitles' )->text() ) . Html::hidden( 'title', $special ) . " \n" . $this->getNamespaceMenu( $namespace ) . " \n" . $this->getLevelMenu( $level ) . " \n" . - " " . Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" . + " " . Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . "\n" . "</fieldset></form>"; } @@ -137,9 +136,17 @@ class SpecialProtectedtitles extends SpecialPage { * @return string */ function getNamespaceMenu( $namespace = null ) { - return Xml::label( wfMsg( 'namespace' ), 'namespace' ) - . ' ' - . Xml::namespaceSelector( $namespace, '' ); + return Html::namespaceSelector( + array( + 'selected' => $namespace, + 'all' => '', + 'label' => $this->msg( 'namespace' )->text() + ), array( + 'name' => 'namespace', + 'id' => 'namespace', + 'class' => 'namespaceselector', + ) + ); } /** @@ -149,13 +156,13 @@ class SpecialProtectedtitles extends SpecialPage { function getLevelMenu( $pr_level ) { global $wgRestrictionLevels; - $m = array( wfMsg('restriction-level-all') => 0 ); // Temporary array + $m = array( $this->msg( 'restriction-level-all' )->text() => 0 ); // Temporary array $options = array(); // First pass to load the log names foreach( $wgRestrictionLevels as $type ) { if ( $type !='' && $type !='*') { - $text = wfMsg("restriction-level-$type"); + $text = $this->msg( "restriction-level-$type" )->text(); $m[$text] = $type; } } @@ -170,7 +177,7 @@ class SpecialProtectedtitles extends SpecialPage { } return - Xml::label( wfMsg('restriction-level') , $this->IdLevel ) . ' ' . + Xml::label( $this->msg( 'restriction-level' )->text(), $this->IdLevel ) . ' ' . Xml::tags( 'select', array( 'id' => $this->IdLevel, 'name' => $this->IdLevel ), implode( "\n", $options ) ); @@ -212,7 +219,7 @@ class ProtectedTitlesPager extends AlphabeticPager { * @return Title */ function getTitle() { - return SpecialPage::getTitleFor( 'Protectedtitles' ); + return $this->mForm->getTitle(); } function formatRow( $row ) { diff --git a/includes/specials/SpecialRandompage.php b/includes/specials/SpecialRandompage.php index 0b6239bb..307088ed 100644 --- a/includes/specials/SpecialRandompage.php +++ b/includes/specials/SpecialRandompage.php @@ -85,7 +85,7 @@ class RandomPage extends SpecialPage { $nsNames = array(); foreach( $this->namespaces as $n ) { if( $n === NS_MAIN ) { - $nsNames[] = wfMsgNoTrans( 'blanknamespace' ); + $nsNames[] = $this->msg( 'blanknamespace' )->plain(); } else { $nsNames[] = $wgContLang->getNsText( $n ); } diff --git a/includes/specials/SpecialRecentchanges.php b/includes/specials/SpecialRecentchanges.php index daf47f62..2bd8b0a9 100644 --- a/includes/specials/SpecialRecentchanges.php +++ b/includes/specials/SpecialRecentchanges.php @@ -190,8 +190,8 @@ class SpecialRecentChanges extends IncludableSpecialPage { public function getFeedObject( $feedFormat ){ $changesFeed = new ChangesFeed( $feedFormat, 'rcfeed' ); $formatter = $changesFeed->getFeedObject( - wfMsgForContent( 'recentchanges' ), - wfMsgForContent( 'recentchanges-feed-description' ), + $this->msg( 'recentchanges' )->inContentLanguage()->text(), + $this->msg( 'recentchanges-feed-description' )->inContentLanguage()->text(), $this->getTitle()->getFullURL() ); return array( $changesFeed, $formatter ); @@ -366,7 +366,7 @@ class SpecialRecentChanges extends IncludableSpecialPage { * * @param $conds Array * @param $opts FormOptions - * @return database result or false (for Recentchangeslinked only) + * @return bool|ResultWrapper result or false (for Recentchangeslinked only) */ public function doMainQuery( $conds, $opts ) { $tables = array( 'recentchanges' ); @@ -396,14 +396,15 @@ class SpecialRecentChanges extends IncludableSpecialPage { $fields[] = 'page_latest'; $join_conds['page'] = array('LEFT JOIN', 'rc_cur_id=page_id'); } - if ( !$this->including() ) { - // Tag stuff. - // Doesn't work when transcluding. See bug 23293 - ChangeTags::modifyDisplayQuery( - $tables, $fields, $conds, $join_conds, $query_options, - $opts['tagfilter'] - ); - } + // Tag stuff. + ChangeTags::modifyDisplayQuery( + $tables, + $fields, + $conds, + $join_conds, + $query_options, + $opts['tagfilter'] + ); if ( !wfRunHooks( 'SpecialRecentChangesQuery', array( &$conds, &$tables, &$join_conds, $opts, &$query_options, &$fields ) ) ) @@ -534,6 +535,7 @@ class SpecialRecentChanges extends IncludableSpecialPage { /** * Get the query string to append to feed link URLs. * This is overridden by RCL to add the target parameter + * @return bool */ public function getFeedQuery() { return false; @@ -564,17 +566,17 @@ class SpecialRecentChanges extends IncludableSpecialPage { $extraOpts = $this->getExtraOptions( $opts ); $extraOptsCount = count( $extraOpts ); $count = 0; - $submit = ' ' . Xml::submitbutton( wfMsg( 'allpagessubmit' ) ); + $submit = ' ' . Xml::submitbutton( $this->msg( 'allpagessubmit' )->text() ); $out = Xml::openElement( 'table', array( 'class' => 'mw-recentchanges-table' ) ); - foreach( $extraOpts as $optionRow ) { + foreach( $extraOpts as $name => $optionRow ) { # Add submit button to the last row only ++$count; - $addSubmit = $count === $extraOptsCount ? $submit : ''; + $addSubmit = ( $count === $extraOptsCount ) ? $submit : ''; $out .= Xml::openElement( 'tr' ); if( is_array( $optionRow ) ) { - $out .= Xml::tags( 'td', array( 'class' => 'mw-label' ), $optionRow[0] ); + $out .= Xml::tags( 'td', array( 'class' => 'mw-label mw-' . $name . '-label' ), $optionRow[0] ); $out .= Xml::tags( 'td', array( 'class' => 'mw-input' ), $optionRow[1] . $addSubmit ); } else { $out .= Xml::tags( 'td', array( 'class' => 'mw-input', 'colspan' => 2 ), $optionRow . $addSubmit ); @@ -595,7 +597,7 @@ class SpecialRecentChanges extends IncludableSpecialPage { $panelString = implode( "\n", $panel ); $this->getOutput()->addHTML( - Xml::fieldset( wfMsg( 'recentchanges-legend' ), $panelString, array( 'class' => 'rcoptions' ) ) + Xml::fieldset( $this->msg( 'recentchanges-legend' )->text(), $panelString, array( 'class' => 'rcoptions' ) ) ); $this->setBottomText( $opts ); @@ -632,14 +634,18 @@ class SpecialRecentChanges extends IncludableSpecialPage { */ function setTopText( FormOptions $opts ) { global $wgContLang; - $this->getOutput()->addWikiText( - Html::rawElement( 'p', - array( 'lang' => $wgContLang->getCode(), 'dir' => $wgContLang->getDir() ), - "\n" . wfMsgForContentNoTrans( 'recentchangestext' ) . "\n" - ), - /* $lineStart */ false, - /* $interface */ false - ); + + $message = $this->msg( 'recentchangestext' )->inContentLanguage(); + if ( !$message->isDisabled() ) { + $this->getOutput()->addWikiText( + Html::rawElement( 'p', + array( 'lang' => $wgContLang->getCode(), 'dir' => $wgContLang->getDir() ), + "\n" . $message->plain() . "\n" + ), + /* $lineStart */ false, + /* $interface */ false + ); + } } /** @@ -662,16 +668,16 @@ class SpecialRecentChanges extends IncludableSpecialPage { array( 'selected' => $opts['namespace'], 'all' => '' ), array( 'name' => 'namespace', 'id' => 'namespace' ) ); - $nsLabel = Xml::label( wfMsg( 'namespace' ), 'namespace' ); + $nsLabel = Xml::label( $this->msg( 'namespace' )->text(), 'namespace' ); $invert = Xml::checkLabel( - wfMsg( 'invert' ), 'invert', 'nsinvert', + $this->msg( 'invert' )->text(), 'invert', 'nsinvert', $opts['invert'], - array( 'title' => wfMsg( 'tooltip-invert' ) ) + array( 'title' => $this->msg( 'tooltip-invert' )->text() ) ); $associated = Xml::checkLabel( - wfMsg( 'namespace_association' ), 'associated', 'nsassociated', + $this->msg( 'namespace_association' )->text(), 'associated', 'nsassociated', $opts['associated'], - array( 'title' => wfMsg( 'tooltip-namespace_association' ) ) + array( 'title' => $this->msg( 'tooltip-namespace_association' )->text() ) ); return array( $nsLabel, "$nsSelect $invert $associated" ); } @@ -683,10 +689,10 @@ class SpecialRecentChanges extends IncludableSpecialPage { * @return Array */ protected function categoryFilterForm( FormOptions $opts ) { - list( $label, $input ) = Xml::inputLabelSep( wfMsg( 'rc_categories' ), + list( $label, $input ) = Xml::inputLabelSep( $this->msg( 'rc_categories' )->text(), 'categories', 'mw-categories', false, $opts['categories'] ); - $input .= ' ' . Xml::checkLabel( wfMsg( 'rc_categories_any' ), + $input .= ' ' . Xml::checkLabel( $this->msg( 'rc_categories_any' )->text(), 'categories_any', 'mw-categories_any', $opts['categories_any'] ); return array( $label, $input ); @@ -763,9 +769,20 @@ class SpecialRecentChanges extends IncludableSpecialPage { * @param $override Array: options to override * @param $options Array: current options * @param $active Boolean: whether to show the link in bold + * @return string */ function makeOptionsLink( $title, $override, $options, $active = false ) { $params = $override + $options; + + // Bug 36524: false values have be converted to "0" otherwise + // wfArrayToCgi() will omit it them. + foreach ( $params as &$value ) { + if ( $value === false ) { + $value = '0'; + } + } + unset( $value ); + $text = htmlspecialchars( $title ); if ( $active ) { $text = '<strong>' . $text . '</strong>'; @@ -778,6 +795,7 @@ class SpecialRecentChanges extends IncludableSpecialPage { * * @param $defaults Array * @param $nondefaults Array + * @return string */ function optionsPanel( $defaults, $nondefaults ) { global $wgRCLinkLimits, $wgRCLinkDays; @@ -785,16 +803,18 @@ class SpecialRecentChanges extends IncludableSpecialPage { $options = $nondefaults + $defaults; $note = ''; - if( !wfEmptyMsg( 'rclegend' ) ) { - $note .= '<div class="mw-rclegend">' . - wfMsgExt( 'rclegend', array( 'parseinline' ) ) . "</div>\n"; + $msg = $this->msg( 'rclegend' ); + if( !$msg->isDisabled() ) { + $note .= '<div class="mw-rclegend">' . $msg->parse() . "</div>\n"; } + + $lang = $this->getLanguage(); + $user = $this->getUser(); if( $options['from'] ) { - $note .= wfMsgExt( 'rcnotefrom', array( 'parseinline' ), - $this->getLanguage()->formatNum( $options['limit'] ), - $this->getLanguage()->timeanddate( $options['from'], true ), - $this->getLanguage()->date( $options['from'], true ), - $this->getLanguage()->time( $options['from'], true ) ) . '<br />'; + $note .= $this->msg( 'rcnotefrom' )->numParams( $options['limit'] )->params( + $lang->userTimeAndDate( $options['from'], $user ), + $lang->userDate( $options['from'], $user ), + $lang->userTime( $options['from'], $user ) )->parse() . '<br />'; } # Sort data for display and make sure it's unique after we've added user data. @@ -807,21 +827,21 @@ class SpecialRecentChanges extends IncludableSpecialPage { // limit links foreach( $wgRCLinkLimits as $value ) { - $cl[] = $this->makeOptionsLink( $this->getLanguage()->formatNum( $value ), + $cl[] = $this->makeOptionsLink( $lang->formatNum( $value ), array( 'limit' => $value ), $nondefaults, $value == $options['limit'] ); } - $cl = $this->getLanguage()->pipeList( $cl ); + $cl = $lang->pipeList( $cl ); // day links, reset 'from' to none foreach( $wgRCLinkDays as $value ) { - $dl[] = $this->makeOptionsLink( $this->getLanguage()->formatNum( $value ), + $dl[] = $this->makeOptionsLink( $lang->formatNum( $value ), array( 'days' => $value, 'from' => '' ), $nondefaults, $value == $options['days'] ); } - $dl = $this->getLanguage()->pipeList( $dl ); + $dl = $lang->pipeList( $dl ); // show/hide links - $showhide = array( wfMsg( 'show' ), wfMsg( 'hide' ) ); + $showhide = array( $this->msg( 'show' )->text(), $this->msg( 'hide' )->text() ); $filters = array( 'hideminor' => 'rcshowhideminor', 'hidebots' => 'rcshowhidebots', @@ -834,7 +854,7 @@ class SpecialRecentChanges extends IncludableSpecialPage { $filters[$key] = $params['msg']; } // Disable some if needed - if ( !$this->getUser()->useRCPatrol() ) { + if ( !$user->useRCPatrol() ) { unset( $filters['hidepatrolled'] ); } @@ -842,19 +862,18 @@ class SpecialRecentChanges extends IncludableSpecialPage { foreach ( $filters as $key => $msg ) { $link = $this->makeOptionsLink( $showhide[1 - $options[$key]], array( $key => 1-$options[$key] ), $nondefaults ); - $links[] = wfMsgHtml( $msg, $link ); + $links[] = $this->msg( $msg )->rawParams( $link )->escaped(); } // show from this onward link $timestamp = wfTimestampNow(); - $now = $this->getLanguage()->timeanddate( $timestamp, true ); + $now = $lang->userTimeAndDate( $timestamp, $user ); $tl = $this->makeOptionsLink( $now, array( 'from' => $timestamp ), $nondefaults ); - $rclinks = wfMsgExt( 'rclinks', array( 'parseinline', 'replaceafter' ), - $cl, $dl, $this->getLanguage()->pipeList( $links ) ); - $rclistfrom = wfMsgExt( 'rclistfrom', array( 'parseinline', 'replaceafter' ), $tl ); + $rclinks = $this->msg( 'rclinks' )->rawParams( $cl, $dl, $lang->pipeList( $links ) )->parse(); + $rclistfrom = $this->msg( 'rclistfrom' )->rawParams( $tl )->parse(); return "{$note}$rclinks<br />$rclistfrom"; } diff --git a/includes/specials/SpecialRecentchangeslinked.php b/includes/specials/SpecialRecentchangeslinked.php index 1f556f89..862736d3 100644 --- a/includes/specials/SpecialRecentchangeslinked.php +++ b/includes/specials/SpecialRecentchangeslinked.php @@ -54,8 +54,9 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges { public function getFeedObject( $feedFormat ){ $feed = new ChangesFeed( $feedFormat, false ); $feedObj = $feed->getFeedObject( - wfMsgForContent( 'recentchangeslinked-title', $this->getTargetTitle()->getPrefixedText() ), - wfMsgForContent( 'recentchangeslinked-feed' ), + $this->msg( 'recentchangeslinked-title', $this->getTargetTitle()->getPrefixedText() ) + ->inContentLanguage()->text(), + $this->msg( 'recentchangeslinked-feed' )->inContentLanguage()->text(), $this->getTitle()->getFullUrl() ); return array( $feed, $feedObj ); @@ -88,7 +89,7 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges { */ $dbr = wfGetDB( DB_SLAVE, 'recentchangeslinked' ); - $id = $title->getArticleId(); + $id = $title->getArticleID(); $ns = $title->getNamespace(); $dbkey = $title->getDBkey(); @@ -109,10 +110,14 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges { $join_conds['page'] = array('LEFT JOIN', 'rc_cur_id=page_id'); $select[] = 'page_latest'; } - if ( !$this->including() ) { // bug 23293 - ChangeTags::modifyDisplayQuery( $tables, $select, $conds, $join_conds, - $query_options, $opts['tagfilter'] ); - } + ChangeTags::modifyDisplayQuery( + $tables, + $select, + $conds, + $join_conds, + $query_options, + $opts['tagfilter'] + ); if ( !wfRunHooks( 'SpecialRecentChangesQuery', array( &$conds, &$tables, &$join_conds, $opts, &$query_options, &$select ) ) ) { return false; @@ -224,10 +229,10 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges { $opts->consumeValues( array( 'showlinkedto', 'target', 'tagfilter' ) ); $extraOpts = array(); $extraOpts['namespace'] = $this->namespaceFilterForm( $opts ); - $extraOpts['target'] = array( wfMsgHtml( 'recentchangeslinked-page' ), + $extraOpts['target'] = array( $this->msg( 'recentchangeslinked-page' )->escaped(), Xml::input( 'target', 40, str_replace('_',' ',$opts['target']) ) . Xml::check( 'showlinkedto', $opts['showlinkedto'], array('id' => 'showlinkedto') ) . ' ' . - Xml::label( wfMsg("recentchangeslinked-to"), 'showlinkedto' ) ); + Xml::label( $this->msg( 'recentchangeslinked-to' )->text(), 'showlinkedto' ) ); $tagFilter = ChangeTags::buildTagFilterSelector( $opts['tagfilter'] ); if ($tagFilter) { $extraOpts['tagfilter'] = $tagFilter; diff --git a/includes/specials/SpecialRevisiondelete.php b/includes/specials/SpecialRevisiondelete.php index df60a26a..aba90cf8 100644 --- a/includes/specials/SpecialRevisiondelete.php +++ b/includes/specials/SpecialRevisiondelete.php @@ -66,6 +66,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { 'success' => 'revdelete-success', 'failure' => 'revdelete-failure', 'list-class' => 'RevDel_RevisionList', + 'permission' => 'deleterevision', ), 'archive' => array( 'check-label' => 'revdelete-hide-text', @@ -73,6 +74,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { 'success' => 'revdelete-success', 'failure' => 'revdelete-failure', 'list-class' => 'RevDel_ArchiveList', + 'permission' => 'deleterevision', ), 'oldimage'=> array( 'check-label' => 'revdelete-hide-image', @@ -80,6 +82,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { 'success' => 'revdelete-success', 'failure' => 'revdelete-failure', 'list-class' => 'RevDel_FileList', + 'permission' => 'deleterevision', ), 'filearchive' => array( 'check-label' => 'revdelete-hide-image', @@ -87,6 +90,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { 'success' => 'revdelete-success', 'failure' => 'revdelete-failure', 'list-class' => 'RevDel_ArchivedFileList', + 'permission' => 'deleterevision', ), 'logging' => array( 'check-label' => 'revdelete-hide-name', @@ -94,6 +98,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { 'success' => 'logdelete-success', 'failure' => 'logdelete-failure', 'list-class' => 'RevDel_LogList', + 'permission' => 'deletelogentry', ), ); @@ -117,7 +122,6 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { $output = $this->getOutput(); $user = $this->getUser(); - $this->mIsAllowed = $user->isAllowed('deleterevision'); // for changes $this->setHeaders(); $this->outputHeader(); $request = $this->getRequest(); @@ -143,6 +147,24 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { } else { $this->typeName = $request->getVal( 'type' ); $this->targetObj = Title::newFromText( $request->getText( 'target' ) ); + if ( $this->targetObj->isSpecial( 'Log' ) ) { + $result = wfGetDB( DB_SLAVE )->select( 'logging', + 'log_type', + array( 'log_id' => $this->ids ), + __METHOD__, + array( 'DISTINCT' ) + ); + + $logTypes = array(); + foreach ( $result as $row ) { + $logTypes[] = $row->log_type; + } + + if ( count( $logTypes ) == 1 ) { + // If there's only one type, the target can be set to include it. + $this->targetObj = SpecialPage::getTitleFor( 'Log', $logTypes[0] ); + } + } } # For reviewing deleted files... @@ -159,10 +181,10 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { # No targets? if( !isset( self::$allowedTypes[$this->typeName] ) || count( $this->ids ) == 0 ) { - $output->showErrorPage( 'revdelete-nooldid-title', 'revdelete-nooldid-text' ); - return; + throw new ErrorPageError( 'revdelete-nooldid-title', 'revdelete-nooldid-text' ); } $this->typeInfo = self::$allowedTypes[$this->typeName]; + $this->mIsAllowed = $user->isAllowed( $this->typeInfo['permission'] ); # If we have revisions, get the title from the first one # since they should all be from the same page. This allows @@ -201,12 +223,14 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { $qc = $this->getLogQueryCond(); # Show relevant lines from the deletion log - $output->addHTML( "<h2>" . htmlspecialchars( LogPage::logName( 'delete' ) ) . "</h2>\n" ); + $deleteLogPage = new LogPage( 'delete' ); + $output->addHTML( "<h2>" . $deleteLogPage->getName()->escaped() . "</h2>\n" ); LogEventsList::showLogExtract( $output, 'delete', $this->targetObj, '', array( 'lim' => 25, 'conds' => $qc ) ); # Show relevant lines from the suppression log if( $user->isAllowed( 'suppressionlog' ) ) { - $output->addHTML( "<h2>" . htmlspecialchars( LogPage::logName( 'suppress' ) ) . "</h2>\n" ); + $suppressLogPage = new LogPage( 'suppress' ); + $output->addHTML( "<h2>" . $suppressLogPage->getName()->escaped() . "</h2>\n" ); LogEventsList::showLogExtract( $output, 'suppress', $this->targetObj, '', array( 'lim' => 25, 'conds' => $qc ) ); } @@ -221,7 +245,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { $links = array(); $links[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Log' ), - wfMsgHtml( 'viewpagelogs' ), + $this->msg( 'viewpagelogs' )->escaped(), array(), array( 'page' => $this->targetObj->getPrefixedText() ) ); @@ -229,7 +253,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { # Give a link to the page history $links[] = Linker::linkKnown( $this->targetObj, - wfMsgHtml( 'pagehist' ), + $this->msg( 'pagehist' )->escaped(), array(), array( 'action' => 'history' ) ); @@ -238,7 +262,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { $undelete = SpecialPage::getTitleFor( 'Undelete' ); $links[] = Linker::linkKnown( $undelete, - wfMsgHtml( 'deletedhist' ), + $this->msg( 'deletedhist' )->escaped(), array(), array( 'target' => $this->targetObj->getPrefixedDBkey() ) ); @@ -251,6 +275,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { /** * Get the condition used for fetching log snippets + * @return array */ protected function getLogQueryCond() { $conds = array(); @@ -275,29 +300,30 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { $this->getOutput()->addWikiMsg( 'revdelete-no-file' ); return; } - if( !$oimage->userCan( File::DELETED_FILE, $this->getUser() ) ) { + $user = $this->getUser(); + if( !$oimage->userCan( File::DELETED_FILE, $user ) ) { if( $oimage->isDeleted( File::DELETED_RESTRICTED ) ) { - $this->getOutput()->permissionRequired( 'suppressrevision' ); + throw new PermissionsError( 'suppressrevision' ); } else { - $this->getOutput()->permissionRequired( 'deletedtext' ); + throw new PermissionsError( 'deletedtext' ); } - return; } - if ( !$this->getUser()->matchEditToken( $this->token, $archiveName ) ) { + if ( !$user->matchEditToken( $this->token, $archiveName ) ) { + $lang = $this->getLanguage(); $this->getOutput()->addWikiMsg( 'revdelete-show-file-confirm', $this->targetObj->getText(), - $this->getLanguage()->date( $oimage->getTimestamp() ), - $this->getLanguage()->time( $oimage->getTimestamp() ) ); + $lang->userDate( $oimage->getTimestamp(), $user ), + $lang->userTime( $oimage->getTimestamp(), $user ) ); $this->getOutput()->addHTML( Xml::openElement( 'form', array( 'method' => 'POST', 'action' => $this->getTitle()->getLocalUrl( - 'target=' . urlencode( $oimage->getName() ) . + 'target=' . urlencode( $this->targetObj->getPrefixedDBkey() ) . '&file=' . urlencode( $archiveName ) . - '&token=' . urlencode( $this->getUser()->getEditToken( $archiveName ) ) ) + '&token=' . urlencode( $user->getEditToken( $archiveName ) ) ) ) ) . - Xml::submitButton( wfMsg( 'revdelete-show-file-submit' ) ) . + Xml::submitButton( $this->msg( 'revdelete-show-file-submit' )->text() ) . '</form>' ); return; @@ -350,8 +376,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { $item = $list->current(); if ( !$item->canView() ) { if( !$this->submitClicked ) { - $this->getOutput()->permissionRequired( 'suppressrevision' ); - return; + throw new PermissionsError( 'suppressrevision' ); } $UserAllowed = false; } @@ -360,8 +385,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { } if( !$numRevisions ) { - $this->getOutput()->showErrorPage( 'revdelete-nooldid-title', 'revdelete-nooldid-text' ); - return; + throw new ErrorPageError( 'revdelete-nooldid-title', 'revdelete-nooldid-text' ); } $this->getOutput()->addHTML( "</ul>" ); @@ -376,22 +400,23 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { $out = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalUrl( array( 'action' => 'submit' ) ), 'id' => 'mw-revdel-form-revisions' ) ) . - Xml::fieldset( wfMsg( 'revdelete-legend' ) ) . + Xml::fieldset( $this->msg( 'revdelete-legend' )->text() ) . $this->buildCheckBoxes() . Xml::openElement( 'table' ) . "<tr>\n" . '<td class="mw-label">' . - Xml::label( wfMsg( 'revdelete-log' ), 'wpRevDeleteReasonList' ) . + Xml::label( $this->msg( 'revdelete-log' )->text(), 'wpRevDeleteReasonList' ) . '</td>' . '<td class="mw-input">' . Xml::listDropDown( 'wpRevDeleteReasonList', - wfMsgForContent( 'revdelete-reason-dropdown' ), - wfMsgForContent( 'revdelete-reasonotherlist' ), '', 'wpReasonDropDown', 1 + $this->msg( 'revdelete-reason-dropdown' )->inContentLanguage()->text(), + $this->msg( 'revdelete-reasonotherlist' )->inContentLanguage()->text(), + '', 'wpReasonDropDown', 1 ) . '</td>' . "</tr><tr>\n" . '<td class="mw-label">' . - Xml::label( wfMsg( 'revdelete-otherreason' ), 'wpReason' ) . + Xml::label( $this->msg( 'revdelete-otherreason' )->text(), 'wpReason' ) . '</td>' . '<td class="mw-input">' . Xml::input( 'wpReason', 60, $this->otherReason, array( 'id' => 'wpReason', 'maxlength' => 100 ) ) . @@ -399,7 +424,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { "</tr><tr>\n" . '<td></td>' . '<td class="mw-submit">' . - Xml::submitButton( wfMsgExt('revdelete-submit','parsemag',$numRevisions), + Xml::submitButton( $this->msg( 'revdelete-submit', $numRevisions )->text(), array( 'name' => 'wpSubmit' ) ) . '</td>' . "</tr>\n" . @@ -416,10 +441,10 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { $out .= Xml::closeElement( 'form' ) . "\n"; // Show link to edit the dropdown reasons if( $this->getUser()->isAllowed( 'editinterface' ) ) { - $title = Title::makeTitle( NS_MEDIAWIKI, 'revdelete-reason-dropdown' ); + $title = Title::makeTitle( NS_MEDIAWIKI, 'Revdelete-reason-dropdown' ); $link = Linker::link( $title, - wfMsgHtml( 'revdelete-edit-reasonlist' ), + $this->msg( 'revdelete-edit-reasonlist' )->escaped(), array(), array( 'action' => 'edit' ) ); @@ -458,7 +483,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { } foreach( $this->checks as $item ) { list( $message, $name, $field ) = $item; - $innerHTML = Xml::checkLabel( wfMsg($message), $name, $name, $bitfield & $field ); + $innerHTML = Xml::checkLabel( $this->msg( $message )->text(), $name, $name, $bitfield & $field ); if( $field == Revision::DELETED_RESTRICTED ) $innerHTML = "<b>$innerHTML</b>"; $line = Xml::tags( 'td', array( 'class' => 'mw-input' ), $innerHTML ); @@ -467,9 +492,9 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { // Otherwise, use tri-state radios } else { $html .= '<tr>'; - $html .= '<th class="mw-revdel-checkbox">'.wfMsgHtml('revdelete-radio-same').'</th>'; - $html .= '<th class="mw-revdel-checkbox">'.wfMsgHtml('revdelete-radio-unset').'</th>'; - $html .= '<th class="mw-revdel-checkbox">'.wfMsgHtml('revdelete-radio-set').'</th>'; + $html .= '<th class="mw-revdel-checkbox">' . $this->msg( 'revdelete-radio-same' )->escaped() . '</th>'; + $html .= '<th class="mw-revdel-checkbox">' . $this->msg( 'revdelete-radio-unset' )->escaped() . '</th>'; + $html .= '<th class="mw-revdel-checkbox">' . $this->msg( 'revdelete-radio-set' )->escaped() . '</th>'; $html .= "<th></th></tr>\n"; foreach( $this->checks as $item ) { list( $message, $name, $field ) = $item; @@ -482,7 +507,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { $line = '<td class="mw-revdel-checkbox">' . Xml::radio( $name, -1, $selected == -1 ) . '</td>'; $line .= '<td class="mw-revdel-checkbox">' . Xml::radio( $name, 0, $selected == 0 ) . '</td>'; $line .= '<td class="mw-revdel-checkbox">' . Xml::radio( $name, 1, $selected == 1 ) . '</td>'; - $label = wfMsgHtml($message); + $label = $this->msg( $message )->escaped(); if( $field == Revision::DELETED_RESTRICTED ) { $label = "<b>$label</b>"; } @@ -497,6 +522,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { /** * UI entry point for form submission. + * @return bool */ protected function submit() { # Check edit token on submission @@ -510,14 +536,13 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { $comment = $listReason; if( $comment != 'other' && $this->otherReason != '' ) { // Entry from drop down menu + additional comment - $comment .= wfMsgForContent( 'colon-separator' ) . $this->otherReason; + $comment .= $this->msg( 'colon-separator' )->inContentLanguage()->text() . $this->otherReason; } elseif( $comment == 'other' ) { $comment = $this->otherReason; } # Can the user set this field? if( $bitParams[Revision::DELETED_RESTRICTED]==1 && !$this->getUser()->isAllowed('suppressrevision') ) { - $this->getOutput()->permissionRequired( 'suppressrevision' ); - return false; + throw new PermissionsError( 'suppressrevision' ); } # If the save went through, go to success message... $status = $this->save( $bitParams, $comment, $this->targetObj ); @@ -592,6 +617,10 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { /** * Do the write operations. Simple wrapper for RevDel_*List::setVisibility(). + * @param $bitfield + * @param $reason + * @param $title + * @return */ protected function save( $bitfield, $reason, $title ) { return $this->getList()->setVisibility( diff --git a/includes/specials/SpecialSearch.php b/includes/specials/SpecialSearch.php index 3fa86875..5f5b6b4d 100644 --- a/includes/specials/SpecialSearch.php +++ b/includes/specials/SpecialSearch.php @@ -174,7 +174,8 @@ class SpecialSearch extends SpecialPage { $t = Title::newFromText( $term ); # If the string cannot be used to create a title if( is_null( $t ) ) { - return $this->showResults( $term ); + $this->showResults( $term ); + return; } # If there's an exact or very near match, jump right there. $t = SearchEngine::getNearMatch( $term ); @@ -201,7 +202,7 @@ class SpecialSearch extends SpecialPage { return; } } - return $this->showResults( $term ); + $this->showResults( $term ); } /** @@ -232,13 +233,13 @@ class SpecialSearch extends SpecialPage { } else { $out->addHTML( Xml::openElement( 'fieldset' ) . - Xml::element( 'legend', null, wfMsg( 'search-external' ) ) . - Xml::element( 'p', array( 'class' => 'mw-searchdisabled' ), wfMsg( 'searchdisabled' ) ) . - wfMsg( 'googlesearch', + Xml::element( 'legend', null, $this->msg( 'search-external' )->text() ) . + Xml::element( 'p', array( 'class' => 'mw-searchdisabled' ), $this->msg( 'searchdisabled' )->text() ) . + $this->msg( 'googlesearch' )->rawParams( htmlspecialchars( $term ), - htmlspecialchars( 'UTF-8' ), - htmlspecialchars( wfMsg( 'searchbutton' ) ) - ) . + 'UTF-8', + $this->msg( 'searchbutton' )->escaped() + )->text() . Xml::closeElement( 'fieldset' ) ); } @@ -285,7 +286,7 @@ class SpecialSearch extends SpecialPage { $stParams ); - $this->didYouMeanHtml = '<div class="searchdidyoumean">'.wfMsg('search-suggest',$suggestLink).'</div>'; + $this->didYouMeanHtml = '<div class="searchdidyoumean">' . $this->msg( 'search-suggest' )->rawParams( $suggestLink )->text() . '</div>'; } // start rendering the page $out->addHtml( @@ -299,7 +300,7 @@ class SpecialSearch extends SpecialPage { ) ); $out->addHtml( - Xml::openElement( 'table', array( 'id'=>'mw-search-top-table', 'border'=>0, 'cellpadding'=>0, 'cellspacing'=>0 ) ) . + Xml::openElement( 'table', array( 'id' => 'mw-search-top-table', 'cellpadding' => 0, 'cellspacing' => 0 ) ) . Xml::openElement( 'tr' ) . Xml::openElement( 'td' ) . "\n" . $this->shortDialog( $term ) . @@ -583,13 +584,8 @@ class SpecialSearch extends SpecialPage { $redirectText = null; $redirect = "<span class='searchalttitle'>" . - wfMsg( - 'search-redirect', - Linker::linkKnown( - $redirectTitle, - $redirectText - ) - ) . + $this->msg( 'search-redirect' )->rawParams( + Linker::linkKnown( $redirectTitle, $redirectText ) )->text() . "</span>"; } @@ -600,12 +596,8 @@ class SpecialSearch extends SpecialPage { $sectionText = null; $section = "<span class='searchalttitle'>" . - wfMsg( - 'search-section', Linker::linkKnown( - $sectionTitle, - $sectionText - ) - ) . + $this->msg( 'search-section' )->rawParams( + Linker::linkKnown( $sectionTitle, $sectionText ) )->text() . "</span>"; } @@ -620,7 +612,7 @@ class SpecialSearch extends SpecialPage { $score = ''; } else { $percent = sprintf( '%2.1f', $result->getScore() * 100 ); - $score = wfMsg( 'search-result-score', $lang->formatNum( $percent ) ) + $score = $this->msg( 'search-result-score' )->numParams( $percent )->text() . ' - '; } @@ -628,25 +620,17 @@ class SpecialSearch extends SpecialPage { $byteSize = $result->getByteSize(); $wordCount = $result->getWordCount(); $timestamp = $result->getTimestamp(); - $size = wfMsgExt( - 'search-result-size', - array( 'parsemag', 'escape' ), - $lang->formatSize( $byteSize ), - $lang->formatNum( $wordCount ) - ); + $size = $this->msg( 'search-result-size', $lang->formatSize( $byteSize ) ) + ->numParams( $wordCount )->escaped(); if( $t->getNamespace() == NS_CATEGORY ) { $cat = Category::newFromTitle( $t ); - $size = wfMsgExt( - 'search-result-category-size', - array( 'parsemag', 'escape' ), - $lang->formatNum( $cat->getPageCount() ), - $lang->formatNum( $cat->getSubcatCount() ), - $lang->formatNum( $cat->getFileCount() ) - ); + $size = $this->msg( 'search-result-category-size' ) + ->numParams( $cat->getPageCount(), $cat->getSubcatCount(), $cat->getFileCount() ) + ->escaped(); } - $date = $lang->timeanddate( $timestamp ); + $date = $lang->userTimeAndDate( $timestamp, $this->getUser() ); // link to related articles if supported $related = ''; @@ -655,14 +639,15 @@ class SpecialSearch extends SpecialPage { $stParams = array_merge( $this->powerSearchOptions(), array( - 'search' => wfMsgForContent( 'searchrelated' ) . ':' . $t->getPrefixedText(), - 'fulltext' => wfMsg( 'search' ) + 'search' => $this->msg( 'searchrelated' )->inContentLanguage()->text() . + ':' . $t->getPrefixedText(), + 'fulltext' => $this->msg( 'search' )->text() ) ); $related = ' -- ' . Linker::linkKnown( $st, - wfMsg('search-relatedarticle'), + $this->msg( 'search-relatedarticle' )->text(), array(), $stParams ); @@ -674,7 +659,7 @@ class SpecialSearch extends SpecialPage { if( $img ) { $thumb = $img->transform( array( 'width' => 120, 'height' => 120 ) ); if( $thumb ) { - $desc = wfMsg( 'parentheses', $img->getShortDesc() ); + $desc = $this->msg( 'parentheses' )->rawParams( $img->getShortDesc() )->escaped(); wfProfileOut( __METHOD__ ); // Float doesn't seem to interact well with the bullets. // Table messes up vertical alignment of the bullets. @@ -682,10 +667,10 @@ class SpecialSearch extends SpecialPage { return "<li>" . '<table class="searchResultImage">' . '<tr>' . - '<td width="120" align="center" valign="top">' . + '<td width="120" style="text-align: center; vertical-align: top;">' . $thumb->toHtml( array( 'desc-link' => true ) ) . '</td>' . - '<td valign="top">' . + '<td style="vertical-align: top;">' . $link . $extract . "<div class='mw-search-result-data'>{$score}{$desc} - {$date}{$related}</div>" . @@ -718,12 +703,12 @@ class SpecialSearch extends SpecialPage { $terms = $wgContLang->convertForSearchResult( $matches->termMatches() ); $out = "<div id='mw-search-interwiki'><div id='mw-search-interwiki-caption'>". - wfMsg('search-interwiki-caption')."</div>\n"; + $this->msg( 'search-interwiki-caption' )->text() . "</div>\n"; $out .= "<ul class='mw-search-iwresults'>\n"; // work out custom project captions $customCaptions = array(); - $customLines = explode("\n",wfMsg('search-interwiki-custom')); // format per line <iwprefix>:<caption> + $customLines = explode( "\n", $this->msg( 'search-interwiki-custom' )->text() ); // format per line <iwprefix>:<caption> foreach($customLines as $line) { $parts = explode(":",$line,2); if(count($parts) == 2) // validate line @@ -786,13 +771,8 @@ class SpecialSearch extends SpecialPage { $redirectText = null; $redirect = "<span class='searchalttitle'>" . - wfMsg( - 'search-redirect', - Linker::linkKnown( - $redirectTitle, - $redirectText - ) - ) . + $this->msg( 'search-redirect' )->rawParams( + Linker::linkKnown( $redirectTitle, $redirectText ) )->text() . "</span>"; } @@ -806,13 +786,13 @@ class SpecialSearch extends SpecialPage { // default is to show the hostname of the other wiki which might suck // if there are many wikis on one hostname $parsed = wfParseUrl( $t->getFullURL() ); - $caption = wfMsg('search-interwiki-default', $parsed['host']); + $caption = $this->msg( 'search-interwiki-default', $parsed['host'] )->text(); } // "more results" link (special page stuff could be localized, but we might not know target lang) $searchTitle = Title::newFromText($t->getInterwiki().":Special:Search"); $searchLink = Linker::linkKnown( $searchTitle, - wfMsg('search-interwiki-more'), + $this->msg( 'search-interwiki-more' )->text(), array(), array( 'search' => $query, @@ -865,7 +845,7 @@ class SpecialSearch extends SpecialPage { } $name = str_replace( '_', ' ', $name ); if( $name == '' ) { - $name = wfMsg( 'blanknamespace' ); + $name = $this->msg( 'blanknamespace' )->text(); } $rows[$subject] .= Xml::openElement( @@ -888,7 +868,7 @@ class SpecialSearch extends SpecialPage { for( $i = 0; $i < $numRows; $i += 4 ) { $namespaceTables .= Xml::openElement( 'table', - array( 'cellpadding' => 0, 'cellspacing' => 0, 'border' => 0 ) + array( 'cellpadding' => 0, 'cellspacing' => 0 ) ); for( $j = $i; $j < $i + 4 && $j < $numRows; $j++ ) { $namespaceTables .= Xml::tags( 'tr', null, $rows[$j] ); @@ -901,7 +881,7 @@ class SpecialSearch extends SpecialPage { // Show redirects check only if backend supports it if( $this->getSearchEngine()->supports( 'list-redirects' ) ) { $showSections['redirects'] = - Xml::checkLabel( wfMsg( 'powersearch-redir' ), 'redirs', 'redirs', $this->searchRedirects ); + Xml::checkLabel( $this->msg( 'powersearch-redir' )->text(), 'redirs', 'redirs', $this->searchRedirects ); } wfRunHooks( 'SpecialSearchPowerBox', array( &$showSections, $term, $opts ) ); @@ -917,29 +897,9 @@ class SpecialSearch extends SpecialPage { 'fieldset', array( 'id' => 'mw-searchoptions', 'style' => 'margin:0em;' ) ) . - Xml::element( 'legend', null, wfMsg('powersearch-legend') ) . - Xml::tags( 'h4', null, wfMsgExt( 'powersearch-ns', array( 'parseinline' ) ) ) . - Xml::tags( - 'div', - array( 'id' => 'mw-search-togglebox' ), - Xml::label( wfMsg( 'powersearch-togglelabel' ), 'mw-search-togglelabel' ) . - Xml::element( - 'input', - array( - 'type'=>'button', - 'id' => 'mw-search-toggleall', - 'value' => wfMsg( 'powersearch-toggleall' ) - ) - ) . - Xml::element( - 'input', - array( - 'type'=>'button', - 'id' => 'mw-search-togglenone', - 'value' => wfMsg( 'powersearch-togglenone' ) - ) - ) - ) . + Xml::element( 'legend', null, $this->msg('powersearch-legend' )->text() ) . + Xml::tags( 'h4', null, $this->msg( 'powersearch-ns' )->parse() ) . + Html::element( 'div', array( 'id' => 'mw-search-togglebox' ) ) . Xml::element( 'div', array( 'class' => 'divider' ), '', false ) . implode( Xml::element( 'div', array( 'class' => 'divider' ), '', false ), $showSections ) . $hidden . @@ -1034,8 +994,8 @@ class SpecialSearch extends SpecialPage { $this->makeSearchLink( $bareterm, array(), - wfMsg( $profile['message'] ), - wfMsg( $profile['tooltip'], $tooltipParam ), + $this->msg( $profile['message'] )->text(), + $this->msg( $profile['tooltip'], $tooltipParam )->text(), $profile['parameters'] ) ); @@ -1046,24 +1006,19 @@ class SpecialSearch extends SpecialPage { // Results-info if ( $resultsShown > 0 ) { if ( $totalNum > 0 ){ - $top = wfMsgExt( 'showingresultsheader', array( 'parseinline' ), - $lang->formatNum( $this->offset + 1 ), - $lang->formatNum( $this->offset + $resultsShown ), - $lang->formatNum( $totalNum ), - wfEscapeWikiText( $term ), - $lang->formatNum( $resultsShown ) - ); + $top = $this->msg( 'showingresultsheader' ) + ->numParams( $this->offset + 1, $this->offset + $resultsShown, $totalNum ) + ->params( wfEscapeWikiText( $term ) ) + ->numParams( $resultsShown ) + ->parse(); } elseif ( $resultsShown >= $this->limit ) { - $top = wfMsgExt( 'showingresults', array( 'parseinline' ), - $lang->formatNum( $this->limit ), - $lang->formatNum( $this->offset + 1 ) - ); + $top = $this->msg( 'showingresults' ) + ->numParams( $this->limit, $this->offset + 1 ) + ->parse(); } else { - $top = wfMsgExt( 'showingresultsnum', array( 'parseinline' ), - $lang->formatNum( $this->limit ), - $lang->formatNum( $this->offset + 1 ), - $lang->formatNum( $resultsShown ) - ); + $top = $this->msg( 'showingresultsnum' ) + ->numParams( $this->limit, $this->offset + 1, $resultsShown ) + ->parse(); } $out .= Xml::tags( 'div', array( 'class' => 'results-info' ), Xml::tags( 'ul', null, Xml::tags( 'li', null, $top ) ) @@ -1090,7 +1045,7 @@ class SpecialSearch extends SpecialPage { 'autofocus' ) ) . "\n"; $out .= Html::hidden( 'fulltext', 'Search' ) . "\n"; - $out .= Xml::submitButton( wfMsg( 'searchbutton' ) ) . "\n"; + $out .= Xml::submitButton( $this->msg( 'searchbutton' )->text() ) . "\n"; return $out . $this->didYouMeanHtml; } @@ -1114,7 +1069,7 @@ class SpecialSearch extends SpecialPage { $stParams = array_merge( array( 'search' => $term, - 'fulltext' => wfMsg( 'search' ) + 'fulltext' => $this->msg( 'search' )->text() ), $opt ); @@ -1152,7 +1107,7 @@ class SpecialSearch extends SpecialPage { */ protected function startsWithAll( $term ) { - $allkeyword = wfMsgForContent('searchall'); + $allkeyword = $this->msg( 'searchall' )->inContentLanguage()->text(); $p = explode( ':', $term ); if( count( $p ) > 1 ) { diff --git a/includes/specials/SpecialShortpages.php b/includes/specials/SpecialShortpages.php index c176f913..5a4e8f03 100644 --- a/includes/specials/SpecialShortpages.php +++ b/includes/specials/SpecialShortpages.php @@ -40,10 +40,11 @@ class ShortPagesPage extends QueryPage { function getQueryInfo() { return array ( 'tables' => array ( 'page' ), - 'fields' => array ( 'page_namespace AS namespace', - 'page_title AS title', - 'page_len AS value' ), - 'conds' => array ( 'page_namespace' => NS_MAIN, + 'fields' => array ( 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'page_len' ), + 'conds' => array ( 'page_namespace' => + MWNamespace::getContentNamespaces(), 'page_is_redirect' => 0 ), 'options' => array ( 'USE INDEX' => 'page_redirect_namespace_len' ) ); @@ -61,16 +62,17 @@ class ShortPagesPage extends QueryPage { function preprocessResults( $db, $res ) { # There's no point doing a batch check if we aren't caching results; # the page must exist for it to have been pulled out of the table - if( $this->isCached() ) { - $batch = new LinkBatch(); - foreach ( $res as $row ) { - $batch->add( $row->namespace, $row->title ); - } - $batch->execute(); - if ( $db->numRows( $res ) > 0 ) { - $db->dataSeek( $res, 0 ); - } + if ( !$this->isCached() || !$res->numRows() ) { + return; } + + $batch = new LinkBatch(); + foreach ( $res as $row ) { + $batch->add( $row->namespace, $row->title ); + } + $batch->execute(); + + $res->seek( 0 ); } function sortDescending() { @@ -80,23 +82,32 @@ class ShortPagesPage extends QueryPage { function formatResult( $skin, $result ) { $dm = $this->getLanguage()->getDirMark(); - $title = Title::makeTitle( $result->namespace, $result->title ); + $title = Title::makeTitleSafe( $result->namespace, $result->title ); if ( !$title ) { - return '<!-- Invalid title ' . htmlspecialchars( "{$result->namespace}:{$result->title}" ). '-->'; + return Html::element( 'span', array( 'class' => 'mw-invalidtitle' ), + Linker::getInvalidTitleDescription( $this->getContext(), $result->namespace, $result->title ) ); } + $hlink = Linker::linkKnown( $title, - wfMsgHtml( 'hist' ), + $this->msg( 'hist' )->escaped(), array(), array( 'action' => 'history' ) ); - $plink = $this->isCached() - ? Linker::link( $title ) - : Linker::linkKnown( $title ); + $hlinkInParentheses = $this->msg( 'parentheses' )->rawParams( $hlink )->escaped(); + + if ( $this->isCached() ) { + $plink = Linker::link( $title ); + $exists = $title->exists(); + } else { + $plink = Linker::linkKnown( $title ); + $exists = true; + } + $size = $this->msg( 'nbytes' )->numParams( $result->value )->escaped(); - return $title->exists() - ? "({$hlink}) {$dm}{$plink} {$dm}[{$size}]" - : "<del>({$hlink}) {$dm}{$plink} {$dm}[{$size}]</del>"; + return $exists + ? "${hlinkInParentheses} {$dm}{$plink} {$dm}[{$size}]" + : "<del>${hlinkInParentheses} {$dm}{$plink} {$dm}[{$size}]</del>"; } } diff --git a/includes/specials/SpecialStatistics.php b/includes/specials/SpecialStatistics.php index b9c092b6..46881ec4 100644 --- a/includes/specials/SpecialStatistics.php +++ b/includes/specials/SpecialStatistics.php @@ -97,7 +97,7 @@ class SpecialStatistics extends SpecialPage { $text .= Xml::closeElement( 'table' ); # Customizable footer - $footer = wfMessage( 'statistics-footer' ); + $footer = $this->msg( 'statistics-footer' ); if ( !$footer->isBlank() ) { $text .= "\n" . $footer->parse(); } @@ -116,11 +116,11 @@ class SpecialStatistics extends SpecialPage { */ private function formatRow( $text, $number, $trExtraParams = array(), $descMsg = '', $descMsgParam = '' ) { if( $descMsg ) { - $msg = wfMessage( $descMsg, $descMsgParam ); + $msg = $this->msg( $descMsg, $descMsgParam ); if ( $msg->exists() ) { - $descriptionText = $msg->parse(); + $descriptionText = $this->msg( 'parentheses' )->rawParams( $msg->parse() )->escaped(); $text .= "<br />" . Xml::element( 'small', array( 'class' => 'mw-statistic-desc'), - " ($descriptionText)" ); + " $descriptionText" ); } } return Html::rawElement( 'tr', $trExtraParams, @@ -136,29 +136,29 @@ class SpecialStatistics extends SpecialPage { */ private function getPageStats() { return Xml::openElement( 'tr' ) . - Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-pages', array( 'parseinline' ) ) ) . + Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-pages' )->parse() ) . Xml::closeElement( 'tr' ) . $this->formatRow( Linker::linkKnown( SpecialPage::getTitleFor( 'Allpages' ), - wfMsgExt( 'statistics-articles', array( 'parseinline' ) ) ), + $this->msg( 'statistics-articles' )->parse() ), $this->getLanguage()->formatNum( $this->good ), array( 'class' => 'mw-statistics-articles' ) ) . - $this->formatRow( wfMsgExt( 'statistics-pages', array( 'parseinline' ) ), + $this->formatRow( $this->msg( 'statistics-pages' )->parse(), $this->getLanguage()->formatNum( $this->total ), array( 'class' => 'mw-statistics-pages' ), 'statistics-pages-desc' ) . $this->formatRow( Linker::linkKnown( SpecialPage::getTitleFor( 'Listfiles' ), - wfMsgExt( 'statistics-files', array( 'parseinline' ) ) ), + $this->msg( 'statistics-files' )->parse() ), $this->getLanguage()->formatNum( $this->images ), array( 'class' => 'mw-statistics-files' ) ); } private function getEditStats() { return Xml::openElement( 'tr' ) . - Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-edits', array( 'parseinline' ) ) ) . + Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-edits' )->parse() ) . Xml::closeElement( 'tr' ) . - $this->formatRow( wfMsgExt( 'statistics-edits', array( 'parseinline' ) ), + $this->formatRow( $this->msg( 'statistics-edits' )->parse(), $this->getLanguage()->formatNum( $this->edits ), array( 'class' => 'mw-statistics-edits' ) ) . - $this->formatRow( wfMsgExt( 'statistics-edits-average', array( 'parseinline' ) ), + $this->formatRow( $this->msg( 'statistics-edits-average' )->parse(), $this->getLanguage()->formatNum( sprintf( '%.2f', $this->total ? $this->edits / $this->total : 0 ) ), array( 'class' => 'mw-statistics-edits-average' ) ); } @@ -166,15 +166,15 @@ class SpecialStatistics extends SpecialPage { private function getUserStats() { global $wgActiveUserDays; return Xml::openElement( 'tr' ) . - Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-users', array( 'parseinline' ) ) ) . + Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-users' )->parse() ) . Xml::closeElement( 'tr' ) . - $this->formatRow( wfMsgExt( 'statistics-users', array( 'parseinline' ) ), + $this->formatRow( $this->msg( 'statistics-users' )->parse(), $this->getLanguage()->formatNum( $this->users ), array( 'class' => 'mw-statistics-users' ) ) . - $this->formatRow( wfMsgExt( 'statistics-users-active', array( 'parseinline' ) ) . ' ' . + $this->formatRow( $this->msg( 'statistics-users-active' )->parse() . ' ' . Linker::linkKnown( SpecialPage::getTitleFor( 'Activeusers' ), - wfMsgHtml( 'listgrouprights-members' ) + $this->msg( 'listgrouprights-members' )->escaped() ), $this->getLanguage()->formatNum( $this->activeUsers ), array( 'class' => 'mw-statistics-users-active' ), @@ -191,13 +191,13 @@ class SpecialStatistics extends SpecialPage { continue; } $groupname = htmlspecialchars( $group ); - $msg = wfMessage( 'group-' . $groupname ); + $msg = $this->msg( 'group-' . $groupname ); if ( $msg->isBlank() ) { $groupnameLocalized = $groupname; } else { $groupnameLocalized = $msg->text(); } - $msg = wfMessage( 'grouppage-' . $groupname )->inContentLanguage(); + $msg = $this->msg( 'grouppage-' . $groupname )->inContentLanguage(); if ( $msg->isBlank() ) { $grouppageLocalized = MWNamespace::getCanonicalName( NS_PROJECT ) . ':' . $groupname; } else { @@ -210,7 +210,7 @@ class SpecialStatistics extends SpecialPage { ); $grouplink = Linker::linkKnown( SpecialPage::getTitleFor( 'Listusers' ), - wfMsgHtml( 'listgrouprights-members' ), + $this->msg( 'listgrouprights-members' )->escaped(), array(), array( 'group' => $group ) ); @@ -229,12 +229,12 @@ class SpecialStatistics extends SpecialPage { private function getViewsStats() { return Xml::openElement( 'tr' ) . - Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-views', array( 'parseinline' ) ) ) . + Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-views' )->parse() ) . Xml::closeElement( 'tr' ) . - $this->formatRow( wfMsgExt( 'statistics-views-total', array( 'parseinline' ) ), + $this->formatRow( $this->msg( 'statistics-views-total' )->parse(), $this->getLanguage()->formatNum( $this->views ), array ( 'class' => 'mw-statistics-views-total' ), 'statistics-views-total-desc' ) . - $this->formatRow( wfMsgExt( 'statistics-views-peredit', array( 'parseinline' ) ), + $this->formatRow( $this->msg( 'statistics-views-peredit' )->parse(), $this->getLanguage()->formatNum( sprintf( '%.2f', $this->edits ? $this->views / $this->edits : 0 ) ), array ( 'class' => 'mw-statistics-views-peredit' ) ); @@ -262,7 +262,7 @@ class SpecialStatistics extends SpecialPage { ); if( $res->numRows() > 0 ) { $text .= Xml::openElement( 'tr' ); - $text .= Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-mostpopular', array( 'parseinline' ) ) ); + $text .= Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-mostpopular' )->parse() ); $text .= Xml::closeElement( 'tr' ); foreach ( $res as $row ) { $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title ); @@ -282,7 +282,7 @@ class SpecialStatistics extends SpecialPage { return ''; $return = Xml::openElement( 'tr' ) . - Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-hooks', array( 'parseinline' ) ) ) . + Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-hooks' )->parse() ) . Xml::closeElement( 'tr' ); foreach( $stats as $name => $number ) { diff --git a/includes/specials/SpecialTags.php b/includes/specials/SpecialTags.php index adfc7441..4036ebb2 100644 --- a/includes/specials/SpecialTags.php +++ b/includes/specials/SpecialTags.php @@ -21,9 +21,6 @@ * @ingroup SpecialPage */ -if (!defined('MEDIAWIKI')) - die; - /** * A special page that lists tags for edits * @@ -44,13 +41,13 @@ class SpecialTags extends SpecialPage { $out->wrapWikiMsg( "<div class='mw-tags-intro'>\n$1\n</div>", 'tags-intro' ); // Write the headers - $html = Xml::tags( 'tr', null, Xml::tags( 'th', null, wfMsgExt( 'tags-tag', 'parseinline' ) ) . - Xml::tags( 'th', null, wfMsgExt( 'tags-display-header', 'parseinline' ) ) . - Xml::tags( 'th', null, wfMsgExt( 'tags-description-header', 'parseinline' ) ) . - Xml::tags( 'th', null, wfMsgExt( 'tags-hitcount-header', 'parseinline' ) ) + $html = Xml::tags( 'tr', null, Xml::tags( 'th', null, $this->msg( 'tags-tag' )->parse() ) . + Xml::tags( 'th', null, $this->msg( 'tags-display-header' )->parse() ) . + Xml::tags( 'th', null, $this->msg( 'tags-description-header' )->parse() ) . + Xml::tags( 'th', null, $this->msg( 'tags-hitcount-header' )->parse() ) ); $dbr = wfGetDB( DB_SLAVE ); - $res = $dbr->select( 'change_tag', array( 'ct_tag', 'count(*) AS hitcount' ), + $res = $dbr->select( 'change_tag', array( 'ct_tag', 'hitcount' => 'count(*)' ), array(), __METHOD__, array( 'GROUP BY' => 'ct_tag', 'ORDER BY' => 'hitcount DESC' ) ); foreach ( $res as $row ) { @@ -72,18 +69,22 @@ class SpecialTags extends SpecialPage { } $newRow = ''; - $newRow .= Xml::tags( 'td', null, Xml::element( 'tt', null, $tag ) ); + $newRow .= Xml::tags( 'td', null, Xml::element( 'code', null, $tag ) ); $disp = ChangeTags::tagDescription( $tag ); - $disp .= ' (' . Linker::link( Title::makeTitle( NS_MEDIAWIKI, "Tag-$tag" ), wfMsgHtml( 'tags-edit' ) ) . ')'; + $disp .= ' '; + $editLink = Linker::link( Title::makeTitle( NS_MEDIAWIKI, "Tag-$tag" ), $this->msg( 'tags-edit' )->escaped() ); + $disp .= $this->msg( 'parentheses' )->rawParams( $editLink )->escaped(); $newRow .= Xml::tags( 'td', null, $disp ); - $msg = wfMessage( "tag-$tag-description" ); + $msg = $this->msg( "tag-$tag-description" ); $desc = !$msg->exists() ? '' : $msg->parse(); - $desc .= ' (' . Linker::link( Title::makeTitle( NS_MEDIAWIKI, "Tag-$tag-description" ), wfMsgHtml( 'tags-edit' ) ) . ')'; + $desc .= ' '; + $editDescLink = Linker::link( Title::makeTitle( NS_MEDIAWIKI, "Tag-$tag-description" ), $this->msg( 'tags-edit' )->escaped() ); + $desc .= $this->msg( 'parentheses' )->rawParams( $editDescLink )->escaped(); $newRow .= Xml::tags( 'td', null, $desc ); - $hitcount = wfMsgExt( 'tags-hitcount', array( 'parsemag' ), $this->getLanguage()->formatNum( $hitcount ) ); + $hitcount = $this->msg( 'tags-hitcount' )->numParams( $hitcount )->escaped(); $hitcount = Linker::link( SpecialPage::getTitleFor( 'Recentchanges' ), $hitcount, array(), array( 'tagfilter' => $tag ) ); $newRow .= Xml::tags( 'td', null, $hitcount ); diff --git a/includes/specials/SpecialUnblock.php b/includes/specials/SpecialUnblock.php index 47944309..fb2005b5 100644 --- a/includes/specials/SpecialUnblock.php +++ b/includes/specials/SpecialUnblock.php @@ -1,5 +1,7 @@ <?php /** + * Implements Special:Unblock + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -49,23 +51,23 @@ class SpecialUnblock extends SpecialPage { $out->addModules( 'mediawiki.special' ); $form = new HTMLForm( $this->getFields(), $this->getContext() ); - $form->setWrapperLegend( wfMsg( 'unblockip' ) ); + $form->setWrapperLegendMsg( 'unblockip' ); $form->setSubmitCallback( array( __CLASS__, 'processUIUnblock' ) ); - $form->setSubmitText( wfMsg( 'ipusubmit' ) ); - $form->addPreText( wfMsgExt( 'unblockiptext', 'parse' ) ); + $form->setSubmitTextMsg( 'ipusubmit' ); + $form->addPreText( $this->msg( 'unblockiptext' )->parseAsBlock() ); if( $form->show() ){ switch( $this->type ){ case Block::TYPE_USER: case Block::TYPE_IP: - $out->addWikiMsg( 'unblocked', $this->target ); + $out->addWikiMsg( 'unblocked', wfEscapeWikiText( $this->target ) ); break; case Block::TYPE_RANGE: - $out->addWikiMsg( 'unblocked-range', $this->target ); + $out->addWikiMsg( 'unblocked-range', wfEscapeWikiText( $this->target ) ); break; case Block::TYPE_ID: case Block::TYPE_AUTO: - $out->addWikiMsg( 'unblocked-id', $this->target ); + $out->addWikiMsg( 'unblocked-id', wfEscapeWikiText( $this->target ) ); break; } } @@ -136,6 +138,7 @@ class SpecialUnblock extends SpecialPage { /** * Submit callback for an HTMLForm object + * @return Array( Array(message key, parameters) */ public static function processUIUnblock( array $data, HTMLForm $form ) { return self::processUnblock( $data, $form->getContext() ); diff --git a/includes/specials/SpecialUncategorizedimages.php b/includes/specials/SpecialUncategorizedimages.php index 3efed747..5865bf62 100644 --- a/includes/specials/SpecialUncategorizedimages.php +++ b/includes/specials/SpecialUncategorizedimages.php @@ -49,9 +49,9 @@ class UncategorizedImagesPage extends ImageQueryPage { function getQueryInfo() { return array ( 'tables' => array( 'page', 'categorylinks' ), - 'fields' => array( 'page_namespace AS namespace', - 'page_title AS title', - 'page_title AS value' ), + 'fields' => array( 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'page_title' ), 'conds' => array( 'cl_from IS NULL', 'page_namespace' => NS_FILE, 'page_is_redirect' => 0 ), diff --git a/includes/specials/SpecialUncategorizedpages.php b/includes/specials/SpecialUncategorizedpages.php index 08a69448..1226a6ca 100644 --- a/includes/specials/SpecialUncategorizedpages.php +++ b/includes/specials/SpecialUncategorizedpages.php @@ -46,9 +46,9 @@ class UncategorizedPagesPage extends PageQueryPage { function getQueryInfo() { return array ( 'tables' => array ( 'page', 'categorylinks' ), - 'fields' => array ( 'page_namespace AS namespace', - 'page_title AS title', - 'page_title AS value' ), + 'fields' => array ( 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'page_title' ), // default for page_namespace is all content namespaces (if requestedNamespace is false) // otherwise, page_namespace is requestedNamespace 'conds' => array ( 'cl_from IS NULL', diff --git a/includes/specials/SpecialUndelete.php b/includes/specials/SpecialUndelete.php index 5d8b17b7..d8e0b97c 100644 --- a/includes/specials/SpecialUndelete.php +++ b/includes/specials/SpecialUndelete.php @@ -92,13 +92,13 @@ class PageArchive { array( 'ar_namespace', 'ar_title', - 'COUNT(*) AS count' + 'count' => 'COUNT(*)' ), $condition, __METHOD__, array( - 'GROUP BY' => 'ar_namespace,ar_title', - 'ORDER BY' => 'ar_namespace,ar_title', + 'GROUP BY' => array( 'ar_namespace', 'ar_title' ), + 'ORDER BY' => array( 'ar_namespace', 'ar_title' ), 'LIMIT' => 100, ) ) @@ -120,7 +120,7 @@ class PageArchive { ), array( 'ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey() ), - 'PageArchive::listRevisions', + __METHOD__, array( 'ORDER BY' => 'ar_timestamp DESC' ) ); $ret = $dbr->resultObject( $res ); return $ret; @@ -195,7 +195,7 @@ class PageArchive { 'ar_timestamp' => $dbr->timestamp( $timestamp ) ), __METHOD__ ); if( $row ) { - return Revision::newFromArchiveRow( $row, array( 'page' => $this->title->getArticleId() ) ); + return Revision::newFromArchiveRow( $row, array( 'page' => $this->title->getArticleID() ) ); } else { return null; } @@ -308,7 +308,9 @@ class PageArchive { $dbr = wfGetDB( DB_SLAVE ); $n = $dbr->selectField( 'archive', 'COUNT(ar_title)', array( 'ar_namespace' => $this->title->getNamespace(), - 'ar_title' => $this->title->getDBkey() ) ); + 'ar_title' => $this->title->getDBkey() ), + __METHOD__ + ); return ( $n > 0 ); } @@ -321,11 +323,14 @@ class PageArchive { * @param $comment String * @param $fileVersions Array * @param $unsuppress Boolean + * @param $user User doing the action, or null to use $wgUser * * @return array(number of file revisions restored, number of image revisions restored, log message) * on success, false on failure */ - function undelete( $timestamps, $comment = '', $fileVersions = array(), $unsuppress = false ) { + function undelete( $timestamps, $comment = '', $fileVersions = array(), $unsuppress = false, User $user = null ) { + global $wgUser; + // If both the set of text revisions and file revisions are empty, // restore everything. Otherwise, just restore the requested items. $restoreAll = empty( $timestamps ) && empty( $fileVersions ); @@ -354,28 +359,35 @@ class PageArchive { } // Touch the log! - global $wgContLang; - $log = new LogPage( 'delete' ); if( $textRestored && $filesRestored ) { - $reason = wfMsgExt( 'undeletedrevisions-files', array( 'content', 'parsemag' ), - $wgContLang->formatNum( $textRestored ), - $wgContLang->formatNum( $filesRestored ) ); + $reason = wfMessage( 'undeletedrevisions-files' ) + ->numParams( $textRestored, $filesRestored )->inContentLanguage()->text(); } elseif( $textRestored ) { - $reason = wfMsgExt( 'undeletedrevisions', array( 'content', 'parsemag' ), - $wgContLang->formatNum( $textRestored ) ); + $reason = wfMessage( 'undeletedrevisions' )->numParams( $textRestored ) + ->inContentLanguage()->text(); } elseif( $filesRestored ) { - $reason = wfMsgExt( 'undeletedfiles', array( 'content', 'parsemag' ), - $wgContLang->formatNum( $filesRestored ) ); + $reason = wfMessage( 'undeletedfiles' )->numParams( $filesRestored ) + ->inContentLanguage()->text(); } else { wfDebug( "Undelete: nothing undeleted...\n" ); return false; } if( trim( $comment ) != '' ) { - $reason .= wfMsgForContent( 'colon-separator' ) . $comment; + $reason .= wfMessage( 'colon-separator' )->inContentLanguage()->text() . $comment; } - $log->addEntry( 'restore', $this->title, $reason ); + + if ( $user === null ) { + $user = $wgUser; + } + + $logEntry = new ManualLogEntry( 'delete', 'restore' ); + $logEntry->setPerformer( $user ); + $logEntry->setTarget( $this->title ); + $logEntry->setComment( $reason ); + $logid = $logEntry->insert(); + $logEntry->publish( $logid ); return array( $textRestored, $filesRestored, $reason ); } @@ -745,14 +757,20 @@ class SpecialUndelete extends SpecialPage { $out->addHTML( "<ul>\n" ); foreach ( $result as $row ) { $title = Title::makeTitleSafe( $row->ar_namespace, $row->ar_title ); - $link = Linker::linkKnown( - $undelete, - htmlspecialchars( $title->getPrefixedText() ), - array(), - array( 'target' => $title->getPrefixedText() ) - ); + if ( $title !== null ) { + $item = Linker::linkKnown( + $undelete, + htmlspecialchars( $title->getPrefixedText() ), + array(), + array( 'target' => $title->getPrefixedText() ) + ); + } else { + // The title is no longer valid, show as text + $item = Html::element( 'span', array( 'class' => 'mw-invalidtitle' ), + Linker::getInvalidTitleDescription( $this->getContext(), $row->ar_namespace, $row->ar_title ) ); + } $revs = $this->msg( 'undeleterevisions' )->numParams( $row->count )->parse(); - $out->addHTML( "<li>{$link} ({$revs})</li>\n" ); + $out->addHTML( "<li>{$item} ({$revs})</li>\n" ); } $result->free(); $out->addHTML( "</ul>\n" ); @@ -890,21 +908,22 @@ class SpecialUndelete extends SpecialPage { $diffEngine->showDiffStyle(); $this->getOutput()->addHTML( "<div>" . - "<table border='0' width='98%' cellpadding='0' cellspacing='4' class='diff'>" . + "<table width='98%' cellpadding='0' cellspacing='4' class='diff'>" . "<col class='diff-marker' />" . "<col class='diff-content' />" . "<col class='diff-marker' />" . "<col class='diff-content' />" . "<tr>" . - "<td colspan='2' width='50%' align='center' class='diff-otitle'>" . + "<td colspan='2' width='50%' style='text-align: center' class='diff-otitle'>" . $this->diffHeader( $previousRev, 'o' ) . "</td>\n" . - "<td colspan='2' width='50%' align='center' class='diff-ntitle'>" . + "<td colspan='2' width='50%' style='text-align: center' class='diff-ntitle'>" . $this->diffHeader( $currentRev, 'n' ) . "</td>\n" . "</tr>" . $diffEngine->generateDiffBody( - $previousRev->getText(), $currentRev->getText() ) . + $previousRev->getText( Revision::FOR_THIS_USER, $this->getUser() ), + $currentRev->getText( Revision::FOR_THIS_USER, $this->getUser() ) ) . "</table>" . "</div>\n" ); @@ -1009,7 +1028,7 @@ class SpecialUndelete extends SpecialPage { } $out->wrapWikiMsg( "<div class='mw-undelete-pagetitle'>\n$1\n</div>\n", - array( 'undeletepagetitle', $this->mTargetObj->getPrefixedText() ) + array( 'undeletepagetitle', wfEscapeWikiText( $this->mTargetObj->getPrefixedText() ) ) ); $archive = new PageArchive( $this->mTargetObj ); @@ -1065,11 +1084,13 @@ class SpecialUndelete extends SpecialPage { } # Show relevant lines from the deletion log: - $out->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) . "\n" ); + $deleteLogPage = new LogPage( 'delete' ); + $out->addHTML( Xml::element( 'h2', null, $deleteLogPage->getName()->text() ) . "\n" ); LogEventsList::showLogExtract( $out, 'delete', $this->mTargetObj ); # Show relevant lines from the suppression log: + $suppressLogPage = new LogPage( 'suppress' ); if( $this->getUser()->isAllowed( 'suppressionlog' ) ) { - $out->addHTML( Xml::element( 'h2', null, LogPage::logName( 'suppress' ) ) . "\n" ); + $out->addHTML( Xml::element( 'h2', null, $suppressLogPage->getName()->text() ) . "\n" ); LogEventsList::showLogExtract( $out, 'suppress', $this->mTargetObj ); } @@ -1159,8 +1180,8 @@ class SpecialUndelete extends SpecialPage { private function formatRevisionRow( $row, $earliestLiveTime, $remaining ) { $rev = Revision::newFromArchiveRow( $row, - array( 'page' => $this->mTargetObj->getArticleId() ) ); - $stxt = ''; + array( 'page' => $this->mTargetObj->getArticleID() ) ); + $revTextSize = ''; $ts = wfTimestamp( TS_MW, $row->ar_timestamp ); // Build checkboxen... if( $this->mAllowed ) { @@ -1209,13 +1230,15 @@ class SpecialUndelete extends SpecialPage { // Revision text size $size = $row->ar_len; if( !is_null( $size ) ) { - $stxt = Linker::formatRevisionSize( $size ); + $revTextSize = Linker::formatRevisionSize( $size ); } // Edit summary $comment = Linker::revComment( $rev ); // Revision delete links $revdlink = Linker::getRevDeleteLink( $user, $rev, $this->mTargetObj ); - return "<li>$checkBox $revdlink ($last) $pageLink . . $userLink $stxt $comment</li>"; + + $revisionRow = $this->msg( 'undelete-revisionrow' )->rawParams( $checkBox, $revdlink, $last, $pageLink , $userLink, $revTextSize, $comment )->escaped(); + return "<li>$revisionRow</li>"; } private function formatFileRow( $row ) { @@ -1232,9 +1255,9 @@ class SpecialUndelete extends SpecialPage { $pageLink = $this->getLanguage()->userTimeAndDate( $ts, $user ); } $userLink = $this->getFileUser( $file ); - $data = $this->msg( 'widthheight' )->numParams( $row->fa_width, $row->fa_height )->text() . - ' (' . $this->msg( 'nbytes' )->numParams( $row->fa_size )->text() . ')'; - $data = htmlspecialchars( $data ); + $data = $this->msg( 'widthheight' )->numParams( $row->fa_width, $row->fa_height )->text(); + $bytes = $this->msg( 'parentheses' )->rawParams( $this->msg( 'nbytes' )->numParams( $row->fa_size )->text() )->plain(); + $data = htmlspecialchars( $data . ' ' . $bytes ); $comment = $this->getFileComment( $file ); // Add show/hide deletion links if available @@ -1263,7 +1286,7 @@ class SpecialUndelete extends SpecialPage { * * @param $rev Revision * @param $titleObj Title - * @param $ts Timestamp + * @param $ts string Timestamp * @return string */ function getPageLink( $rev, $titleObj, $ts ) { @@ -1294,7 +1317,7 @@ class SpecialUndelete extends SpecialPage { * * @param $file File * @param $titleObj Title - * @param $ts A timestamp + * @param $ts string A timestamp * @param $key String: a storage key * * @return String: HTML fragment @@ -1379,7 +1402,9 @@ class SpecialUndelete extends SpecialPage { $this->mTargetTimestamp, $this->mComment, $this->mFileVersions, - $this->mUnsuppress ); + $this->mUnsuppress, + $this->getUser() + ); if( is_array( $ok ) ) { if ( $ok[1] ) { // Undeleted file count @@ -1399,7 +1424,7 @@ class SpecialUndelete extends SpecialPage { // Show file deletion warnings and errors $status = $archive->getFileStatus(); if( $status && !$status->isGood() ) { - $out->addWikiText( $status->getWikiText( 'undelete-error-short', 'undelete-error-long' ) ); + $out->addWikiText( '<div class="error">' . $status->getWikiText( 'undelete-error-short', 'undelete-error-long' ) . '</div>' ); } } } diff --git a/includes/specials/SpecialUnusedcategories.php b/includes/specials/SpecialUnusedcategories.php index 48a93e8d..1bd38e17 100644 --- a/includes/specials/SpecialUnusedcategories.php +++ b/includes/specials/SpecialUnusedcategories.php @@ -39,9 +39,9 @@ class UnusedCategoriesPage extends QueryPage { function getQueryInfo() { return array ( 'tables' => array ( 'page', 'categorylinks' ), - 'fields' => array ( 'page_namespace AS namespace', - 'page_title AS title', - 'page_title AS value' ), + 'fields' => array ( 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'page_title' ), 'conds' => array ( 'cl_from IS NULL', 'page_namespace' => NS_CATEGORY, 'page_is_redirect' => 0 ), @@ -52,6 +52,7 @@ class UnusedCategoriesPage extends QueryPage { /** * A should come before Z (bug 30907) + * @return bool */ function sortDescending() { return false; diff --git a/includes/specials/SpecialUnusedimages.php b/includes/specials/SpecialUnusedimages.php index 6407de44..cdab557e 100644 --- a/includes/specials/SpecialUnusedimages.php +++ b/includes/specials/SpecialUnusedimages.php @@ -47,9 +47,9 @@ class UnusedimagesPage extends ImageQueryPage { global $wgCountCategorizedImagesAsUsed; $retval = array ( 'tables' => array ( 'image', 'imagelinks' ), - 'fields' => array ( "'" . NS_FILE . "' AS namespace", - 'img_name AS title', - 'img_timestamp AS value', + 'fields' => array ( 'namespace' => NS_FILE, + 'title' => 'img_name', + 'value' => 'img_timestamp', 'img_user', 'img_user_text', 'img_description' ), 'conds' => array ( 'il_to IS NULL' ), @@ -77,7 +77,7 @@ class UnusedimagesPage extends ImageQueryPage { } function getPageHeader() { - return wfMsgExt( 'unusedimagestext', array( 'parse' ) ); + return $this->msg( 'unusedimagestext' )->parseAsBlock(); } } diff --git a/includes/specials/SpecialUnusedtemplates.php b/includes/specials/SpecialUnusedtemplates.php index e5c55b83..06077d1f 100644 --- a/includes/specials/SpecialUnusedtemplates.php +++ b/includes/specials/SpecialUnusedtemplates.php @@ -42,9 +42,9 @@ class UnusedtemplatesPage extends QueryPage { function getQueryInfo() { return array ( 'tables' => array ( 'page', 'templatelinks' ), - 'fields' => array ( 'page_namespace AS namespace', - 'page_title AS title', - 'page_title AS value' ), + 'fields' => array ( 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'page_title' ), 'conds' => array ( 'page_namespace' => NS_TEMPLATE, 'tl_from IS NULL', 'page_is_redirect' => 0 ), @@ -68,17 +68,13 @@ class UnusedtemplatesPage extends QueryPage { array( 'redirect' => 'no' ) ); $wlhLink = Linker::linkKnown( - SpecialPage::getTitleFor( 'Whatlinkshere' ), - wfMsgHtml( 'unusedtemplateswlh' ), - array(), - array( 'target' => $title->getPrefixedText() ) + SpecialPage::getTitleFor( 'Whatlinkshere', $title->getPrefixedText() ), + $this->msg( 'unusedtemplateswlh' )->escaped() ); return $this->getLanguage()->specialList( $pageLink, $wlhLink ); } function getPageHeader() { - return wfMsgExt( 'unusedtemplatestext', array( 'parse' ) ); + return $this->msg( 'unusedtemplatestext' )->parseAsBlock(); } - } - diff --git a/includes/specials/SpecialUnwatchedpages.php b/includes/specials/SpecialUnwatchedpages.php index 22c64858..e5a79413 100644 --- a/includes/specials/SpecialUnwatchedpages.php +++ b/includes/specials/SpecialUnwatchedpages.php @@ -41,9 +41,9 @@ class UnwatchedpagesPage extends QueryPage { function getQueryInfo() { return array ( 'tables' => array ( 'page', 'watchlist' ), - 'fields' => array ( 'page_namespace AS namespace', - 'page_title AS title', - 'page_namespace AS value' ), + 'fields' => array ( 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'page_namespace' ), 'conds' => array ( 'wl_title IS NULL', 'page_is_redirect' => 0, "page_namespace != '" . NS_MEDIAWIKI . @@ -68,17 +68,19 @@ class UnwatchedpagesPage extends QueryPage { function formatResult( $skin, $result ) { global $wgContLang; - $nt = Title::makeTitle( $result->namespace, $result->title ); + $nt = Title::makeTitleSafe( $result->namespace, $result->title ); + if ( !$nt ) { + return Html::element( 'span', array( 'class' => 'mw-invalidtitle' ), + Linker::getInvalidTitleDescription( $this->getContext(), $result->namespace, $result->title ) ); + } + $text = $wgContLang->convert( $nt->getPrefixedText() ); - $plink = Linker::linkKnown( - $nt, - htmlspecialchars( $text ) - ); + $plink = Linker::linkKnown( $nt, htmlspecialchars( $text ) ); $token = WatchAction::getWatchToken( $nt, $this->getUser() ); $wlink = Linker::linkKnown( $nt, - wfMsgHtml( 'watch' ), + $this->msg( 'watch' )->escaped(), array(), array( 'action' => 'watch', 'token' => $token ) ); diff --git a/includes/specials/SpecialUpload.php b/includes/specials/SpecialUpload.php index d6a76d02..43ea345b 100644 --- a/includes/specials/SpecialUpload.php +++ b/includes/specials/SpecialUpload.php @@ -150,7 +150,7 @@ class SpecialUpload extends SpecialPage { # Check blocks if( $user->isBlocked() ) { - throw new UserBlockedError( $user->mBlock ); + throw new UserBlockedError( $user->getBlock() ); } # Check whether we actually want to allow changing stuff @@ -235,7 +235,7 @@ class SpecialUpload extends SpecialPage { !$this->mTokenOk && !$this->mCancelUpload && ( $this->mUpload && $this->mUploadClicked ) ) { - $form->addPreText( wfMsgExt( 'session_fail_preview', 'parseinline' ) ); + $form->addPreText( $this->msg( 'session_fail_preview' )->parse() ); } # Give a notice if the user is uploading a file that has been deleted or moved @@ -255,16 +255,16 @@ class SpecialUpload extends SpecialPage { # Add text to form $form->addPreText( '<div id="uploadtext">' . - wfMsgExt( 'uploadtext', 'parse', array( $this->mDesiredDestName ) ) . + $this->msg( 'uploadtext', array( $this->mDesiredDestName ) )->parseAsBlock() . '</div>' ); # Add upload error message $form->addPreText( $message ); # Add footer to form - $uploadFooter = wfMessage( 'uploadfooter' ); + $uploadFooter = $this->msg( 'uploadfooter' ); if ( !$uploadFooter->isDisabled() ) { $form->addPostText( '<div id="mw-upload-footer-message">' - . $this->getOutput()->parse( $uploadFooter->plain() ) . "</div>\n" ); + . $uploadFooter->parseAsBlock() . "</div>\n" ); } return $form; @@ -280,14 +280,12 @@ class SpecialUpload extends SpecialPage { if( $title instanceof Title ) { $count = $title->isDeleted(); if ( $count > 0 && $user->isAllowed( 'deletedhistory' ) ) { - $link = wfMsgExt( - $user->isAllowed( 'delete' ) ? 'thisisdeleted' : 'viewdeleted', - array( 'parse', 'replaceafter' ), - Linker::linkKnown( - SpecialPage::getTitleFor( 'Undelete', $title->getPrefixedText() ), - wfMsgExt( 'restorelink', array( 'parsemag', 'escape' ), $count ) - ) + $restorelink = Linker::linkKnown( + SpecialPage::getTitleFor( 'Undelete', $title->getPrefixedText() ), + $this->msg( 'restorelink' )->numParams( $count )->escaped() ); + $link = $this->msg( $user->isAllowed( 'delete' ) ? 'thisisdeleted' : 'viewdeleted' ) + ->rawParams( $restorelink )->parseAsBlock(); $this->getOutput()->addHTML( "<div id=\"contentSub2\">{$link}</div>" ); } } @@ -306,11 +304,11 @@ class SpecialUpload extends SpecialPage { */ protected function showRecoverableUploadError( $message ) { $sessionKey = $this->mUpload->stashSession(); - $message = '<h2>' . wfMsgHtml( 'uploaderror' ) . "</h2>\n" . + $message = '<h2>' . $this->msg( 'uploaderror' )->escaped() . "</h2>\n" . '<div class="error">' . $message . "</div>\n"; $form = $this->getUploadForm( $message, $sessionKey ); - $form->setSubmitText( wfMsg( 'upload-tryagain' ) ); + $form->setSubmitText( $this->msg( 'upload-tryagain' )->escaped() ); $this->showUploadForm( $form ); } /** @@ -335,7 +333,7 @@ class SpecialUpload extends SpecialPage { $sessionKey = $this->mUpload->stashSession(); - $warningHtml = '<h2>' . wfMsgHtml( 'uploadwarning' ) . "</h2>\n" + $warningHtml = '<h2>' . $this->msg( 'uploadwarning' )->escaped() . "</h2>\n" . '<ul class="warning">'; foreach( $warnings as $warning => $args ) { if( $warning == 'exists' ) { @@ -343,8 +341,8 @@ class SpecialUpload extends SpecialPage { } elseif( $warning == 'duplicate' ) { $msg = self::getDupeWarning( $args ); } elseif( $warning == 'duplicate-archive' ) { - $msg = "\t<li>" . wfMsgExt( 'file-deleted-duplicate', 'parseinline', - array( Title::makeTitle( NS_FILE, $args )->getPrefixedText() ) ) + $msg = "\t<li>" . $this->msg( 'file-deleted-duplicate', + Title::makeTitle( NS_FILE, $args )->getPrefixedText() )->parse() . "</li>\n"; } else { if ( $args === true ) { @@ -352,17 +350,17 @@ class SpecialUpload extends SpecialPage { } elseif ( !is_array( $args ) ) { $args = array( $args ); } - $msg = "\t<li>" . wfMsgExt( $warning, 'parseinline', $args ) . "</li>\n"; + $msg = "\t<li>" . $this->msg( $warning, $args )->parse() . "</li>\n"; } $warningHtml .= $msg; } $warningHtml .= "</ul>\n"; - $warningHtml .= wfMsgExt( 'uploadwarning-text', 'parse' ); + $warningHtml .= $this->msg( 'uploadwarning-text' )->parseAsBlock(); $form = $this->getUploadForm( $warningHtml, $sessionKey, /* $hideIgnoreWarning */ true ); - $form->setSubmitText( wfMsg( 'upload-tryagain' ) ); - $form->addButton( 'wpUploadIgnoreWarning', wfMsg( 'ignorewarning' ) ); - $form->addButton( 'wpCancelUpload', wfMsg( 'reuploaddesc' ) ); + $form->setSubmitText( $this->msg( 'upload-tryagain' )->text() ); + $form->addButton( 'wpUploadIgnoreWarning', $this->msg( 'ignorewarning' )->text() ); + $form->addButton( 'wpCancelUpload', $this->msg( 'reuploaddesc' )->text() ); $this->showUploadForm( $form ); @@ -376,7 +374,7 @@ class SpecialUpload extends SpecialPage { * @param $message string HTML string */ protected function showUploadError( $message ) { - $message = '<h2>' . wfMsgHtml( 'uploadwarning' ) . "</h2>\n" . + $message = '<h2>' . $this->msg( 'uploadwarning' )->escaped() . "</h2>\n" . '<div class="error">' . $message . "</div>\n"; $this->showUploadForm( $this->getUploadForm( $message ) ); } @@ -414,8 +412,7 @@ class SpecialUpload extends SpecialPage { $permErrors = $this->mUpload->verifyTitlePermissions( $this->getUser() ); if( $permErrors !== true ) { $code = array_shift( $permErrors[0] ); - $this->showRecoverableUploadError( wfMsgExt( $code, - 'parseinline', $permErrors[0] ) ); + $this->showRecoverableUploadError( $this->msg( $code, $permErrors[0] )->parse() ); return; } @@ -469,7 +466,7 @@ class SpecialUpload extends SpecialPage { if ( in_array( $msgName, $wgForceUIMsgAsContentMsg ) ) { $msg[$msgName] = "{{int:$msgName}}"; } else { - $msg[$msgName] = wfMsgForContent( $msgName ); + $msg[$msgName] = wfMessage( $msgName )->inContentLanguage()->text(); } } @@ -516,7 +513,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' ); @@ -536,33 +533,31 @@ class SpecialUpload extends SpecialPage { /** Statuses that only require name changing **/ case UploadBase::MIN_LENGTH_PARTNAME: - $this->showRecoverableUploadError( wfMsgHtml( 'minlength1' ) ); + $this->showRecoverableUploadError( $this->msg( 'minlength1' )->escaped() ); break; case UploadBase::ILLEGAL_FILENAME: - $this->showRecoverableUploadError( wfMsgExt( 'illegalfilename', - 'parseinline', $details['filtered'] ) ); + $this->showRecoverableUploadError( $this->msg( 'illegalfilename', + $details['filtered'] )->parse() ); break; case UploadBase::FILENAME_TOO_LONG: - $this->showRecoverableUploadError( wfMsgHtml( 'filename-toolong' ) ); + $this->showRecoverableUploadError( $this->msg( 'filename-toolong' )->escaped() ); break; case UploadBase::FILETYPE_MISSING: - $this->showRecoverableUploadError( wfMsgExt( 'filetype-missing', - 'parseinline' ) ); + $this->showRecoverableUploadError( $this->msg( 'filetype-missing' )->parse() ); break; case UploadBase::WINDOWS_NONASCII_FILENAME: - $this->showRecoverableUploadError( wfMsgExt( 'windows-nonascii-filename', - 'parseinline' ) ); + $this->showRecoverableUploadError( $this->msg( 'windows-nonascii-filename' )->parse() ); break; /** Statuses that require reuploading **/ case UploadBase::EMPTY_FILE: - $this->showUploadError( wfMsgHtml( 'emptyfile' ) ); + $this->showUploadError( $this->msg( 'emptyfile' )->escaped() ); break; case UploadBase::FILE_TOO_LARGE: - $this->showUploadError( wfMsgHtml( 'largefileserver' ) ); + $this->showUploadError( $this->msg( 'largefileserver' )->escaped() ); break; case UploadBase::FILETYPE_BADTYPE: - $msg = wfMessage( 'filetype-banned-type' ); + $msg = $this->msg( 'filetype-banned-type' ); if ( isset( $details['blacklistedExt'] ) ) { $msg->params( $this->getLanguage()->commaList( $details['blacklistedExt'] ) ); } else { @@ -585,7 +580,7 @@ class SpecialUpload extends SpecialPage { case UploadBase::VERIFICATION_ERROR: unset( $details['status'] ); $code = array_shift( $details['details'] ); - $this->showUploadError( wfMsgExt( $code, 'parseinline', $details['details'] ) ); + $this->showUploadError( $this->msg( $code, $details['details'] )->parse() ); break; case UploadBase::HOOK_ABORTED: if ( is_array( $details['error'] ) ) { # allow hooks to return error details in an array @@ -596,7 +591,7 @@ class SpecialUpload extends SpecialPage { $args = null; } - $this->showUploadError( wfMsgExt( $error, 'parseinline', $args ) ); + $this->showUploadError( $this->msg( $error, $args )->parse() ); break; default: throw new MWException( __METHOD__ . ": Unknown value `{$details['status']}`" ); @@ -641,37 +636,37 @@ class SpecialUpload extends SpecialPage { if( $exists['warning'] == 'exists' ) { // Exact match - $warning = wfMsgExt( 'fileexists', 'parseinline', $filename ); + $warning = wfMessage( 'fileexists', $filename )->parse(); } elseif( $exists['warning'] == 'page-exists' ) { // Page exists but file does not - $warning = wfMsgExt( 'filepageexists', 'parseinline', $filename ); + $warning = wfMessage( 'filepageexists', $filename )->parse(); } elseif ( $exists['warning'] == 'exists-normalized' ) { - $warning = wfMsgExt( 'fileexists-extension', 'parseinline', $filename, - $exists['normalizedFile']->getTitle()->getPrefixedText() ); + $warning = wfMessage( 'fileexists-extension', $filename, + $exists['normalizedFile']->getTitle()->getPrefixedText() )->parse(); } elseif ( $exists['warning'] == 'thumb' ) { // Swapped argument order compared with other messages for backwards compatibility - $warning = wfMsgExt( 'fileexists-thumbnail-yes', 'parseinline', - $exists['thumbFile']->getTitle()->getPrefixedText(), $filename ); + $warning = wfMessage( 'fileexists-thumbnail-yes', + $exists['thumbFile']->getTitle()->getPrefixedText(), $filename )->parse(); } elseif ( $exists['warning'] == 'thumb-name' ) { // Image w/o '180px-' does not exists, but we do not like these filenames $name = $file->getName(); $badPart = substr( $name, 0, strpos( $name, '-' ) + 1 ); - $warning = wfMsgExt( 'file-thumbnail-no', 'parseinline', $badPart ); + $warning = wfMessage( 'file-thumbnail-no', $badPart )->parse(); } elseif ( $exists['warning'] == 'bad-prefix' ) { - $warning = wfMsgExt( 'filename-bad-prefix', 'parseinline', $exists['prefix'] ); + $warning = wfMessage( 'filename-bad-prefix', $exists['prefix'] )->parse(); } elseif ( $exists['warning'] == 'was-deleted' ) { # If the file existed before and was deleted, warn the user of this $ltitle = SpecialPage::getTitleFor( 'Log' ); $llink = Linker::linkKnown( $ltitle, - wfMsgHtml( 'deletionlog' ), + wfMessage( 'deletionlog' )->escaped(), array(), array( 'type' => 'delete', 'page' => $filename ) ); - $warning = wfMsgExt( 'filewasdeleted', array( 'parse', 'replaceafter' ), $llink ); + $warning = wfMessage( 'filewasdeleted' )->rawParams( $llink )->parseAsBlock(); } return $warning; @@ -707,22 +702,18 @@ class SpecialUpload extends SpecialPage { * @return string */ public static function getDupeWarning( $dupes ) { - global $wgOut; - if( $dupes ) { - $msg = '<gallery>'; - foreach( $dupes as $file ) { - $title = $file->getTitle(); - $msg .= $title->getPrefixedText() . - '|' . $title->getText() . "\n"; - } - $msg .= '</gallery>'; - return '<li>' . - wfMsgExt( 'file-exists-duplicate', array( 'parse' ), count( $dupes ) ) . - $wgOut->parse( $msg ) . - "</li>\n"; - } else { + if ( !$dupes ) { return ''; } + + $gallery = new ImageGallery; + $gallery->setShowBytes( false ); + foreach( $dupes as $file ) { + $gallery->add( $file->getTitle() ); + } + return '<li>' . + wfMessage( 'file-exists-duplicate' )->numParams( count( $dupes ) )->parse() . + $gallery->toHtml() . "</li>\n"; } } @@ -775,7 +766,7 @@ class UploadForm extends HTMLForm { parent::__construct( $descriptor, $context, 'upload' ); # Set some form properties - $this->setSubmitText( wfMsg( 'uploadbtn' ) ); + $this->setSubmitText( $this->msg( 'uploadbtn' )->text() ); $this->setSubmitName( 'wpUpload' ); # Used message keys: 'accesskey-upload', 'tooltip-upload' $this->setSubmitTooltip( 'upload' ); @@ -830,7 +821,9 @@ class UploadForm extends HTMLForm { # that setting doesn't exist if ( !wfIsHipHop() ) { $this->mMaxUploadSize['file'] = min( $this->mMaxUploadSize['file'], - wfShorthandToInteger( ini_get( 'upload_max_filesize' ) ) ); + wfShorthandToInteger( ini_get( 'upload_max_filesize' ) ), + wfShorthandToInteger( ini_get( 'post_max_size' ) ) + ); } $descriptor['UploadFile'] = array( @@ -841,10 +834,9 @@ class UploadForm extends HTMLForm { 'label-message' => 'sourcefilename', 'upload-type' => 'File', 'radio' => &$radio, - 'help' => wfMsgExt( 'upload-maxfilesize', - array( 'parseinline', 'escapenoentities' ), + 'help' => $this->msg( 'upload-maxfilesize', $this->getContext()->getLanguage()->formatSize( $this->mMaxUploadSize['file'] ) - ) . ' ' . wfMsgHtml( 'upload_source_file' ), + )->parse() . ' ' . $this->msg( 'upload_source_file' )->escaped(), 'checked' => $selectedSourceType == 'file', ); if ( $canUploadByUrl ) { @@ -856,10 +848,9 @@ class UploadForm extends HTMLForm { 'label-message' => 'sourceurl', 'upload-type' => 'url', 'radio' => &$radio, - 'help' => wfMsgExt( 'upload-maxfilesize', - array( 'parseinline', 'escapenoentities' ), + 'help' => $this->msg( 'upload-maxfilesize', $this->getContext()->getLanguage()->formatSize( $this->mMaxUploadSize['url'] ) - ) . ' ' . wfMsgHtml( 'upload_source_url' ), + )->parse() . ' ' . $this->msg( 'upload_source_url' )->escaped(), 'checked' => $selectedSourceType == 'url', ); } @@ -890,16 +881,16 @@ class UploadForm extends HTMLForm { # Everything not permitted is banned $extensionsList = '<div id="mw-upload-permitted">' . - wfMsgExt( 'upload-permitted', 'parse', $this->getContext()->getLanguage()->commaList( $wgFileExtensions ) ) . + $this->msg( 'upload-permitted', $this->getContext()->getLanguage()->commaList( $wgFileExtensions ) )->parseAsBlock() . "</div>\n"; } else { # We have to list both preferred and prohibited $extensionsList = '<div id="mw-upload-preferred">' . - wfMsgExt( 'upload-preferred', 'parse', $this->getContext()->getLanguage()->commaList( $wgFileExtensions ) ) . + $this->msg( 'upload-preferred', $this->getContext()->getLanguage()->commaList( $wgFileExtensions ) )->parseAsBlock() . "</div>\n" . '<div id="mw-upload-prohibited">' . - wfMsgExt( 'upload-prohibited', 'parse', $this->getContext()->getLanguage()->commaList( $wgFileBlacklist ) ) . + $this->msg( 'upload-prohibited', $this->getContext()->getLanguage()->commaList( $wgFileBlacklist ) )->parseAsBlock() . "</div>\n"; } } else { diff --git a/includes/specials/SpecialUploadStash.php b/includes/specials/SpecialUploadStash.php index 121b6a44..1a00d731 100644 --- a/includes/specials/SpecialUploadStash.php +++ b/includes/specials/SpecialUploadStash.php @@ -1,7 +1,28 @@ <?php /** - * Implements Special:UploadStash + * Implements Special:UploadStash. * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + * @ingroup SpecialPage + * @ingroup Upload + */ + +/** * Web access for files temporarily stored by UploadStash. * * For example -- files that were uploaded with the UploadWizard extension are stored temporarily @@ -10,12 +31,7 @@ * * Since this is based on the user's session, in effect this creates a private temporary file area. * However, the URLs for the files cannot be shared. - * - * @file - * @ingroup SpecialPage - * @ingroup Upload */ - class SpecialUploadStash extends UnlistedSpecialPage { // UploadStash private $stash; @@ -58,6 +74,7 @@ class SpecialUploadStash extends UnlistedSpecialPage { * n.b. Most sanity checking done in UploadStashLocalFile, so this is straightforward. * * @param $key String: the key of a particular requested file + * @return bool */ public function showUpload( $key ) { // prevent callers from doing standard HTML output -- we'll take it from here @@ -241,6 +258,7 @@ class SpecialUploadStash extends UnlistedSpecialPage { * Side effect: writes HTTP response to STDOUT. * * @param $file File object with a local path (e.g. UnregisteredLocalFile, LocalFile. Oddly these don't share an ancestor!) + * @return bool */ private function outputLocalFile( File $file ) { if ( $file->getSize() > self::MAX_SERVE_BYTES ) { @@ -255,8 +273,9 @@ class SpecialUploadStash extends UnlistedSpecialPage { /** * Output HTTP response of raw content * Side effect: writes HTTP response to STDOUT. - * @param String $content: content - * @param String $mimeType: mime type + * @param $content String content + * @param $contentType String mime type + * @return bool */ private function outputContents( $content, $contentType ) { $size = strlen( $content ); @@ -303,7 +322,8 @@ class SpecialUploadStash extends UnlistedSpecialPage { /** * Default action when we don't have a subpage -- just show links to the uploads we have, * Also show a button to clear stashed files - * @param Status : $status - the result of processRequest + * @param $status [optional] Status: the result of processRequest + * @return bool */ private function showUploads( $status = null ) { if ( $status === null ) { @@ -326,7 +346,7 @@ class SpecialUploadStash extends UnlistedSpecialPage { ), $this->getContext(), 'clearStashedUploads' ); $form->setSubmitCallback( array( __CLASS__ , 'tryClearStashedUploads' ) ); $form->setTitle( $this->getTitle() ); - $form->setSubmitText( wfMsg( 'uploadstash-clear' ) ); + $form->setSubmitTextMsg( 'uploadstash-clear' ); $form->prepareForm(); $formResult = $form->tryAuthorizedSubmit(); @@ -334,7 +354,7 @@ class SpecialUploadStash extends UnlistedSpecialPage { // show the files + form, if there are any, or just say there are none $refreshHtml = Html::element( 'a', array( 'href' => $this->getTitle()->getLocalURL() ), - wfMsg( 'uploadstash-refresh' ) ); + $this->msg( 'uploadstash-refresh' )->text() ); $files = $this->stash->listFiles(); if ( $files && count( $files ) ) { sort( $files ); @@ -351,7 +371,7 @@ class SpecialUploadStash extends UnlistedSpecialPage { $this->getOutput()->addHtml( Html::rawElement( 'p', array(), $refreshHtml ) ); } else { $this->getOutput()->addHtml( Html::rawElement( 'p', array(), - Html::element( 'span', array(), wfMsg( 'uploadstash-nofiles' ) ) + Html::element( 'span', array(), $this->msg( 'uploadstash-nofiles' )->text() ) . ' ' . $refreshHtml ) ); diff --git a/includes/specials/SpecialUserlogin.php b/includes/specials/SpecialUserlogin.php index 4c5a2376..58da77da 100644 --- a/includes/specials/SpecialUserlogin.php +++ b/includes/specials/SpecialUserlogin.php @@ -74,7 +74,7 @@ class LoginForm extends SpecialPage { * Loader */ function load() { - global $wgAuth, $wgHiddenPrefs, $wgEnableEmail, $wgRedirectOnLogin; + global $wgAuth, $wgHiddenPrefs, $wgEnableEmail; if ( $this->mLoaded ) { return; @@ -93,8 +93,6 @@ class LoginForm extends SpecialPage { $this->mRetype = $request->getText( 'wpRetype' ); $this->mDomain = $request->getText( 'wpDomain' ); $this->mReason = $request->getText( 'wpReason' ); - $this->mReturnTo = $request->getVal( 'returnto' ); - $this->mReturnToQuery = $request->getVal( 'returntoquery' ); $this->mCookieCheck = $request->getVal( 'wpCookieCheck' ); $this->mPosted = $request->wasPosted(); $this->mCreateaccount = $request->getCheck( 'wpCreateaccount' ); @@ -107,11 +105,8 @@ class LoginForm extends SpecialPage { $this->mLanguage = $request->getText( 'uselang' ); $this->mSkipCookieCheck = $request->getCheck( 'wpSkipCookieCheck' ); $this->mToken = ( $this->mType == 'signup' ) ? $request->getVal( 'wpCreateaccountToken' ) : $request->getVal( 'wpLoginToken' ); - - if ( $wgRedirectOnLogin ) { - $this->mReturnTo = $wgRedirectOnLogin; - $this->mReturnToQuery = ''; - } + $this->mReturnTo = $request->getVal( 'returnto', '' ); + $this->mReturnToQuery = $request->getVal( 'returntoquery', '' ); if( $wgEnableEmail ) { $this->mEmail = $request->getText( 'wpEmail' ); @@ -125,17 +120,17 @@ class LoginForm extends SpecialPage { } if( !$wgAuth->validDomain( $this->mDomain ) ) { - if ( isset( $_SESSION['wsDomain'] ) ) { - $this->mDomain = $_SESSION['wsDomain']; - } else { - $this->mDomain = 'invaliddomain'; - } + $this->mDomain = $wgAuth->getDomain(); } $wgAuth->setDomain( $this->mDomain ); - # When switching accounts, it sucks to get automatically logged out + # 1. When switching accounts, it sucks to get automatically logged out + # 2. Do not return to PasswordReset after a successful password change + # but goto Wiki start page (Main_Page) instead ( bug 33997 ) $returnToTitle = Title::newFromText( $this->mReturnTo ); - if( is_object( $returnToTitle ) && $returnToTitle->isSpecial( 'Userlogout' ) ) { + if( is_object( $returnToTitle ) && ( + $returnToTitle->isSpecial( 'Userlogout' ) + || $returnToTitle->isSpecial( 'PasswordReset' ) ) ) { $this->mReturnTo = ''; $this->mReturnToQuery = ''; } @@ -163,11 +158,14 @@ class LoginForm extends SpecialPage { return; } elseif( $this->mPosted ) { if( $this->mCreateaccount ) { - return $this->addNewAccount(); + $this->addNewAccount(); + return; } elseif ( $this->mCreateaccountMail ) { - return $this->addNewAccountMailPassword(); + $this->addNewAccountMailPassword(); + return; } elseif ( ( 'submitlogin' == $this->mAction ) || $this->mLoginattempt ) { - return $this->processLogin(); + $this->processLogin(); + return; } } $this->mainLoginForm( '' ); @@ -203,12 +201,13 @@ class LoginForm extends SpecialPage { $this->mainLoginForm( $this->msg( 'mailerror', $result->getWikiText() )->text() ); } else { $out->addWikiMsg( 'accmailtext', $u->getName(), $u->getEmail() ); - $out->returnToMain( false ); + $this->executeReturnTo( 'success' ); } } /** * @private + * @return bool */ function addNewAccount() { global $wgUser, $wgEmailAuthentication, $wgLoginLanguageSelector; @@ -216,7 +215,7 @@ class LoginForm extends SpecialPage { # Create the account and abort if there's a problem doing so $u = $this->addNewAccountInternal(); if( $u == null ) { - return; + return false; } # If we showed up language selection links, and one was in use, be @@ -253,23 +252,24 @@ class LoginForm extends SpecialPage { wfRunHooks( 'AddNewAccount', array( $u, false ) ); $u->addNewUserLogEntry(); if( $this->hasSessionCookie() ) { - return $this->successfulCreation(); + $this->successfulCreation(); } else { - return $this->cookieRedirectCheck( 'new' ); + $this->cookieRedirectCheck( 'new' ); } } else { # Confirm that the account was created $out->setPageTitle( $this->msg( 'accountcreated' ) ); $out->addWikiMsg( 'accountcreatedtext', $u->getName() ); - $out->returnToMain( false, $this->getTitle() ); + $out->addReturnTo( $this->getTitle() ); wfRunHooks( 'AddNewAccount', array( $u, false ) ); $u->addNewUserLogEntry( false, $this->mReason ); - return true; } + return true; } /** * @private + * @return bool|User */ function addNewAccountInternal() { global $wgAuth, $wgMemc, $wgAccountCreationThrottle, @@ -334,7 +334,7 @@ class LoginForm extends SpecialPage { $ip = $this->getRequest()->getIP(); if ( $currentUser->isDnsBlacklisted( $ip, true /* check $wgProxyWhitelist */ ) ) { - $this->mainLoginForm( $this->msg( 'sorbs_create_account_reason' )->text() . ' (' . htmlspecialchars( $ip ) . ')' ); + $this->mainLoginForm( $this->msg( 'sorbs_create_account_reason' )->text() . ' ' . $this->msg( 'parentheses', $ip )->escaped() ); return false; } @@ -476,6 +476,7 @@ class LoginForm extends SpecialPage { * This may create a local account as a side effect if the * authentication plugin allows transparent local account * creation. + * @return int */ public function authenticateUserData() { global $wgUser, $wgAuth; @@ -747,9 +748,9 @@ class LoginForm extends SpecialPage { $this->getContext()->setLanguage( $userLang ); // Reset SessionID on Successful login (bug 40995) $this->renewSessionId(); - return $this->successfulLogin(); + $this->successfulLogin(); } else { - return $this->cookieRedirectCheck( 'login' ); + $this->cookieRedirectCheck( 'login' ); } break; @@ -769,7 +770,7 @@ class LoginForm extends SpecialPage { case self::NOT_EXISTS: if( $this->getUser()->isAllowed( 'createaccount' ) ) { $this->mainLoginForm( $this->msg( 'nosuchuser', - wfEscapeWikiText( $this->mUsername ) )->parse() ); + wfEscapeWikiText( $this->mUsername ) )->parse() ); } else { $this->mainLoginForm( $this->msg( 'nosuchusershort', wfEscapeWikiText( $this->mUsername ) )->text() ); @@ -861,16 +862,7 @@ class LoginForm extends SpecialPage { if( $injected_html !== '' ) { $this->displaySuccessfulLogin( 'loginsuccess', $injected_html ); } else { - $titleObj = Title::newFromText( $this->mReturnTo ); - if ( !$titleObj instanceof Title ) { - $titleObj = Title::newMainPage(); - } - $redirectUrl = $titleObj->getFullURL( $this->mReturnToQuery ); - global $wgSecureLogin; - if( $wgSecureLogin && !$this->mStickHTTPS ) { - $redirectUrl = preg_replace( '/^https:/', 'http:', $redirectUrl ); - } - $this->getOutput()->redirect( $redirectUrl ); + $this->executeReturnTo( 'successredirect' ); } } @@ -900,6 +892,8 @@ class LoginForm extends SpecialPage { /** * Display a "login successful" page. + * @param $msgname string + * @param $injected_html string */ private function displaySuccessfulLogin( $msgname, $injected_html ) { $out = $this->getOutput(); @@ -910,11 +904,7 @@ class LoginForm extends SpecialPage { $out->addHTML( $injected_html ); - if ( !empty( $this->mReturnTo ) ) { - $out->returnToMain( null, $this->mReturnTo, $this->mReturnToQuery ); - } else { - $out->returnToMain( null ); - } + $this->executeReturnTo( 'success' ); } /** @@ -948,7 +938,42 @@ class LoginForm extends SpecialPage { $block->getByName() ); - $out->returnToMain( false ); + $this->executeReturnTo( 'error' ); + } + + /** + * Add a "return to" link or redirect to it. + * + * @param $type string, one of the following: + * - error: display a return to link ignoring $wgRedirectOnLogin + * - success: display a return to link using $wgRedirectOnLogin if needed + * - successredirect: send an HTTP redirect using $wgRedirectOnLogin if needed + */ + private function executeReturnTo( $type ) { + global $wgRedirectOnLogin, $wgSecureLogin; + + if ( $type != 'error' && $wgRedirectOnLogin !== null ) { + $returnTo = $wgRedirectOnLogin; + $returnToQuery = array(); + } else { + $returnTo = $this->mReturnTo; + $returnToQuery = wfCgiToArray( $this->mReturnToQuery ); + } + + $returnToTitle = Title::newFromText( $returnTo ); + if ( !$returnToTitle ) { + $returnToTitle = Title::newMainPage(); + } + + if ( $type == 'successredirect' ) { + $redirectUrl = $returnToTitle->getFullURL( $returnToQuery ); + if( $wgSecureLogin && !$this->mStickHTTPS ) { + $redirectUrl = preg_replace( '/^https:/', 'http:', $redirectUrl ); + } + $this->getOutput()->redirect( $redirectUrl ); + } else { + $this->getOutput()->addReturnTo( $returnToTitle, $returnToQuery ); + } } /** @@ -998,9 +1023,9 @@ class LoginForm extends SpecialPage { $linkmsg = 'nologin'; } - if ( !empty( $this->mReturnTo ) ) { + if ( $this->mReturnTo !== '' ) { $returnto = '&returnto=' . wfUrlencode( $this->mReturnTo ); - if ( !empty( $this->mReturnToQuery ) ) { + if ( $this->mReturnToQuery !== '' ) { $returnto .= '&returntoquery=' . wfUrlencode( $this->mReturnToQuery ); } @@ -1125,6 +1150,7 @@ class LoginForm extends SpecialPage { * previous pass through the system. * * @private + * @return bool */ function hasSessionCookie() { global $wgDisableCookieCheck; @@ -1133,6 +1159,7 @@ class LoginForm extends SpecialPage { /** * Get the login token from the current session + * @return Mixed */ public static function getLoginToken() { global $wgRequest; @@ -1159,6 +1186,7 @@ class LoginForm extends SpecialPage { /** * Get the createaccount token from the current session + * @return Mixed */ public static function getCreateaccountToken() { global $wgRequest; @@ -1181,7 +1209,7 @@ class LoginForm extends SpecialPage { $wgRequest->setSessionData( 'wsCreateaccountToken', null ); } - /** + /** * Renew the user's session id, using strong entropy */ private function renewSessionId() { @@ -1204,12 +1232,13 @@ class LoginForm extends SpecialPage { function cookieRedirectCheck( $type ) { $titleObj = SpecialPage::getTitleFor( 'Userlogin' ); $query = array( 'wpCookieCheck' => $type ); - if ( $this->mReturnTo ) { + if ( $this->mReturnTo !== '' ) { $query['returnto'] = $this->mReturnTo; + $query['returntoquery'] = $this->mReturnToQuery; } $check = $titleObj->getFullURL( $query ); - return $this->getOutput()->redirect( $check ); + $this->getOutput()->redirect( $check ); } /** @@ -1218,15 +1247,15 @@ class LoginForm extends SpecialPage { function onCookieRedirectCheck( $type ) { if ( !$this->hasSessionCookie() ) { if ( $type == 'new' ) { - return $this->mainLoginForm( $this->msg( 'nocookiesnew' )->parse() ); + $this->mainLoginForm( $this->msg( 'nocookiesnew' )->parse() ); } elseif ( $type == 'login' ) { - return $this->mainLoginForm( $this->msg( 'nocookieslogin' )->parse() ); + $this->mainLoginForm( $this->msg( 'nocookieslogin' )->parse() ); } else { # shouldn't happen - return $this->mainLoginForm( $this->msg( 'error' )->text() ); + $this->mainLoginForm( $this->msg( 'error' )->text() ); } } else { - return $this->successfulLogin(); + $this->successfulLogin(); } } @@ -1268,20 +1297,31 @@ class LoginForm extends SpecialPage { * * @param $text Link text * @param $lang Language code + * @return string */ function makeLanguageSelectorLink( $text, $lang ) { - $attr = array( 'uselang' => $lang ); + if( $this->getLanguage()->getCode() == $lang ) { + // no link for currently used language + return htmlspecialchars( $text ); + } + $query = array( 'uselang' => $lang ); if( $this->mType == 'signup' ) { - $attr['type'] = 'signup'; + $query['type'] = 'signup'; } - if( $this->mReturnTo ) { - $attr['returnto'] = $this->mReturnTo; + if( $this->mReturnTo !== '' ) { + $query['returnto'] = $this->mReturnTo; + $query['returntoquery'] = $this->mReturnToQuery; } + + $attr = array(); + $targetLanguage = Language::factory( $lang ); + $attr['lang'] = $attr['hreflang'] = $targetLanguage->getHtmlCode(); + return Linker::linkKnown( $this->getTitle(), htmlspecialchars( $text ), - array(), - $attr + $attr, + $query ); } } diff --git a/includes/specials/SpecialUserlogout.php b/includes/specials/SpecialUserlogout.php index d747448f..ab2bf0ac 100644 --- a/includes/specials/SpecialUserlogout.php +++ b/includes/specials/SpecialUserlogout.php @@ -39,7 +39,7 @@ class SpecialUserlogout extends UnlistedSpecialPage { */ if ( isset( $_SERVER['REQUEST_URI'] ) && strpos( $_SERVER['REQUEST_URI'], '&' ) !== false ) { wfDebug( "Special:Userlogout request {$_SERVER['REQUEST_URI']} looks suspicious, denying.\n" ); - throw new HttpError( 400, wfMessage( 'suspicious-userlogout' ), wfMessage( 'loginerror' ) ); + throw new HttpError( 400, $this->msg( 'suspicious-userlogout' ), $this->msg( 'loginerror' ) ); } $this->setHeaders(); diff --git a/includes/specials/SpecialUserrights.php b/includes/specials/SpecialUserrights.php index e2e0f38b..9f5a48a5 100644 --- a/includes/specials/SpecialUserrights.php +++ b/includes/specials/SpecialUserrights.php @@ -47,6 +47,9 @@ class UserrightsPage extends SpecialPage { public function userCanChangeRights( $user, $checkIfSelf = true ) { $available = $this->changeableGroups(); + if ( $user->getId() == 0 ) { + return false; + } return !empty( $available['add'] ) || !empty( $available['remove'] ) || ( ( $this->isself || !$checkIfSelf ) && @@ -72,7 +75,7 @@ class UserrightsPage extends SpecialPage { * allow them to use Special:UserRights. */ if( $user->isBlocked() && !$user->isAllowed( 'userrights' ) ) { - throw new UserBlockedError( $user->mBlock ); + throw new UserBlockedError( $user->getBlock() ); } $request = $this->getRequest(); @@ -345,7 +348,7 @@ class UserrightsPage extends SpecialPage { function makeGroupNameList( $ids ) { if( empty( $ids ) ) { - return wfMsgForContent( 'rightsnone' ); + return $this->msg( 'rightsnone' )->inContentLanguage()->text(); } else { return implode( ', ', $ids ); } @@ -367,9 +370,9 @@ class UserrightsPage extends SpecialPage { $this->getOutput()->addHTML( Html::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'name' => 'uluser', 'id' => 'mw-userrights-form1' ) ) . Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . - Xml::fieldset( wfMsg( 'userrights-lookup-user' ) ) . - Xml::inputLabel( wfMsg( 'userrights-user-editname' ), 'user', 'username', 30, str_replace( '_', ' ', $this->mTarget ) ) . ' ' . - Xml::submitButton( wfMsg( 'editusergroup' ) ) . + Xml::fieldset( $this->msg( 'userrights-lookup-user' )->text() ) . + Xml::inputLabel( $this->msg( 'userrights-user-editname' )->text(), 'user', 'username', 30, str_replace( '_', ' ', $this->mTarget ) ) . ' ' . + Xml::submitButton( $this->msg( 'editusergroup' )->text() ) . Html::closeElement( 'fieldset' ) . Html::closeElement( 'form' ) . "\n" ); @@ -420,12 +423,12 @@ class UserrightsPage extends SpecialPage { $grouplist = ''; $count = count( $list ); if( $count > 0 ) { - $grouplist = wfMessage( 'userrights-groupsmember', $count)->parse(); + $grouplist = $this->msg( 'userrights-groupsmember', $count, $user->getName() )->parse(); $grouplist = '<p>' . $grouplist . ' ' . $this->getLanguage()->listToText( $list ) . "</p>\n"; } $count = count( $autolist ); if( $count > 0 ) { - $autogrouplistintro = wfMessage( 'userrights-groupsmember-auto', $count)->parse(); + $autogrouplistintro = $this->msg( 'userrights-groupsmember-auto', $count, $user->getName() )->parse(); $grouplist .= '<p>' . $autogrouplistintro . ' ' . $this->getLanguage()->listToText( $autolist ) . "</p>\n"; } @@ -441,15 +444,15 @@ class UserrightsPage extends SpecialPage { Html::hidden( 'user', $this->mTarget ) . Html::hidden( 'wpEditToken', $this->getUser()->getEditToken( $this->mTarget ) ) . Xml::openElement( 'fieldset' ) . - Xml::element( 'legend', array(), wfMessage( 'userrights-editusergroup', $user->getName() )->text() ) . - wfMessage( 'editinguser' )->params( wfEscapeWikiText( $user->getName() ) )->rawParams( $userToolLinks )->parse() . - wfMessage( 'userrights-groups-help', $user->getName() )->parse() . + Xml::element( 'legend', array(), $this->msg( 'userrights-editusergroup', $user->getName() )->text() ) . + $this->msg( 'editinguser' )->params( wfEscapeWikiText( $user->getName() ) )->rawParams( $userToolLinks )->parse() . + $this->msg( 'userrights-groups-help', $user->getName() )->parse() . $grouplist . Xml::tags( 'p', null, $this->groupCheckboxes( $groups, $user ) ) . - Xml::openElement( 'table', array( 'border' => '0', 'id' => 'mw-userrights-table-outer' ) ) . + Xml::openElement( 'table', array( 'id' => 'mw-userrights-table-outer' ) ) . "<tr> <td class='mw-label'>" . - Xml::label( wfMsg( 'userrights-reason' ), 'wpReason' ) . + Xml::label( $this->msg( 'userrights-reason' )->text(), 'wpReason' ) . "</td> <td class='mw-input'>" . Xml::input( 'user-reason', 60, $this->getRequest()->getVal( 'user-reason', false ), @@ -459,7 +462,7 @@ class UserrightsPage extends SpecialPage { <tr> <td></td> <td class='mw-submit'>" . - Xml::submitButton( wfMsg( 'saveusergroups' ), + Xml::submitButton( $this->msg( 'saveusergroups' )->text(), array( 'name' => 'saveusergroups' ) + Linker::tooltipAndAccesskeyAttribs( 'userrights-set' ) ) . "</td> </tr>" . @@ -531,12 +534,12 @@ class UserrightsPage extends SpecialPage { } # Build the HTML table - $ret .= Xml::openElement( 'table', array( 'border' => '0', 'class' => 'mw-userrights-groups' ) ) . + $ret .= Xml::openElement( 'table', array( 'class' => 'mw-userrights-groups' ) ) . "<tr>\n"; foreach( $columns as $name => $column ) { if( $column === array() ) continue; - $ret .= Xml::element( 'th', null, wfMessage( 'userrights-' . $name . '-col', count( $column ) )->text() ); + $ret .= Xml::element( 'th', null, $this->msg( 'userrights-' . $name . '-col', count( $column ) )->text() ); } $ret.= "</tr>\n<tr>\n"; foreach( $columns as $column ) { @@ -548,7 +551,7 @@ class UserrightsPage extends SpecialPage { $member = User::getGroupMember( $group, $user->getName() ); if ( $checkbox['irreversible'] ) { - $text = wfMessage( 'userrights-irreversible-marker', $member )->escaped(); + $text = $this->msg( 'userrights-irreversible-marker', $member )->escaped(); } else { $text = htmlspecialchars( $member ); } @@ -602,7 +605,8 @@ class UserrightsPage extends SpecialPage { * @param $output OutputPage to use */ protected function showLogFragment( $user, $output ) { - $output->addHTML( Xml::element( 'h2', null, LogPage::logName( 'rights' ) . "\n" ) ); + $rightsLogPage = new LogPage( 'rights' ); + $output->addHTML( Xml::element( 'h2', null, $rightsLogPage->getName()->text() ) ); LogEventsList::showLogExtract( $output, 'rights', $user->getUserPage() ); } } diff --git a/includes/specials/SpecialVersion.php b/includes/specials/SpecialVersion.php index 8185fe88..4e5b6bf5 100644 --- a/includes/specials/SpecialVersion.php +++ b/includes/specials/SpecialVersion.php @@ -37,7 +37,7 @@ class SpecialVersion extends SpecialPage { protected static $viewvcUrls = array( 'svn+ssh://svn.wikimedia.org/svnroot/mediawiki' => 'http://svn.wikimedia.org/viewvc/mediawiki', 'http://svn.wikimedia.org/svnroot/mediawiki' => 'http://svn.wikimedia.org/viewvc/mediawiki', - 'https://svn.wikimedia.org/viewvc/mediawiki' => 'https://svn.wikimedia.org/viewvc/mediawiki', + 'https://svn.wikimedia.org/svnroot/mediawiki' => 'https://svn.wikimedia.org/viewvc/mediawiki', ); public function __construct(){ @@ -58,6 +58,7 @@ class SpecialVersion extends SpecialPage { $text = $this->getMediaWikiCredits() . $this->softwareInformation() . + $this->getEntryPointInfo() . $this->getExtensionCredits(); if ( $wgSpecialVersionShowHooks ) { $text .= $this->getWgHooks(); @@ -79,13 +80,13 @@ class SpecialVersion extends SpecialPage { * @return string */ private static function getMediaWikiCredits() { - $ret = Xml::element( 'h2', array( 'id' => 'mw-version-license' ), wfMsg( 'version-license' ) ); + $ret = Xml::element( 'h2', array( 'id' => 'mw-version-license' ), wfMessage( 'version-license' )->text() ); // This text is always left-to-right. - $ret .= '<div>'; + $ret .= '<div class="plainlinks">'; $ret .= "__NOTOC__ " . self::getCopyrightAndAuthorList() . "\n - " . wfMsg( 'version-license-info' ); + " . wfMessage( 'version-license-info' )->text(); $ret .= '</div>'; return str_replace( "\t\t", '', $ret ) . "\n"; @@ -107,11 +108,14 @@ class SpecialVersion extends SpecialPage { 'Alexandre Emsenhuber', 'Siebrand Mazeland', 'Chad Horohoe', 'Roan Kattouw', 'Trevor Parscal', 'Bryan Tong Minh', 'Sam Reed', 'Victor Vasiliev', 'Rotem Liss', 'Platonides', 'Antoine Musso', - wfMsg( 'version-poweredby-others' ) + 'Timo Tijhof', + '[{{SERVER}}{{SCRIPTPATH}}/CREDITS ' . + wfMessage( 'version-poweredby-others' )->text() . + ']' ); - return wfMsg( 'version-poweredby-credits', date( 'Y' ), - $wgLang->listToText( $authorList ) ); + return wfMessage( 'version-poweredby-credits', date( 'Y' ), + $wgLang->listToText( $authorList ) )->text(); } /** @@ -123,8 +127,8 @@ class SpecialVersion extends SpecialPage { $dbr = wfGetDB( DB_SLAVE ); // Put the software in an array of form 'name' => 'version'. All messages should - // be loaded here, so feel free to use wfMsg*() in the 'name'. Raw HTML or wikimarkup - // can be used. + // be loaded here, so feel free to use wfMessage in the 'name'. Raw HTML or + // wikimarkup can be used. $software = array(); $software['[https://www.mediawiki.org/ MediaWiki]'] = self::getVersionLinked(); $software['[http://www.php.net/ PHP]'] = phpversion() . " (" . php_sapi_name() . ")"; @@ -133,11 +137,11 @@ class SpecialVersion extends SpecialPage { // Allow a hook to add/remove items. wfRunHooks( 'SoftwareInfo', array( &$software ) ); - $out = Xml::element( 'h2', array( 'id' => 'mw-version-software' ), wfMsg( 'version-software' ) ) . - Xml::openElement( 'table', array( 'class' => 'wikitable', 'id' => 'sv-software' ) ) . + $out = Xml::element( 'h2', array( 'id' => 'mw-version-software' ), wfMessage( 'version-software' )->text() ) . + Xml::openElement( 'table', array( 'class' => 'wikitable plainlinks', 'id' => 'sv-software' ) ) . "<tr> - <th>" . wfMsg( 'version-software-product' ) . "</th> - <th>" . wfMsg( 'version-software-version' ) . "</th> + <th>" . wfMessage( 'version-software-product' )->text() . "</th> + <th>" . wfMessage( 'version-software-version' )->text() . "</th> </tr>\n"; foreach( $software as $name => $version ) { @@ -160,18 +164,26 @@ class SpecialVersion extends SpecialPage { global $wgVersion, $IP; wfProfileIn( __METHOD__ ); - $info = self::getSvnInfo( $IP ); - if ( !$info ) { + $gitInfo = self::getGitHeadSha1( $IP ); + $svnInfo = self::getSvnInfo( $IP ); + if ( !$svnInfo && !$gitInfo ) { $version = $wgVersion; - } elseif( $flags === 'nodb' ) { - $version = "$wgVersion (r{$info['checkout-rev']})"; + } elseif ( $gitInfo && $flags === 'nodb' ) { + $shortSha1 = substr( $gitInfo, 0, 7 ); + $version = "$wgVersion ($shortSha1)"; + } elseif ( $gitInfo ) { + $shortSha1 = substr( $gitInfo, 0, 7 ); + $shortSha1 = wfMessage( 'parentheses' )->params( $shortSha1 )->escaped(); + $version = "$wgVersion $shortSha1"; + } elseif ( $flags === 'nodb' ) { + $version = "$wgVersion (r{$svnInfo['checkout-rev']})"; } else { $version = $wgVersion . ' ' . - wfMsg( + wfMessage( 'version-svn-revision', isset( $info['directory-rev'] ) ? $info['directory-rev'] : '', $info['checkout-rev'] - ); + )->text(); } wfProfileOut( __METHOD__ ); @@ -180,37 +192,79 @@ class SpecialVersion extends SpecialPage { /** * Return a wikitext-formatted string of the MediaWiki version with a link to - * the SVN revision if available. + * the SVN revision or the git SHA1 of head if available. + * Git is prefered over Svn + * The fallback is just $wgVersion * * @return mixed */ public static function getVersionLinked() { - global $wgVersion, $IP; + global $wgVersion; wfProfileIn( __METHOD__ ); + $gitVersion = self::getVersionLinkedGit(); + if( $gitVersion ) { + $v = $gitVersion; + } else { + $svnVersion = self::getVersionLinkedSvn(); + if( $svnVersion ) { + $v = $svnVersion; + } else { + $v = $wgVersion; // fallback + } + } + + wfProfileOut( __METHOD__ ); + return $v; + } + + /** + * @return string wgVersion + a link to subversion revision of svn BASE + */ + private static function getVersionLinkedSvn() { + global $wgVersion, $IP; + $info = self::getSvnInfo( $IP ); + if( !isset( $info['checkout-rev'] ) ) { + return false; + } - if ( isset( $info['checkout-rev'] ) ) { - $linkText = wfMsg( - 'version-svn-revision', - isset( $info['directory-rev'] ) ? $info['directory-rev'] : '', - $info['checkout-rev'] - ); + $linkText = wfMessage( + 'version-svn-revision', + isset( $info['directory-rev'] ) ? $info['directory-rev'] : '', + $info['checkout-rev'] + )->text(); - if ( isset( $info['viewvc-url'] ) ) { - $version = "$wgVersion [{$info['viewvc-url']} $linkText]"; - } else { - $version = "$wgVersion $linkText"; - } + if ( isset( $info['viewvc-url'] ) ) { + $version = "$wgVersion [{$info['viewvc-url']} $linkText]"; } else { - $version = $wgVersion; + $version = "$wgVersion $linkText"; } - wfProfileOut( __METHOD__ ); return $version; } /** + * @return bool|string wgVersion + HEAD sha1 stripped to the first 7 chars. False on failure + */ + private static function getVersionLinkedGit() { + global $wgVersion, $IP; + + $gitInfo = new GitInfo( $IP ); + $headSHA1 = $gitInfo->getHeadSHA1(); + if( !$headSHA1 ) { + return false; + } + + $shortSHA1 = '(' . substr( $headSHA1, 0, 7 ) . ')'; + $viewerUrl = $gitInfo->getHeadViewUrl(); + if ( $viewerUrl !== false ) { + $shortSHA1 = "[$viewerUrl $shortSHA1]"; + } + return "$wgVersion $shortSHA1"; + } + + /** * Returns an array with the base extension types. * Type is stored as array key, the message as array value. * @@ -225,14 +279,14 @@ class SpecialVersion extends SpecialPage { public static function getExtensionTypes() { if ( self::$extensionTypes === false ) { self::$extensionTypes = array( - 'specialpage' => wfMsg( 'version-specialpages' ), - 'parserhook' => wfMsg( 'version-parserhooks' ), - 'variable' => wfMsg( 'version-variables' ), - 'media' => wfMsg( 'version-mediahandlers' ), - 'antispam' => wfMsg( 'version-antispam' ), - 'skin' => wfMsg( 'version-skins' ), - 'api' => wfMsg( 'version-api' ), - 'other' => wfMsg( 'version-other' ), + 'specialpage' => wfMessage( 'version-specialpages' )->text(), + 'parserhook' => wfMessage( 'version-parserhooks' )->text(), + 'variable' => wfMessage( 'version-variables' )->text(), + 'media' => wfMessage( 'version-mediahandlers' )->text(), + 'antispam' => wfMessage( 'version-antispam' )->text(), + 'skin' => wfMessage( 'version-skins' )->text(), + 'api' => wfMessage( 'version-api' )->text(), + 'other' => wfMessage( 'version-other' )->text(), ); wfRunHooks( 'ExtensionTypes', array( &self::$extensionTypes ) ); @@ -274,8 +328,8 @@ class SpecialVersion extends SpecialPage { */ wfRunHooks( 'SpecialVersionExtensionTypes', array( &$this, &$extensionTypes ) ); - $out = Xml::element( 'h2', array( 'id' => 'mw-version-ext' ), wfMsg( 'version-extensions' ) ) . - Xml::openElement( 'table', array( 'class' => 'wikitable', 'id' => 'sv-ext' ) ); + $out = Xml::element( 'h2', array( 'id' => 'mw-version-ext' ), $this->msg( 'version-extensions' )->text() ) . + Xml::openElement( 'table', array( 'class' => 'wikitable plainlinks', 'id' => 'sv-ext' ) ); // Make sure the 'other' type is set to an array. if ( !array_key_exists( 'other', $wgExtensionCredits ) ) { @@ -300,7 +354,7 @@ class SpecialVersion extends SpecialPage { $out .= $this->getExtensionCategory( 'other', $extensionTypes['other'] ); if ( count( $wgExtensionFunctions ) ) { - $out .= $this->openExtType( wfMsg( 'version-extension-functions' ), 'extension-functions' ); + $out .= $this->openExtType( $this->msg( 'version-extension-functions' )->text(), 'extension-functions' ); $out .= '<tr><td colspan="4">' . $this->listToText( $wgExtensionFunctions ) . "</td></tr>\n"; } @@ -311,13 +365,13 @@ class SpecialVersion extends SpecialPage { for ( $i = 0; $i < $cnt; ++$i ) { $tags[$i] = "<{$tags[$i]}>"; } - $out .= $this->openExtType( wfMsg( 'version-parser-extensiontags' ), 'parser-tags' ); + $out .= $this->openExtType( $this->msg( 'version-parser-extensiontags' )->text(), 'parser-tags' ); $out .= '<tr><td colspan="4">' . $this->listToText( $tags ). "</td></tr>\n"; } $fhooks = $wgParser->getFunctionHooks(); if( count( $fhooks ) ) { - $out .= $this->openExtType( wfMsg( 'version-parser-function-hooks' ), 'parser-function-hooks' ); + $out .= $this->openExtType( $this->msg( 'version-parser-function-hooks' )->text(), 'parser-function-hooks' ); $out .= '<tr><td colspan="4">' . $this->listToText( $fhooks ) . "</td></tr>\n"; } @@ -356,6 +410,9 @@ class SpecialVersion extends SpecialPage { /** * Callback to sort extensions by type. + * @param $a array + * @param $b array + * @return int */ function compare( $a, $b ) { if( $a['name'] === $b['name'] ) { @@ -377,15 +434,26 @@ class SpecialVersion extends SpecialPage { function getCreditsForExtension( array $extension ) { $name = isset( $extension['name'] ) ? $extension['name'] : '[no name]'; + $vcsText = false; + if ( isset( $extension['path'] ) ) { - $svnInfo = self::getSvnInfo( dirname($extension['path']) ); - $directoryRev = isset( $svnInfo['directory-rev'] ) ? $svnInfo['directory-rev'] : null; - $checkoutRev = isset( $svnInfo['checkout-rev'] ) ? $svnInfo['checkout-rev'] : null; - $viewvcUrl = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : null; - } else { - $directoryRev = null; - $checkoutRev = null; - $viewvcUrl = null; + $gitInfo = new GitInfo( dirname( $extension['path'] ) ); + $gitHeadSHA1 = $gitInfo->getHeadSHA1(); + if ( $gitHeadSHA1 !== false ) { + $vcsText = '(' . substr( $gitHeadSHA1, 0, 7 ) . ')'; + $gitViewerUrl = $gitInfo->getHeadViewUrl(); + if ( $gitViewerUrl !== false ) { + $vcsText = "[$gitViewerUrl $vcsText]"; + } + } else { + $svnInfo = self::getSvnInfo( dirname( $extension['path'] ) ); + # Make subversion text/link. + if ( $svnInfo !== false ) { + $directoryRev = isset( $svnInfo['directory-rev'] ) ? $svnInfo['directory-rev'] : null; + $vcsText = $this->msg( 'version-svn-revision', $directoryRev, $svnInfo['checkout-rev'] )->text(); + $vcsText = isset( $svnInfo['viewvc-url'] ) ? '[' . $svnInfo['viewvc-url'] . " $vcsText]" : $vcsText; + } + } } # Make main link (or just the name if there is no URL). @@ -397,20 +465,12 @@ class SpecialVersion extends SpecialPage { if ( isset( $extension['version'] ) ) { $versionText = '<span class="mw-version-ext-version">' . - wfMsg( 'version-version', $extension['version'] ) . + $this->msg( 'version-version', $extension['version'] )->text() . '</span>'; } else { $versionText = ''; } - # Make subversion text/link. - if ( $checkoutRev ) { - $svnText = wfMsg( 'version-svn-revision', $directoryRev, $checkoutRev ); - $svnText = isset( $viewvcUrl ) ? "[$viewvcUrl $svnText]" : $svnText; - } else { - $svnText = false; - } - # Make description text. $description = isset ( $extension['description'] ) ? $extension['description'] : ''; @@ -422,16 +482,16 @@ class SpecialVersion extends SpecialPage { $descriptionMsgKey = $descriptionMsg[0]; // Get the message key array_shift( $descriptionMsg ); // Shift out the message key to get the parameters only array_map( "htmlspecialchars", $descriptionMsg ); // For sanity - $description = wfMsg( $descriptionMsgKey, $descriptionMsg ); + $description = $this->msg( $descriptionMsgKey, $descriptionMsg )->text(); } else { - $description = wfMsg( $descriptionMsg ); + $description = $this->msg( $descriptionMsg )->text(); } } - if ( $svnText !== false ) { + if ( $vcsText !== false ) { $extNameVer = "<tr> <td><em>$mainLink $versionText</em></td> - <td><em>$svnText</em></td>"; + <td><em>$vcsText</em></td>"; } else { $extNameVer = "<tr> <td colspan=\"2\"><em>$mainLink $versionText</em></td>"; @@ -457,11 +517,11 @@ class SpecialVersion extends SpecialPage { $myWgHooks = $wgHooks; ksort( $myWgHooks ); - $ret = Xml::element( 'h2', array( 'id' => 'mw-version-hooks' ), wfMsg( 'version-hooks' ) ) . + $ret = Xml::element( 'h2', array( 'id' => 'mw-version-hooks' ), $this->msg( 'version-hooks' )->text() ) . Xml::openElement( 'table', array( 'class' => 'wikitable', 'id' => 'sv-hooks' ) ) . "<tr> - <th>" . wfMsg( 'version-hook-name' ) . "</th> - <th>" . wfMsg( 'version-hook-subscribedby' ) . "</th> + <th>" . $this->msg( 'version-hook-name' )->text() . "</th> + <th>" . $this->msg( 'version-hook-subscribedby' )->text() . "</th> </tr>\n"; foreach ( $myWgHooks as $hook => $hooks ) { @@ -517,7 +577,7 @@ class SpecialVersion extends SpecialPage { $list = array(); foreach( (array)$authors as $item ) { if( $item == '...' ) { - $list[] = wfMsg( 'version-poweredby-others' ); + $list[] = $this->msg( 'version-poweredby-others' )->text(); } else { $list[] = $item; } @@ -562,8 +622,8 @@ class SpecialVersion extends SpecialPage { $list = $list[0]; } if( is_object( $list ) ) { - $class = get_class( $list ); - return "($class)"; + $class = wfMessage( 'parentheses' )->params( get_class( $list ) )->escaped(); + return $class; } elseif ( !is_array( $list ) ) { return $list; } else { @@ -572,7 +632,7 @@ class SpecialVersion extends SpecialPage { } else { $class = $list[0]; } - return "($class, {$list[1]})"; + return wfMessage( 'parentheses' )->params( "$class, {$list[1]}" )->escaped(); } } @@ -589,6 +649,8 @@ class SpecialVersion extends SpecialPage { * url The subversion URL of the directory * repo-url The base URL of the repository * viewvc-url A ViewVC URL pointing to the checked-out revision + * @param $dir string + * @return array|bool */ public static function getSvnInfo( $dir ) { // http://svnbook.red-bean.com/nightly/en/svn.developer.insidewc.html @@ -676,6 +738,50 @@ class SpecialVersion extends SpecialPage { } } + /** + * @param $dir String: directory of the git checkout + * @return bool|String sha1 of commit HEAD points to + */ + public static function getGitHeadSha1( $dir ) { + $repo = new GitInfo( $dir ); + return $repo->getHeadSHA1(); + } + + /** + * Get the list of entry points and their URLs + * @return string Wikitext + */ + public function getEntryPointInfo() { + global $wgArticlePath, $wgScriptPath; + $entryPoints = array( + 'version-entrypoints-articlepath' => $wgArticlePath, + 'version-entrypoints-scriptpath' => $wgScriptPath, + 'version-entrypoints-index-php' => wfScript( 'index' ), + 'version-entrypoints-api-php' => wfScript( 'api' ), + 'version-entrypoints-load-php' => wfScript( 'load' ), + ); + + $out = Html::element( 'h2', array( 'id' => 'mw-version-entrypoints' ), $this->msg( 'version-entrypoints' )->text() ) . + Html::openElement( 'table', array( 'class' => 'wikitable plainlinks', 'id' => 'mw-version-entrypoints-table' ) ) . + Html::openElement( 'tr' ) . + Html::element( 'th', array(), $this->msg( 'version-entrypoints-header-entrypoint' )->text() ) . + Html::element( 'th', array(), $this->msg( 'version-entrypoints-header-url' )->text() ) . + Html::closeElement( 'tr' ); + + foreach ( $entryPoints as $message => $value ) { + $url = wfExpandUrl( $value, PROTO_RELATIVE ); + $out .= Html::openElement( 'tr' ) . + // ->text() looks like it should be ->parse(), but this function + // returns wikitext, not HTML, boo + Html::rawElement( 'td', array(), $this->msg( $message )->text() ) . + Html::rawElement( 'td', array(), Html::rawElement( 'code', array(), "[$url $value]" ) ) . + Html::closeElement( 'tr' ); + } + + $out .= Html::closeElement( 'table' ); + return $out; + } + function showEasterEgg() { $rx = $rp = $xe = ''; $alpha = array("", "kbQW", "\$\n()"); diff --git a/includes/specials/SpecialWantedcategories.php b/includes/specials/SpecialWantedcategories.php index f497e4e2..0b1fb251 100644 --- a/includes/specials/SpecialWantedcategories.php +++ b/includes/specials/SpecialWantedcategories.php @@ -37,9 +37,9 @@ class WantedCategoriesPage extends WantedQueryPage { function getQueryInfo() { return array ( 'tables' => array ( 'categorylinks', 'page' ), - 'fields' => array ( "'" . NS_CATEGORY . "' AS namespace", - 'cl_to AS title', - 'COUNT(*) AS value' ), + 'fields' => array ( 'namespace' => NS_CATEGORY, + 'title' => 'cl_to', + 'value' => 'COUNT(*)' ), 'conds' => array ( 'page_title IS NULL' ), 'options' => array ( 'GROUP BY' => 'cl_to' ), 'join_conds' => array ( 'page' => array ( 'LEFT JOIN', diff --git a/includes/specials/SpecialWantedfiles.php b/includes/specials/SpecialWantedfiles.php index ec0912df..f52f7bb9 100644 --- a/includes/specials/SpecialWantedfiles.php +++ b/includes/specials/SpecialWantedfiles.php @@ -39,7 +39,7 @@ class WantedFilesPage extends WantedQueryPage { # Specifically setting to use "Wanted Files" (NS_MAIN) as title, so as to get what # category would be used on main namespace pages, for those tricky wikipedia # admins who like to do {{#ifeq:{{NAMESPACE}}|foo|bar|....}}. - $catMessage = wfMessage( 'broken-file-category' ) + $catMessage = $this->msg( 'broken-file-category' ) ->title( Title::newFromText( "Wanted Files", NS_MAIN ) ) ->inContentLanguage(); @@ -66,6 +66,7 @@ class WantedFilesPage extends WantedQueryPage { * that exist e.g. in a shared repo. Setting this at least * keeps them from showing up as redlinks in the output, even * if it doesn't fix the real problem (bug 6220). + * @return bool */ function forceExistenceCheck() { return true; @@ -74,9 +75,9 @@ class WantedFilesPage extends WantedQueryPage { function getQueryInfo() { return array ( 'tables' => array ( 'imagelinks', 'image' ), - 'fields' => array ( "'" . NS_FILE . "' AS namespace", - 'il_to AS title', - 'COUNT(*) AS value' ), + 'fields' => array ( 'namespace' => NS_FILE, + 'title' => 'il_to', + 'value' => 'COUNT(*)' ), 'conds' => array ( 'img_name IS NULL' ), 'options' => array ( 'GROUP BY' => 'il_to' ), 'join_conds' => array ( 'image' => diff --git a/includes/specials/SpecialWantedpages.php b/includes/specials/SpecialWantedpages.php index 4624b355..7673305d 100644 --- a/includes/specials/SpecialWantedpages.php +++ b/includes/specials/SpecialWantedpages.php @@ -60,9 +60,9 @@ class WantedPagesPage extends WantedQueryPage { 'pg2' => 'page' ), 'fields' => array( - 'pl_namespace AS namespace', - 'pl_title AS title', - 'COUNT(*) AS value' + 'namespace' => 'pl_namespace', + 'title' => 'pl_title', + 'value' => 'COUNT(*)' ), 'conds' => array( 'pg1.page_namespace IS NULL', @@ -72,7 +72,7 @@ class WantedPagesPage extends WantedQueryPage { ), 'options' => array( 'HAVING' => "COUNT(*) > $count", - 'GROUP BY' => 'pl_namespace, pl_title' + 'GROUP BY' => array( 'pl_namespace', 'pl_title' ) ), 'join_conds' => array( 'pg1' => array( diff --git a/includes/specials/SpecialWantedtemplates.php b/includes/specials/SpecialWantedtemplates.php index ab9d6046..f3e33698 100644 --- a/includes/specials/SpecialWantedtemplates.php +++ b/includes/specials/SpecialWantedtemplates.php @@ -40,13 +40,13 @@ class WantedTemplatesPage extends WantedQueryPage { function getQueryInfo() { return array ( 'tables' => array ( 'templatelinks', 'page' ), - 'fields' => array ( 'tl_namespace AS namespace', - 'tl_title AS title', - 'COUNT(*) AS value' ), + 'fields' => array ( 'namespace' => 'tl_namespace', + 'title' => 'tl_title', + 'value' => 'COUNT(*)' ), 'conds' => array ( 'page_title IS NULL', 'tl_namespace' => NS_TEMPLATE ), 'options' => array ( - 'GROUP BY' => 'tl_namespace, tl_title' ), + 'GROUP BY' => array( 'tl_namespace', 'tl_title' ) ), 'join_conds' => array ( 'page' => array ( 'LEFT JOIN', array ( 'page_namespace = tl_namespace', 'page_title = tl_title' ) ) ) diff --git a/includes/specials/SpecialWatchlist.php b/includes/specials/SpecialWatchlist.php index fef54911..5dfc1133 100644 --- a/includes/specials/SpecialWatchlist.php +++ b/includes/specials/SpecialWatchlist.php @@ -91,14 +91,6 @@ class SpecialWatchlist extends SpecialPage { return; } - if( ( $wgEnotifWatchlist || $wgShowUpdatedMarker ) && $request->getVal( 'reset' ) && - $request->wasPosted() ) - { - $user->clearAllNotifications(); - $output->redirect( $this->getTitle()->getFullUrl() ); - return; - } - $nitems = $this->countItems(); if ( $nitems == 0 ) { $output->addWikiMsg( 'nowatchlist' ); @@ -116,6 +108,7 @@ class SpecialWatchlist extends SpecialPage { /* bool */ 'hideOwn' => (int)$user->getBoolOption( 'watchlisthideown' ), /* ? */ 'namespace' => 'all', /* ? */ 'invert' => false, + /* bool */ 'associated' => false, ); $this->customFilters = array(); wfRunHooks( 'SpecialWatchlistFilters', array( $this, &$this->customFilters ) ); @@ -148,13 +141,20 @@ class SpecialWatchlist extends SpecialPage { # Get namespace value, if supplied, and prepare a WHERE fragment $nameSpace = $request->getIntOrNull( 'namespace' ); - $invert = $request->getIntOrNull( 'invert' ); + $invert = $request->getBool( 'invert' ); + $associated = $request->getBool( 'associated' ); if ( !is_null( $nameSpace ) ) { + $eq_op = $invert ? '!=' : '='; + $bool_op = $invert ? 'AND' : 'OR'; $nameSpace = intval( $nameSpace ); // paranioa - if ( $invert ) { - $nameSpaceClause = "rc_namespace != $nameSpace"; + if ( !$associated ) { + $nameSpaceClause = "rc_namespace $eq_op $nameSpace"; } else { - $nameSpaceClause = "rc_namespace = $nameSpace"; + $associatedNS = MWNamespace::getAssociated( $nameSpace ); + $nameSpaceClause = + "rc_namespace $eq_op $nameSpace " . + $bool_op . + " rc_namespace $eq_op $associatedNS"; } } else { $nameSpace = ''; @@ -162,6 +162,7 @@ class SpecialWatchlist extends SpecialPage { } $values['namespace'] = $nameSpace; $values['invert'] = $invert; + $values['associated'] = $associated; if( is_null( $values['days'] ) || !is_numeric( $values['days'] ) ) { $big = 1000; /* The magical big */ @@ -181,6 +182,14 @@ class SpecialWatchlist extends SpecialPage { wfAppendToArrayIfNotDefault( $name, $values[$name], $defaults, $nondefaults ); } + if( ( $wgEnotifWatchlist || $wgShowUpdatedMarker ) && $request->getVal( 'reset' ) && + $request->wasPosted() ) + { + $user->clearAllNotifications(); + $output->redirect( $this->getTitle()->getFullUrl( $nondefaults ) ); + return; + } + $dbr = wfGetDB( DB_SLAVE, 'watchlist' ); # Possible where conditions @@ -254,15 +263,25 @@ class SpecialWatchlist extends SpecialPage { 'id' => 'mw-watchlist-resetbutton' ) ) . $this->msg( 'wlheader-showupdated' )->parse() . ' ' . Xml::submitButton( $this->msg( 'enotif_reset' )->text(), array( 'name' => 'dummy' ) ) . - Html::hidden( 'reset', 'all' ) . - Xml::closeElement( 'form' ); + Html::hidden( 'reset', 'all' ); + foreach ( $nondefaults as $key => $value ) { + $form .= Html::hidden( $key, $value ); + } + $form .= Xml::closeElement( 'form' ); } $form .= '<hr />'; $tables = array( 'recentchanges', 'watchlist' ); $fields = array( $dbr->tableName( 'recentchanges' ) . '.*' ); $join_conds = array( - 'watchlist' => array('INNER JOIN',"wl_user='{$user->getId()}' AND wl_namespace=rc_namespace AND wl_title=rc_title"), + 'watchlist' => array( + 'INNER JOIN', + array( + 'wl_user' => $user->getId(), + 'wl_namespace=rc_namespace', + 'wl_title=rc_title' + ), + ), ); $options = array( 'ORDER BY' => 'rc_timestamp DESC' ); if( $wgShowUpdatedMarker ) { @@ -285,7 +304,7 @@ class SpecialWatchlist extends SpecialPage { wfRunHooks('SpecialWatchlistQuery', array(&$conds,&$tables,&$join_conds,&$fields) ); $res = $dbr->select( $tables, $fields, $conds, __METHOD__, $options, $join_conds ); - $numRows = $dbr->numRows( $res ); + $numRows = $res->numRows(); /* Start bottom header */ @@ -327,9 +346,31 @@ class SpecialWatchlist extends SpecialPage { $form .= $lang->pipeList( $links ); $form .= Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalUrl(), 'id' => 'mw-watchlist-form-namespaceselector' ) ); $form .= '<hr /><p>'; - $form .= Xml::label( $this->msg( 'namespace' )->text(), 'namespace' ) . ' '; - $form .= Xml::namespaceSelector( $nameSpace, '' ) . ' '; - $form .= Xml::checkLabel( $this->msg( 'invert' )->text(), 'invert', 'nsinvert', $invert ) . ' '; + $form .= Html::namespaceSelector( + array( + 'selected' => $nameSpace, + 'all' => '', + 'label' => $this->msg( 'namespace' )->text() + ), array( + 'name' => 'namespace', + 'id' => 'namespace', + 'class' => 'namespaceselector', + ) + ) . ' '; + $form .= Xml::checkLabel( + $this->msg( 'invert' )->text(), + 'invert', + 'nsinvert', + $invert, + array( 'title' => $this->msg( 'tooltip-invert' )->text() ) + ) . ' '; + $form .= Xml::checkLabel( + $this->msg( 'namespace_association' )->text(), + 'associated', + 'associated', + $associated, + array( 'title' => $this->msg( 'tooltip-namespace_association' )->text() ) + ) . ' '; $form .= Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . '</p>'; $form .= Html::hidden( 'days', $values['days'] ); foreach ( $filters as $key => $msg ) { @@ -459,7 +500,7 @@ class SpecialWatchlist extends SpecialPage { $dbr = wfGetDB( DB_SLAVE, 'watchlist' ); # Fetch the raw count - $res = $dbr->select( 'watchlist', 'COUNT(*) AS count', + $res = $dbr->select( 'watchlist', array( 'count' => 'COUNT(*)' ), array( 'wl_user' => $this->getUser()->getId() ), __METHOD__ ); $row = $dbr->fetchObject( $res ); $count = $row->count; diff --git a/includes/specials/SpecialWhatlinkshere.php b/includes/specials/SpecialWhatlinkshere.php index d5129bf6..f1356493 100644 --- a/includes/specials/SpecialWhatlinkshere.php +++ b/includes/specials/SpecialWhatlinkshere.php @@ -163,7 +163,7 @@ class SpecialWhatLinksHere extends SpecialPage { 'rd_from = page_id', 'rd_namespace' => $target->getNamespace(), 'rd_title' => $target->getDBkey(), - '(rd_interwiki is NULL) or (rd_interwiki = \'\')' + 'rd_interwiki = ' . $dbr->addQuotes( '' ) . ' OR rd_interwiki IS NULL' ))); if( $fetchlinks ) { @@ -288,7 +288,7 @@ class SpecialWhatLinksHere extends SpecialPage { 'whatlinkshere-links', 'isimage' ); $msgcache = array(); foreach ( $msgs as $msg ) { - $msgcache[$msg] = wfMsgExt( $msg, array( 'escapenoentities' ) ); + $msgcache[$msg] = $this->msg( $msg )->escaped(); } } @@ -316,12 +316,12 @@ class SpecialWhatLinksHere extends SpecialPage { $props[] = $msgcache['isimage']; if ( count( $props ) ) { - $propsText = '(' . implode( $msgcache['semicolon-separator'], $props ) . ')'; + $propsText = $this->msg( 'parentheses' )->rawParams( implode( $msgcache['semicolon-separator'], $props ) )->escaped(); } # Space for utilities links, with a what-links-here link provided $wlhLink = $this->wlhLink( $nt, $msgcache['whatlinkshere-links'] ); - $wlh = Xml::wrapClass( "($wlhLink)", 'mw-whatlinkshere-tools' ); + $wlh = Xml::wrapClass( $this->msg( 'parentheses' )->rawParams( $wlhLink )->escaped(), 'mw-whatlinkshere-tools' ); return $notClose ? Xml::openElement( 'li' ) . "$link $propsText $dirmark $wlh\n" : @@ -356,8 +356,8 @@ class SpecialWhatLinksHere extends SpecialPage { function getPrevNext( $prevId, $nextId ) { $currentLimit = $this->opts->getValue( 'limit' ); - $prev = wfMessage( 'whatlinkshere-prev' )->numParams( $currentLimit )->escaped(); - $next = wfMessage( 'whatlinkshere-next' )->numParams( $currentLimit )->escaped(); + $prev = $this->msg( 'whatlinkshere-prev' )->numParams( $currentLimit )->escaped(); + $next = $this->msg( 'whatlinkshere-next' )->numParams( $currentLimit )->escaped(); $changed = $this->opts->getChangedValues(); unset($changed['target']); // Already in the request title @@ -381,7 +381,7 @@ class SpecialWhatLinksHere extends SpecialPage { $nums = $lang->pipeList( $limitLinks ); - return wfMsgHtml( 'viewprevnext', $prev, $next, $nums ); + return $this->msg( 'viewprevnext' )->rawParams( $prev, $next, $nums )->escaped(); } function whatlinkshereForm() { @@ -404,22 +404,31 @@ class SpecialWhatLinksHere extends SpecialPage { $f .= Html::hidden( $name, $value ); } - $f .= Xml::fieldset( wfMsg( 'whatlinkshere' ) ); + $f .= Xml::fieldset( $this->msg( 'whatlinkshere' )->text() ); # Target input - $f .= Xml::inputLabel( wfMsg( 'whatlinkshere-page' ), 'target', + $f .= Xml::inputLabel( $this->msg( 'whatlinkshere-page' )->text(), 'target', 'mw-whatlinkshere-target', 40, $target ); $f .= ' '; # Namespace selector - $f .= Xml::label( wfMsg( 'namespace' ), 'namespace' ) . ' ' . - Xml::namespaceSelector( $namespace, '' ); + $f .= Html::namespaceSelector( + array( + 'selected' => $namespace, + 'all' => '', + 'label' => $this->msg( 'namespace' )->text() + ), array( + 'name' => 'namespace', + 'id' => 'namespace', + 'class' => 'namespaceselector', + ) + ); $f .= ' '; # Submit - $f .= Xml::submitButton( wfMsg( 'allpagessubmit' ) ); + $f .= Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ); # Close $f .= Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' ) . "\n"; @@ -433,8 +442,8 @@ class SpecialWhatLinksHere extends SpecialPage { * @return string HTML fieldset and filter panel with the show/hide links */ function getFilterPanel() { - $show = wfMsgHtml( 'show' ); - $hide = wfMsgHtml( 'hide' ); + $show = $this->msg( 'show' )->escaped(); + $hide = $this->msg( 'hide' )->escaped(); $changed = $this->opts->getChangedValues(); unset($changed['target']); // Already in the request title @@ -445,13 +454,14 @@ class SpecialWhatLinksHere extends SpecialPage { $types[] = 'hideimages'; // Combined message keys: 'whatlinkshere-hideredirs', 'whatlinkshere-hidetrans', 'whatlinkshere-hidelinks', 'whatlinkshere-hideimages' - // To be sure they will be find by grep + // To be sure they will be found by grep foreach( $types as $type ) { $chosen = $this->opts->getValue( $type ); $msg = $chosen ? $show : $hide; $overrides = array( $type => !$chosen ); - $links[] = wfMsgHtml( "whatlinkshere-{$type}", $this->makeSelfLink( $msg, array_merge( $changed, $overrides ) ) ); + $links[] = $this->msg( "whatlinkshere-{$type}" )->rawParams( + $this->makeSelfLink( $msg, array_merge( $changed, $overrides ) ) )->escaped(); } - return Xml::fieldset( wfMsg( 'whatlinkshere-filters' ), $this->getLanguage()->pipeList( $links ) ); + return Xml::fieldset( $this->msg( 'whatlinkshere-filters' )->text(), $this->getLanguage()->pipeList( $links ) ); } } diff --git a/includes/specials/SpecialWithoutinterwiki.php b/includes/specials/SpecialWithoutinterwiki.php index 89dae203..2988b04f 100644 --- a/includes/specials/SpecialWithoutinterwiki.php +++ b/includes/specials/SpecialWithoutinterwiki.php @@ -41,10 +41,10 @@ class WithoutInterwikiPage extends PageQueryPage { } function getPageHeader() { - global $wgScript, $wgMiserMode; + global $wgScript; - # Do not show useless input form if wiki is running in misermode - if( $wgMiserMode ) { + # Do not show useless input form if special page is cached + if( $this->isCached() ) { return ''; } @@ -53,10 +53,10 @@ class WithoutInterwikiPage extends PageQueryPage { return Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) . Xml::openElement( 'fieldset' ) . - Xml::element( 'legend', null, wfMsg( 'withoutinterwiki-legend' ) ) . + Xml::element( 'legend', null, $this->msg( 'withoutinterwiki-legend' )->text() ) . Html::hidden( 'title', $t->getPrefixedText() ) . - Xml::inputLabel( wfMsg( 'allpagesprefix' ), 'prefix', 'wiprefix', 20, $prefix ) . ' ' . - Xml::submitButton( wfMsg( 'withoutinterwiki-submit' ) ) . + Xml::inputLabel( $this->msg( 'allpagesprefix' )->text(), 'prefix', 'wiprefix', 20, $prefix ) . ' ' . + Xml::submitButton( $this->msg( 'withoutinterwiki-submit' )->text() ) . Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' ); } @@ -80,9 +80,9 @@ class WithoutInterwikiPage extends PageQueryPage { function getQueryInfo() { $query = array ( 'tables' => array ( 'page', 'langlinks' ), - 'fields' => array ( 'page_namespace AS namespace', - 'page_title AS title', - 'page_title AS value' ), + 'fields' => array ( 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'value' => 'page_title' ), 'conds' => array ( 'll_title IS NULL', 'page_namespace' => MWNamespace::getContentNamespaces(), 'page_is_redirect' => 0 ), |