From d9022f63880ce039446fba8364f68e656b7bf4cb Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Thu, 3 May 2012 13:01:35 +0200 Subject: Update to MediaWiki 1.19.0 --- includes/specials/SpecialActiveusers.php | 90 ++-- includes/specials/SpecialAllmessages.php | 78 +-- includes/specials/SpecialAllpages.php | 58 ++- includes/specials/SpecialAncientpages.php | 8 +- includes/specials/SpecialBlock.php | 317 +++++++----- includes/specials/SpecialBlockList.php | 171 +++--- includes/specials/SpecialBlockme.php | 15 +- includes/specials/SpecialBooksources.php | 9 +- includes/specials/SpecialBrokenRedirects.php | 29 +- includes/specials/SpecialCategories.php | 40 +- includes/specials/SpecialChangeEmail.php | 213 ++++++++ includes/specials/SpecialChangePassword.php | 91 ++-- includes/specials/SpecialComparePages.php | 51 +- includes/specials/SpecialConfirmemail.php | 22 +- includes/specials/SpecialContributions.php | 600 ++++++++++++++-------- includes/specials/SpecialDeadendpages.php | 2 +- includes/specials/SpecialDeletedContributions.php | 200 ++++---- includes/specials/SpecialDisambiguations.php | 14 +- includes/specials/SpecialDoubleRedirects.php | 24 +- includes/specials/SpecialEditWatchlist.php | 250 +++++---- includes/specials/SpecialEmailuser.php | 70 ++- includes/specials/SpecialExport.php | 209 +++++--- includes/specials/SpecialFewestrevisions.php | 20 +- includes/specials/SpecialFileDuplicateSearch.php | 49 +- includes/specials/SpecialFilepath.php | 17 +- includes/specials/SpecialImport.php | 141 ++--- includes/specials/SpecialJavaScriptTest.php | 142 +++++ includes/specials/SpecialLinkSearch.php | 4 +- includes/specials/SpecialListfiles.php | 32 +- includes/specials/SpecialListgrouprights.php | 43 +- includes/specials/SpecialListredirects.php | 11 +- includes/specials/SpecialListusers.php | 68 ++- includes/specials/SpecialLockdb.php | 120 ++--- includes/specials/SpecialLog.php | 70 ++- includes/specials/SpecialMIMEsearch.php | 23 +- includes/specials/SpecialMergeHistory.php | 144 ++---- includes/specials/SpecialMostcategories.php | 7 +- includes/specials/SpecialMostimages.php | 4 +- includes/specials/SpecialMostlinked.php | 13 +- includes/specials/SpecialMostlinkedcategories.php | 19 +- includes/specials/SpecialMostlinkedtemplates.php | 17 +- includes/specials/SpecialMovepage.php | 364 +++++++------ includes/specials/SpecialNewimages.php | 41 +- includes/specials/SpecialNewpages.php | 85 ++- includes/specials/SpecialPasswordReset.php | 80 ++- includes/specials/SpecialPopularpages.php | 13 +- includes/specials/SpecialPreferences.php | 48 +- includes/specials/SpecialPrefixindex.php | 42 +- includes/specials/SpecialProtectedpages.php | 59 +-- includes/specials/SpecialProtectedtitles.php | 49 +- includes/specials/SpecialRandompage.php | 13 +- includes/specials/SpecialRecentchanges.php | 67 ++- includes/specials/SpecialRecentchangeslinked.php | 55 +- includes/specials/SpecialRevisiondelete.php | 42 +- includes/specials/SpecialSearch.php | 302 ++++++----- includes/specials/SpecialShortpages.php | 23 +- includes/specials/SpecialSpecialpages.php | 2 +- includes/specials/SpecialStatistics.php | 32 +- includes/specials/SpecialTags.php | 25 +- includes/specials/SpecialUnblock.php | 65 +-- includes/specials/SpecialUndelete.php | 415 +++++++-------- includes/specials/SpecialUnlockdb.php | 104 ++-- includes/specials/SpecialUnusedcategories.php | 4 +- includes/specials/SpecialUnusedtemplates.php | 6 +- includes/specials/SpecialUnwatchedpages.php | 2 +- includes/specials/SpecialUpload.php | 176 +++---- includes/specials/SpecialUploadStash.php | 58 +-- includes/specials/SpecialUserlogin.php | 414 ++++++++------- includes/specials/SpecialUserlogout.php | 21 +- includes/specials/SpecialUserrights.php | 126 +++-- includes/specials/SpecialVersion.php | 31 +- includes/specials/SpecialWantedcategories.php | 11 +- includes/specials/SpecialWantedfiles.php | 26 + includes/specials/SpecialWantedpages.php | 9 +- includes/specials/SpecialWatchlist.php | 93 ++-- includes/specials/SpecialWhatlinkshere.php | 61 ++- includes/specials/SpecialWithoutinterwiki.php | 6 +- 77 files changed, 3614 insertions(+), 2861 deletions(-) create mode 100644 includes/specials/SpecialChangeEmail.php create mode 100644 includes/specials/SpecialJavaScriptTest.php (limited to 'includes/specials') diff --git a/includes/specials/SpecialActiveusers.php b/includes/specials/SpecialActiveusers.php index e4bf42d3..617a8026 100644 --- a/includes/specials/SpecialActiveusers.php +++ b/includes/specials/SpecialActiveusers.php @@ -42,10 +42,18 @@ class ActiveUsersPager extends UsersPager { */ protected $groups; - function __construct( $group = null ) { - global $wgRequest, $wgActiveUserDays; + /** + * @param $context IContextSource + * @param $group null Unused + * @param $par string Parameter passed to the page + */ + function __construct( IContextSource $context = null, $group = null, $par = null ) { + global $wgActiveUserDays; + + parent::__construct( $context ); + $this->RCMaxAge = $wgActiveUserDays; - $un = $wgRequest->getText( 'username' ); + $un = $this->getRequest()->getText( 'username', $par ); $this->requestedUser = ''; if ( $un != '' ) { $username = Title::makeTitleSafe( NS_USER, $un ); @@ -55,23 +63,15 @@ class ActiveUsersPager extends UsersPager { } $this->setupOptions(); - - parent::__construct(); - } - - function getTitle() { - return SpecialPage::getTitleFor( 'Activeusers' ); } public function setupOptions() { - global $wgRequest; - $this->opts = new FormOptions(); $this->opts->add( 'hidebots', false, FormOptions::BOOL ); $this->opts->add( 'hidesysops', false, FormOptions::BOOL ); - $this->opts->fetchValuesFromRequest( $wgRequest ); + $this->opts->fetchValuesFromRequest( $this->getRequest() ); $this->groups = array(); if ( $this->opts->getValue( 'hidebots' ) == 1 ) { @@ -119,29 +119,26 @@ class ActiveUsersPager extends UsersPager { } function formatRow( $row ) { - global $wgLang; $userName = $row->user_name; - $ulinks = $this->getSkin()->userLink( $row->user_id, $userName ); - $ulinks .= $this->getSkin()->userToolLinks( $row->user_id, $userName ); + $ulinks = Linker::userLink( $row->user_id, $userName ); + $ulinks .= Linker::userToolLinks( $row->user_id, $userName ); + + $lang = $this->getLanguage(); $list = array(); foreach( self::getGroups( $row->user_id ) as $group ) { if ( isset( $this->groups[$group] ) ) { return; } - $list[] = self::buildGroupLink( $group ); + $list[] = self::buildGroupLink( $group, $userName ); } - $groups = $wgLang->commaList( $list ); - - $item = wfSpecialList( $ulinks, $groups ); - $count = wfMsgExt( 'activeusers-count', - array( 'parsemag' ), - $wgLang->formatNum( $row->recentedits ), - $userName, - $wgLang->formatNum ( $this->RCMaxAge ) - ); - $blocked = $row->blocked ? ' ' . wfMsgExt( 'listusers-blocked', array( 'parsemag' ), $userName ) : ''; + $groups = $lang->commaList( $list ); + + $item = $lang->specialList( $ulinks, $groups ); + $count = $this->msg( 'activeusers-count' )->numParams( $row->recentedits ) + ->params( $userName )->numParams( $this->RCMaxAge )->escaped(); + $blocked = $row->blocked ? ' ' . $this->msg( 'listusers-blocked', $userName )->escaped() : ''; return Html::rawElement( 'li', array(), "{$item} [{$count}]{$blocked}" ); } @@ -153,16 +150,19 @@ class ActiveUsersPager extends UsersPager { $limit = $this->mLimit ? Html::hidden( 'limit', $this->mLimit ) : ''; $out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ); # Form tag - $out .= Xml::fieldset( wfMsg( 'activeusers' ) ) . "\n"; + $out .= Xml::fieldset( $this->msg( 'activeusers' )->text() ) . "\n"; $out .= Html::hidden( 'title', $self->getPrefixedDBkey() ) . $limit . "\n"; - $out .= Xml::inputLabel( wfMsg( 'activeusers-from' ), 'username', 'offset', 20, $this->requestedUser ) . '
';# Username field + $out .= Xml::inputLabel( $this->msg( 'activeusers-from' )->text(), + 'username', 'offset', 20, $this->requestedUser ) . '
';# Username field - $out .= Xml::checkLabel( wfMsg('activeusers-hidebots'), 'hidebots', 'hidebots', $this->opts->getValue( 'hidebots' ) ); + $out .= Xml::checkLabel( $this->msg( 'activeusers-hidebots' )->text(), + 'hidebots', 'hidebots', $this->opts->getValue( 'hidebots' ) ); - $out .= Xml::checkLabel( wfMsg('activeusers-hidesysops'), 'hidesysops', 'hidesysops', $this->opts->getValue( 'hidesysops' ) ) . '
'; + $out .= Xml::checkLabel( $this->msg( 'activeusers-hidesysops' )->text(), + 'hidesysops', 'hidesysops', $this->opts->getValue( 'hidesysops' ) ) . '
'; - $out .= Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n";# Submit button and form bottom + $out .= Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . "\n";# Submit button and form bottom $out .= Xml::closeElement( 'fieldset' ); $out .= Xml::closeElement( 'form' ); @@ -188,30 +188,30 @@ class SpecialActiveUsers extends SpecialPage { * @param $par Mixed: parameter passed to the page or null */ public function execute( $par ) { - global $wgOut, $wgLang, $wgActiveUserDays; + global $wgActiveUserDays; $this->setHeaders(); $this->outputHeader(); - $up = new ActiveUsersPager(); + $out = $this->getOutput(); + $out->wrapWikiMsg( "
\n$1\n
", + array( 'activeusers-intro', $this->getLanguage()->formatNum( $wgActiveUserDays ) ) ); + + $up = new ActiveUsersPager( $this->getContext(), null, $par ); # getBody() first to check, if empty $usersbody = $up->getBody(); - $s = Html::rawElement( 'div', array( 'class' => 'mw-activeusers-intro' ), - wfMsgExt( 'activeusers-intro', array( 'parsemag', 'escape' ), $wgLang->formatNum( $wgActiveUserDays ) ) - ); - - $s .= $up->getPageHeader(); - if( $usersbody ) { - $s .= $up->getNavigationBar(); - $s .= Html::rawElement( 'ul', array(), $usersbody ); - $s .= $up->getNavigationBar(); + $out->addHTML( $up->getPageHeader() ); + if ( $usersbody ) { + $out->addHTML( + $up->getNavigationBar() . + Html::rawElement( 'ul', array(), $usersbody ) . + $up->getNavigationBar() + ); } else { - $s .= Html::element( 'p', array(), wfMsg( 'activeusers-noresult' ) ); + $out->addWikiMsg( 'activeusers-noresult' ); } - - $wgOut->addHTML( $s ); } } diff --git a/includes/specials/SpecialAllmessages.php b/includes/specials/SpecialAllmessages.php index 24815825..2bfea4c3 100644 --- a/includes/specials/SpecialAllmessages.php +++ b/includes/specials/SpecialAllmessages.php @@ -100,22 +100,22 @@ class AllmessagesTablePager extends TablePager { public $custom; function __construct( $page, $conds, $langObj = null ) { - parent::__construct(); + parent::__construct( $page->getContext() ); $this->mIndexField = 'am_title'; $this->mPage = $page; $this->mConds = $conds; $this->mDefaultDirection = true; // always sort ascending $this->mLimitsShown = array( 20, 50, 100, 250, 500, 5000 ); - global $wgLang, $wgContLang, $wgRequest; + global $wgContLang; - $this->talk = htmlspecialchars( wfMsg( 'talkpagelinktext' ) ); + $this->talk = $this->msg( 'talkpagelinktext' )->escaped(); $this->lang = ( $langObj ? $langObj : $wgContLang ); $this->langcode = $this->lang->getCode(); $this->foreign = $this->langcode != $wgContLang->getCode(); - $request = $wgRequest; + $request = $this->getRequest(); $this->filter = $request->getVal( 'filter', 'all' ); if( $this->filter === 'all' ){ @@ -124,8 +124,8 @@ class AllmessagesTablePager extends TablePager { $this->custom = ($this->filter == 'unmodified'); } - $prefix = $wgLang->ucfirst( $wgRequest->getVal( 'prefix', '' ) ); - $prefix = $prefix != '' ? Title::makeTitleSafe( NS_MEDIAWIKI, $wgRequest->getVal( 'prefix', null ) ) : null; + $prefix = $this->getLanguage()->ucfirst( $request->getVal( 'prefix', '' ) ); + $prefix = $prefix != '' ? Title::makeTitleSafe( NS_MEDIAWIKI, $request->getVal( 'prefix', null ) ) : null; if( $prefix !== null ){ $this->displayPrefix = $prefix->getDBkey(); $this->prefix = '/^' . preg_quote( $this->displayPrefix ) . '/i'; @@ -150,12 +150,12 @@ class AllmessagesTablePager extends TablePager { ksort( $languages ); $out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'mw-allmessages-form' ) ) . - Xml::fieldset( wfMsg( 'allmessages-filter-legend' ) ) . + Xml::fieldset( $this->msg( 'allmessages-filter-legend' )->text() ) . Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . Xml::openElement( 'table', array( 'class' => 'mw-allmessages-table' ) ) . "\n" . ' ' . - Xml::label( wfMsg( 'allmessages-prefix' ), 'mw-allmessages-form-prefix' ) . + Xml::label( $this->msg( 'allmessages-prefix' )->text(), 'mw-allmessages-form-prefix' ) . "\n " . Xml::input( 'prefix', 20, str_replace( '_', ' ', $this->displayPrefix ), array( 'id' => 'mw-allmessages-form-prefix' ) ) . @@ -163,22 +163,22 @@ class AllmessagesTablePager extends TablePager { \n " . - wfMsg( 'allmessages-filter' ) . + $this->msg( 'allmessages-filter' )->escaped() . "\n " . - Xml::radioLabel( wfMsg( 'allmessages-filter-unmodified' ), + Xml::radioLabel( $this->msg( 'allmessages-filter-unmodified' )->text(), 'filter', 'unmodified', 'mw-allmessages-form-filter-unmodified', ( $this->filter == 'unmodified' ) ) . - Xml::radioLabel( wfMsg( 'allmessages-filter-all' ), + Xml::radioLabel( $this->msg( 'allmessages-filter-all' )->text(), 'filter', 'all', 'mw-allmessages-form-filter-all', ( $this->filter == 'all' ) ) . - Xml::radioLabel( wfMsg( 'allmessages-filter-modified' ), + Xml::radioLabel( $this->msg( 'allmessages-filter-modified' )->text(), 'filter', 'modified', 'mw-allmessages-form-filter-modified', @@ -188,7 +188,7 @@ class AllmessagesTablePager extends TablePager { \n " . - Xml::label( wfMsg( 'allmessages-language' ), 'mw-allmessages-form-lang' ) . + Xml::label( $this->msg( 'allmessages-language' )->text(), 'mw-allmessages-form-lang' ) . "\n " . Xml::openElement( 'select', array( 'id' => 'mw-allmessages-form-lang', 'name' => 'lang' ) ); @@ -203,7 +203,7 @@ class AllmessagesTablePager extends TablePager { ' ' . - Xml::label( wfMsg( 'table_pager_limit_label'), 'mw-table_pager_limit_label' ) . + Xml::label( $this->msg( 'table_pager_limit_label' )->text(), 'mw-table_pager_limit_label' ) . ' ' . $this->getLimitSelect() . @@ -211,7 +211,7 @@ class AllmessagesTablePager extends TablePager { ' . - Xml::submitButton( wfMsg( 'allmessages-filter-submit' ) ) . + Xml::submitButton( $this->msg( 'allmessages-filter-submit' )->text() ) . "\n " . @@ -247,8 +247,10 @@ class AllmessagesTablePager extends TablePager { * @param array $messageNames * @param string $langcode What language code * @param bool $foreign Whether the $langcode is not the content language + * @return array: a 'pages' and 'talks' array with the keys of existing pages */ public static function getCustomisedStatuses( $messageNames, $langcode = 'en', $foreign = false ) { + // FIXME: This function should be moved to Language:: or something. wfProfileIn( __METHOD__ . '-db' ); $dbr = wfGetDB( DB_SLAVE ); @@ -263,18 +265,20 @@ class AllmessagesTablePager extends TablePager { $pageFlags = $talkFlags = array(); foreach ( $res as $s ) { - if( $s->page_namespace == NS_MEDIAWIKI ) { - if( $foreign ) { - $title = explode( '/', $s->page_title ); - if( count( $title ) === 2 && $langcode == $title[1] - && isset( $xNames[$title[0]] ) ) { - $pageFlags["{$title[0]}"] = true; - } - } elseif( isset( $xNames[$s->page_title] ) ) { - $pageFlags[$s->page_title] = true; + $exists = false; + if( $foreign ) { + $title = explode( '/', $s->page_title ); + if( count( $title ) === 2 && $langcode == $title[1] + && isset( $xNames[$title[0]] ) ) { + $exists = $title[0]; } - } elseif( $s->page_namespace == NS_MEDIAWIKI_TALK ){ - $talkFlags[$s->page_title] = true; + } elseif( isset( $xNames[$s->page_title] ) ) { + $exists = $s->page_title; + } + if( $exists && $s->page_namespace == NS_MEDIAWIKI ) { + $pageFlags[$exists] = true; + } elseif( $exists && $s->page_namespace == NS_MEDIAWIKI_TALK ) { + $talkFlags[$exists] = true; } } @@ -319,24 +323,23 @@ class AllmessagesTablePager extends TablePager { } function getStartBody() { - return Xml::openElement( 'table', array( 'class' => 'TablePager', 'id' => 'mw-allmessagestable' ) ) . "\n" . + return Xml::openElement( 'table', array( 'class' => 'mw-datatable TablePager', 'id' => 'mw-allmessagestable' ) ) . "\n" . " " . - wfMsg( 'allmessagesname' ) . " + $this->msg( 'allmessagesname' )->escaped() . " " . - wfMsg( 'allmessagesdefault' ) . + $this->msg( 'allmessagesdefault' )->escaped() . " \n " . - wfMsg( 'allmessagescurrent' ) . + $this->msg( 'allmessagescurrent' )->escaped() . " \n"; } function formatValue( $field, $value ){ - global $wgLang; switch( $field ){ case 'am_title' : @@ -345,11 +348,11 @@ class AllmessagesTablePager extends TablePager { $talk = Title::makeTitle( NS_MEDIAWIKI_TALK, $value . $this->suffix ); if( $this->mCurrentRow->am_customised ){ - $title = Linker::linkKnown( $title, $wgLang->lcfirst( $value ) ); + $title = Linker::linkKnown( $title, $this->getLanguage()->lcfirst( $value ) ); } else { $title = Linker::link( $title, - $wgLang->lcfirst( $value ), + $this->getLanguage()->lcfirst( $value ), array(), array(), array( 'broken' ) @@ -394,12 +397,11 @@ class AllmessagesTablePager extends TablePager { function getRowAttrs( $row, $isSecond = false ){ $arr = array(); - global $wgLang; if( $row->am_customised ){ $arr['class'] = 'allmessages-customised'; } if( !$isSecond ){ - $arr['id'] = Sanitizer::escapeId( 'msg_' . $wgLang->lcfirst( $row->am_title ) ); + $arr['id'] = Sanitizer::escapeId( 'msg_' . $this->getLanguage()->lcfirst( $row->am_title ) ); } return $arr; } @@ -407,7 +409,7 @@ class AllmessagesTablePager extends TablePager { function getCellAttrs( $field, $value ){ if( $this->mCurrentRow->am_customised && $field == 'am_title' ){ return array( 'rowspan' => '2', 'class' => $field ); - } else if( $field == 'am_title' ) { + } elseif( $field == 'am_title' ) { return array( 'class' => $field ); } else { return array( 'lang' => $this->langcode, 'dir' => $this->lang->getDir(), 'class' => $field ); @@ -417,8 +419,8 @@ class AllmessagesTablePager extends TablePager { // This is not actually used, as getStartBody is overridden above function getFieldNames() { return array( - 'am_title' => wfMsg( 'allmessagesname' ), - 'am_default' => wfMsg( 'allmessagesdefault' ) + 'am_title' => $this->msg( 'allmessagesname' )->text(), + 'am_default' => $this->msg( 'allmessagesdefault' )->text() ); } diff --git a/includes/specials/SpecialAllpages.php b/includes/specials/SpecialAllpages.php index a9cbf3ab..960a327a 100644 --- a/includes/specials/SpecialAllpages.php +++ b/includes/specials/SpecialAllpages.php @@ -73,16 +73,16 @@ class SpecialAllpages extends IncludableSpecialPage { $namespaces = $wgContLang->getNamespaces(); - $out->setPagetitle( + $out->setPageTitle( ( $namespace > 0 && in_array( $namespace, array_keys( $namespaces) ) ) ? - wfMsg( 'allinnamespace', str_replace( '_', ' ', $namespaces[$namespace] ) ) : - wfMsg( 'allarticles' ) + $this->msg( 'allinnamespace', str_replace( '_', ' ', $namespaces[$namespace] ) ) : + $this->msg( 'allarticles' ) ); $out->addModuleStyles( 'mediawiki.special' ); - if( isset($par) ) { + if( $par !== null ) { $this->showChunk( $namespace, $par, $to ); - } elseif( isset($from) && !isset($to) ) { + } elseif( $from !== null && $to === null ) { $this->showChunk( $namespace, $from, $to ); } else { $this->showToplevel( $namespace, $from, $to ); @@ -104,11 +104,11 @@ class SpecialAllpages extends IncludableSpecialPage { $out .= Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ); $out .= Html::hidden( 'title', $t->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 .= " " . - Xml::label( wfMsg( 'allpagesfrom' ), 'nsfrom' ) . + Xml::label( $this->msg( 'allpagesfrom' )->text(), 'nsfrom' ) . " " . Xml::input( 'from', 30, str_replace('_',' ',$from), array( 'id' => 'nsfrom' ) ) . @@ -116,7 +116,7 @@ class SpecialAllpages extends IncludableSpecialPage { " . - Xml::label( wfMsg( 'allpagesto' ), 'nsto' ) . + Xml::label( $this->msg( 'allpagesto' )->text(), 'nsto' ) . " " . Xml::input( 'to', 30, str_replace('_',' ',$to), array( 'id' => 'nsto' ) ) . @@ -124,11 +124,14 @@ class SpecialAllpages extends IncludableSpecialPage { " . - Xml::label( wfMsg( 'namespace' ), 'namespace' ) . + Xml::label( $this->msg( 'namespace' )->text(), 'namespace' ) . " " . - Xml::namespaceSelector( $namespace, null ) . ' ' . - Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . + Html::namespaceSelector( + array( 'selected' => $namespace ), + array( 'name' => 'namespace', 'id' => 'namespace' ) + ) . ' ' . + Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . " "; $out .= Xml::closeElement( 'table' ); @@ -249,7 +252,7 @@ class SpecialAllpages extends IncludableSpecialPage { $nsForm . ' ' . - $this->getSkin()->link( $this->getTitle(), wfMsgHtml ( 'allpages' ), + Linker::link( $this->getTitle(), $this->msg( 'allpages' )->escaped(), array(), array(), 'known' ) . " " . @@ -278,12 +281,12 @@ class SpecialAllpages extends IncludableSpecialPage { $queryparams = $namespace ? "namespace=$namespace&" : ''; $special = $this->getTitle(); - $link = $special->escapeLocalUrl( $queryparams . 'from=' . urlencode($inpoint) . '&to=' . urlencode($outpoint) ); + $link = htmlspecialchars( $special->getLocalUrl( $queryparams . 'from=' . urlencode($inpoint) . '&to=' . urlencode($outpoint) ) ); - $out = wfMsgHtml( 'alphaindexline', + $out = $this->msg( 'alphaindexline' )->rawParams( "$inpointf", "$outpointf" - ); + )->escaped(); return '' . $out . ''; } @@ -293,9 +296,8 @@ class SpecialAllpages extends IncludableSpecialPage { * @param $to String: list all pages to this name (default FALSE) */ function showChunk( $namespace = NS_MAIN, $from = false, $to = false ) { - global $wgContLang, $wgLang; + global $wgContLang; $output = $this->getOutput(); - $sk = $this->getSkin(); $fromList = $this->getNamespaceKeyAndText($namespace, $from); $toList = $this->getNamespaceKeyAndText( $namespace, $to ); @@ -303,10 +305,10 @@ class SpecialAllpages extends IncludableSpecialPage { $n = 0; if ( !$fromList || !$toList ) { - $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, $fromKey, $from ) = $fromList; @@ -338,7 +340,7 @@ class SpecialAllpages extends IncludableSpecialPage { $t = Title::newFromRow( $s ); if( $t ) { $link = ( $s->page_is_redirect ? '
' : '' ) . - $sk->link( $t ) . + Linker::link( $t ) . ($s->page_is_redirect ? '
' : '' ); } else { $link = '[[' . htmlspecialchars( $s->page_title ) . ']]'; @@ -411,7 +413,7 @@ class SpecialAllpages extends IncludableSpecialPage { $nsForm . ' ' . - $sk->link( $self, wfMsgHtml ( 'allpages' ) ); + Linker::link( $self, $this->msg( 'allpages' )->escaped() ); # Do we put a previous link ? if( isset( $prevTitle ) && $pt = $prevTitle->getText() ) { @@ -420,13 +422,13 @@ class SpecialAllpages extends IncludableSpecialPage { if( $namespace ) $query['namespace'] = $namespace; - $prevLink = $sk->linkKnown( + $prevLink = Linker::linkKnown( $self, - wfMessage( 'prevpage', $pt )->escaped(), + $this->msg( 'prevpage', $pt )->escaped(), array(), $query ); - $out2 = $wgLang->pipeList( array( $out2, $prevLink ) ); + $out2 = $this->getLanguage()->pipeList( array( $out2, $prevLink ) ); } if( $n == $this->maxPerPage && $s = $res->fetchObject() ) { @@ -437,13 +439,13 @@ class SpecialAllpages extends IncludableSpecialPage { if( $namespace ) $query['namespace'] = $namespace; - $nextLink = $sk->linkKnown( + $nextLink = Linker::linkKnown( $self, - wfMessage( 'nextpage', $t->getText() )->escaped(), + $this->msg( 'nextpage', $t->getText() )->escaped(), array(), $query ); - $out2 = $wgLang->pipeList( array( $out2, $nextLink ) ); + $out2 = $this->getLanguage()->pipeList( array( $out2, $nextLink ) ); } $out2 .= ""; } @@ -458,7 +460,7 @@ class SpecialAllpages extends IncludableSpecialPage { $output->addHTML( Html::element( 'hr' ) . Html::rawElement( 'div', array( 'class' => 'mw-allpages-nav' ), - $wgLang->pipeList( $links ) + $this->getLanguage()->pipeList( $links ) ) ); } diff --git a/includes/specials/SpecialAncientpages.php b/includes/specials/SpecialAncientpages.php index cbb5df80..1203e1fd 100644 --- a/includes/specials/SpecialAncientpages.php +++ b/includes/specials/SpecialAncientpages.php @@ -59,14 +59,14 @@ class AncientPagesPage extends QueryPage { } function formatResult( $skin, $result ) { - global $wgLang, $wgContLang; + global $wgContLang; - $d = $wgLang->timeanddate( wfTimestamp( TS_MW, $result->value ), true ); + $d = $this->getLanguage()->userTimeAndDate( $result->value, $this->getUser() ); $title = Title::makeTitle( $result->namespace, $result->title ); - $link = $skin->linkKnown( + $link = Linker::linkKnown( $title, htmlspecialchars( $wgContLang->convert( $title->getPrefixedText() ) ) ); - return wfSpecialList( $link, htmlspecialchars($d) ); + return $this->getLanguage()->specialList( $link, htmlspecialchars( $d ) ); } } diff --git a/includes/specials/SpecialBlock.php b/includes/specials/SpecialBlock.php index f1fe8386..7d93cc75 100644 --- a/includes/specials/SpecialBlock.php +++ b/includes/specials/SpecialBlock.php @@ -27,8 +27,7 @@ * * @ingroup SpecialPage */ -class SpecialBlock extends SpecialPage { - +class SpecialBlock extends FormSpecialPage { /** The maximum number of edits a user can have and still be hidden * TODO: config setting? */ const HIDEUSER_CONTRIBLIMIT = 1000; @@ -56,65 +55,66 @@ class SpecialBlock extends SpecialPage { parent::__construct( 'Block', 'block' ); } - public function execute( $par ) { - global $wgUser, $wgOut, $wgRequest; - - # Permission check - if( !$this->userCanExecute( $wgUser ) ) { - $this->displayRestrictionError(); - return; - } + /** + * Checks that the user can unblock themselves if they are trying to do so + * + * @param User $user + * @throws ErrorPageError + */ + protected function checkExecutePermissions( User $user ) { + parent::checkExecutePermissions( $user ); - # Can't block when the database is locked - if( wfReadOnly() ) { - throw new ReadOnlyError; + # bug 15810: blocked admins should have limited access here + $status = self::checkUnblockSelf( $this->target, $user ); + if ( $status !== true ) { + throw new ErrorPageError( 'badaccess', $status ); } + } + /** + * Handle some magic here + * + * @param $par String + */ + protected function setParameter( $par ) { # Extract variables from the request. Try not to get into a situation where we # need to extract *every* variable from the form just for processing here, but # there are legitimate uses for some variables - list( $this->target, $this->type ) = self::getTargetAndType( $par, $wgRequest ); + $request = $this->getRequest(); + list( $this->target, $this->type ) = self::getTargetAndType( $par, $request ); if ( $this->target instanceof User ) { # Set the 'relevant user' in the skin, so it displays links like Contributions, # User logs, UserRights, etc. $this->getSkin()->setRelevantUser( $this->target ); } - list( $this->previousTarget, /*...*/ ) = Block::parseTarget( $wgRequest->getVal( 'wpPreviousTarget' ) ); - $this->requestedHideUser = $wgRequest->getBool( 'wpHideUser' ); - - # bug 15810: blocked admins should have limited access here - $status = self::checkUnblockSelf( $this->target ); - if ( $status !== true ) { - throw new ErrorPageError( 'badaccess', $status ); - } - - $wgOut->setPageTitle( wfMsg( 'blockip-title' ) ); - $wgOut->addModules( 'mediawiki.special', 'mediawiki.special.block' ); - - $out = $this->getOutput(); - $out->setPageTitle( wfMsg( 'blockip-title' ) ); - $out->addModules( array( 'mediawiki.special', 'mediawiki.special.block' ) ); - - $fields = $this->getFormFields(); - $this->maybeAlterFormDefaults( $fields ); - - $form = new HTMLForm( $fields, $this->getContext() ); - $form->setWrapperLegend( wfMsg( 'blockip-legend' ) ); - $form->setSubmitCallback( array( __CLASS__, 'processForm' ) ); + list( $this->previousTarget, /*...*/ ) = Block::parseTarget( $request->getVal( 'wpPreviousTarget' ) ); + $this->requestedHideUser = $request->getBool( 'wpHideUser' ); + } - $t = $this->alreadyBlocked - ? wfMsg( 'ipb-change-block' ) - : wfMsg( 'ipbsubmit' ); - $form->setSubmitText( $t ); + /** + * Customizes the HTMLForm a bit + * + * @param $form HTMLForm + */ + protected function alterForm( HTMLForm $form ) { + $form->setWrapperLegendMsg( 'blockip-legend' ); + $form->setHeaderText( '' ); + $form->setSubmitCallback( array( __CLASS__, 'processUIForm' ) ); - $this->doPreText( $form ); - $this->doHeadertext( $form ); - $this->doPostText( $form ); + $msg = $this->alreadyBlocked ? 'ipb-change-block' : 'ipbsubmit'; + $form->setSubmitTextMsg( $msg ); - if( $form->show() ){ - $wgOut->setPageTitle( wfMsg( 'blockipsuccesssub' ) ); - $wgOut->addWikiMsg( 'blockipsuccesstext', $this->target ); + # Don't need to do anything if the form has been posted + if( !$this->getRequest()->wasPosted() && $this->preErrors ){ + $s = HTMLForm::formatErrors( $this->preErrors ); + if( $s ){ + $form->addHeaderText( Html::rawElement( + 'div', + array( 'class' => 'error' ), + $s + ) ); + } } } @@ -122,8 +122,10 @@ class SpecialBlock extends SpecialPage { * Get the HTMLForm descriptor array for the block form * @return Array */ - protected static function getFormFields(){ - global $wgUser, $wgBlockAllowsUTEdit; + protected function getFormFields(){ + global $wgBlockAllowsUTEdit; + + $user = $this->getUser(); $a = array( 'Target' => array( @@ -141,7 +143,7 @@ class SpecialBlock extends SpecialPage { 'required' => true, 'tabindex' => '2', 'options' => self::getSuggestedDurations(), - 'other' => wfMsg( 'ipbother' ), + 'other' => $this->msg( 'ipbother' )->text(), ), 'Reason' => array( 'type' => 'selectandother', @@ -155,7 +157,7 @@ class SpecialBlock extends SpecialPage { ), ); - if( self::canBlockEmail( $wgUser ) ) { + if( self::canBlockEmail( $user ) ) { $a['DisableEmail'] = array( 'type' => 'check', 'label-message' => 'ipbemailban', @@ -177,7 +179,7 @@ class SpecialBlock extends SpecialPage { ); # Allow some users to hide name from block log, blocklist and listusers - if( $wgUser->isAllowed( 'hideuser' ) ) { + if( $user->isAllowed( 'hideuser' ) ) { $a['HideUser'] = array( 'type' => 'check', 'label-message' => 'ipbhidename', @@ -186,7 +188,7 @@ class SpecialBlock extends SpecialPage { } # Watchlist their user page? (Only if user is logged in) - if( $wgUser->isLoggedIn() ) { + if( $user->isLoggedIn() ) { $a['Watch'] = array( 'type' => 'check', 'label-message' => 'ipbwatchuser', @@ -213,19 +215,19 @@ class SpecialBlock extends SpecialPage { 'label-message' => 'ipb-confirm', ); + $this->maybeAlterFormDefaults( $a ); + return $a; } /** * If the user has already been blocked with similar settings, load that block * and change the defaults for the form fields to match the existing settings. - * @param &$fields Array HTMLForm descriptor array + * @param $fields Array HTMLForm descriptor array * @return Bool whether fields were altered (that is, whether the target is * already blocked) */ protected function maybeAlterFormDefaults( &$fields ){ - global $wgRequest, $wgUser; - # This will be overwritten by request data $fields['Target']['default'] = (string)$this->target; @@ -242,18 +244,22 @@ class SpecialBlock extends SpecialPage { $fields['HardBlock']['default'] = $block->isHardblock(); $fields['CreateAccount']['default'] = $block->prevents( 'createaccount' ); $fields['AutoBlock']['default'] = $block->isAutoblocking(); + if( isset( $fields['DisableEmail'] ) ){ $fields['DisableEmail']['default'] = $block->prevents( 'sendemail' ); } + if( isset( $fields['HideUser'] ) ){ $fields['HideUser']['default'] = $block->mHideName; } + if( isset( $fields['DisableUTEdit'] ) ){ $fields['DisableUTEdit']['default'] = $block->prevents( 'editownusertalk' ); } + $fields['Reason']['default'] = $block->mReason; - if( $wgRequest->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'; @@ -282,7 +288,7 @@ class SpecialBlock extends SpecialPage { } # Or if the user is trying to block themselves - if( (string)$this->target === $wgUser->getName() ){ + if( (string)$this->target === $this->getUser()->getName() ){ $fields['Confirm']['type'] = 'check'; unset( $fields['Confirm']['default'] ); $this->preErrors[] = 'ipb-blockingself'; @@ -291,11 +297,9 @@ class SpecialBlock extends SpecialPage { /** * Add header elements like block log entries, etc. - * @param $form HTMLForm - * @return void */ - protected function doPreText( HTMLForm &$form ){ - $form->addPreText( wfMsgExt( 'blockiptext', 'parse' ) ); + protected function preText(){ + $text = $this->msg( 'blockiptext' )->parse(); $otherBlockMessages = array(); if( $this->target !== null ) { @@ -306,65 +310,48 @@ class SpecialBlock extends SpecialPage { $s = Html::rawElement( 'h2', array(), - wfMsgExt( 'ipb-otherblocks-header', 'parseinline', count( $otherBlockMessages ) ) + $this->msg( 'ipb-otherblocks-header', count( $otherBlockMessages ) )->parse() ) . "\n"; + $list = ''; + foreach( $otherBlockMessages as $link ) { $list .= Html::rawElement( 'li', array(), $link ) . "\n"; } + $s .= Html::rawElement( 'ul', array( 'class' => 'mw-blockip-alreadyblocked' ), $list ) . "\n"; - $form->addPreText( $s ); - } - } - } - /** - * Add header text inside the form, just underneath where the errors would go - * @param $form HTMLForm - * @return void - */ - protected function doHeaderText( HTMLForm &$form ){ - global $wgRequest; - # Don't need to do anything if the form has been posted - if( !$wgRequest->wasPosted() && $this->preErrors ){ - $s = HTMLForm::formatErrors( $this->preErrors ); - if( $s ){ - $form->addHeaderText( Html::rawElement( - 'div', - array( 'class' => 'error' ), - $s - ) ); + $text .= $s; } } + + return $text; } /** * Add footer elements to the form - * @param $form HTMLForm - * @return void + * @return string */ - protected function doPostText( HTMLForm &$form ){ - global $wgUser, $wgLang; - + protected function postText(){ # Link to the user's contributions, if applicable if( $this->target instanceof User ){ $contribsPage = SpecialPage::getTitleFor( 'Contributions', $this->target->getName() ); $links[] = Linker::link( $contribsPage, - wfMsgExt( 'ipb-blocklist-contribs', 'escape', $this->target->getName() ) + $this->msg( 'ipb-blocklist-contribs', $this->target->getName() )->escaped() ); } # Link to unblock the specified user, or to a blank unblock form if( $this->target instanceof User ) { - $message = wfMsgExt( 'ipb-unblock-addr', array( 'parseinline' ), $this->target->getName() ); + $message = $this->msg( 'ipb-unblock-addr', $this->target->getName() )->parse(); $list = SpecialPage::getTitleFor( 'Unblock', $this->target->getName() ); } else { - $message = wfMsgExt( 'ipb-unblock', array( 'parseinline' ) ); + $message = $this->msg( 'ipb-unblock' )->parse(); $list = SpecialPage::getTitleFor( 'Unblock' ); } $links[] = Linker::linkKnown( $list, $message, array() ); @@ -372,24 +359,26 @@ class SpecialBlock extends SpecialPage { # Link to the block list $links[] = Linker::linkKnown( SpecialPage::getTitleFor( 'BlockList' ), - wfMsg( 'ipb-blocklist' ) + $this->msg( 'ipb-blocklist' )->escaped() ); + $user = $this->getUser(); + # Link to edit the block dropdown reasons, if applicable - if ( $wgUser->isAllowed( 'editinterface' ) ) { + if ( $user->isAllowed( 'editinterface' ) ) { $links[] = Linker::link( Title::makeTitle( NS_MEDIAWIKI, 'Ipbreason-dropdown' ), - wfMsgHtml( 'ipb-edit-dropdown' ), + $this->msg( 'ipb-edit-dropdown' )->escaped(), array(), array( 'action' => 'edit' ) ); } - $form->addPostText( Html::rawElement( + $text = Html::rawElement( 'p', array( 'class' => 'mw-ipb-conveniencelinks' ), - $wgLang->pipeList( $links ) - ) ); + $this->getLanguage()->pipeList( $links ) + ); if( $this->target instanceof User ){ # Get relevant extracts from the block and suppression logs, if possible @@ -399,7 +388,7 @@ class SpecialBlock extends SpecialPage { LogEventsList::showLogExtract( $out, 'block', - $userpage->getPrefixedText(), + $userpage, '', array( 'lim' => 10, @@ -407,14 +396,14 @@ class SpecialBlock extends SpecialPage { 'showIfEmpty' => false ) ); - $form->addPostText( $out ); + $text .= $out; # Add suppression block entries if allowed - if( $wgUser->isAllowed( 'suppressionlog' ) ) { + if( $user->isAllowed( 'suppressionlog' ) ) { LogEventsList::showLogExtract( $out, 'suppress', - $userpage->getPrefixedText(), + $userpage, '', array( 'lim' => 10, @@ -423,9 +412,12 @@ class SpecialBlock extends SpecialPage { 'showIfEmpty' => false ) ); - $form->addPostText( $out ); + + $text .= $out; } } + + return $text; } /** @@ -434,11 +426,12 @@ class SpecialBlock extends SpecialPage { * @param $par String subpage parameter passed to setup, or data value from * the HTMLForm * @param $request WebRequest optionally try and get data from a request too - * @return void + * @return array( User|string|null, Block::TYPE_ constant|null ) */ public static function getTargetAndType( $par, WebRequest $request = null ){ $i = 0; $target = null; + while( true ){ switch( $i++ ){ case 0: @@ -467,11 +460,14 @@ class SpecialBlock extends SpecialPage { case 4: break 2; } + list( $target, $type ) = Block::parseTarget( $target ); + if( $type !== null ){ return array( $target, $type ); } } + return array( null, null ); } @@ -480,9 +476,10 @@ class SpecialBlock extends SpecialPage { * @since 1.18 * @param $value String * @param $alldata Array + * @param $form HTMLForm * @return Message */ - public static function validateTargetField( $value, $alldata = null ) { + public static function validateTargetField( $value, $alldata, $form ) { global $wgBlockCIDRLimit; list( $target, $type ) = self::getTargetAndType( $value ); @@ -490,13 +487,13 @@ class SpecialBlock extends SpecialPage { if( $type == Block::TYPE_USER ){ # TODO: why do we not have a User->exists() method? if( !$target->getId() ){ - return wfMessage( 'nosuchusershort', + return $form->msg( 'nosuchusershort', wfEscapeWikiText( $target->getName() ) ); } - $status = self::checkUnblockSelf( $target ); + $status = self::checkUnblockSelf( $target, $form->getUser() ); if ( $status !== true ) { - return wfMessage( 'badaccess', $status ); + return $form->msg( 'badaccess', $status ); } } elseif( $type == Block::TYPE_RANGE ){ @@ -506,41 +503,52 @@ class SpecialBlock extends SpecialPage { || ( IP::isIPv6( $ip ) && $wgBlockCIDRLimit['IPv6'] == 128 ) ) { # Range block effectively disabled - return wfMessage( 'range_block_disabled' ); + return $form->msg( 'range_block_disabled' ); } if( ( IP::isIPv4( $ip ) && $range > 32 ) || ( IP::isIPv6( $ip ) && $range > 128 ) ) { # Dodgy range - return wfMessage( 'ip_range_invalid' ); + return $form->msg( 'ip_range_invalid' ); } if( IP::isIPv4( $ip ) && $range < $wgBlockCIDRLimit['IPv4'] ) { - return wfMessage( 'ip_range_toolarge', $wgBlockCIDRLimit['IPv4'] ); + return $form->msg( 'ip_range_toolarge', $wgBlockCIDRLimit['IPv4'] ); } if( IP::isIPv6( $ip ) && $range < $wgBlockCIDRLimit['IPv6'] ) { - return wfMessage( 'ip_range_toolarge', $wgBlockCIDRLimit['IPv6'] ); + return $form->msg( 'ip_range_toolarge', $wgBlockCIDRLimit['IPv6'] ); } - } elseif( $type == Block::TYPE_IP ){ # All is well - } else { - return wfMessage( 'badipaddress' ); + return $form->msg( 'badipaddress' ); } return true; } + /** + * Submit callback for an HTMLForm object, will simply pass + * @param $data array + * @param $form HTMLForm + * @return Bool|String + */ + public static function processUIForm( array $data, HTMLForm $form ) { + return self::processForm( $data, $form->getContext() ); + } + /** * Given the form data, actually implement a block * @param $data Array + * @param $context IContextSource * @return Bool|String */ - public static function processForm( array $data ){ - global $wgUser, $wgBlockAllowsUTEdit; + public static function processForm( array $data, IContextSource $context ){ + global $wgBlockAllowsUTEdit; + + $performer = $context->getUser(); // Handled by field validator callback // self::validateTargetField( $data['Target'] ); @@ -557,20 +565,21 @@ class SpecialBlock extends SpecialPage { # Give admins a heads-up before they go and block themselves. Much messier # to do this for IPs, but it's pretty unlikely they'd ever get the 'block' - # permission anyway, although the code does allow for it - if( $target === $wgUser->getName() && - ( $data['PreviousTarget'] !== $data['Target'] || !$data['Confirm'] ) ) + # permission anyway, although the code does allow for it. + # Note: Important to use $target instead of $data['Target'] + # 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() && + ( $data['PreviousTarget'] !== $target || !$data['Confirm'] ) ) { return array( 'ipb-blockingself' ); } - } elseif( $type == Block::TYPE_RANGE ){ $userId = 0; - } elseif( $type == Block::TYPE_IP ){ $target = $target->getName(); $userId = 0; - } else { # This should have been caught in the form field validation return array( 'badipaddress' ); @@ -591,8 +600,9 @@ class SpecialBlock extends SpecialPage { if( !isset( $data['HideUser'] ) ){ $data['HideUser'] = false; } + if( $data['HideUser'] ) { - if( !$wgUser->isAllowed('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 @@ -603,16 +613,13 @@ class SpecialBlock extends SpecialPage { # Recheck params here... if( $type != Block::TYPE_USER ) { $data['HideUser'] = false; # IP users should not be hidden - } elseif( !in_array( $data['Expiry'], array( 'infinite', 'infinity', 'indefinite' ) ) ) { # Bad expiry. return array( 'ipb_expiry_temp' ); - } 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'] ){ return array( 'ipb-confirmhideuser' ); } @@ -621,7 +628,7 @@ class SpecialBlock extends SpecialPage { # Create block object. $block = new Block(); $block->setTarget( $target ); - $block->setBlocker( $wgUser ); + $block->setBlocker( $performer ); $block->mReason = $data['Reason'][0]; $block->mExpiry = self::parseExpiryInput( $data['Expiry'] ); $block->prevents( 'createaccount', $data['CreateAccount'] ); @@ -631,7 +638,7 @@ class SpecialBlock extends SpecialPage { $block->isAutoblocking( $data['AutoBlock'] ); $block->mHideName = $data['HideUser']; - if( !wfRunHooks( 'BlockIp', array( &$block, &$wgUser ) ) ) { + if( !wfRunHooks( 'BlockIp', array( &$block, &$performer ) ) ) { return array( 'hookaborted' ); } @@ -655,7 +662,7 @@ class SpecialBlock extends SpecialPage { # If the name was hidden and the blocking user cannot hide # names, then don't allow any block changes... - if( $currentBlock->mHideName && !$wgUser->isAllowed( 'hideuser' ) ) { + if( $currentBlock->mHideName && !$performer->isAllowed( 'hideuser' ) ) { return array( 'cant-see-hidden-user' ); } @@ -677,7 +684,7 @@ class SpecialBlock extends SpecialPage { $logaction = 'block'; } - wfRunHooks( 'BlockIpComplete', array( $block, $wgUser ) ); + wfRunHooks( 'BlockIpComplete', array( $block, $performer ) ); # Set *_deleted fields if requested if( $data['HideUser'] ) { @@ -686,7 +693,7 @@ class SpecialBlock extends SpecialPage { # Can't watch a rangeblock if( $type != Block::TYPE_RANGE && $data['Watch'] ) { - $wgUser->addWatch( Title::makeTitle( NS_USER, $target ) ); + $performer->addWatch( Title::makeTitle( NS_USER, $target ) ); } # Block constructor sanitizes certain block options on insert @@ -737,9 +744,11 @@ class SpecialBlock extends SpecialPage { if( strpos( $option, ':' ) === false ){ $option = "$option:$option"; } + list( $show, $value ) = explode( ':', $option ); $a[htmlspecialchars( $show )] = htmlspecialchars( $value ); } + return $a; } @@ -754,15 +763,19 @@ class SpecialBlock extends SpecialPage { if( $infinity == null ){ $infinity = wfGetDB( DB_SLAVE )->getInfinity(); } + if ( $expiry == 'infinite' || $expiry == 'indefinite' ) { $expiry = $infinity; } else { $expiry = strtotime( $expiry ); + if ( $expiry < 0 || $expiry === false ) { return false; } + $expiry = wfTimestamp( TS_MW, $expiry ); } + return $expiry; } @@ -773,6 +786,7 @@ class SpecialBlock extends SpecialPage { */ public static function canBlockEmail( $user ) { global $wgEnableUserEmail, $wgSysopEmailBans; + return ( $wgEnableUserEmail && $wgSysopEmailBans && $user->isAllowed( 'blockemail' ) ); } @@ -781,22 +795,23 @@ class SpecialBlock extends SpecialPage { * others, and probably shouldn't be able to unblock themselves * either. * @param $user User|Int|String + * @param $performer User user doing the request * @return Bool|String true or error message key */ - public static function checkUnblockSelf( $user ) { - global $wgUser; + public static function checkUnblockSelf( $user, User $performer ) { if ( is_int( $user ) ) { $user = User::newFromId( $user ); } elseif ( is_string( $user ) ) { $user = User::newFromName( $user ); } - if( $wgUser->isBlocked() ){ - if( $user instanceof User && $user->getId() == $wgUser->getId() ) { + + if( $performer->isBlocked() ){ + if( $user instanceof User && $user->getId() == $performer->getId() ) { # User is trying to unblock themselves - if ( $wgUser->isAllowed( 'unblockself' ) ) { + if ( $performer->isAllowed( 'unblockself' ) ) { return true; # User blocked themselves and is now trying to reverse it - } elseif ( $wgUser->blockedBy() === $wgUser->getName() ) { + } elseif ( $performer->blockedBy() === $performer->getName() ) { return true; } else { return 'ipbnounblockself'; @@ -814,7 +829,7 @@ class SpecialBlock extends SpecialPage { * Return a comma-delimited list of "flags" to be passed to the log * reader for this block, to provide more information in the logs * @param $data Array from HTMLForm data - * @param $type Block::TYPE_ constant + * @param $type Block::TYPE_ constant (USER, RANGE, or IP) * @return array */ protected static function blockLogFlags( array $data, $type ) { @@ -823,32 +838,58 @@ class SpecialBlock extends SpecialPage { # 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'] ){ + // 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_IP ){ + if( !$data['AutoBlock'] && $type == Block::TYPE_USER ){ + // For grepping: message block-log-flags-noautoblock $flags[] = 'noautoblock'; } if( $data['DisableEmail'] ){ + // For grepping: message block-log-flags-noemail $flags[] = 'noemail'; } if( $wgBlockAllowsUTEdit && $data['DisableUTEdit'] ){ + // For grepping: message block-log-flags-nousertalk $flags[] = 'nousertalk'; } if( $data['HideUser'] ){ + // For grepping: message block-log-flags-hiddenname $flags[] = 'hiddenname'; } return implode( ',', $flags ); } + + /** + * Process the form on POST submission. + * @param $data Array + * @return Bool|Array true for success, false for didn't-try, array of errors on failure + */ + public function onSubmit( array $data ) { + // This isn't used since we need that HTMLForm that's passed in the + // second parameter. See alterForm for the real function + } + + /** + * Do something exciting on successful processing of the form, most likely to show a + * confirmation message + */ + public function onSuccess() { + $out = $this->getOutput(); + $out->setPageTitle( $this->msg( 'blockipsuccesssub' ) ); + $out->addWikiMsg( 'blockipsuccesstext', $this->target ); + } } # BC @since 1.18 diff --git a/includes/specials/SpecialBlockList.php b/includes/specials/SpecialBlockList.php index 04787a65..0a3a28fe 100644 --- a/includes/specials/SpecialBlockList.php +++ b/includes/specials/SpecialBlockList.php @@ -40,24 +40,25 @@ class SpecialBlockList extends SpecialPage { * @param $par String title fragment */ public function execute( $par ) { - global $wgOut, $wgRequest, $wgLang; - $this->setHeaders(); $this->outputHeader(); - $wgOut->setPageTitle( wfMsg( 'ipblocklist' ) ); - $wgOut->addModuleStyles( 'mediawiki.special' ); + $out = $this->getOutput(); + $lang = $this->getLanguage(); + $out->setPageTitle( $this->msg( 'ipblocklist' ) ); + $out->addModuleStyles( 'mediawiki.special' ); - $par = $wgRequest->getVal( 'ip', $par ); - $this->target = trim( $wgRequest->getVal( 'wpTarget', $par ) ); + $request = $this->getRequest(); + $par = $request->getVal( 'ip', $par ); + $this->target = trim( $request->getVal( 'wpTarget', $par ) ); - $this->options = $wgRequest->getArray( 'wpOptions', array() ); + $this->options = $request->getArray( 'wpOptions', array() ); - $action = $wgRequest->getText( 'action' ); + $action = $request->getText( 'action' ); - if( $action == 'unblock' || $action == 'submit' && $wgRequest->wasPosted() ) { + if( $action == 'unblock' || $action == 'submit' && $request->wasPosted() ) { # B/C @since 1.18: Unblock interface is now at Special:Unblock $title = SpecialPage::getTitleFor( 'Unblock', $this->target ); - $wgOut->redirect( $title->getFullUrl() ); + $out->redirect( $title->getFullUrl() ); return; } @@ -68,13 +69,15 @@ class SpecialBlockList extends SpecialPage { 'label-message' => 'ipadressorusername', 'tabindex' => '1', 'size' => '45', + 'default' => $this->target, ), 'Options' => array( 'type' => 'multiselect', 'options' => array( - wfMsg( 'blocklist-userblocks' ) => 'userblocks', - wfMsg( 'blocklist-tempblocks' ) => 'tempblocks', - wfMsg( 'blocklist-addressblocks' ) => 'addressblocks', + $this->msg( 'blocklist-userblocks' )->text() => 'userblocks', + $this->msg( 'blocklist-tempblocks' )->text() => 'tempblocks', + $this->msg( 'blocklist-addressblocks' )->text() => 'addressblocks', + $this->msg( 'blocklist-rangeblocks' )->text() => 'rangeblocks', ), 'flatlist' => true, ), @@ -82,11 +85,11 @@ class SpecialBlockList extends SpecialPage { 'class' => 'HTMLBlockedUsersItemSelect', 'label-message' => 'table_pager_limit_label', 'options' => array( - $wgLang->formatNum( 20 ) => 20, - $wgLang->formatNum( 50 ) => 50, - $wgLang->formatNum( 100 ) => 100, - $wgLang->formatNum( 250 ) => 250, - $wgLang->formatNum( 500 ) => 500, + $lang->formatNum( 20 ) => 20, + $lang->formatNum( 50 ) => 50, + $lang->formatNum( 100 ) => 100, + $lang->formatNum( 250 ) => 250, + $lang->formatNum( 500 ) => 500, ), 'name' => 'limit', 'default' => 50, @@ -94,8 +97,8 @@ class SpecialBlockList extends SpecialPage { ); $form = new HTMLForm( $fields, $this->getContext() ); $form->setMethod( 'get' ); - $form->setWrapperLegend( wfMsg( 'ipblocklist-legend' ) ); - $form->setSubmitText( wfMsg( 'ipblocklist-submit' ) ); + $form->setWrapperLegendMsg( 'ipblocklist-legend' ); + $form->setSubmitTextMsg( 'ipblocklist-submit' ); $form->prepareForm(); $form->displayForm( '' ); @@ -103,8 +106,6 @@ class SpecialBlockList extends SpecialPage { } function showList() { - global $wgOut, $wgUser; - # Purge expired entries on one in every 10 queries if ( !mt_rand( 0, 10 ) ) { Block::purgeExpired(); @@ -112,7 +113,7 @@ class SpecialBlockList extends SpecialPage { $conds = array(); # Is the user allowed to see hidden blocks? - if ( !$wgUser->isAllowed( 'hideuser' ) ){ + if ( !$this->getUser()->isAllowed( 'hideuser' ) ){ $conds['ipb_deleted'] = 0; } @@ -121,6 +122,7 @@ class SpecialBlockList extends SpecialPage { switch( $type ){ case Block::TYPE_ID: + case Block::TYPE_AUTO: $conds['ipb_id'] = $target; break; @@ -155,51 +157,52 @@ class SpecialBlockList extends SpecialPage { if( in_array( 'addressblocks', $this->options ) ) { $conds[] = "ipb_user != 0 OR ipb_range_end > ipb_range_start"; } + if( in_array( 'rangeblocks', $this->options ) ) { + $conds[] = "ipb_range_end = ipb_range_start"; + } # Check for other blocks, i.e. global/tor blocks $otherBlockLink = array(); wfRunHooks( 'OtherBlockLogLink', array( &$otherBlockLink, $this->target ) ); + $out = $this->getOutput(); + # Show additional header for the local block only when other blocks exists. # Not necessary in a standard installation without such extensions enabled if( count( $otherBlockLink ) ) { - $wgOut->addHTML( - Html::rawElement( 'h2', array(), wfMsg( 'ipblocklist-localblock' ) ) . "\n" + $out->addHTML( + Html::element( 'h2', array(), $this->msg( 'ipblocklist-localblock' )->text() ) . "\n" ); } $pager = new BlockListPager( $this, $conds ); if ( $pager->getNumRows() ) { - $wgOut->addHTML( + $out->addHTML( $pager->getNavigationBar() . $pager->getBody(). $pager->getNavigationBar() ); } elseif ( $this->target ) { - $wgOut->addWikiMsg( 'ipblocklist-no-results' ); + $out->addWikiMsg( 'ipblocklist-no-results' ); } else { - $wgOut->addWikiMsg( 'ipblocklist-empty' ); + $out->addWikiMsg( 'ipblocklist-empty' ); } if( count( $otherBlockLink ) ) { - $wgOut->addHTML( + $out->addHTML( Html::rawElement( 'h2', array(), - wfMsgExt( - 'ipblocklist-otherblocks', - 'parseinline', - count( $otherBlockLink ) - ) + $this->msg( 'ipblocklist-otherblocks', count( $otherBlockLink ) )->parse() ) . "\n" ); $list = ''; foreach( $otherBlockLink as $link ) { $list .= Html::rawElement( 'li', array(), $link ) . "\n"; } - $wgOut->addHTML( Html::rawElement( 'ul', array( 'class' => 'mw-ipblocklist-otherblocks' ), $list ) . "\n" ); + $out->addHTML( Html::rawElement( 'ul', array( 'class' => 'mw-ipblocklist-otherblocks' ), $list ) . "\n" ); } } } @@ -208,11 +211,15 @@ class BlockListPager extends TablePager { protected $conds; protected $page; + /** + * @param $page SpecialPage + * @param $conds Array + */ function __construct( $page, $conds ) { $this->page = $page; $this->conds = $conds; $this->mDefaultDirection = true; - parent::__construct(); + parent::__construct( $page->getContext() ); } function getFieldNames() { @@ -227,18 +234,17 @@ class BlockListPager extends TablePager { 'ipb_params' => 'blocklist-params', 'ipb_reason' => 'blocklist-reason', ); - $headers = array_map( 'wfMsg', $headers ); + foreach( $headers as $key => $val ) { + $headers[$key] = $this->msg( $val )->text(); + } } return $headers; } function formatValue( $name, $value ) { - global $wgLang, $wgUser; - - static $sk, $msg; - if ( empty( $sk ) ) { - $sk = $this->getSkin(); + static $msg = null; + if ( $msg === null ) { $msg = array( 'anononlyblock', 'createaccountblock', @@ -249,27 +255,29 @@ class BlockListPager extends TablePager { 'change-blocklink', 'infiniteblock', ); - $msg = array_combine( $msg, array_map( 'wfMessage', $msg ) ); + $msg = array_combine( $msg, array_map( array( $this, 'msg' ), $msg ) ); } + /** @var $row object */ $row = $this->mCurrentRow; + $formatted = ''; switch( $name ) { case 'ipb_timestamp': - $formatted = $wgLang->timeanddate( $value, /* User preference timezone */ true ); + $formatted = $this->getLanguage()->userTimeAndDate( $value, $this->getUser() ); break; case 'ipb_target': if( $row->ipb_auto ){ - $formatted = wfMessage( 'autoblockid', $row->ipb_id )->parse(); + $formatted = $this->msg( 'autoblockid', $row->ipb_id )->parse(); } else { list( $target, $type ) = Block::parseTarget( $row->ipb_address ); switch( $type ){ case Block::TYPE_USER: case Block::TYPE_IP: - $formatted = $sk->userLink( $target->getId(), $target ); - $formatted .= $sk->userToolLinks( + $formatted = Linker::userLink( $target->getId(), $target ); + $formatted .= Linker::userToolLinks( $target->getId(), $target, false, @@ -283,21 +291,21 @@ class BlockListPager extends TablePager { break; case 'ipb_expiry': - $formatted = $wgLang->formatExpiry( $value, /* User preference timezone */ true ); - if( $wgUser->isAllowed( 'block' ) ){ + $formatted = $this->getLanguage()->formatExpiry( $value, /* User preference timezone */ true ); + if( $this->getUser()->isAllowed( 'block' ) ){ if( $row->ipb_auto ){ - $links[] = $sk->linkKnown( + $links[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Unblock' ), $msg['unblocklink'], array(), array( 'wpTarget' => "#{$row->ipb_id}" ) ); } else { - $links[] = $sk->linkKnown( + $links[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Unblock', $row->ipb_address ), $msg['unblocklink'] ); - $links[] = $sk->linkKnown( + $links[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Block', $row->ipb_address ), $msg['change-blocklink'] ); @@ -305,21 +313,23 @@ class BlockListPager extends TablePager { $formatted .= ' ' . Html::rawElement( 'span', array( 'class' => 'mw-blocklist-actions' ), - wfMsg( 'parentheses', $wgLang->pipeList( $links ) ) + $this->msg( 'parentheses' )->rawParams( + $this->getLanguage()->pipeList( $links ) )->escaped() ); } break; case 'ipb_by': - $user = User::newFromId( $value ); - if( $user instanceof User ){ - $formatted = $sk->userLink( $user->getId(), $user->getName() ); - $formatted .= $sk->userToolLinks( $user->getId(), $user->getName() ); + if ( isset( $row->by_user_name ) ) { + $formatted = Linker::userLink( $value, $row->by_user_name ); + $formatted .= Linker::userToolLinks( $value, $row->by_user_name ); + } else { + $formatted = htmlspecialchars( $row->ipb_by_text ); // foreign user? } break; case 'ipb_reason': - $formatted = $sk->commentBlock( $value ); + $formatted = Linker::commentBlock( $value ); break; case 'ipb_params': @@ -342,7 +352,7 @@ class BlockListPager extends TablePager { $properties[] = $msg['blocklist-nousertalk']; } - $formatted = $wgLang->commaList( $properties ); + $formatted = $this->getLanguage()->commaList( $properties ); break; default: @@ -355,12 +365,14 @@ class BlockListPager extends TablePager { function getQueryInfo() { $info = array( - 'tables' => array( 'ipblocks' ), + 'tables' => array( 'ipblocks', 'user' ), 'fields' => array( 'ipb_id', 'ipb_address', 'ipb_user', 'ipb_by', + 'ipb_by_text', + 'user_name AS by_user_name', 'ipb_reason', 'ipb_timestamp', 'ipb_auto', @@ -375,12 +387,12 @@ class BlockListPager extends TablePager { 'ipb_allow_usertalk', ), 'conds' => $this->conds, + 'join_conds' => array( 'user' => array( 'LEFT JOIN', 'user_id = ipb_by' ) ) ); - global $wgUser; # Is the user allowed to see hidden blocks? - if ( !$wgUser->isAllowed( 'hideuser' ) ){ - $conds['ipb_deleted'] = 0; + if ( !$this->getUser()->isAllowed( 'hideuser' ) ){ + $info['conds']['ipb_deleted'] = 0; } return $info; @@ -402,8 +414,37 @@ class BlockListPager extends TablePager { return false; } - function getTitle() { - return $this->page->getTitle(); + /** + * Do a LinkBatch query to minimise database load when generating all these links + * @param $result + */ + function preprocessResults( $result ){ + wfProfileIn( __METHOD__ ); + # Do a link batch query + $lb = new LinkBatch; + $lb->setCaller( __METHOD__ ); + + $userids = array(); + + foreach ( $result as $row ) { + $userids[] = $row->ipb_by; + + # Usernames and titles are in fact related by a simple substitution of space -> underscore + # The last few lines of Title::secureAndSplit() tell the story. + $name = str_replace( ' ', '_', $row->ipb_address ); + $lb->add( NS_USER, $name ); + $lb->add( NS_USER_TALK, $name ); + } + + $ua = UserArray::newFromIDs( $userids ); + foreach( $ua as $user ){ + $name = str_replace( ' ', '_', $user->getName() ); + $lb->add( NS_USER, $name ); + $lb->add( NS_USER_TALK, $name ); + } + + $lb->execute(); + wfProfileOut( __METHOD__ ); } } diff --git a/includes/specials/SpecialBlockme.php b/includes/specials/SpecialBlockme.php index 40747667..3840b2ff 100644 --- a/includes/specials/SpecialBlockme.php +++ b/includes/specials/SpecialBlockme.php @@ -33,18 +33,19 @@ class SpecialBlockme extends UnlistedSpecialPage { } function execute( $par ) { - global $wgRequest, $wgOut, $wgBlockOpenProxies, $wgProxyKey; + global $wgBlockOpenProxies, $wgProxyKey; $this->setHeaders(); $this->outputHeader(); - $ip = wfGetIP(); - if( !$wgBlockOpenProxies || $wgRequest->getText( 'ip' ) != md5( $ip . $wgProxyKey ) ) { - $wgOut->addWikiMsg( 'proxyblocker-disabled' ); + $ip = $this->getRequest()->getIP(); + if( !$wgBlockOpenProxies || $this->getRequest()->getText( 'ip' ) != md5( $ip . $wgProxyKey ) ) { + $this->getOutput()->addWikiMsg( 'proxyblocker-disabled' ); return; } - $user = User::newFromName( wfMsgForContent( 'proxyblocker' ) ); + $user = User::newFromName( $this->msg( 'proxyblocker' )->inContentLanguage()->text() ); + # FIXME: newFromName could return false on a badly configured wiki. if ( !$user->isLoggedIn() ) { $user->addToDatabase(); } @@ -52,10 +53,10 @@ class SpecialBlockme extends UnlistedSpecialPage { $block = new Block(); $block->setTarget( $ip ); $block->setBlocker( $user ); - $block->mReason = wfMsg( 'proxyblockreason' ); + $block->mReason = $this->msg( 'proxyblockreason' )->inContentLanguage()->text(); $block->insert(); - $wgOut->addWikiMsg( 'proxyblocksuccess' ); + $this->getOutput()->addWikiMsg( 'proxyblocksuccess' ); } } diff --git a/includes/specials/SpecialBooksources.php b/includes/specials/SpecialBooksources.php index 20819329..48ca4f05 100644 --- a/includes/specials/SpecialBooksources.php +++ b/includes/specials/SpecialBooksources.php @@ -115,11 +115,11 @@ class SpecialBookSources extends SpecialPage { private function makeForm() { global $wgScript; - $form = '
' . wfMsgHtml( 'booksources-search-legend' ) . ''; + $form = '
' . $this->msg( 'booksources-search-legend' )->escaped() . ''; $form .= Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ); $form .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ); - $form .= '

' . Xml::inputLabel( wfMsg( 'booksources-isbn' ), 'isbn', 'isbn', 20, $this->isbn ); - $form .= ' ' . Xml::submitButton( wfMsg( 'booksources-go' ) ) . '

'; + $form .= '

' . Xml::inputLabel( $this->msg( 'booksources-isbn' )->text(), 'isbn', 'isbn', 20, $this->isbn ); + $form .= ' ' . Xml::submitButton( $this->msg( 'booksources-go' )->text() ) . '

'; $form .= Xml::closeElement( 'form' ); $form .= '
'; return $form; @@ -139,7 +139,8 @@ class SpecialBookSources extends SpecialPage { wfRunHooks( 'BookInformation', array( $this->isbn, $this->getOutput() ) ); # Check for a local page such as Project:Book_sources and use that if available - $title = Title::makeTitleSafe( NS_PROJECT, wfMsgForContent( 'booksources' ) ); # Show list in content language + $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 ); $this->getOutput()->addWikiText( str_replace( 'MAGICNUMBER', $this->isbn, $rev->getText() ) ); diff --git a/includes/specials/SpecialBrokenRedirects.php b/includes/specials/SpecialBrokenRedirects.php index 2330c896..b8dbe9e8 100644 --- a/includes/specials/SpecialBrokenRedirects.php +++ b/includes/specials/SpecialBrokenRedirects.php @@ -22,7 +22,7 @@ */ /** - * A special page listing redirects tonon existent page. Those should be + * A special page listing redirects to non existent page. Those should be * fixed to point to an existing page. * * @ingroup SpecialPage @@ -38,7 +38,7 @@ class BrokenRedirectsPage extends PageQueryPage { function sortDescending() { return false; } function getPageHeader() { - return wfMsgExt( 'brokenredirectstext', array( 'parse' ) ); + return $this->msg( 'brokenredirectstext' )->parseAsBlock(); } function getQueryInfo() { @@ -47,6 +47,7 @@ class BrokenRedirectsPage extends PageQueryPage { 'p2' => 'page' ), 'fields' => array( 'p1.page_namespace AS namespace', 'p1.page_title AS title', + 'p1.page_title AS value', 'rd_namespace', 'rd_title' ), @@ -77,8 +78,6 @@ class BrokenRedirectsPage extends PageQueryPage { * @return String */ function formatResult( $skin, $result ) { - global $wgUser, $wgLang; - $fromObj = Title::makeTitle( $result->namespace, $result->title ); if ( isset( $result->rd_title ) ) { $toObj = Title::makeTitle( $result->rd_namespace, $result->rd_title ); @@ -93,43 +92,43 @@ class BrokenRedirectsPage extends PageQueryPage { // $toObj may very easily be false if the $result list is cached if ( !is_object( $toObj ) ) { - return '' . $skin->link( $fromObj ) . ''; + return '' . Linker::link( $fromObj ) . ''; } - $from = $skin->linkKnown( + $from = Linker::linkKnown( $fromObj, null, array(), array( 'redirect' => 'no' ) ); $links = array(); - $links[] = $skin->linkKnown( + $links[] = Linker::linkKnown( $fromObj, - wfMsgHtml( 'brokenredirects-edit' ), + $this->msg( 'brokenredirects-edit' )->escaped(), array(), array( 'action' => 'edit' ) ); - $to = $skin->link( + $to = Linker::link( $toObj, null, array(), array(), array( 'broken' ) ); - $arr = $wgLang->getArrow(); + $arr = $this->getLanguage()->getArrow(); - $out = $from . wfMsg( 'word-separator' ); + $out = $from . $this->msg( 'word-separator' )->escaped(); - if( $wgUser->isAllowed( 'delete' ) ) { - $links[] = $skin->linkKnown( + if( $this->getUser()->isAllowed( 'delete' ) ) { + $links[] = Linker::linkKnown( $fromObj, - wfMsgHtml( 'brokenredirects-delete' ), + $this->msg( 'brokenredirects-delete' )->escaped(), array(), array( 'action' => 'delete' ) ); } - $out .= wfMsg( 'parentheses', $wgLang->pipeList( $links ) ); + $out .= $this->msg( 'parentheses' )->rawParams( $this->getLanguage()->pipeList( $links ) )->escaped(); $out .= " {$arr} {$to}"; return $out; } diff --git a/includes/specials/SpecialCategories.php b/includes/specials/SpecialCategories.php index 91d98b86..338cd706 100644 --- a/includes/specials/SpecialCategories.php +++ b/includes/specials/SpecialCategories.php @@ -31,20 +31,18 @@ class SpecialCategories extends SpecialPage { } function execute( $par ) { - global $wgOut, $wgRequest; - $this->setHeaders(); $this->outputHeader(); - $wgOut->allowClickjacking(); + $this->getOutput()->allowClickjacking(); - $from = $wgRequest->getText( 'from', $par ); + $from = $this->getRequest()->getText( 'from', $par ); - $cap = new CategoryPager( $from ); + $cap = new CategoryPager( $this->getContext(), $from ); $cap->doQuery(); - $wgOut->addHTML( + $this->getOutput()->addHTML( Html::openElement( 'div', array( 'class' => 'mw-spcontent' ) ) . - wfMsgExt( 'categoriespagetext', array( 'parse' ), $cap->getNumRows() ) . + $this->msg( 'categoriespagetext', $cap->getNumRows() )->parseAsBlock() . $cap->getStartForm( $from ) . $cap->getNavigationBar() . '' . @@ -61,12 +59,16 @@ class SpecialCategories extends SpecialPage { * @ingroup SpecialPage Pager */ class CategoryPager extends AlphabeticPager { - function __construct( $from ) { - parent::__construct(); + 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 ); - $this->mOffset = $from; + $dbr = wfGetDB( DB_SLAVE ); + $this->conds[] = 'cat_title >= ' . $dbr->addQuotes( $from ); + $this->setOffset( '' ); } } @@ -74,15 +76,11 @@ class CategoryPager extends AlphabeticPager { return array( 'tables' => array( 'category' ), 'fields' => array( 'cat_title','cat_pages' ), - 'conds' => array( 'cat_pages > 0' ), + 'conds' => $this->conds, 'options' => array( 'USE INDEX' => 'cat_title' ), ); } - function getTitle() { - return SpecialPage::getTitleFor( 'Categories' ); - } - function getIndexField() { # return array( 'abc' => 'cat_title', 'count' => 'cat_pages' ); return 'cat_title'; @@ -118,12 +116,10 @@ class CategoryPager extends AlphabeticPager { } function formatRow($result) { - global $wgLang; $title = Title::makeTitle( NS_CATEGORY, $result->cat_title ); $titleText = Linker::link( $title, htmlspecialchars( $title->getText() ) ); - $count = wfMsgExt( 'nmembers', array( 'parsemag', 'escape' ), - $wgLang->formatNum( $result->cat_pages ) ); - return Xml::tags('li', null, wfSpecialList( $titleText, $count ) ) . "\n"; + $count = $this->msg( 'nmembers' )->numParams( $result->cat_pages )->escaped(); + return Xml::tags( 'li', null, $this->getLanguage()->specialList( $titleText, $count ) ) . "\n"; } public function getStartForm( $from ) { @@ -132,10 +128,10 @@ class CategoryPager extends AlphabeticPager { return Xml::tags( 'form', array( 'method' => 'get', 'action' => $wgScript ), Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . - Xml::fieldset( wfMsg( 'categories' ), - Xml::inputLabel( wfMsg( 'categoriesfrom' ), + Xml::fieldset( $this->msg( 'categories' )->text(), + Xml::inputLabel( $this->msg( 'categoriesfrom' )->text(), 'from', 'from', 20, $from ) . ' ' . - Xml::submitButton( wfMsg( 'allpagessubmit' ) ) ) ); + Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) ) ); } } diff --git a/includes/specials/SpecialChangeEmail.php b/includes/specials/SpecialChangeEmail.php new file mode 100644 index 00000000..0f85f516 --- /dev/null +++ b/includes/specials/SpecialChangeEmail.php @@ -0,0 +1,213 @@ +allowPropChange( 'emailaddress' ); + } + + /** + * Main execution point + */ + function execute( $par ) { + global $wgAuth; + + $this->checkReadOnly(); + + $this->setHeaders(); + $this->outputHeader(); + + if ( !$wgAuth->allowPropChange( 'emailaddress' ) ) { + $this->error( 'cannotchangeemail' ); + return; + } + + $user = $this->getUser(); + $request = $this->getRequest(); + + if ( !$request->wasPosted() && !$user->isLoggedIn() ) { + $this->error( 'changeemail-no-info' ); + return; + } + + if ( $request->wasPosted() && $request->getBool( 'wpCancel' ) ) { + $this->doReturnTo(); + return; + } + + $out = $this->getOutput(); + $out->disallowUserJs(); + $out->addModules( 'mediawiki.special.changeemail' ); + + $this->mPassword = $request->getVal( 'wpPassword' ); + $this->mNewEmail = $request->getVal( 'wpNewEmail' ); + + if ( $request->wasPosted() + && $user->matchEditToken( $request->getVal( 'token' ) ) ) + { + $info = $this->attemptChange( $user, $this->mPassword, $this->mNewEmail ); + if ( $info === true ) { + $this->doReturnTo(); + } elseif ( $info === 'eauth' ) { + # Notify user that a confirmation email has been sent... + $out->wrapWikiMsg( "
\n$1\n
", + 'eauthentsent', $user->getName() ); + $this->doReturnTo( 'soft' ); // just show the link to go back + return; // skip form + } + } + + $this->showForm(); + } + + protected function doReturnTo( $type = 'hard' ) { + $titleObj = Title::newFromText( $this->getRequest()->getVal( 'returnto' ) ); + if ( !$titleObj instanceof Title ) { + $titleObj = Title::newMainPage(); + } + if ( $type == 'hard' ) { + $this->getOutput()->redirect( $titleObj->getFullURL() ); + } else { + $this->getOutput()->addReturnTo( $titleObj ); + } + } + + protected function error( $msg ) { + $this->getOutput()->wrapWikiMsg( "

\n$1\n

", $msg ); + } + + protected function showForm() { + $user = $this->getUser(); + + $oldEmailText = $user->getEmail() + ? $user->getEmail() + : $this->msg( 'changeemail-none' )->text(); + + $this->getOutput()->addHTML( + Xml::fieldset( $this->msg( 'changeemail-header' )->text() ) . + Xml::openElement( 'form', + array( + 'method' => 'post', + 'action' => $this->getTitle()->getLocalUrl(), + 'id' => 'mw-changeemail-form' ) ) . "\n" . + 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" . + "\n" . + "\n" . + '' . + Xml::submitButton( $this->msg( 'changeemail-submit' )->text() ) . + Xml::submitButton( $this->msg( 'changeemail-cancel' )->text(), array( 'name' => 'wpCancel' ) ) . + "\n" . + "\n" . + Xml::closeElement( 'table' ) . + Xml::closeElement( 'form' ) . + Xml::closeElement( 'fieldset' ) . "\n" + ); + } + + protected function pretty( $fields ) { + $out = ''; + foreach ( $fields as $list ) { + list( $name, $label, $type, $value ) = $list; + if( $type == 'text' ) { + $field = htmlspecialchars( $value ); + } else { + $attribs = array( 'id' => $name ); + if ( $name == 'wpPassword' ) { + $attribs[] = 'autofocus'; + } + $field = Html::input( $name, $value, $type, $attribs ); + } + $out .= "\n"; + $out .= "\t"; + if ( $type != 'text' ) { + $out .= Xml::label( $this->msg( $label )->text(), $name ); + } else { + $out .= $this->msg( $label )->escaped(); + } + $out .= "\n"; + $out .= "\t"; + $out .= $field; + $out .= "\n"; + $out .= ""; + } + return $out; + } + + /** + * @return bool|string true or string on success, false on failure + */ + protected function attemptChange( User $user, $pass, $newaddr ) { + if ( $newaddr != '' && !Sanitizer::validateEmail( $newaddr ) ) { + $this->error( 'invalidemailaddress' ); + return false; + } + + $throttleCount = LoginForm::incLoginThrottle( $user->getName() ); + if ( $throttleCount === true ) { + $this->error( 'login-throttled' ); + return false; + } + + if ( !$user->checkTemporaryPassword( $pass ) && !$user->checkPassword( $pass ) ) { + $this->error( 'wrongpassword' ); + return false; + } + + if ( $throttleCount ) { + LoginForm::clearLoginThrottle( $user->getName() ); + } + + list( $status, $info ) = Preferences::trySetUserEmail( $user, $newaddr ); + if ( $status !== true ) { + if ( $status instanceof Status ) { + $this->getOutput()->addHTML( + '

' . + $this->getOutput()->parseInline( $status->getWikiText( $info ) ) . + '

' ); + } + return false; + } + + $user->saveSettings(); + return $info ? $info : true; + } +} diff --git a/includes/specials/SpecialChangePassword.php b/includes/specials/SpecialChangePassword.php index 46562b36..f6482ef5 100644 --- a/includes/specials/SpecialChangePassword.php +++ b/includes/specials/SpecialChangePassword.php @@ -26,7 +26,7 @@ * * @ingroup SpecialPage */ -class SpecialChangePassword extends SpecialPage { +class SpecialChangePassword extends UnlistedSpecialPage { public function __construct() { parent::__construct( 'ChangePassword' ); } @@ -35,47 +35,46 @@ class SpecialChangePassword extends SpecialPage { * Main execution point */ function execute( $par ) { - global $wgUser, $wgAuth, $wgOut, $wgRequest; + global $wgAuth; - if ( wfReadOnly() ) { - $wgOut->readOnlyPage(); - return; - } + $this->checkReadOnly(); - $this->mUserName = $wgRequest->getVal( 'wpName' ); - $this->mOldpass = $wgRequest->getVal( 'wpPassword' ); - $this->mNewpass = $wgRequest->getVal( 'wpNewPassword' ); - $this->mRetype = $wgRequest->getVal( 'wpRetype' ); - $this->mDomain = $wgRequest->getVal( 'wpDomain' ); + $request = $this->getRequest(); + $this->mUserName = trim( $request->getVal( 'wpName' ) ); + $this->mOldpass = $request->getVal( 'wpPassword' ); + $this->mNewpass = $request->getVal( 'wpNewPassword' ); + $this->mRetype = $request->getVal( 'wpRetype' ); + $this->mDomain = $request->getVal( 'wpDomain' ); $this->setHeaders(); $this->outputHeader(); - $wgOut->disallowUserJs(); + $this->getOutput()->disallowUserJs(); - if( !$wgRequest->wasPosted() && !$wgUser->isLoggedIn() ) { - $this->error( wfMsg( 'resetpass-no-info' ) ); + $user = $this->getUser(); + if( !$request->wasPosted() && !$user->isLoggedIn() ) { + $this->error( $this->msg( 'resetpass-no-info' )->text() ); return; } - if( $wgRequest->wasPosted() && $wgRequest->getBool( 'wpCancel' ) ) { + if( $request->wasPosted() && $request->getBool( 'wpCancel' ) ) { $this->doReturnTo(); return; } - if( $wgRequest->wasPosted() && $wgUser->matchEditToken( $wgRequest->getVal( 'token' ) ) ) { + if( $request->wasPosted() && $user->matchEditToken( $request->getVal( 'token' ) ) ) { try { if ( isset( $_SESSION['wsDomain'] ) ) { $this->mDomain = $_SESSION['wsDomain']; } $wgAuth->setDomain( $this->mDomain ); if( !$wgAuth->allowPasswordChange() ) { - $this->error( wfMsg( 'resetpass_forbidden' ) ); + $this->error( $this->msg( 'resetpass_forbidden' )->text() ); return; } $this->attemptReset( $this->mNewpass, $this->mRetype ); - $wgOut->addWikiMsg( 'resetpass_success' ); - if( !$wgUser->isLoggedIn() ) { + $this->getOutput()->addWikiMsg( 'resetpass_success' ); + if( !$user->isLoggedIn() ) { LoginForm::setLoginToken(); $token = LoginForm::getLoginToken(); $data = array( @@ -84,12 +83,13 @@ class SpecialChangePassword extends SpecialPage { 'wpDomain' => $this->mDomain, 'wpLoginToken' => $token, 'wpPassword' => $this->mNewpass, - 'returnto' => $wgRequest->getVal( 'returnto' ), + 'returnto' => $request->getVal( 'returnto' ), ); - if( $wgRequest->getCheck( 'wpRemember' ) ) { + if( $request->getCheck( 'wpRemember' ) ) { $data['wpRemember'] = 1; } $login = new LoginForm( new FauxRequest( $data, true ) ); + $login->setContext( $this->getContext() ); $login->execute( null ); } $this->doReturnTo(); @@ -101,36 +101,33 @@ class SpecialChangePassword extends SpecialPage { } function doReturnTo() { - global $wgRequest, $wgOut; - $titleObj = Title::newFromText( $wgRequest->getVal( 'returnto' ) ); + $titleObj = Title::newFromText( $this->getRequest()->getVal( 'returnto' ) ); if ( !$titleObj instanceof Title ) { $titleObj = Title::newMainPage(); } - $wgOut->redirect( $titleObj->getFullURL() ); + $this->getOutput()->redirect( $titleObj->getFullURL() ); } function error( $msg ) { - global $wgOut; - $wgOut->addHTML( Xml::element('p', array( 'class' => 'error' ), $msg ) ); + $this->getOutput()->addHTML( Xml::element('p', array( 'class' => 'error' ), $msg ) ); } function showForm() { - global $wgOut, $wgUser, $wgRequest; + global $wgCookieExpiration; - $self = $this->getTitle(); + $user = $this->getUser(); if ( !$this->mUserName ) { - $this->mUserName = $wgUser->getName(); + $this->mUserName = $user->getName(); } $rememberMe = ''; - if ( !$wgUser->isLoggedIn() ) { - global $wgCookieExpiration, $wgLang; + if ( !$user->isLoggedIn() ) { $rememberMe = '' . '' . '' . Xml::checkLabel( - wfMsgExt( 'remembermypassword', 'parsemag', $wgLang->formatNum( ceil( $wgCookieExpiration / ( 3600 * 24 ) ) ) ), + $this->msg( 'remembermypassword' )->numParams( ceil( $wgCookieExpiration / ( 3600 * 24 ) ) )->text(), 'wpRemember', 'wpRemember', - $wgRequest->getCheck( 'wpRemember' ) ) . + $this->getRequest()->getCheck( 'wpRemember' ) ) . '' . ''; $submitMsg = 'resetpass_submit'; @@ -139,18 +136,18 @@ class SpecialChangePassword extends SpecialPage { $oldpassMsg = 'oldpassword'; $submitMsg = 'resetpass-submit-loggedin'; } - $wgOut->addHTML( - Xml::fieldset( wfMsg( 'resetpass_header' ) ) . + $this->getOutput()->addHTML( + Xml::fieldset( $this->msg( 'resetpass_header' )->text() ) . Xml::openElement( 'form', array( 'method' => 'post', - 'action' => $self->getLocalUrl(), + 'action' => $this->getTitle()->getLocalUrl(), 'id' => 'mw-resetpass-form' ) ) . "\n" . - Html::hidden( 'token', $wgUser->editToken() ) . "\n" . + Html::hidden( 'token', $user->getEditToken() ) . "\n" . Html::hidden( 'wpName', $this->mUserName ) . "\n" . Html::hidden( 'wpDomain', $this->mDomain ) . "\n" . - Html::hidden( 'returnto', $wgRequest->getVal( 'returnto' ) ) . "\n" . - wfMsgExt( 'resetpass_text', array( 'parse' ) ) . "\n" . + 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 ), @@ -162,8 +159,8 @@ class SpecialChangePassword extends SpecialPage { "\n" . "\n" . '' . - Xml::submitButton( wfMsg( $submitMsg ) ) . - Xml::submitButton( wfMsg( 'resetpass-submit-cancel' ), array( 'name' => 'wpCancel' ) ) . + Xml::submitButton( $this->msg( $submitMsg )->text() ) . + Xml::submitButton( $this->msg( 'resetpass-submit-cancel' )->text(), array( 'name' => 'wpCancel' ) ) . "\n" . "\n" . Xml::closeElement( 'table' ) . @@ -192,9 +189,9 @@ class SpecialChangePassword extends SpecialPage { $out .= "\n"; $out .= "\t"; if ( $type != 'text' ) - $out .= Xml::label( wfMsg( $label ), $name ); + $out .= Xml::label( $this->msg( $label )->text(), $name ); else - $out .= wfMsgHtml( $label ); + $out .= $this->msg( $label )->escaped(); $out .= "\n"; $out .= "\t"; $out .= $field; @@ -210,22 +207,22 @@ class SpecialChangePassword extends SpecialPage { protected function attemptReset( $newpass, $retype ) { $user = User::newFromName( $this->mUserName ); if( !$user || $user->isAnon() ) { - throw new PasswordError( wfMsg( 'nosuchusershort', $this->mUserName ) ); + throw new PasswordError( $this->msg( 'nosuchusershort', $this->mUserName )->text() ); } if( $newpass !== $retype ) { wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'badretype' ) ); - throw new PasswordError( wfMsg( 'badretype' ) ); + throw new PasswordError( $this->msg( 'badretype' )->text() ); } $throttleCount = LoginForm::incLoginThrottle( $this->mUserName ); if ( $throttleCount === true ) { - throw new PasswordError( wfMsg( 'login-throttled' ) ); + throw new PasswordError( $this->msg( 'login-throttled' )->text() ); } if( !$user->checkTemporaryPassword($this->mOldpass) && !$user->checkPassword($this->mOldpass) ) { wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'wrongpassword' ) ); - throw new PasswordError( wfMsg( 'resetpass-wrong-oldpass' ) ); + throw new PasswordError( $this->msg( 'resetpass-wrong-oldpass' )->text() ); } // Please reset throttle for successful logins, thanks! diff --git a/includes/specials/SpecialComparePages.php b/includes/specials/SpecialComparePages.php index 6b9ef0a9..9e3c52b9 100644 --- a/includes/specials/SpecialComparePages.php +++ b/includes/specials/SpecialComparePages.php @@ -57,6 +57,7 @@ class SpecialComparePages extends SpecialPage { 'label-message' => 'compare-page1', 'size' => '40', 'section' => 'page1', + 'validation-callback' => array( $this, 'checkExistingTitle' ), ), 'Revision1' => array( 'type' => 'int', @@ -64,6 +65,7 @@ class SpecialComparePages extends SpecialPage { 'label-message' => 'compare-rev1', 'size' => '8', 'section' => 'page1', + 'validation-callback' => array( $this, 'checkExistingRevision' ), ), 'Page2' => array( 'type' => 'text', @@ -71,6 +73,7 @@ class SpecialComparePages extends SpecialPage { 'label-message' => 'compare-page2', 'size' => '40', 'section' => 'page2', + 'validation-callback' => array( $this, 'checkExistingTitle' ), ), 'Revision2' => array( 'type' => 'int', @@ -78,6 +81,7 @@ class SpecialComparePages extends SpecialPage { 'label-message' => 'compare-rev2', 'size' => '8', 'section' => 'page2', + 'validation-callback' => array( $this, 'checkExistingRevision' ), ), 'Action' => array( 'type' => 'hidden', @@ -87,29 +91,33 @@ class SpecialComparePages extends SpecialPage { 'type' => 'hidden', 'name' => 'diffonly', ), - ), 'compare' ); - $form->setSubmitText( wfMsg( 'compare-submit' ) ); + 'Unhide' => array( + 'type' => 'hidden', + 'name' => 'unhide', + ), + ), $this->getContext(), 'compare' ); + $form->setSubmitTextMsg( 'compare-submit' ); $form->suppressReset(); $form->setMethod( 'get' ); - $form->setTitle( $this->getTitle() ); + $form->setSubmitCallback( array( __CLASS__, 'showDiff' ) ); $form->loadData(); $form->displayForm( '' ); - - self::showDiff( $form->mFieldData ); + $form->trySubmit(); } - public static function showDiff( $data ){ + public static function showDiff( $data, HTMLForm $form ){ $rev1 = self::revOrTitle( $data['Revision1'], $data['Page1'] ); $rev2 = self::revOrTitle( $data['Revision2'], $data['Page2'] ); if( $rev1 && $rev2 ) { - $de = new DifferenceEngine( null, + $de = new DifferenceEngine( $form->getContext(), $rev1, $rev2, null, // rcid - ( $data["Action"] == 'purge' ), - false ); + ( $data['Action'] == 'purge' ), + ( $data['Unhide'] == '1' ) + ); $de->showDiffPage( true ); } } @@ -125,4 +133,29 @@ class SpecialComparePages extends SpecialPage { } return null; } + + public function checkExistingTitle( $value, $alldata ) { + if ( $value === '' || $value === null ) { + return true; + } + $title = Title::newFromText( $value ); + if ( !$title instanceof Title ) { + return $this->msg( 'compare-invalid-title' )->parseAsBlock(); + } + if ( !$title->exists() ) { + return $this->msg( 'compare-title-not-exists' )->parseAsBlock(); + } + return true; + } + + public function checkExistingRevision( $value, $alldata ) { + if ( $value === '' || $value === null ) { + return true; + } + $revision = Revision::newFromId( $value ); + if ( $revision === null ) { + return $this->msg( 'compare-revision-not-exists' )->parseAsBlock(); + } + return true; + } } diff --git a/includes/specials/SpecialConfirmemail.php b/includes/specials/SpecialConfirmemail.php index 70bbfe39..912f7733 100644 --- a/includes/specials/SpecialConfirmemail.php +++ b/includes/specials/SpecialConfirmemail.php @@ -46,11 +46,9 @@ class EmailConfirmation extends UnlistedSpecialPage { function execute( $code ) { $this->setHeaders(); - if ( wfReadOnly() ) { - throw new ReadOnlyError; - } + $this->checkReadOnly(); - if( empty( $code ) ) { + if( $code === null || $code === '' ) { if( $this->getUser()->isLoggedIn() ) { if( Sanitizer::validateEmail( $this->getUser()->getEmail() ) ) { $this->showRequestForm(); @@ -60,11 +58,11 @@ class EmailConfirmation extends UnlistedSpecialPage { } else { $llink = Linker::linkKnown( SpecialPage::getTitleFor( 'Userlogin' ), - wfMsgHtml( 'loginreqlink' ), + $this->msg( 'loginreqlink' )->escaped(), array(), array( 'returnto' => $this->getTitle()->getPrefixedText() ) ); - $this->getOutput()->addHTML( wfMessage( 'confirmemail_needlogin' )->rawParams( $llink )->parse() ); + $this->getOutput()->addHTML( $this->msg( 'confirmemail_needlogin' )->rawParams( $llink )->parse() ); } } else { $this->attemptConfirm( $code ); @@ -89,9 +87,11 @@ class EmailConfirmation extends UnlistedSpecialPage { // date and time are separate parameters to facilitate localisation. // $time is kept for backward compat reasons. // 'emailauthenticated' is also used in SpecialPreferences.php - $time = $this->getLang()->timeAndDate( $user->mEmailAuthenticated, true ); - $d = $this->getLang()->date( $user->mEmailAuthenticated, true ); - $t = $this->getLang()->time( $user->mEmailAuthenticated, true ); + $lang = $this->getLanguage(); + $emailAuthenticated = $user->getEmailAuthenticationTimestamp(); + $time = $lang->userTimeAndDate( $emailAuthenticated, $user ); + $d = $lang->userDate( $emailAuthenticated, $user ); + $t = $lang->userTime( $emailAuthenticated, $user ); $out->addWikiMsg( 'emailauthenticated', $time, $d, $t ); } if( $user->isEmailConfirmationPending() ) { @@ -99,8 +99,8 @@ class EmailConfirmation extends UnlistedSpecialPage { } $out->addWikiMsg( 'confirmemail_text' ); $form = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalUrl() ) ); - $form .= Html::hidden( 'token', $user->editToken() ); - $form .= Xml::submitButton( wfMsg( 'confirmemail_send' ) ); + $form .= Html::hidden( 'token', $user->getEditToken() ); + $form .= Xml::submitButton( $this->msg( 'confirmemail_send' )->text() ); $form .= Xml::closeElement( 'form' ); $out->addHTML( $form ); } diff --git a/includes/specials/SpecialContributions.php b/includes/specials/SpecialContributions.php index fea27bfd..31df4a9b 100644 --- a/includes/specials/SpecialContributions.php +++ b/includes/specials/SpecialContributions.php @@ -36,86 +36,96 @@ class SpecialContributions extends SpecialPage { } public function execute( $par ) { - global $wgUser, $wgOut, $wgRequest; - $this->setHeaders(); $this->outputHeader(); - $wgOut->addModuleStyles( 'mediawiki.special' ); + $out = $this->getOutput(); + $out->addModuleStyles( 'mediawiki.special' ); $this->opts = array(); + $request = $this->getRequest(); - if( $par == 'newbies' ) { + if ( $par == 'newbies' ) { $target = 'newbies'; $this->opts['contribs'] = 'newbie'; - } elseif( isset( $par ) ) { + } elseif ( $par !== null ) { $target = $par; } else { - $target = $wgRequest->getVal( 'target' ); + $target = $request->getVal( 'target' ); } // check for radiobox - if( $wgRequest->getVal( 'contribs' ) == 'newbie' ) { + if ( $request->getVal( 'contribs' ) == 'newbie' ) { $target = 'newbies'; $this->opts['contribs'] = 'newbie'; + } else { + $this->opts['contribs'] = 'user'; } - $this->opts['deletedOnly'] = $wgRequest->getBool( 'deletedOnly' ); + $this->opts['deletedOnly'] = $request->getBool( 'deletedOnly' ); - if( !strlen( $target ) ) { - $wgOut->addHTML( $this->getForm() ); + if ( !strlen( $target ) ) { + $out->addHTML( $this->getForm() ); return; } - $this->opts['limit'] = $wgRequest->getInt( 'limit', $wgUser->getOption('rclimit') ); + $user = $this->getUser(); + + $this->opts['limit'] = $request->getInt( 'limit', $user->getOption( 'rclimit' ) ); $this->opts['target'] = $target; - $this->opts['topOnly'] = $wgRequest->getBool( 'topOnly' ); + $this->opts['topOnly'] = $request->getBool( 'topOnly' ); $nt = Title::makeTitleSafe( NS_USER, $target ); - if( !$nt ) { - $wgOut->addHTML( $this->getForm() ); + if ( !$nt ) { + $out->addHTML( $this->getForm() ); return; } - $id = User::idFromName( $nt->getText() ); + $userObj = User::newFromName( $nt->getText(), false ); + if ( !$userObj ) { + $out->addHTML( $this->getForm() ); + return; + } + $id = $userObj->getID(); - if( $target != 'newbies' ) { + if ( $this->opts['contribs'] != 'newbie' ) { $target = $nt->getText(); - $wgOut->setSubtitle( $this->contributionsSub( $nt, $id ) ); - $wgOut->setHTMLTitle( wfMsg( 'pagetitle', wfMsgExt( 'contributions-title', array( 'parsemag' ),$target ) ) ); - $user = User::newFromName( $target, false ); - if ( is_object( $user ) ) { - $this->getSkin()->setRelevantUser( $user ); - } + $out->addSubtitle( $this->contributionsSub( $userObj ) ); + $out->setHTMLTitle( $this->msg( 'pagetitle', $this->msg( 'contributions-title', $target )->plain() ) ); + $this->getSkin()->setRelevantUser( $userObj ); } else { - $wgOut->setSubtitle( wfMsgHtml( 'sp-contributions-newbies-sub') ); - $wgOut->setHTMLTitle( wfMsg( 'pagetitle', wfMsg( 'sp-contributions-newbies-title' ) ) ); + $out->addSubtitle( $this->msg( 'sp-contributions-newbies-sub' ) ); + $out->setHTMLTitle( $this->msg( 'pagetitle', $this->msg( 'sp-contributions-newbies-title' )->plain() ) ); } - if( ( $ns = $wgRequest->getVal( 'namespace', null ) ) !== null && $ns !== '' ) { + if ( ( $ns = $request->getVal( 'namespace', null ) ) !== null && $ns !== '' ) { $this->opts['namespace'] = intval( $ns ); } else { $this->opts['namespace'] = ''; } - $this->opts['tagFilter'] = (string) $wgRequest->getVal( 'tagFilter' ); + $this->opts['associated'] = $request->getBool( 'associated' ); + + $this->opts['nsInvert'] = (bool) $request->getVal( 'nsInvert' ); + + $this->opts['tagfilter'] = (string) $request->getVal( 'tagfilter' ); // Allows reverts to have the bot flag in recent changes. It is just here to // be passed in the form at the top of the page - if( $wgUser->isAllowed( 'markbotedits' ) && $wgRequest->getBool( 'bot' ) ) { + if ( $user->isAllowed( 'markbotedits' ) && $request->getBool( 'bot' ) ) { $this->opts['bot'] = '1'; } - $skip = $wgRequest->getText( 'offset' ) || $wgRequest->getText( 'dir' ) == 'prev'; + $skip = $request->getText( 'offset' ) || $request->getText( 'dir' ) == 'prev'; # Offset overrides year/month selection - if( $skip ) { + if ( $skip ) { $this->opts['year'] = ''; $this->opts['month'] = ''; } else { - $this->opts['year'] = $wgRequest->getIntOrNull( 'year' ); - $this->opts['month'] = $wgRequest->getIntOrNull( 'month' ); + $this->opts['year'] = $request->getIntOrNull( 'year' ); + $this->opts['month'] = $request->getIntOrNull( 'month' ); } - $feedType = $wgRequest->getVal( 'feed' ); - if( $feedType ) { + $feedType = $request->getVal( 'feed' ); + if ( $feedType ) { // Maintain some level of backwards compatability // If people request feeds using the old parameters, redirect to API $apiParams = array( @@ -129,8 +139,8 @@ class SpecialContributions extends SpecialPage { if ( $this->opts['deletedOnly'] ) { $apiParams['deletedonly'] = true; } - if ( $this->opts['tagFilter'] !== '' ) { - $apiParams['tagfilter'] = $this->opts['tagFilter']; + if ( $this->opts['tagfilter'] !== '' ) { + $apiParams['tagfilter'] = $this->opts['tagfilter']; } if ( $this->opts['namespace'] !== '' ) { $apiParams['namespace'] = $this->opts['namespace']; @@ -144,7 +154,7 @@ class SpecialContributions extends SpecialPage { $url = wfScript( 'api' ) . '?' . wfArrayToCGI( $apiParams ); - $wgOut->redirect( $url, '301' ); + $out->redirect( $url, '301' ); return; } @@ -153,47 +163,49 @@ class SpecialContributions extends SpecialPage { if ( wfRunHooks( 'SpecialContributionsBeforeMainOutput', array( $id ) ) ) { - $wgOut->addHTML( $this->getForm() ); + $out->addHTML( $this->getForm() ); - $pager = new ContribsPager( array( + $pager = new ContribsPager( $this->getContext(), array( 'target' => $target, + 'contribs' => $this->opts['contribs'], 'namespace' => $this->opts['namespace'], 'year' => $this->opts['year'], 'month' => $this->opts['month'], 'deletedOnly' => $this->opts['deletedOnly'], 'topOnly' => $this->opts['topOnly'], + 'nsInvert' => $this->opts['nsInvert'], + 'associated' => $this->opts['associated'], ) ); - if( !$pager->getNumRows() ) { - $wgOut->addWikiMsg( 'nocontribs', $target ); + if ( !$pager->getNumRows() ) { + $out->addWikiMsg( 'nocontribs', $target ); } else { # Show a message about slave lag, if applicable $lag = wfGetLB()->safeGetLag( $pager->getDatabase() ); - if( $lag > 0 ) - $wgOut->showLagWarning( $lag ); + if ( $lag > 0 ) + $out->showLagWarning( $lag ); - $wgOut->addHTML( + $out->addHTML( '

' . $pager->getNavigationBar() . '

' . $pager->getBody() . '

' . $pager->getNavigationBar() . '

' ); } - $wgOut->preventClickjacking( $pager->getPreventClickjacking() ); + $out->preventClickjacking( $pager->getPreventClickjacking() ); # Show the appropriate "footer" message - WHOIS tools, etc. - if( $target != 'newbies' ) { + if ( $this->opts['contribs'] != 'newbie' ) { $message = 'sp-contributions-footer'; if ( IP::isIPAddress( $target ) ) { $message = 'sp-contributions-footer-anon'; } else { - $user = User::newFromName( $target ); - if ( !$user || $user->isAnon() ) { + if ( $userObj->isAnon() ) { // No message for non-existing users return; } } - if( !wfMessage( $message, $target )->isDisabled() ) { - $wgOut->wrapWikiMsg( + if ( !$this->msg( $message, $target )->isDisabled() ) { + $out->wrapWikiMsg( "", array( $message, $target ) ); } @@ -203,33 +215,29 @@ class SpecialContributions extends SpecialPage { /** * Generates the subheading with links - * @param $nt Title object for the target - * @param $id Integer: User ID for the target + * @param $userObj User object for the target * @return String: appropriately-escaped HTML to be output literally * @todo FIXME: Almost the same as getSubTitle in SpecialDeletedContributions.php. Could be combined. */ - protected function contributionsSub( $nt, $id ) { - global $wgLang, $wgUser, $wgOut; - - $sk = $this->getSkin(); - - if ( $id === null ) { - $user = htmlspecialchars( $nt->getText() ); + protected function contributionsSub( $userObj ) { + if ( $userObj->isAnon() ) { + $user = htmlspecialchars( $userObj->getName() ); } else { - $user = $sk->link( $nt, htmlspecialchars( $nt->getText() ) ); + $user = Linker::link( $userObj->getUserPage(), htmlspecialchars( $userObj->getName() ) ); } - $userObj = User::newFromName( $nt->getText(), /* check for username validity not needed */ false ); - $talk = $nt->getTalkPage(); - if( $talk ) { - $tools = self::getUserLinks( $nt, $talk, $userObj, $wgUser ); - $links = $wgLang->pipeList( $tools ); + $nt = $userObj->getUserPage(); + $talk = $userObj->getTalkPage(); + 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() ) { + $out = $this->getOutput(); // showLogExtract() wants first parameter by reference LogEventsList::showLogExtract( - $wgOut, + $out, 'block', - $nt->getPrefixedText(), + $nt, '', array( 'lim' => 1, @@ -238,9 +246,9 @@ class SpecialContributions extends SpecialPage { $userObj->isAnon() ? 'sp-contributions-blocked-notice-anon' : 'sp-contributions-blocked-notice', - $nt->getText() # Support GENDER in 'sp-contributions-blocked-notice' + $userObj->getName() # Support GENDER in 'sp-contributions-blocked-notice' ), - 'offset' => '' # don't use $wgRequest parameter offset + 'offset' => '' # don't use WebRequest parameter offset ) ); } @@ -250,10 +258,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'. - if( wfEmptyMsg( 'contribsub' ) ) { - return wfMsgHtml( 'contribsub2', $user, $links ); + $oldMsg = $this->msg( 'contribsub' ); + if ( $oldMsg->exists() ) { + return $oldMsg->rawParams( "$user ($links)" ); } else { - return wfMsgHtml( 'contribsub', "$user ($links)" ); + return $this->msg( 'contribsub2' )->rawParams( $user, $links ); } } @@ -262,38 +271,37 @@ class SpecialContributions extends SpecialPage { * @param $userpage Title: Target user page * @param $talkpage Title: Talk page * @param $target User: Target user object - * @param $subject User: The viewing user ($wgUser is still checked in some cases, like userrights page!!) + * @return array */ - public static function getUserLinks( Title $userpage, Title $talkpage, User $target, User $subject ) { + public function getUserLinks( Title $userpage, Title $talkpage, User $target ) { - $sk = $subject->getSkin(); $id = $target->getId(); $username = $target->getName(); - $tools[] = $sk->link( $talkpage, wfMsgHtml( 'sp-contributions-talk' ) ); + $tools[] = Linker::link( $talkpage, $this->msg( 'sp-contributions-talk' )->escaped() ); - if( ( $id !== null ) || ( $id === null && IP::isIPAddress( $username ) ) ) { - if( $subject->isAllowed( 'block' ) ) { # Block / Change block / Unblock links + if ( ( $id !== null ) || ( $id === null && IP::isIPAddress( $username ) ) ) { + if ( $this->getUser()->isAllowed( 'block' ) ) { # Block / Change block / Unblock links if ( $target->isBlocked() ) { - $tools[] = $sk->linkKnown( # Change block link + $tools[] = Linker::linkKnown( # Change block link SpecialPage::getTitleFor( 'Block', $username ), - wfMsgHtml( 'change-blocklink' ) + $this->msg( 'change-blocklink' )->escaped() ); - $tools[] = $sk->linkKnown( # Unblock link + $tools[] = Linker::linkKnown( # Unblock link SpecialPage::getTitleFor( 'Unblock', $username ), - wfMsgHtml( 'unblocklink' ) + $this->msg( 'unblocklink' )->escaped() ); } else { # User is not blocked - $tools[] = $sk->linkKnown( # Block link + $tools[] = Linker::linkKnown( # Block link SpecialPage::getTitleFor( 'Block', $username ), - wfMsgHtml( 'blocklink' ) + $this->msg( 'blocklink' )->escaped() ); } } # Block log link - $tools[] = $sk->linkKnown( + $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Log', 'block' ), - wfMsgHtml( 'sp-contributions-blocklog' ), + $this->msg( 'sp-contributions-blocklog' )->escaped(), array(), array( 'page' => $userpage->getPrefixedText() @@ -301,31 +309,32 @@ class SpecialContributions extends SpecialPage { ); } # Uploads - $tools[] = $sk->linkKnown( + $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Listfiles', $username ), - wfMsgHtml( 'sp-contributions-uploads' ) + $this->msg( 'sp-contributions-uploads' )->escaped() ); # Other logs link - $tools[] = $sk->linkKnown( + $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Log', $username ), - wfMsgHtml( 'sp-contributions-logs' ) + $this->msg( 'sp-contributions-logs' )->escaped() ); # Add link to deleted user contributions for priviledged users - if( $subject->isAllowed( 'deletedhistory' ) ) { - $tools[] = $sk->linkKnown( + if ( $this->getUser()->isAllowed( 'deletedhistory' ) ) { + $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( 'DeletedContributions', $username ), - wfMsgHtml( 'sp-contributions-deleted' ) + $this->msg( 'sp-contributions-deleted' )->escaped() ); } # Add a link to change user rights for privileged users $userrightsPage = new UserrightsPage(); - if( $id !== null && $userrightsPage->userCanChangeRights( $target ) ) { - $tools[] = $sk->linkKnown( + $userrightsPage->setContext( $this->getContext() ); + if ( $id !== null && $userrightsPage->userCanChangeRights( $target ) ) { + $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Userrights', $username ), - wfMsgHtml( 'sp-contributions-userrights' ) + $this->msg( 'sp-contributions-userrights' )->escaped() ); } @@ -341,82 +350,185 @@ class SpecialContributions extends SpecialPage { global $wgScript; $this->opts['title'] = $this->getTitle()->getPrefixedText(); - if( !isset( $this->opts['target'] ) ) { + if ( !isset( $this->opts['target'] ) ) { $this->opts['target'] = ''; } else { $this->opts['target'] = str_replace( '_' , ' ' , $this->opts['target'] ); } - if( !isset( $this->opts['namespace'] ) ) { + if ( !isset( $this->opts['namespace'] ) ) { $this->opts['namespace'] = ''; } - if( !isset( $this->opts['contribs'] ) ) { + if ( !isset( $this->opts['nsInvert'] ) ) { + $this->opts['nsInvert'] = ''; + } + + if ( !isset( $this->opts['associated'] ) ) { + $this->opts['associated'] = false; + } + + if ( !isset( $this->opts['contribs'] ) ) { $this->opts['contribs'] = 'user'; } - if( !isset( $this->opts['year'] ) ) { + if ( !isset( $this->opts['year'] ) ) { $this->opts['year'] = ''; } - if( !isset( $this->opts['month'] ) ) { + if ( !isset( $this->opts['month'] ) ) { $this->opts['month'] = ''; } - if( $this->opts['contribs'] == 'newbie' ) { + if ( $this->opts['contribs'] == 'newbie' ) { $this->opts['target'] = ''; } - if( !isset( $this->opts['tagFilter'] ) ) { - $this->opts['tagFilter'] = ''; + if ( !isset( $this->opts['tagfilter'] ) ) { + $this->opts['tagfilter'] = ''; } - if( !isset( $this->opts['topOnly'] ) ) { + if ( !isset( $this->opts['topOnly'] ) ) { $this->opts['topOnly'] = false; } - $f = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'class' => 'mw-contributions-form' ) ); + $form = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'class' => 'mw-contributions-form' ) ); # Add hidden params for tracking except for parameters in $skipParameters - $skipParameters = array( 'namespace', 'deletedOnly', 'target', 'contribs', 'year', 'month', 'topOnly' ); + $skipParameters = array( 'namespace', 'nsInvert', 'deletedOnly', 'target', 'contribs', 'year', 'month', 'topOnly', 'associated' ); foreach ( $this->opts as $name => $value ) { - if( in_array( $name, $skipParameters ) ) { + if ( in_array( $name, $skipParameters ) ) { continue; } - $f .= "\t" . Html::hidden( $name, $value ) . "\n"; + $form .= "\t" . Html::hidden( $name, $value ) . "\n"; } - $tagFilter = ChangeTags::buildTagFilterSelector( $this->opts['tagFilter'] ); + $tagFilter = ChangeTags::buildTagFilterSelector( $this->opts['tagfilter'] ); - $f .= Xml::fieldset( wfMsg( 'sp-contributions-search' ) ) . - Xml::radioLabel( wfMsgExt( 'sp-contributions-newbies', array( 'parsemag' ) ), - 'contribs', 'newbie' , 'newbie', $this->opts['contribs'] == 'newbie' ) . '
' . - Xml::radioLabel( wfMsgExt( 'sp-contributions-username', array( 'parsemag' ) ), - 'contribs' , 'user', 'user', $this->opts['contribs'] == 'user' ) . ' ' . - Html::input( 'target', $this->opts['target'], 'text', array( - 'size' => '20', - 'required' => '' - ) + ( $this->opts['target'] ? array() : array( 'autofocus' ) ) ) . ' '. + if ( $tagFilter ) { + $filterSelection = + Xml::tags( 'td', array( 'class' => 'mw-label' ), array_shift( $tagFilter ) ) . + Xml::tags( 'td', array( 'class' => 'mw-input' ), implode( ' ', $tagFilter ) ); + } else { + $filterSelection = Xml::tags( 'td', array( 'colspan' => 2 ), '' ); + } + + $targetSelection = Xml::tags( 'td', array( 'colspan' => 2 ), + Xml::radioLabel( + $this->msg( 'sp-contributions-newbies' )->text(), + 'contribs', + 'newbie' , + 'newbie', + $this->opts['contribs'] == 'newbie', + array( 'class' => 'mw-input' ) + ) . '
' . + Xml::radioLabel( + $this->msg( 'sp-contributions-username' )->text(), + 'contribs', + 'user', + 'user', + $this->opts['contribs'] == 'user', + array( 'class' => 'mw-input' ) + ) . ' ' . + Html::input( + 'target', + $this->opts['target'], + 'text', + array( 'size' => '20', 'required' => '', 'class' => 'mw-input' ) + + ( $this->opts['target'] ? array() : array( 'autofocus' ) + ) + ) . ' ' + ) ; + + $namespaceSelection = + Xml::tags( 'td', array( 'class' => 'mw-label' ), + Xml::label( + $this->msg( 'namespace' )->text(), + 'namespace', + '' + ) + ) . + Xml::tags( 'td', null, + Xml::namespaceSelector( $this->opts['namespace'], '' ) . ' ' . + Html::rawElement( 'span', array( 'style' => 'white-space: nowrap' ), + Xml::checkLabel( + $this->msg( 'invert' )->text(), + 'nsInvert', + 'nsInvert', + $this->opts['nsInvert'], + array( 'title' => $this->msg( 'tooltip-invert' )->text(), 'class' => 'mw-input' ) + ) . ' ' + ) . + Html::rawElement( 'span', array( 'style' => 'white-space: nowrap' ), + Xml::checkLabel( + $this->msg( 'namespace_association' )->text(), + 'associated', + 'associated', + $this->opts['associated'], + array( 'title' => $this->msg( 'tooltip-namespace_association' )->text(), 'class' => 'mw-input' ) + ) . ' ' + ) + ) ; + + $extraOptions = Xml::tags( 'td', array( 'colspan' => 2 ), Html::rawElement( 'span', array( 'style' => 'white-space: nowrap' ), - Xml::label( wfMsg( 'namespace' ), 'namespace' ) . ' ' . - Xml::namespaceSelector( $this->opts['namespace'], '' ) + Xml::checkLabel( + $this->msg( 'history-show-deleted' )->text(), + 'deletedOnly', + 'mw-show-deleted-only', + $this->opts['deletedOnly'], + array( 'class' => 'mw-input' ) + ) ) . - Xml::checkLabel( wfMsg( 'history-show-deleted' ), - 'deletedOnly', 'mw-show-deleted-only', $this->opts['deletedOnly'] ) . '
' . - Xml::tags( 'p', null, Xml::checkLabel( wfMsg( 'sp-contributions-toponly' ), - 'topOnly', 'mw-show-top-only', $this->opts['topOnly'] ) ) . - ( $tagFilter ? Xml::tags( 'p', null, implode( ' ', $tagFilter ) ) : '' ) . - Html::rawElement( 'p', array( 'style' => 'white-space: nowrap' ), - Xml::dateMenu( $this->opts['year'], $this->opts['month'] ) . ' ' . - Xml::submitButton( wfMsg( 'sp-contributions-submit' ) ) - ) . ' '; - $explain = wfMessage( 'sp-contributions-explain' ); + Html::rawElement( 'span', array( 'style' => 'white-space: nowrap' ), + Xml::checkLabel( + $this->msg( 'sp-contributions-toponly' )->text(), + 'topOnly', + 'mw-show-top-only', + $this->opts['topOnly'], + array( 'class' => 'mw-input' ) + ) + ) + ) ; + + $dateSelectionAndSubmit = Xml::tags( 'td', array( 'colspan' => 2 ), + Xml::dateMenu( + $this->opts['year'], + $this->opts['month'] + ) . ' ' . + Xml::submitButton( + $this->msg( 'sp-contributions-submit' )->text(), + array( 'class' => 'mw-submit' ) + ) + ) ; + + $form .= + Xml::fieldset( $this->msg( 'sp-contributions-search' )->text() ) . + Xml::openElement( 'table', array( 'class' => 'mw-contributions-table' ) ) . + Xml::openElement( 'tr' ) . + $targetSelection . + Xml::closeElement( 'tr' ) . + Xml::openElement( 'tr' ) . + $namespaceSelection . + Xml::closeElement( 'tr' ) . + Xml::openElement( 'tr' ) . + $filterSelection . + Xml::closeElement( 'tr' ) . + Xml::openElement( 'tr' ) . + $extraOptions . + Xml::closeElement( 'tr' ) . + Xml::openElement( 'tr' ) . + $dateSelectionAndSubmit . + Xml::closeElement( 'tr' ) . + Xml::closeElement( 'table' ); + + $explain = $this->msg( 'sp-contributions-explain' ); if ( $explain->exists() ) { - $f .= "

{$explain}

"; + $form .= "

{$explain}

"; } - $f .= Xml::closeElement('fieldset' ) . + $form .= Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' ); - return $f; + return $form; } } @@ -430,18 +542,21 @@ class ContribsPager extends ReverseChronologicalPager { var $namespace = '', $mDb; var $preventClickjacking = false; - function __construct( $options ) { - parent::__construct(); + function __construct( IContextSource $context, array $options ) { + parent::__construct( $context ); $msgs = array( 'uctop', 'diff', 'newarticle', 'rollbacklink', 'diff', 'hist', 'rev-delundel', 'pipe-separator' ); - foreach( $msgs as $msg ) { - $this->messages[$msg] = wfMsgExt( $msg, array( 'escapenoentities' ) ); + foreach ( $msgs as $msg ) { + $this->messages[$msg] = $this->msg( $msg )->escaped(); } $this->target = isset( $options['target'] ) ? $options['target'] : ''; + $this->contribs = isset( $options['contribs'] ) ? $options['contribs'] : 'users'; $this->namespace = isset( $options['namespace'] ) ? $options['namespace'] : ''; - $this->tagFilter = isset( $options['tagFilter'] ) ? $options['tagFilter'] : false; + $this->tagFilter = isset( $options['tagfilter'] ) ? $options['tagfilter'] : false; + $this->nsInvert = isset( $options['nsInvert'] ) ? $options['nsInvert'] : false; + $this->associated = isset( $options['associated'] ) ? $options['associated'] : false; $this->deletedOnly = !empty( $options['deletedOnly'] ); $this->topOnly = !empty( $options['topOnly'] ); @@ -459,33 +574,35 @@ class ContribsPager extends ReverseChronologicalPager { return $query; } - function getTitle() { - return SpecialPage::getTitleFor( 'Contributions' ); - } - function getQueryInfo() { - global $wgUser; list( $tables, $index, $userCond, $join_cond ) = $this->getUserCond(); + $user = $this->getUser(); $conds = array_merge( $userCond, $this->getNamespaceCond() ); + // Paranoia: avoid brute force searches (bug 17342) - if( !$wgUser->isAllowed( 'deletedhistory' ) ) { - $conds[] = $this->mDb->bitAnd('rev_deleted',Revision::DELETED_USER) . ' = 0'; - } elseif( !$wgUser->isAllowed( 'suppressrevision' ) ) { - $conds[] = $this->mDb->bitAnd('rev_deleted',Revision::SUPPRESSED_USER) . + if ( !$user->isAllowed( 'deletedhistory' ) ) { + $conds[] = $this->mDb->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0'; + } elseif ( !$user->isAllowed( 'suppressrevision' ) ) { + $conds[] = $this->mDb->bitAnd( 'rev_deleted', Revision::SUPPRESSED_USER ) . ' != ' . Revision::SUPPRESSED_USER; } - $join_cond['page'] = array( 'INNER JOIN', 'page_id=rev_page' ); + + # Don't include orphaned revisions + $join_cond['page'] = Revision::pageJoinCond(); + # Get the current user name for accounts + $join_cond['user'] = Revision::userJoinCond(); $queryInfo = array( - 'tables' => $tables, - 'fields' => array( - 'page_namespace', 'page_title', 'page_is_new', 'page_latest', 'page_is_redirect', - 'page_len','rev_id', 'rev_page', 'rev_text_id', 'rev_timestamp', 'rev_comment', - 'rev_minor_edit', 'rev_user', 'rev_user_text', 'rev_parent_id', 'rev_deleted' + 'tables' => $tables, + 'fields' => array_merge( + Revision::selectFields(), + Revision::selectUserFields(), + array( 'page_namespace', 'page_title', 'page_is_new', + 'page_latest', 'page_is_redirect', 'page_len' ) ), - 'conds' => $conds, - 'options' => array( 'USE INDEX' => array('revision' => $index) ), + 'conds' => $conds, + 'options' => array( 'USE INDEX' => array( 'revision' => $index ) ), 'join_conds' => $join_cond ); @@ -505,31 +622,52 @@ class ContribsPager extends ReverseChronologicalPager { function getUserCond() { $condition = array(); $join_conds = array(); - if( $this->target == 'newbies' ) { - $tables = array( 'user_groups', 'page', 'revision' ); + $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[] = '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'" ); } else { - $tables = array( 'page', 'revision' ); - $condition['rev_user_text'] = $this->target; - $index = 'usertext_timestamp'; + if ( IP::isIPAddress( $this->target ) ) { + $condition['rev_user_text'] = $this->target; + $index = 'usertext_timestamp'; + } else { + $condition['rev_user'] = User::idFromName( $this->target ); + $index = 'user_timestamp'; + } } - if( $this->deletedOnly ) { + if ( $this->deletedOnly ) { $condition[] = "rev_deleted != '0'"; } - if( $this->topOnly ) { + if ( $this->topOnly ) { $condition[] = "rev_id = page_latest"; } return array( $tables, $index, $condition, $join_conds ); } function getNamespaceCond() { - if( $this->namespace !== '' ) { - return array( 'page_namespace' => (int)$this->namespace ); + if ( $this->namespace !== '' ) { + $selectedNS = $this->mDb->addQuotes( $this->namespace ); + $eq_op = $this->nsInvert ? '!=' : '='; + $bool_op = $this->nsInvert ? 'AND' : 'OR'; + + if ( !$this->associated ) { + return array( "page_namespace $eq_op $selectedNS" ); + } else { + $associatedNS = $this->mDb->addQuotes ( + MWNamespace::getAssociated( $this->namespace ) + ); + return array( + "page_namespace $eq_op $selectedNS " . + $bool_op . + " page_namespace $eq_op $associatedNS" + ); + } + } else { return array(); } @@ -539,10 +677,62 @@ class ContribsPager extends ReverseChronologicalPager { return 'rev_timestamp'; } + 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 ); + $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 ); + } + $batch->add( $row->page_namespace, $row->page_title ); + } + $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() { return "\n"; } @@ -558,15 +748,13 @@ class ContribsPager extends ReverseChronologicalPager { * @todo This would probably look a lot nicer in a table. */ function formatRow( $row ) { - global $wgUser, $wgLang; wfProfileIn( __METHOD__ ); - $sk = $this->getSkin(); $rev = new Revision( $row ); $classes = array(); $page = Title::newFromRow( $row ); - $link = $sk->link( + $link = Linker::link( $page, htmlspecialchars( $page->getPrefixedText() ), array(), @@ -574,19 +762,20 @@ class ContribsPager extends ReverseChronologicalPager { ); # Mark current revisions $topmarktext = ''; - if( $row->rev_id == $row->page_latest ) { + if ( $row->rev_id == $row->page_latest ) { $topmarktext .= '' . $this->messages['uctop'] . ''; # Add rollback link - if( !$row->page_is_new && $page->quickUserCan( 'rollback' ) + if ( !$row->page_is_new && $page->quickUserCan( 'rollback' ) && $page->quickUserCan( 'edit' ) ) { $this->preventClickjacking(); - $topmarktext .= ' '.$sk->generateRollback( $rev ); + $topmarktext .= ' ' . Linker::generateRollback( $rev ); } } + $user = $this->getUser(); # Is there a visible previous revision? - if( $rev->userCan( Revision::DELETED_TEXT ) && $rev->getParentId() !== 0 ) { - $difftext = $sk->linkKnown( + if ( $rev->userCan( Revision::DELETED_TEXT, $user ) && $rev->getParentId() !== 0 ) { + $difftext = Linker::linkKnown( $page, $this->messages['diff'], array(), @@ -598,77 +787,78 @@ class ContribsPager extends ReverseChronologicalPager { } else { $difftext = $this->messages['diff']; } - $histlink = $sk->linkKnown( + $histlink = Linker::linkKnown( $page, $this->messages['hist'], array(), array( 'action' => 'history' ) ); - $comment = $wgLang->getDirMark() . $sk->revComment( $rev, false, true ); - $date = $wgLang->timeanddate( wfTimestamp( TS_MW, $row->rev_timestamp ), true ); - if( $rev->userCan( Revision::DELETED_TEXT ) ) { - $d = $sk->linkKnown( + 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 ) . ' . . '; + } + + $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), + htmlspecialchars( $date ), array(), array( 'oldid' => intval( $row->rev_id ) ) ); } else { $d = htmlspecialchars( $date ); } - if( $rev->isDeleted( Revision::DELETED_TEXT ) ) { + if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) { $d = '' . $d . ''; } - if( $this->target == 'newbies' ) { - $userlink = ' . . ' . $sk->userLink( $row->rev_user, $row->rev_user_text ); - $userlink .= ' ' . wfMsg( 'parentheses', $sk->userTalkLink( $row->rev_user, $row->rev_user_text ) ) . ' '; + # 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 ) { + if ( $rev->getParentId() === 0 ) { $nflag = ChangesList::flag( 'newpage' ); } else { $nflag = ''; } - if( $rev->isMinor() ) { + if ( $rev->isMinor() ) { $mflag = ChangesList::flag( 'minor' ); } else { $mflag = ''; } - // Don't show useless link to people who cannot hide revisions - $canHide = $wgUser->isAllowed( 'deleterevision' ); - if( $canHide || ($rev->getVisibility() && $wgUser->isAllowed('deletedhistory')) ) { - if( !$rev->userCan( Revision::DELETED_RESTRICTED ) ) { - $del = $this->mSkin->revDeleteLinkDisabled( $canHide ); // revision was hidden from sysops - } else { - $query = array( - 'type' => 'revision', - 'target' => $page->getPrefixedDbkey(), - 'ids' => $rev->getId() - ); - $del = $this->mSkin->revDeleteLink( $query, - $rev->isDeleted( Revision::DELETED_RESTRICTED ), $canHide ); - } + $del = Linker::getRevDeleteLink( $user, $rev, $page ); + if ( $del !== '' ) { $del .= ' '; - } else { - $del = ''; } $diffHistLinks = '(' . $difftext . $this->messages['pipe-separator'] . $histlink . ')'; - $ret = "{$del}{$d} {$diffHistLinks} {$nflag}{$mflag} {$link}{$userlink} {$comment} {$topmarktext}"; + $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 .= " " . wfMsgHtml('rev-deleted-user-contribs') . ""; + if ( $rev->isDeleted( Revision::DELETED_USER ) ) { + $ret .= " " . $this->msg( 'rev-deleted-user-contribs' )->escaped() . ""; } # Tags, if any. - list($tagSummary, $newClasses) = ChangeTags::formatSummaryRow( $row->ts_tags, 'contributions' ); + list( $tagSummary, $newClasses ) = ChangeTags::formatSummaryRow( $row->ts_tags, 'contributions' ); $classes = array_merge( $classes, $newClasses ); $ret .= " $tagSummary"; diff --git a/includes/specials/SpecialDeadendpages.php b/includes/specials/SpecialDeadendpages.php index f8ef4d44..1266a0ce 100644 --- a/includes/specials/SpecialDeadendpages.php +++ b/includes/specials/SpecialDeadendpages.php @@ -33,7 +33,7 @@ class DeadendPagesPage extends PageQueryPage { } function getPageHeader() { - return wfMsgExt( 'deadendpagestext', array( 'parse' ) ); + return $this->msg( 'deadendpagestext' )->parseAsBlock(); } /** diff --git a/includes/specials/SpecialDeletedContributions.php b/includes/specials/SpecialDeletedContributions.php index 65858482..3498a16d 100644 --- a/includes/specials/SpecialDeletedContributions.php +++ b/includes/specials/SpecialDeletedContributions.php @@ -31,11 +31,11 @@ class DeletedContribsPager extends IndexPager { var $messages, $target; var $namespace = '', $mDb; - function __construct( $target, $namespace = false ) { - parent::__construct(); + function __construct( IContextSource $context, $target, $namespace = false ) { + parent::__construct( $context ); $msgs = array( 'deletionlog', 'undeleteviewlink', 'diff' ); foreach( $msgs as $msg ) { - $this->messages[$msg] = wfMsgExt( $msg, array( 'escapenoentities') ); + $this->messages[$msg] = $this->msg( $msg )->escaped(); } $this->target = $target; $this->namespace = $namespace; @@ -49,13 +49,13 @@ class DeletedContribsPager extends IndexPager { } function getQueryInfo() { - global $wgUser; list( $index, $userCond ) = $this->getUserCond(); $conds = array_merge( $userCond, $this->getNamespaceCond() ); + $user = $this->getUser(); // Paranoia: avoid brute force searches (bug 17792) - if( !$wgUser->isAllowed( 'deletedhistory' ) ) { + if( !$user->isAllowed( 'deletedhistory' ) ) { $conds[] = $this->mDb->bitAnd('ar_deleted',Revision::DELETED_USER) . ' = 0'; - } elseif( !$wgUser->isAllowed( 'suppressrevision' ) ) { + } elseif( !$user->isAllowed( 'suppressrevision' ) ) { $conds[] = $this->mDb->bitAnd('ar_deleted',Revision::SUPPRESSED_USER) . ' != ' . Revision::SUPPRESSED_USER; } @@ -92,25 +92,24 @@ class DeletedContribsPager extends IndexPager { } function getNavigationBar() { - global $wgLang; - if ( isset( $this->mNavigationBar ) ) { return $this->mNavigationBar; } - $fmtLimit = $wgLang->formatNum( $this->mLimit ); + $lang = $this->getLanguage(); + $fmtLimit = $lang->formatNum( $this->mLimit ); $linkTexts = array( - 'prev' => wfMsgExt( 'pager-newer-n', array( 'escape', 'parsemag' ), $fmtLimit ), - 'next' => wfMsgExt( 'pager-older-n', array( 'escape', 'parsemag' ), $fmtLimit ), - 'first' => wfMsgHtml( 'histlast' ), - 'last' => wfMsgHtml( 'histfirst' ) + 'prev' => $this->msg( 'pager-newer-n', $fmtLimit )->escaped(), + 'next' => $this->msg( 'pager-older-n', $fmtLimit )->escaped(), + 'first' => $this->msg( 'histlast' )->escaped(), + 'last' => $this->msg( 'histfirst' )->escaped() ); $pagingLinks = $this->getPagingLinks( $linkTexts ); $limitLinks = $this->getLimitLinks(); - $limits = $wgLang->pipeList( $limitLinks ); + $limits = $lang->pipeList( $limitLinks ); - $this->mNavigationBar = "(" . $wgLang->pipeList( array( $pagingLinks['first'], $pagingLinks['last'] ) ) . ") " . - wfMsgExt( 'viewprevnext', array( 'parsemag', 'escape', 'replaceafter' ), $pagingLinks['prev'], $pagingLinks['next'], $limits ); + $this->mNavigationBar = "(" . $lang->pipeList( array( $pagingLinks['first'], $pagingLinks['last'] ) ) . ") " . + $this->msg( 'viewprevnext' )->rawParams( $pagingLinks['prev'], $pagingLinks['next'], $limits )->escaped(); return $this->mNavigationBar; } @@ -133,11 +132,8 @@ class DeletedContribsPager extends IndexPager { * @todo This would probably look a lot nicer in a table. */ function formatRow( $row ) { - global $wgUser, $wgLang; wfProfileIn( __METHOD__ ); - $sk = $this->getSkin(); - $rev = new Revision( array( 'id' => $row->ar_rev_id, 'comment' => $row->ar_comment, @@ -153,7 +149,7 @@ class DeletedContribsPager extends IndexPager { $undelete = SpecialPage::getTitleFor( 'Undelete' ); $logs = SpecialPage::getTitleFor( 'Log' ); - $dellog = $sk->linkKnown( + $dellog = Linker::linkKnown( $logs, $this->messages['deletionlog'], array(), @@ -163,13 +159,15 @@ class DeletedContribsPager extends IndexPager { ) ); - $reviewlink = $sk->linkKnown( + $reviewlink = Linker::linkKnown( SpecialPage::getTitleFor( 'Undelete', $page->getPrefixedDBkey() ), $this->messages['undeleteviewlink'] ); - if( $wgUser->isAllowed('deletedtext') ) { - $last = $sk->linkKnown( + $user = $this->getUser(); + + if( $user->isAllowed('deletedtext') ) { + $last = Linker::linkKnown( $undelete, $this->messages['diff'], array(), @@ -183,13 +181,13 @@ class DeletedContribsPager extends IndexPager { $last = $this->messages['diff']; } - $comment = $sk->revComment( $rev ); - $date = htmlspecialchars( $wgLang->timeanddate( $rev->getTimestamp(), true ) ); + $comment = Linker::revComment( $rev ); + $date = htmlspecialchars( $this->getLanguage()->userTimeAndDate( $rev->getTimestamp(), $user ) ); - if( !$wgUser->isAllowed('undelete') || !$rev->userCan(Revision::DELETED_TEXT) ) { + if( !$user->isAllowed( 'undelete' ) || !$rev->userCan( Revision::DELETED_TEXT, $user ) ) { $link = $date; // unusable link } else { - $link = $sk->linkKnown( + $link = Linker::linkKnown( $undelete, $date, array(), @@ -204,7 +202,7 @@ class DeletedContribsPager extends IndexPager { $link = '' . $link . ''; } - $pagelink = $sk->link( $page ); + $pagelink = Linker::link( $page ); if( $rev->isMinor() ) { $mflag = ChangesList::flag( 'minor' ); @@ -213,33 +211,21 @@ class DeletedContribsPager extends IndexPager { } // Revision delete link - $canHide = $wgUser->isAllowed( 'deleterevision' ); - if( $canHide || ($rev->getVisibility() && $wgUser->isAllowed('deletedhistory')) ) { - if( !$rev->userCan( Revision::DELETED_RESTRICTED ) ) { - $del = $this->mSkin->revDeleteLinkDisabled( $canHide ); // revision was hidden from sysops - } else { - $query = array( - 'type' => 'archive', - 'target' => $page->getPrefixedDbkey(), - 'ids' => $rev->getTimestamp() ); - $del = $this->mSkin->revDeleteLink( $query, - $rev->isDeleted( Revision::DELETED_RESTRICTED ), $canHide ) . ' '; - } - } else { - $del = ''; - } + $del = Linker::getRevDeleteLink( $user, $rev, $page ); + if ( $del ) $del .= ' '; $tools = Html::rawElement( 'span', array( 'class' => 'mw-deletedcontribs-tools' ), - wfMsg( 'parentheses', $wgLang->pipeList( array( $last, $dellog, $reviewlink ) ) ) + $this->msg( 'parentheses' )->rawParams( $this->getLanguage()->pipeList( + array( $last, $dellog, $reviewlink ) ) )->escaped() ); $ret = "{$del}{$link} {$tools} . . {$mflag} {$pagelink} {$comment}"; # Denote if username is redacted for this edit if( $rev->isDeleted( Revision::DELETED_USER ) ) { - $ret .= " " . wfMsgHtml('rev-deleted-user-contribs') . ""; + $ret .= " " . $this->msg( 'rev-deleted-user-contribs' )->escaped() . ""; } $ret = Html::rawElement( 'li', array(), $ret ) . "\n"; @@ -272,64 +258,65 @@ class DeletedContributionsPage extends SpecialPage { * @param $par String: (optional) user name of the user for which to show the contributions */ function execute( $par ) { - global $wgUser; + global $wgQueryPageDefaultLimit; $this->setHeaders(); - if ( !$this->userCanExecute( $wgUser ) ) { + $user = $this->getUser(); + + if ( !$this->userCanExecute( $user ) ) { $this->displayRestrictionError(); return; } - global $wgOut, $wgRequest; - - $wgOut->setPageTitle( wfMsgExt( 'deletedcontributions-title', array( 'parsemag' ) ) ); + $request = $this->getRequest(); + $out = $this->getOutput(); + $out->setPageTitle( $this->msg( 'deletedcontributions-title' ) ); $options = array(); - if ( isset( $par ) ) { + if ( $par !== null ) { $target = $par; } else { - $target = $wgRequest->getVal( 'target' ); + $target = $request->getVal( 'target' ); } if ( !strlen( $target ) ) { - $wgOut->addHTML( $this->getForm( '' ) ); + $out->addHTML( $this->getForm( '' ) ); return; } - $options['limit'] = $wgRequest->getInt( 'limit', 50 ); + $options['limit'] = $request->getInt( 'limit', $wgQueryPageDefaultLimit ); $options['target'] = $target; - $nt = Title::makeTitleSafe( NS_USER, $target ); - if ( !$nt ) { - $wgOut->addHTML( $this->getForm( '' ) ); + $userObj = User::newFromName( $target, false ); + if ( !$userObj ) { + $out->addHTML( $this->getForm( '' ) ); return; } - $id = User::idFromName( $nt->getText() ); - $target = $nt->getText(); - $wgOut->setSubtitle( $this->getSubTitle( $nt, $id ) ); + $target = $userObj->getName(); + $out->addSubtitle( $this->getSubTitle( $userObj ) ); - if ( ( $ns = $wgRequest->getVal( 'namespace', null ) ) !== null && $ns !== '' ) { + if ( ( $ns = $request->getVal( 'namespace', null ) ) !== null && $ns !== '' ) { $options['namespace'] = intval( $ns ); } else { $options['namespace'] = ''; } - $wgOut->addHTML( $this->getForm( $options ) ); + $out->addHTML( $this->getForm( $options ) ); - $pager = new DeletedContribsPager( $target, $options['namespace'] ); + $pager = new DeletedContribsPager( $this->getContext(), $target, $options['namespace'] ); if ( !$pager->getNumRows() ) { - $wgOut->addWikiMsg( 'nocontribs' ); + $out->addWikiMsg( 'nocontribs' ); return; } # Show a message about slave lag, if applicable $lag = wfGetLB()->safeGetLag( $pager->getDatabase() ); if( $lag > 0 ) - $wgOut->showLagWarning( $lag ); + $out->showLagWarning( $lag ); - $wgOut->addHTML( + $out->addHTML( '

' . $pager->getNavigationBar() . '

' . $pager->getBody() . '

' . $pager->getNavigationBar() . '

' ); @@ -341,44 +328,40 @@ class DeletedContributionsPage extends SpecialPage { ? 'sp-contributions-footer-anon' : 'sp-contributions-footer'; - if( !wfMessage( $message )->isDisabled() ) { - $wgOut->wrapWikiMsg( "", array( $message, $target ) ); + if( !$this->msg( $message )->isDisabled() ) { + $out->wrapWikiMsg( "", array( $message, $target ) ); } } } /** * Generates the subheading with links - * @param $nt Title object for the target - * @param $id Integer: User ID for the target + * @param $userObj User object for the target * @return String: appropriately-escaped HTML to be output literally * @todo FIXME: Almost the same as contributionsSub in SpecialContributions.php. Could be combined. */ - function getSubTitle( $nt, $id ) { - global $wgLang, $wgUser, $wgOut; - - $sk = $this->getSkin(); - - if ( $id === null ) { - $user = htmlspecialchars( $nt->getText() ); + function getSubTitle( $userObj ) { + if ( $userObj->isAnon() ) { + $user = htmlspecialchars( $userObj->getName() ); } else { - $user = $sk->link( $nt, htmlspecialchars( $nt->getText() ) ); + $user = Linker::link( $userObj->getUserPage(), htmlspecialchars( $userObj->getName() ) ); } - $userObj = User::newFromName( $nt->getText(), /* check for username validity not needed */ false ); + $nt = $userObj->getUserPage(); + $id = $userObj->getID(); $talk = $nt->getTalkPage(); if( $talk ) { # Talk page link - $tools[] = $sk->link( $talk, wfMsgHtml( 'sp-contributions-talk' ) ); + $tools[] = Linker::link( $talk, $this->msg( 'sp-contributions-talk' )->escaped() ); if( ( $id !== null ) || ( $id === null && IP::isIPAddress( $nt->getText() ) ) ) { - if( $wgUser->isAllowed( 'block' ) ) { # Block / Change block / Unblock links + if( $this->getUser()->isAllowed( 'block' ) ) { # Block / Change block / Unblock links if ( $userObj->isBlocked() ) { - $tools[] = $sk->linkKnown( # Change block link + $tools[] = Linker::linkKnown( # Change block link SpecialPage::getTitleFor( 'Block', $nt->getDBkey() ), - wfMsgHtml( 'change-blocklink' ) + $this->msg( 'change-blocklink' )->escaped() ); - $tools[] = $sk->linkKnown( # Unblock link + $tools[] = Linker::linkKnown( # Unblock link SpecialPage::getTitleFor( 'BlockList' ), - wfMsgHtml( 'unblocklink' ), + $this->msg( 'unblocklink' )->escaped(), array(), array( 'action' => 'unblock', @@ -387,16 +370,16 @@ class DeletedContributionsPage extends SpecialPage { ); } else { # User is not blocked - $tools[] = $sk->linkKnown( # Block link + $tools[] = Linker::linkKnown( # Block link SpecialPage::getTitleFor( 'Block', $nt->getDBkey() ), - wfMsgHtml( 'blocklink' ) + $this->msg( 'blocklink' )->escaped() ); } } # Block log link - $tools[] = $sk->linkKnown( + $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Log' ), - wfMsgHtml( 'sp-contributions-blocklog' ), + $this->msg( 'sp-contributions-blocklog' )->escaped(), array(), array( 'type' => 'block', @@ -405,37 +388,39 @@ class DeletedContributionsPage extends SpecialPage { ); } # Other logs link - $tools[] = $sk->linkKnown( + $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Log' ), - wfMsgHtml( 'sp-contributions-logs' ), + $this->msg( 'sp-contributions-logs' )->escaped(), array(), array( 'user' => $nt->getText() ) ); # Link to contributions - $tools[] = $sk->linkKnown( + $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Contributions', $nt->getDBkey() ), - wfMsgHtml( 'sp-deletedcontributions-contribs' ) + $this->msg( 'sp-deletedcontributions-contribs' )->escaped() ); # 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 ) ) ) { - $tools[] = $sk->linkKnown( + $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Userrights', $nt->getDBkey() ), - wfMsgHtml( 'sp-contributions-userrights' ) + $this->msg( 'sp-contributions-userrights' )->escaped() ); } wfRunHooks( 'ContributionsToolLinks', array( $id, $nt, &$tools ) ); - $links = $wgLang->pipeList( $tools ); + $links = $this->getLanguage()->pipeList( $tools ); // Show a note if the user is blocked and display the last block log entry. if ( $userObj->isBlocked() ) { + $out = $this->getOutput(); // LogEventsList::showLogExtract() wants the first parameter by ref LogEventsList::showLogExtract( - $wgOut, + $out, 'block', - $nt->getPrefixedText(), + $nt, '', array( 'lim' => 1, @@ -444,7 +429,7 @@ class DeletedContributionsPage extends SpecialPage { 'sp-contributions-blocked-notice', $nt->getText() # Support GENDER in 'sp-contributions-blocked-notice' ), - 'offset' => '' # don't use $wgRequest parameter offset + 'offset' => '' # don't use $this->getRequest() parameter offset ) ); } @@ -454,10 +439,11 @@ class DeletedContributionsPage 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'. - if( wfEmptyMsg( 'contribsub' ) ) { - return wfMsgHtml( 'contribsub2', $user, $links ); + $oldMsg = $this->msg( 'contribsub' ); + if ( $oldMsg->exists() ) { + return $oldMsg->rawParams( "$user ($links)" ); } else { - return wfMsgHtml( 'contribsub', "$user ($links)" ); + return $this->msg( 'contribsub2' )->rawParams( $user, $links ); } } @@ -468,7 +454,7 @@ class DeletedContributionsPage extends SpecialPage { function getForm( $options ) { global $wgScript; - $options['title'] = SpecialPage::getTitleFor( 'DeletedContributions' )->getPrefixedText(); + $options['title'] = $this->getTitle()->getPrefixedText(); if ( !isset( $options['target'] ) ) { $options['target'] = ''; } else { @@ -497,15 +483,15 @@ class DeletedContributionsPage extends SpecialPage { } $f .= Xml::openElement( 'fieldset' ) . - Xml::element( 'legend', array(), wfMsg( 'sp-contributions-search' ) ) . - Xml::tags( 'label', array( 'for' => 'target' ), wfMsgExt( 'sp-contributions-username', 'parseinline' ) ) . ' ' . + Xml::element( 'legend', array(), $this->msg( 'sp-contributions-search' )->text() ) . + Xml::tags( 'label', array( 'for' => 'target' ), $this->msg( 'sp-contributions-username' )->parse() ) . ' ' . Html::input( 'target', $options['target'], 'text', array( 'size' => '20', 'required' => '' ) + ( $options['target'] ? array() : array( 'autofocus' ) ) ) . ' '. - Xml::label( wfMsg( 'namespace' ), 'namespace' ) . ' ' . + Xml::label( $this->msg( 'namespace' )->text(), 'namespace' ) . ' ' . Xml::namespaceSelector( $options['namespace'], '' ) . ' ' . - Xml::submitButton( wfMsg( 'sp-contributions-submit' ) ) . + Xml::submitButton( $this->msg( 'sp-contributions-submit' )->text() ) . Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' ); return $f; diff --git a/includes/specials/SpecialDisambiguations.php b/includes/specials/SpecialDisambiguations.php index 431dfe76..2b05fb6b 100644 --- a/includes/specials/SpecialDisambiguations.php +++ b/includes/specials/SpecialDisambiguations.php @@ -36,12 +36,12 @@ class DisambiguationsPage extends PageQueryPage { function isSyndicated() { return false; } function getPageHeader() { - return wfMsgExt( 'disambiguations-text', array( 'parse' ) ); + return $this->msg( 'disambiguations-text' )->parseAsBlock(); } function getQueryInfo() { $dbr = wfGetDB( DB_SLAVE ); - $dMsgText = wfMsgForContent( 'disambiguationspage' ); + $dMsgText = $this->msg( 'disambiguationspage' )->inContentLanguage()->text(); $linkBatch = new LinkBatch; # If the text can be treated as a title, use it verbatim. @@ -122,16 +122,14 @@ class DisambiguationsPage extends PageQueryPage { } function formatResult( $skin, $result ) { - global $wgLang; - $title = Title::newFromID( $result->value ); $dp = Title::makeTitle( $result->namespace, $result->title ); - $from = $skin->link( $title ); - $edit = $skin->link( $title, wfMsgExt( 'parentheses', array( 'escape' ), wfMsg( 'editlink' ) ) , + $from = Linker::link( $title ); + $edit = Linker::link( $title, $this->msg( 'parentheses', $this->msg( 'editlink' )->text() )->escaped(), array(), array( 'redirect' => 'no', 'action' => 'edit' ) ); - $arr = $wgLang->getArrow(); - $to = $skin->link( $dp ); + $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 ec899d8a..a6df66f6 100644 --- a/includes/specials/SpecialDoubleRedirects.php +++ b/includes/specials/SpecialDoubleRedirects.php @@ -38,7 +38,7 @@ class DoubleRedirectsPage extends PageQueryPage { function sortDescending() { return false; } function getPageHeader() { - return wfMsgExt( 'doubleredirectstext', array( 'parse' ) ); + return $this->msg( 'doubleredirectstext' )->parseAsBlock(); } function reallyGetQueryInfo( $namespace = null, $title = null ) { @@ -49,6 +49,7 @@ class DoubleRedirectsPage extends PageQueryPage { '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', @@ -76,8 +77,6 @@ class DoubleRedirectsPage extends PageQueryPage { } function formatResult( $skin, $result ) { - global $wgLang; - $titleA = Title::makeTitle( $result->namespace, $result->title ); if ( $result && !isset( $result->nsb ) ) { @@ -91,35 +90,40 @@ class DoubleRedirectsPage extends PageQueryPage { } } if ( !$result ) { - return '' . $skin->link( $titleA, null, array(), array( 'redirect' => 'no' ) ) . ''; + return '' . Linker::link( $titleA, null, array(), array( 'redirect' => 'no' ) ) . ''; } $titleB = Title::makeTitle( $result->nsb, $result->tb ); $titleC = Title::makeTitle( $result->nsc, $result->tc ); - $linkA = $skin->linkKnown( + $linkA = Linker::linkKnown( $titleA, null, array(), array( 'redirect' => 'no' ) ); - $edit = $skin->linkKnown( + + $edit = Linker::linkKnown( $titleA, - wfMsgExt( 'parentheses', array( 'escape' ), wfMsg( 'editlink' ) ), + $this->msg( 'parentheses', $this->msg( 'editlink' )->text() )->escaped(), array(), array( 'redirect' => 'no', 'action' => 'edit' ) ); - $linkB = $skin->linkKnown( + + $linkB = Linker::linkKnown( $titleB, null, array(), array( 'redirect' => 'no' ) ); - $linkC = $skin->linkKnown( $titleC ); - $arr = $wgLang->getArrow() . $wgLang->getDirMark(); + + $linkC = Linker::linkKnown( $titleC ); + + $lang = $this->getLanguage(); + $arr = $lang->getArrow() . $lang->getDirMark(); return( "{$linkA} {$edit} {$arr} {$linkB} {$arr} {$linkC}" ); } diff --git a/includes/specials/SpecialEditWatchlist.php b/includes/specials/SpecialEditWatchlist.php index bb2ecd80..9c9689ae 100644 --- a/includes/specials/SpecialEditWatchlist.php +++ b/includes/specials/SpecialEditWatchlist.php @@ -20,6 +20,8 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { protected $toc; + private $badItems = array(); + public function __construct(){ parent::__construct( 'EditWatchlist' ); } @@ -30,32 +32,29 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { * @param $mode int */ public function execute( $mode ) { - if( wfReadOnly() ) { - throw new ReadOnlyError; - } + $this->setHeaders(); $out = $this->getOutput(); # Anons don't get a watchlist if( $this->getUser()->isAnon() ) { - $out->setPageTitle( wfMsg( 'watchnologin' ) ); + $out->setPageTitle( $this->msg( 'watchnologin' ) ); $llink = Linker::linkKnown( SpecialPage::getTitleFor( 'Userlogin' ), - wfMsgHtml( 'loginreqlink' ), + $this->msg( 'loginreqlink' )->escaped(), array(), array( 'returnto' => $this->getTitle()->getPrefixedText() ) ); - $out->addHTML( wfMessage( 'watchlistanontext' )->rawParams( $llink )->parse() ); + $out->addHTML( $this->msg( 'watchlistanontext' )->rawParams( $llink )->parse() ); return; } - $sub = wfMsgExt( - 'watchlistfor2', - array( 'parseinline', 'replaceafter' ), - $this->getUser()->getName(), - SpecialEditWatchlist::buildTools( null ) - ); - $out->setSubtitle( $sub ); + $this->checkPermissions(); + + $this->outputHeader(); + + $out->addSubtitle( $this->msg( 'watchlistfor2', $this->getUser()->getName() + )->rawParams( SpecialEditWatchlist::buildTools( null ) ) ); # B/C: $mode used to be waaay down the parameter list, and the first parameter # was $wgUser @@ -73,7 +72,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { // Pass on to the raw editor, from which it's very easy to clear. case self::EDIT_RAW: - $out->setPageTitle( wfMsg( 'watchlistedit-raw-title' ) ); + $out->setPageTitle( $this->msg( 'watchlistedit-raw-title' ) ); $form = $this->getRawForm(); if( $form->show() ){ $out->addHTML( $this->successMessage ); @@ -83,7 +82,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { case self::EDIT_NORMAL: default: - $out->setPageTitle( wfMsg( 'watchlistedit-normal-title' ) ); + $out->setPageTitle( $this->msg( 'watchlistedit-normal-title' ) ); $form = $this->getNormalForm(); if( $form->show() ){ $out->addHTML( $this->successMessage ); @@ -132,33 +131,34 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { $this->getUser()->invalidateCache(); if( count( $toWatch ) > 0 || count( $toUnwatch ) > 0 ){ - $this->successMessage = wfMessage( 'watchlistedit-raw-done' )->parse(); + $this->successMessage = $this->msg( 'watchlistedit-raw-done' )->parse(); } else { return false; } if( count( $toWatch ) > 0 ) { - $this->successMessage .= wfMessage( - 'watchlistedit-raw-added', - $this->getLang()->formatNum( count( $toWatch ) ) - ); + $this->successMessage .= ' ' . $this->msg( 'watchlistedit-raw-added' + )->numParams( count( $toWatch ) )->parse(); $this->showTitles( $toWatch, $this->successMessage ); } if( count( $toUnwatch ) > 0 ) { - $this->successMessage .= wfMessage( - 'watchlistedit-raw-removed', - $this->getLang()->formatNum( count( $toUnwatch ) ) - ); + $this->successMessage .= ' ' . $this->msg( 'watchlistedit-raw-removed' + )->numParams( count( $toUnwatch ) )->parse(); $this->showTitles( $toUnwatch, $this->successMessage ); } } else { $this->clearWatchlist(); $this->getUser()->invalidateCache(); - $this->successMessage .= wfMessage( - 'watchlistedit-raw-removed', - $this->getLang()->formatNum( count( $current ) ) - ); + + if( count( $current ) > 0 ){ + $this->successMessage = $this->msg( 'watchlistedit-raw-done' )->parse(); + } else { + return false; + } + + $this->successMessage .= ' ' . $this->msg( 'watchlistedit-raw-removed' + )->numParams( count( $current ) )->parse(); $this->showTitles( $current, $this->successMessage ); } return true; @@ -174,7 +174,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { * @param $output String */ private function showTitles( $titles, &$output ) { - $talk = wfMsgHtml( 'talkpagelinktext' ); + $talk = $this->msg( 'talkpagelinktext' )->escaped(); // Do a batch existence check $batch = new LinkBatch(); foreach( $titles as $title ) { @@ -223,18 +223,21 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { if( $res->numRows() > 0 ) { foreach ( $res as $row ) { $title = Title::makeTitleSafe( $row->wl_namespace, $row->wl_title ); - if( $title instanceof Title && !$title->isTalkPage() ) + if ( $this->checkTitle( $title, $row->wl_namespace, $row->wl_title ) + && !$title->isTalkPage() + ) { $list[] = $title->getPrefixedText(); + } } $res->free(); } + $this->cleanupWatchlist(); return $list; } /** * Get a list of titles on a user's watchlist, excluding talk pages, - * and return as a two-dimensional array with namespace, title and - * redirect status + * and return as a two-dimensional array with namespace and title. * * @return array */ @@ -243,45 +246,79 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { $dbr = wfGetDB( DB_MASTER ); $res = $dbr->select( - array( 'watchlist', 'page' ), - array( - 'wl_namespace', - 'wl_title', - 'page_id', - 'page_len', - 'page_is_redirect', - 'page_latest' - ), + array( 'watchlist' ), + array( 'wl_namespace', 'wl_title' ), array( 'wl_user' => $this->getUser()->getId() ), __METHOD__, - array( 'ORDER BY' => 'wl_namespace, wl_title' ), - array( 'page' => array( - 'LEFT JOIN', - 'wl_namespace = page_namespace AND wl_title = page_title' - ) ) + array( 'ORDER BY' => 'wl_namespace, wl_title' ) ); - if( $res && $dbr->numRows( $res ) > 0 ) { - $cache = LinkCache::singleton(); - foreach ( $res as $row ) { - $title = Title::makeTitleSafe( $row->wl_namespace, $row->wl_title ); - if( $title instanceof Title ) { - // Update the link cache while we're at it - if( $row->page_id ) { - $cache->addGoodLinkObj( $row->page_id, $title, $row->page_len, $row->page_is_redirect, $row->page_latest ); - } else { - $cache->addBadLinkObj( $title ); - } - // Ignore non-talk - if( !$title->isTalkPage() ) { - $titles[$row->wl_namespace][$row->wl_title] = $row->page_is_redirect; - } - } + $lb = new LinkBatch(); + foreach ( $res as $row ) { + $lb->add( $row->wl_namespace, $row->wl_title ); + if ( !MWNamespace::isTalk( $row->wl_namespace ) ) { + $titles[$row->wl_namespace][$row->wl_title] = 1; } } + + $lb->execute(); return $titles; } + /** + * Validates watchlist entry + * + * @param Title $title + * @param int $namespace + * @param String $dbKey + * @return bool: Whether this item is valid + */ + private function checkTitle( $title, $namespace, $dbKey ) { + if ( $title + && ( $title->isExternal() + || $title->getNamespace() < 0 + ) + ) { + $title = false; // unrecoverable + } + if ( !$title + || $title->getNamespace() != $namespace + || $title->getDBkey() != $dbKey + ) { + $this->badItems[] = array( $title, $namespace, $dbKey ); + } + return (bool)$title; + } + + /** + * Attempts to clean up broken items + */ + private function cleanupWatchlist() { + if ( count( $this->badItems ) ) { + $dbw = wfGetDB( DB_MASTER ); + } + foreach ( $this->badItems as $row ) { + list( $title, $namespace, $dbKey ) = $row; + wfDebug( "User {$this->getUser()} has broken watchlist item ns($namespace):$dbKey, " + . ( $title ? 'cleaning up' : 'deleting' ) . ".\n" + ); + + $dbw->delete( 'watchlist', + array( + 'wl_user' => $this->getUser()->getId(), + 'wl_namespace' => $namespace, + 'wl_title' => $dbKey, + ), + __METHOD__ + ); + + // Can't just do an UPDATE instead of DELETE/INSERT due to unique index + if ( $title ) { + $this->getUser()->addWatch( $title ); + } + } + } + /** * Remove all titles from a user's watchlist */ @@ -360,8 +397,8 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { ), __METHOD__ ); - $article = new Article( $title, 0 ); - wfRunHooks( 'UnwatchArticleComplete', array( $this->getUser(), &$article ) ); + $page = WikiPage::factory( $title ); + wfRunHooks( 'UnwatchArticleComplete', array( $this->getUser(), &$page ) ); } } } @@ -375,10 +412,8 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { } if( count( $removed ) > 0 ) { - $this->successMessage = wfMessage( - 'watchlistedit-normal-done', - $this->getLang()->formatNum( count( $removed ) ) - ); + $this->successMessage = $this->msg( 'watchlistedit-normal-done' + )->numParams( count( $removed ) )->parse(); $this->showTitles( $removed, $this->successMessage ); return true; } else { @@ -397,40 +432,39 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { $fields = array(); $count = 0; - $haveInvalidNamespaces = false; foreach( $this->getWatchlistInfo() as $namespace => $pages ){ - if ( $namespace < 0 ) { - $haveInvalidNamespaces = true; - continue; + if ( $namespace >= 0 ) { + $fields['TitlesNs'.$namespace] = array( + 'class' => 'EditWatchlistCheckboxSeriesField', + 'options' => array(), + 'section' => "ns$namespace", + ); } - $fields['TitlesNs'.$namespace] = array( - 'class' => 'EditWatchlistCheckboxSeriesField', - 'options' => array(), - 'section' => "ns$namespace", - ); - - foreach( $pages as $dbkey => $redirect ){ + foreach( array_keys( $pages ) as $dbkey ){ $title = Title::makeTitleSafe( $namespace, $dbkey ); - $text = $this->buildRemoveLine( $title, $redirect ); - $fields['TitlesNs'.$namespace]['options'][$text] = $title->getEscapedText(); - $count++; + if ( $this->checkTitle( $title, $namespace, $dbkey ) ) { + $text = $this->buildRemoveLine( $title ); + $fields['TitlesNs'.$namespace]['options'][$text] = $title->getEscapedText(); + $count++; + } } } - if ( $haveInvalidNamespaces ) { - wfDebug( "User {$this->getContext()->getUser()->getId()} has invalid watchlist entries, clening up...\n" ); - $this->getContext()->getUser()->cleanupWatchlist(); - } + $this->cleanupWatchlist(); if ( count( $fields ) > 1 && $count > 30 ) { $this->toc = Linker::tocIndent(); $tocLength = 0; foreach( $fields as $key => $data ) { + + # strip out the 'ns' prefix from the section name: $ns = substr( $data['section'], 2 ); - $nsText = $ns == NS_MAIN - ? wfMsgHtml( 'blanknamespace' ) + + $nsText = ($ns == NS_MAIN) + ? $this->msg( 'blanknamespace' )->escaped() : htmlspecialchars( $wgContLang->getFormattedNsText( $ns ) ); - $this->toc .= Linker::tocLine( "editwatchlist-{$data['section']}", $nsText, ++$tocLength, 1 ) . Linker::tocLineEnd(); + $this->toc .= Linker::tocLine( "editwatchlist-{$data['section']}", $nsText, + $this->getLanguage()->formatNum( ++$tocLength ), 1 ) . Linker::tocLineEnd(); } $this->toc = Linker::tocList( $this->toc ); } else { @@ -439,9 +473,11 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { $form = new EditWatchlistNormalHTMLForm( $fields, $this->getContext() ); $form->setTitle( $this->getTitle() ); - $form->setSubmitText( wfMessage( 'watchlistedit-normal-submit' )->text() ); - $form->setWrapperLegend( wfMessage( 'watchlistedit-normal-legend' )->text() ); - $form->addHeaderText( wfMessage( 'watchlistedit-normal-explain' )->parse() ); + $form->setSubmitTextMsg( 'watchlistedit-normal-submit' ); + # Used message keys: 'accesskey-watchlistedit-normal-submit', 'tooltip-watchlistedit-normal-submit' + $form->setSubmitTooltip('watchlistedit-normal-submit'); + $form->setWrapperLegendMsg( 'watchlistedit-normal-legend' ); + $form->addHeaderText( $this->msg( 'watchlistedit-normal-explain' )->parse() ); $form->setSubmitCallback( array( $this, 'submitNormal' ) ); return $form; } @@ -450,19 +486,19 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { * Build the label for a checkbox, with a link to the title, and various additional bits * * @param $title Title - * @param $redirect bool * @return string */ - private function buildRemoveLine( $title, $redirect ) { + private function buildRemoveLine( $title ) { $link = Linker::link( $title ); - if( $redirect ) { + if( $title->isRedirect() ) { + // Linker already makes class mw-redirect, so this is redundant $link = '' . $link . ''; } - $tools[] = Linker::link( $title->getTalkPage(), wfMsgHtml( 'talkpagelinktext' ) ); + $tools[] = Linker::link( $title->getTalkPage(), $this->msg( 'talkpagelinktext' )->escaped() ); if( $title->exists() ) { $tools[] = Linker::linkKnown( $title, - wfMsgHtml( 'history_short' ), + $this->msg( 'history_short' )->escaped(), array(), array( 'action' => 'history' ) ); @@ -470,13 +506,13 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { if( $title->getNamespace() == NS_USER && !$title->isSubpage() ) { $tools[] = Linker::linkKnown( SpecialPage::getTitleFor( 'Contributions', $title->getText() ), - wfMsgHtml( 'contributions' ) + $this->msg( 'contributions' )->escaped() ); } - wfRunHooks( 'WatchlistEditorBuildRemoveLine', array( &$tools, $title, $redirect, $this->getSkin() ) ); + wfRunHooks( 'WatchlistEditorBuildRemoveLine', array( &$tools, $title, $title->isRedirect(), $this->getSkin() ) ); - return $link . " (" . $this->getLang()->pipeList( $tools ) . ")"; + return $link . " (" . $this->getLanguage()->pipeList( $tools ) . ")"; } /** @@ -493,11 +529,13 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { 'default' => $titles, ), ); - $form = new HTMLForm( $fields ); + $form = new HTMLForm( $fields, $this->getContext() ); $form->setTitle( $this->getTitle( 'raw' ) ); - $form->setSubmitText( wfMessage( 'watchlistedit-raw-submit' )->text() ); - $form->setWrapperLegend( wfMessage( 'watchlistedit-raw-legend' )->text() ); - $form->addHeaderText( wfMessage( 'watchlistedit-raw-explain' )->parse() ); + $form->setSubmitTextMsg( 'watchlistedit-raw-submit' ); + # Used message keys: 'accesskey-watchlistedit-raw-submit', 'tooltip-watchlistedit-raw-submit' + $form->setSubmitTooltip('watchlistedit-raw-submit'); + $form->setWrapperLegendMsg( 'watchlistedit-raw-legend' ); + $form->addHeaderText( $this->msg( 'watchlistedit-raw-explain' )->parse() ); $form->setSubmitCallback( array( $this, 'submitRaw' ) ); return $form; } @@ -569,8 +607,8 @@ class EditWatchlistNormalHTMLForm extends HTMLForm { public function getLegend( $namespace ){ $namespace = substr( $namespace, 2 ); return $namespace == NS_MAIN - ? wfMsgHtml( 'blanknamespace' ) - : htmlspecialchars( $this->getContext()->getLang()->getFormattedNsText( $namespace ) ); + ? $this->msg( 'blanknamespace' )->escaped() + : htmlspecialchars( $this->getContext()->getLanguage()->getFormattedNsText( $namespace ) ); } public function getBody() { return $this->displaySection( $this->mFieldTree, '', 'editwatchlist-' ); diff --git a/includes/specials/SpecialEmailuser.php b/includes/specials/SpecialEmailuser.php index 7c2ba570..314da727 100644 --- a/includes/specials/SpecialEmailuser.php +++ b/includes/specials/SpecialEmailuser.php @@ -34,14 +34,13 @@ class SpecialEmailUser extends UnlistedSpecialPage { } protected function getFormFields() { - global $wgUser; return array( 'From' => array( 'type' => 'info', 'raw' => 1, - 'default' => $this->getSkin()->link( - $wgUser->getUserPage(), - htmlspecialchars( $wgUser->getName() ) + 'default' => Linker::link( + $this->getUser()->getUserPage(), + htmlspecialchars( $this->getUser()->getName() ) ), 'label-message' => 'emailfrom', 'id' => 'mw-emailuser-sender', @@ -49,7 +48,7 @@ class SpecialEmailUser extends UnlistedSpecialPage { 'To' => array( 'type' => 'info', 'raw' => 1, - 'default' => $this->getSkin()->link( + 'default' => Linker::link( $this->mTargetObj->getUserPage(), htmlspecialchars( $this->mTargetObj->getName() ) ), @@ -62,7 +61,7 @@ class SpecialEmailUser extends UnlistedSpecialPage { ), 'Subject' => array( 'type' => 'text', - 'default' => wfMsgExt( 'defemailsubject', array( 'content', 'parsemag' ) ), + 'default' => wfMsgExt( 'defemailsubject', array( 'content', 'parsemag' ), $this->getUser()->getName() ), 'label-message' => 'emailsubject', 'maxlength' => 200, 'size' => 60, @@ -78,59 +77,53 @@ class SpecialEmailUser extends UnlistedSpecialPage { 'CCMe' => array( 'type' => 'check', 'label-message' => 'emailccme', - 'default' => $wgUser->getBoolOption( 'ccmeonemails' ), + 'default' => $this->getUser()->getBoolOption( 'ccmeonemails' ), ), ); } public function execute( $par ) { - global $wgRequest, $wgOut, $wgUser; - $this->setHeaders(); $this->outputHeader(); - $wgOut->addModuleStyles( 'mediawiki.special' ); + $out = $this->getOutput(); + $out->addModuleStyles( 'mediawiki.special' ); $this->mTarget = is_null( $par ) - ? $wgRequest->getVal( 'wpTarget', $wgRequest->getVal( 'target', '' ) ) + ? $this->getRequest()->getVal( 'wpTarget', $this->getRequest()->getVal( 'target', '' ) ) : $par; // error out if sending user cannot do this - $error = self::getPermissionsError( $wgUser, $wgRequest->getVal( 'wpEditToken' ) ); + $error = self::getPermissionsError( $this->getUser(), $this->getRequest()->getVal( 'wpEditToken' ) ); switch ( $error ) { case null: # Wahey! break; case 'badaccess': - $wgOut->permissionRequired( 'sendemail' ); - return; + throw new PermissionsError( 'sendemail' ); case 'blockedemailuser': - $wgOut->blockedPage(); - return; + throw new UserBlockedError( $this->getUser()->mBlock ); case 'actionthrottledtext': - $wgOut->rateLimited(); - return; + throw new ThrottledError; case 'mailnologin': case 'usermaildisabled': - $wgOut->showErrorPage( $error, "{$error}text" ); - return; + throw new ErrorPageError( $error, "{$error}text" ); default: # It's a hook error list( $title, $msg, $params ) = $error; - $wgOut->showErrorPage( $title, $msg, $params ); - return; + throw new ErrorPageError( $title, $msg, $params ); } // Got a valid target user name? Else ask for one. $ret = self::getTarget( $this->mTarget ); if( !$ret instanceof User ) { if( $this->mTarget != '' ) { $ret = ( $ret == 'notarget' ) ? 'emailnotarget' : ( $ret . 'text' ); - $wgOut->wrapWikiMsg( "

$1

", $ret ); + $out->wrapWikiMsg( "

$1

", $ret ); } - $wgOut->addHTML( self::userForm( $this->mTarget ) ); + $out->addHTML( $this->userForm( $this->mTarget ) ); return false; } $this->mTargetObj = $ret; - $form = new HTMLForm( $this->getFormFields() ); + $form = new HTMLForm( $this->getFormFields(), $this->getContext() ); $form->addPreText( wfMsgExt( 'emailpagetext', 'parseinline' ) ); $form->setSubmitText( wfMsg( 'emailsend' ) ); $form->setTitle( $this->getTitle() ); @@ -142,13 +135,13 @@ class SpecialEmailUser extends UnlistedSpecialPage { return false; } - $wgOut->setPageTitle( wfMsg( 'emailpage' ) ); + $out->setPageTitle( $this->msg( 'emailpage' ) ); $result = $form->show(); if( $result === true || ( $result instanceof Status && $result->isGood() ) ) { - $wgOut->setPageTitle( wfMsg( 'emailsent' ) ); - $wgOut->addWikiMsg( 'emailsenttext' ); - $wgOut->returnToMain( false, $this->mTargetObj->getUserPage() ); + $out->setPageTitle( $this->msg( 'emailsent' ) ); + $out->addWikiMsg( 'emailsenttext' ); + $out->returnToMain( false, $this->mTargetObj->getUserPage() ); } } @@ -226,17 +219,16 @@ class SpecialEmailUser extends UnlistedSpecialPage { * @param $name String: user name submitted. * @return String: form asking for user name. */ - - function userForm( $name ) { - global $wgScript ; + protected function userForm( $name ) { + global $wgScript; $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() ) . - Xml::closeElement( 'fieldset' ) . - Xml::closeElement( 'form' ) . "\n"; + 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() ) . + Xml::closeElement( 'fieldset' ) . + Xml::closeElement( 'form' ) . "\n"; return $string; } diff --git a/includes/specials/SpecialExport.php b/includes/specials/SpecialExport.php index 50754b6a..d061389e 100644 --- a/includes/specials/SpecialExport.php +++ b/includes/specials/SpecialExport.php @@ -38,9 +38,9 @@ class SpecialExport extends SpecialPage { } public function execute( $par ) { - global $wgOut, $wgRequest, $wgSitename, $wgExportAllowListContributors; + global $wgSitename, $wgExportAllowListContributors, $wgExportFromNamespaces; global $wgExportAllowHistory, $wgExportMaxHistory, $wgExportMaxLinkDepth; - global $wgExportFromNamespaces; + global $wgExportAllowAll; $this->setHeaders(); $this->outputHeader(); @@ -48,16 +48,18 @@ class SpecialExport extends SpecialPage { // Set some variables $this->curonly = true; $this->doExport = false; - $this->templates = $wgRequest->getCheck( 'templates' ); - $this->images = $wgRequest->getCheck( 'images' ); // Doesn't do anything yet + $request = $this->getRequest(); + $this->templates = $request->getCheck( 'templates' ); + $this->images = $request->getCheck( 'images' ); // Doesn't do anything yet $this->pageLinkDepth = $this->validateLinkDepth( - $wgRequest->getIntOrNull( 'pagelink-depth' ) + $request->getIntOrNull( 'pagelink-depth' ) ); $nsindex = ''; + $exportall = false; - if ( $wgRequest->getCheck( 'addcat' ) ) { - $page = $wgRequest->getText( 'pages' ); - $catname = $wgRequest->getText( 'catname' ); + if ( $request->getCheck( 'addcat' ) ) { + $page = $request->getText( 'pages' ); + $catname = $request->getText( 'catname' ); if ( $catname !== '' && $catname !== null && $catname !== false ) { $t = Title::makeTitleSafe( NS_MAIN, $catname ); @@ -74,9 +76,9 @@ class SpecialExport extends SpecialPage { } } } - elseif( $wgRequest->getCheck( 'addns' ) && $wgExportFromNamespaces ) { - $page = $wgRequest->getText( 'pages' ); - $nsindex = $wgRequest->getText( 'nsindex', '' ); + elseif( $request->getCheck( 'addns' ) && $wgExportFromNamespaces ) { + $page = $request->getText( 'pages' ); + $nsindex = $request->getText( 'nsindex', '' ); if ( strval( $nsindex ) !== '' ) { /** @@ -88,10 +90,14 @@ class SpecialExport extends SpecialPage { } } } - elseif( $wgRequest->wasPosted() && $par == '' ) { - $page = $wgRequest->getText( 'pages' ); - $this->curonly = $wgRequest->getCheck( 'curonly' ); - $rawOffset = $wgRequest->getVal( 'offset' ); + elseif( $request->getCheck( 'exportall' ) && $wgExportAllowAll ) { + $this->doExport = true; + $exportall = true; + } + elseif( $request->wasPosted() && $par == '' ) { + $page = $request->getText( 'pages' ); + $this->curonly = $request->getCheck( 'curonly' ); + $rawOffset = $request->getVal( 'offset' ); if( $rawOffset ) { $offset = wfTimestamp( TS_MW, $rawOffset ); @@ -99,14 +105,14 @@ class SpecialExport extends SpecialPage { $offset = null; } - $limit = $wgRequest->getInt( 'limit' ); - $dir = $wgRequest->getVal( 'dir' ); + $limit = $request->getInt( 'limit' ); + $dir = $request->getVal( 'dir' ); $history = array( 'dir' => 'asc', 'offset' => false, 'limit' => $wgExportMaxHistory, ); - $historyCheck = $wgRequest->getCheck( 'history' ); + $historyCheck = $request->getCheck( 'history' ); if ( $this->curonly ) { $history = WikiExporter::CURRENT; @@ -127,8 +133,8 @@ class SpecialExport extends SpecialPage { } } else { // Default to current-only for GET requests. - $page = $wgRequest->getText( 'pages', $par ); - $historyCheck = $wgRequest->getCheck( 'history' ); + $page = $request->getText( 'pages', $par ); + $historyCheck = $request->getCheck( 'history' ); if( $historyCheck ) { $history = WikiExporter::FULL; @@ -146,31 +152,32 @@ class SpecialExport extends SpecialPage { $history = WikiExporter::CURRENT; } - $list_authors = $wgRequest->getCheck( 'listauthors' ); + $list_authors = $request->getCheck( 'listauthors' ); if ( !$this->curonly || !$wgExportAllowListContributors ) { $list_authors = false ; } if ( $this->doExport ) { - $wgOut->disable(); + $this->getOutput()->disable(); // Cancel output buffering and gzipping if set // This should provide safer streaming for pages with history wfResetOutputBuffers(); - $wgRequest->response()->header( "Content-type: application/xml; charset=utf-8" ); + $request->response()->header( "Content-type: application/xml; charset=utf-8" ); - if( $wgRequest->getCheck( 'wpDownload' ) ) { + if( $request->getCheck( 'wpDownload' ) ) { // Provide a sane filename suggestion $filename = urlencode( $wgSitename . '-' . wfTimestampNow() . '.xml' ); - $wgRequest->response()->header( "Content-disposition: attachment;filename={$filename}" ); + $request->response()->header( "Content-disposition: attachment;filename={$filename}" ); } - $this->doExport( $page, $history, $list_authors ); + $this->doExport( $page, $history, $list_authors, $exportall ); return; } - $wgOut->addWikiMsg( 'exporttext' ); + $out = $this->getOutput(); + $out->addWikiMsg( 'exporttext' ); $form = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalUrl( 'action=submit' ) ) ); @@ -182,6 +189,15 @@ class SpecialExport extends SpecialPage { $form .= Xml::submitButton( wfMsg( 'export-addns' ), array( 'name' => 'addns' ) ) . '
'; } + if ( $wgExportAllowAll ) { + $form .= Xml::checkLabel( + wfMsg( 'exportall' ), + 'exportall', + 'exportall', + $request->wasPosted() ? $request->getCheck( 'exportall' ) : false + ) . '
'; + } + $form .= Xml::element( 'textarea', array( 'name' => 'pages', 'cols' => 40, 'rows' => 10 ), $page, false ); $form .= '
'; @@ -190,17 +206,17 @@ class SpecialExport extends SpecialPage { wfMsg( 'exportcuronly' ), 'curonly', 'curonly', - $wgRequest->wasPosted() ? $wgRequest->getCheck( 'curonly' ) : true + $request->wasPosted() ? $request->getCheck( 'curonly' ) : true ) . '
'; } else { - $wgOut->addHTML( wfMsgExt( 'exportnohistory', 'parse' ) ); + $out->addHTML( wfMsgExt( 'exportnohistory', 'parse' ) ); } $form .= Xml::checkLabel( wfMsg( 'export-templates' ), 'templates', 'wpExportTemplates', - $wgRequest->wasPosted() ? $wgRequest->getCheck( 'templates' ) : false + $request->wasPosted() ? $request->getCheck( 'templates' ) : false ) . '
'; if( $wgExportMaxLinkDepth || $this->userCanOverrideExportDepth() ) { @@ -212,18 +228,29 @@ class SpecialExport extends SpecialPage { wfMsg( 'export-download' ), 'wpDownload', 'wpDownload', - $wgRequest->wasPosted() ? $wgRequest->getCheck( 'wpDownload' ) : true + $request->wasPosted() ? $request->getCheck( 'wpDownload' ) : true ) . '
'; + if ( $wgExportAllowListContributors ) { + $form .= Xml::checkLabel( + wfMsg( 'exportlistauthors' ), + 'listauthors', + 'listauthors', + $request->wasPosted() ? $request->getCheck( 'listauthors' ) : false + ) . '
'; + } + $form .= Xml::submitButton( wfMsg( 'export-submit' ), Linker::tooltipAndAccesskeyAttribs( 'export' ) ); $form .= Xml::closeElement( 'form' ); - $wgOut->addHTML( $form ); + $out->addHTML( $form ); } + /** + * @return bool + */ private function userCanOverrideExportDepth() { - global $wgUser; - return $wgUser->isAllowed( 'override-export-depth' ); + return $this->getUser()->isAllowed( 'override-export-depth' ); } /** @@ -233,47 +260,55 @@ class SpecialExport extends SpecialPage { * @param $history Mixed: one of the WikiExporter history export constants * @param $list_authors Boolean: Whether to add distinct author list (when * not returning full history) + * @param $exportall Boolean: Whether to export everything */ - private function doExport( $page, $history, $list_authors ) { - $pageSet = array(); // Inverted index of all pages to look up - - // Split up and normalize input - foreach( explode( "\n", $page ) as $pageName ) { - $pageName = trim( $pageName ); - $title = Title::newFromText( $pageName ); - if( $title && $title->getInterwiki() == '' && $title->getText() !== '' ) { - // Only record each page once! - $pageSet[$title->getPrefixedText()] = true; + private function doExport( $page, $history, $list_authors, $exportall ) { + + // If we are grabbing everything, enable full history and ignore the rest + if ( $exportall ) { + $history = WikiExporter::FULL; + } else { + + $pageSet = array(); // Inverted index of all pages to look up + + // Split up and normalize input + foreach( explode( "\n", $page ) as $pageName ) { + $pageName = trim( $pageName ); + $title = Title::newFromText( $pageName ); + if( $title && $title->getInterwiki() == '' && $title->getText() !== '' ) { + // Only record each page once! + $pageSet[$title->getPrefixedText()] = true; + } } - } - // Set of original pages to pass on to further manipulation... - $inputPages = array_keys( $pageSet ); + // Set of original pages to pass on to further manipulation... + $inputPages = array_keys( $pageSet ); - // Look up any linked pages if asked... - if( $this->templates ) { - $pageSet = $this->getTemplates( $inputPages, $pageSet ); - } - $linkDepth = $this->pageLinkDepth; - if( $linkDepth ) { - $pageSet = $this->getPageLinks( $inputPages, $pageSet, $linkDepth ); - } + // Look up any linked pages if asked... + if( $this->templates ) { + $pageSet = $this->getTemplates( $inputPages, $pageSet ); + } + $linkDepth = $this->pageLinkDepth; + if( $linkDepth ) { + $pageSet = $this->getPageLinks( $inputPages, $pageSet, $linkDepth ); + } - /* - // Enable this when we can do something useful exporting/importing image information. :) - if( $this->images ) ) { - $pageSet = $this->getImages( $inputPages, $pageSet ); - } - */ + /* + // Enable this when we can do something useful exporting/importing image information. :) + if( $this->images ) ) { + $pageSet = $this->getImages( $inputPages, $pageSet ); + } + */ - $pages = array_keys( $pageSet ); + $pages = array_keys( $pageSet ); - // Normalize titles to the same format and remove dupes, see bug 17374 - foreach( $pages as $k => $v ) { - $pages[$k] = str_replace( " ", "_", $v ); - } + // Normalize titles to the same format and remove dupes, see bug 17374 + foreach( $pages as $k => $v ) { + $pages[$k] = str_replace( " ", "_", $v ); + } - $pages = array_unique( $pages ); + $pages = array_unique( $pages ); + } /* Ok, let's get to it... */ if( $history == WikiExporter::CURRENT ) { @@ -296,7 +331,10 @@ class SpecialExport extends SpecialPage { $exporter->list_authors = $list_authors; $exporter->openStream(); - foreach( $pages as $page ) { + if ( $exportall ) { + $exporter->allPages(); + } else { + foreach( $pages as $page ) { /* if( $wgExportMaxHistory && !$this->curonly ) { $title = Title::newFromText( $page ); @@ -310,15 +348,16 @@ class SpecialExport extends SpecialPage { } }*/ #Bug 8824: Only export pages the user can read - $title = Title::newFromText( $page ); - if( is_null( $title ) ) { - continue; #TODO: perhaps output an tag or something. - } - if( !$title->userCanRead() ) { - continue; #TODO: perhaps output an tag or something. - } + $title = Title::newFromText( $page ); + if( is_null( $title ) ) { + continue; #TODO: perhaps output an tag or something. + } + if( !$title->userCan( 'read', $this->getUser() ) ) { + continue; #TODO: perhaps output an tag or something. + } - $exporter->pageByTitle( $title ); + $exporter->pageByTitle( $title ); + } } $exporter->closeStream(); @@ -328,6 +367,10 @@ class SpecialExport extends SpecialPage { } } + /** + * @param $title Title + * @return array + */ private function getPagesFromCategory( $title ) { global $wgContLang; @@ -356,6 +399,10 @@ class SpecialExport extends SpecialPage { return $pages; } + /** + * @param $nsindex int + * @return array + */ private function getPagesFromNamespace( $nsindex ) { global $wgContLang; @@ -399,6 +446,8 @@ class SpecialExport extends SpecialPage { /** * Validate link depth setting, if available. + * @param $depth int + * @return int */ private function validateLinkDepth( $depth ) { global $wgExportMaxLinkDepth; @@ -421,7 +470,13 @@ class SpecialExport extends SpecialPage { return intval( min( $depth, 5 ) ); } - /** Expand a list of pages to include pages linked to from that page. */ + /** + * Expand a list of pages to include pages linked to from that page. + * @param $inputPages array + * @param $pageSet array + * @param $depth int + * @return array + */ private function getPageLinks( $inputPages, $pageSet, $depth ) { for( ; $depth > 0; --$depth ) { $pageSet = $this->getLinks( diff --git a/includes/specials/SpecialFewestrevisions.php b/includes/specials/SpecialFewestrevisions.php index 6d621a2e..27d17f63 100644 --- a/includes/specials/SpecialFewestrevisions.php +++ b/includes/specials/SpecialFewestrevisions.php @@ -70,30 +70,26 @@ class FewestrevisionsPage extends QueryPage { * @param $result Object: database row */ function formatResult( $skin, $result ) { - global $wgLang, $wgContLang; + global $wgContLang; $nt = Title::makeTitleSafe( $result->namespace, $result->title ); if( !$nt ) { return ''; } - $text = $wgContLang->convert( $nt->getPrefixedText() ); + $text = htmlspecialchars( $wgContLang->convert( $nt->getPrefixedText() ) ); + $plink = Linker::linkKnown( $nt, $text ); - $plink = $skin->linkKnown( - $nt, - $text - ); - - $nl = wfMsgExt( 'nrevisions', array( 'parsemag', 'escape' ), - $wgLang->formatNum( $result->value ) ); - $redirect = $result->redirect ? ' - ' . wfMsgHtml( 'isredirect' ) : ''; - $nlink = $skin->linkKnown( + $nl = $this->msg( 'nrevisions' )->numParams( $result->value )->escaped(); + $redirect = isset( $result->redirect ) && $result->redirect ? + ' - ' . wfMsgHtml( 'isredirect' ) : ''; + $nlink = Linker::linkKnown( $nt, $nl, array(), array( 'action' => 'history' ) ) . $redirect; - return wfSpecialList( $plink, $nlink ); + return $this->getLanguage()->specialList( $plink, $nlink ); } } diff --git a/includes/specials/SpecialFileDuplicateSearch.php b/includes/specials/SpecialFileDuplicateSearch.php index a296fd95..18d19db8 100644 --- a/includes/specials/SpecialFileDuplicateSearch.php +++ b/includes/specials/SpecialFileDuplicateSearch.php @@ -62,19 +62,16 @@ class FileDuplicateSearchPage extends QueryPage { * @param $dupes Array of File objects */ function showList( $dupes ) { - global $wgOut; - $skin = $this->getSkin(); - $html = array(); $html[] = $this->openList( 0 ); foreach ( $dupes as $dupe ) { - $line = $this->formatResult( $skin, $dupe ); + $line = $this->formatResult( null, $dupe ); $html[] = "
  • " . $line . "
  • "; } $html[] = $this->closeList(); - $wgOut->addHtml( implode( "\n", $html ) ); + $this->getOutput()->addHtml( implode( "\n", $html ) ); } function getQueryInfo() { @@ -91,12 +88,12 @@ class FileDuplicateSearchPage extends QueryPage { } function execute( $par ) { - global $wgRequest, $wgOut, $wgLang, $wgScript; + global $wgScript; $this->setHeaders(); $this->outputHeader(); - $this->filename = isset( $par ) ? $par : $wgRequest->getText( 'filename' ); + $this->filename = isset( $par ) ? $par : $this->getRequest()->getText( 'filename' ); $this->file = null; $this->hash = ''; $title = Title::newFromText( $this->filename, NS_FILE ); @@ -104,14 +101,16 @@ class FileDuplicateSearchPage extends QueryPage { $this->file = wfFindFile( $title ); } + $out = $this->getOutput(); + # Create the input form - $wgOut->addHTML( + $out->addHTML( Xml::openElement( 'form', array( 'id' => 'fileduplicatesearch', 'method' => 'get', 'action' => $wgScript ) ) . Html::hidden( 'title', $this->getTitle()->getPrefixedDbKey() ) . Xml::openElement( 'fieldset' ) . - Xml::element( 'legend', null, wfMsg( 'fileduplicatesearch-legend' ) ) . - Xml::inputLabel( wfMsg( 'fileduplicatesearch-filename' ), 'filename', 'filename', 50, $this->filename ) . ' ' . - Xml::submitButton( wfMsg( 'fileduplicatesearch-submit' ) ) . + Xml::element( 'legend', null, $this->msg( 'fileduplicatesearch-legend' )->text() ) . + Xml::inputLabel( $this->msg( 'fileduplicatesearch-filename' )->text(), 'filename', 'filename', 50, $this->filename ) . ' ' . + Xml::submitButton( $this->msg( 'fileduplicatesearch-submit' )->text() ) . Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' ) ); @@ -119,7 +118,7 @@ class FileDuplicateSearchPage extends QueryPage { if( $this->file ) { $this->hash = $this->file->getSha1(); } elseif( $this->filename !== '' ) { - $wgOut->wrapWikiMsg( + $out->wrapWikiMsg( "

    \n$1\n

    ", array( 'fileduplicatesearch-noresults', wfEscapeWikiText( $this->filename ) ) ); @@ -131,14 +130,12 @@ class FileDuplicateSearchPage extends QueryPage { if ( $img ) { $thumb = $img->transform( array( 'width' => 120, 'height' => 120 ) ); if( $thumb ) { - $wgOut->addHTML( '
    ' . + $out->addHTML( '
    ' . $thumb->toHtml( array( 'desc-link' => false ) ) . '
    ' . - wfMsgExt( 'fileduplicatesearch-info', array( 'parse' ), - $wgLang->formatNum( $img->getWidth() ), - $wgLang->formatNum( $img->getHeight() ), - $wgLang->formatSize( $img->getSize() ), - $img->getMimeType() - ) . + $this->msg( 'fileduplicatesearch-info' )->numParams( + $img->getWidth(), $img->getHeight() )->params( + $this->getLanguage()->formatSize( $img->getSize() ), + $img->getMimeType() )->parseAsBlock() . '
    ' ); } } @@ -148,15 +145,15 @@ class FileDuplicateSearchPage extends QueryPage { # Show a short summary if( $numRows == 1 ) { - $wgOut->wrapWikiMsg( + $out->wrapWikiMsg( "

    \n$1\n

    ", array( 'fileduplicatesearch-result-1', wfEscapeWikiText( $this->filename ) ) ); } elseif ( $numRows ) { - $wgOut->wrapWikiMsg( + $out->wrapWikiMsg( "

    \n$1\n

    ", array( 'fileduplicatesearch-result-n', wfEscapeWikiText( $this->filename ), - $wgLang->formatNum( $numRows - 1 ) ) + $this->getLanguage()->formatNum( $numRows - 1 ) ) ); } @@ -171,18 +168,18 @@ class FileDuplicateSearchPage extends QueryPage { * @return string */ function formatResult( $skin, $result ) { - global $wgContLang, $wgLang; + global $wgContLang; $nt = $result->getTitle(); $text = $wgContLang->convert( $nt->getText() ); - $plink = $skin->link( + $plink = Linker::link( Title::newFromText( $nt->getPrefixedText() ), $text ); $userText = $result->getUser( 'text' ); - $user = $skin->link( Title::makeTitle( NS_USER, $userText ), $userText ); - $time = $wgLang->timeanddate( $result->getTimestamp() ); + $user = Linker::link( Title::makeTitle( NS_USER, $userText ), $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 08f90fd2..101a33f4 100644 --- a/includes/specials/SpecialFilepath.php +++ b/includes/specials/SpecialFilepath.php @@ -33,12 +33,11 @@ class SpecialFilepath extends SpecialPage { } function execute( $par ) { - global $wgRequest, $wgOut; - $this->setHeaders(); $this->outputHeader(); - $file = !is_null( $par ) ? $par : $wgRequest->getText( 'file' ); + $request = $this->getRequest(); + $file = !is_null( $par ) ? $par : $request->getText( 'file' ); $title = Title::newFromText( $file, NS_FILE ); @@ -50,8 +49,8 @@ class SpecialFilepath extends SpecialPage { if ( $file && $file->exists() ) { // Default behaviour: Use the direct link to the file. $url = $file->getURL(); - $width = $wgRequest->getInt( 'width', -1 ); - $height = $wgRequest->getInt( 'height', -1 ); + $width = $request->getInt( 'width', -1 ); + $height = $request->getInt( 'height', -1 ); // If a width is requested... if ( $width != -1 ) { @@ -62,9 +61,9 @@ class SpecialFilepath extends SpecialPage { $url = $mto->getURL(); } } - $wgOut->redirect( $url ); + $this->getOutput()->redirect( $url ); } else { - $wgOut->setStatusCode( 404 ); + $this->getOutput()->setStatusCode( 404 ); $this->showForm( $title ); } } @@ -74,9 +73,9 @@ class SpecialFilepath extends SpecialPage { * @param $title Title */ function showForm( $title ) { - global $wgOut, $wgScript; + global $wgScript; - $wgOut->addHTML( + $this->getOutput()->addHTML( Html::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'specialfilepath' ) ) . Html::openElement( 'fieldset' ) . Html::element( 'legend', null, wfMsg( 'filepath' ) ) . diff --git a/includes/specials/SpecialImport.php b/includes/specials/SpecialImport.php index fc904a23..a2380fbe 100644 --- a/includes/specials/SpecialImport.php +++ b/includes/specials/SpecialImport.php @@ -52,18 +52,12 @@ class SpecialImport extends SpecialPage { * Execute */ function execute( $par ) { - global $wgRequest, $wgUser, $wgOut; - $this->setHeaders(); $this->outputHeader(); - if ( wfReadOnly() ) { - $wgOut->readOnlyPage(); - return; - } - - if( !$wgUser->isAllowedAny( 'import', 'importupload' ) ) { - return $wgOut->permissionRequired( 'import' ); + $user = $this->getUser(); + if ( !$user->isAllowedAny( 'import', 'importupload' ) ) { + throw new PermissionsError( 'import' ); } # @todo Allow Title::getUserPermissionsErrors() to take an array @@ -71,21 +65,23 @@ class SpecialImport extends SpecialPage { # getUserPermissionsErrors() might actually be used for, hence the 'ns-specialprotected' $errors = wfMergeErrorArrays( $this->getTitle()->getUserPermissionsErrors( - 'import', $wgUser, true, + 'import', $user, true, array( 'ns-specialprotected', 'badaccess-group0', 'badaccess-groups' ) ), $this->getTitle()->getUserPermissionsErrors( - 'importupload', $wgUser, true, + 'importupload', $user, true, array( 'ns-specialprotected', 'badaccess-group0', 'badaccess-groups' ) ) ); - if( $errors ){ - $wgOut->showPermissionsErrorPage( $errors ); - return; + if ( $errors ) { + throw new PermissionsError( 'import', $errors ); } - if ( $wgRequest->wasPosted() && $wgRequest->getVal( 'action' ) == 'submit' ) { + $this->checkReadOnly(); + + $request = $this->getRequest(); + if ( $request->wasPosted() && $request->getVal( 'action' ) == 'submit' ) { $this->doImport(); } $this->showForm(); @@ -95,34 +91,37 @@ class SpecialImport extends SpecialPage { * Do the actual import */ private function doImport() { - global $wgOut, $wgRequest, $wgUser, $wgImportSources, $wgExportMaxLinkDepth; + global $wgImportSources, $wgExportMaxLinkDepth; + $isUpload = false; - $this->namespace = $wgRequest->getIntOrNull( 'namespace' ); - $sourceName = $wgRequest->getVal( "source" ); + $request = $this->getRequest(); + $this->namespace = $request->getIntOrNull( 'namespace' ); + $sourceName = $request->getVal( "source" ); - $this->logcomment = $wgRequest->getText( 'log-comment' ); - $this->pageLinkDepth = $wgExportMaxLinkDepth == 0 ? 0 : $wgRequest->getIntOrNull( 'pagelink-depth' ); + $this->logcomment = $request->getText( 'log-comment' ); + $this->pageLinkDepth = $wgExportMaxLinkDepth == 0 ? 0 : $request->getIntOrNull( 'pagelink-depth' ); - if ( !$wgUser->matchEditToken( $wgRequest->getVal( 'editToken' ) ) ) { + $user = $this->getUser(); + if ( !$user->matchEditToken( $request->getVal( 'editToken' ) ) ) { $source = Status::newFatal( 'import-token-mismatch' ); } elseif ( $sourceName == 'upload' ) { $isUpload = true; - if( $wgUser->isAllowed( 'importupload' ) ) { + if( $user->isAllowed( 'importupload' ) ) { $source = ImportStreamSource::newFromUpload( "xmlimport" ); } else { - return $wgOut->permissionRequired( 'importupload' ); + throw new PermissionsError( 'importupload' ); } } elseif ( $sourceName == "interwiki" ) { - if( !$wgUser->isAllowed( 'import' ) ){ - return $wgOut->permissionRequired( 'import' ); + if( !$user->isAllowed( 'import' ) ){ + throw new PermissionsError( 'import' ); } - $this->interwiki = $wgRequest->getVal( 'interwiki' ); + $this->interwiki = $request->getVal( 'interwiki' ); if ( !in_array( $this->interwiki, $wgImportSources ) ) { $source = Status::newFatal( "import-invalid-interwiki" ); } else { - $this->history = $wgRequest->getCheck( 'interwikiHistory' ); - $this->frompage = $wgRequest->getText( "frompage" ); - $this->includeTemplates = $wgRequest->getCheck( 'interwikiTemplates' ); + $this->history = $request->getCheck( 'interwikiHistory' ); + $this->frompage = $request->getText( "frompage" ); + $this->includeTemplates = $request->getCheck( 'interwikiTemplates' ); $source = ImportStreamSource::newFromInterwiki( $this->interwiki, $this->frompage, @@ -134,16 +133,18 @@ class SpecialImport extends SpecialPage { $source = Status::newFatal( "importunknownsource" ); } + $out = $this->getOutput(); if( !$source->isGood() ) { - $wgOut->wrapWikiMsg( "

    \n$1\n

    ", array( 'importfailed', $source->getWikiText() ) ); + $out->wrapWikiMsg( "

    \n$1\n

    ", array( 'importfailed', $source->getWikiText() ) ); } else { - $wgOut->addWikiMsg( "importstart" ); + $out->addWikiMsg( "importstart" ); $importer = new WikiImporter( $source->value ); if( !is_null( $this->namespace ) ) { $importer->setTargetNamespace( $this->namespace ); } $reporter = new ImportReporter( $importer, $isUpload, $this->interwiki , $this->logcomment); + $reporter->setContext( $this->getContext() ); $exception = false; $reporter->open(); @@ -156,26 +157,28 @@ class SpecialImport extends SpecialPage { if ( $exception ) { # No source or XML parse error - $wgOut->wrapWikiMsg( "

    \n$1\n

    ", array( 'importfailed', $exception->getMessage() ) ); + $out->wrapWikiMsg( "

    \n$1\n

    ", array( 'importfailed', $exception->getMessage() ) ); } elseif( !$result->isGood() ) { # Zero revisions - $wgOut->wrapWikiMsg( "

    \n$1\n

    ", array( 'importfailed', $result->getWikiText() ) ); + $out->wrapWikiMsg( "

    \n$1\n

    ", array( 'importfailed', $result->getWikiText() ) ); } else { # Success! - $wgOut->addWikiMsg( 'importsuccess' ); + $out->addWikiMsg( 'importsuccess' ); } - $wgOut->addHTML( '
    ' ); + $out->addHTML( '
    ' ); } } private function showForm() { - global $wgUser, $wgOut, $wgImportSources, $wgExportMaxLinkDepth; + global $wgImportSources, $wgExportMaxLinkDepth; $action = $this->getTitle()->getLocalUrl( array( 'action' => 'submit' ) ); + $user = $this->getUser(); + $out = $this->getOutput(); - if( $wgUser->isAllowed( 'importupload' ) ) { - $wgOut->addWikiMsg( "importtext" ); - $wgOut->addHTML( + if( $user->isAllowed( 'importupload' ) ) { + $out->addWikiMsg( "importtext" ); + $out->addHTML( Xml::fieldset( wfMsg( 'import-upload' ) ). Xml::openElement( 'form', array( 'enctype' => 'multipart/form-data', 'method' => 'post', 'action' => $action, 'id' => 'mw-import-upload-form' ) ) . @@ -207,17 +210,17 @@ class SpecialImport extends SpecialPage { " " . Xml::closeElement( 'table' ). - Html::hidden( 'editToken', $wgUser->editToken() ) . + Html::hidden( 'editToken', $user->getEditToken() ) . Xml::closeElement( 'form' ) . Xml::closeElement( 'fieldset' ) ); } else { if( empty( $wgImportSources ) ) { - $wgOut->addWikiMsg( 'importnosources' ); + $out->addWikiMsg( 'importnosources' ); } } - if( $wgUser->isAllowed( 'import' ) && !empty( $wgImportSources ) ) { + if( $user->isAllowed( 'import' ) && !empty( $wgImportSources ) ) { # Show input field for import depth only if $wgExportMaxLinkDepth > 0 $importDepth = ''; if( $wgExportMaxLinkDepth > 0 ) { @@ -231,13 +234,13 @@ class SpecialImport extends SpecialPage { "; } - $wgOut->addHTML( + $out->addHTML( Xml::fieldset( wfMsg( 'importinterwiki' ) ) . Xml::openElement( 'form', array( 'method' => 'post', 'action' => $action, 'id' => 'mw-import-interwiki-form' ) ) . wfMsgExt( 'import-interwiki-text', array( 'parse' ) ) . Html::hidden( 'action', 'submit' ) . Html::hidden( 'source', 'interwiki' ) . - Html::hidden( 'editToken', $wgUser->editToken() ) . + Html::hidden( 'editToken', $user->getEditToken() ) . Xml::openElement( 'table', array( 'id' => 'mw-import-table' ) ) . " " . @@ -248,10 +251,10 @@ class SpecialImport extends SpecialPage { ); foreach( $wgImportSources as $prefix ) { $selected = ( $this->interwiki === $prefix ) ? ' selected="selected"' : ''; - $wgOut->addHTML( Xml::option( $prefix, $prefix, $selected ) ); + $out->addHTML( Xml::option( $prefix, $prefix, $selected ) ); } - $wgOut->addHTML( + $out->addHTML( Xml::closeElement( 'select' ) . Xml::input( 'frompage', 50, $this->frompage ) . " @@ -307,7 +310,7 @@ class SpecialImport extends SpecialPage { * Reporting callback * @ingroup SpecialPage */ -class ImportReporter { +class ImportReporter extends ContextSource { private $reason=false; private $mOriginalLogCallback = null; private $mOriginalPageOutCallback = null; @@ -318,6 +321,7 @@ class ImportReporter { $importer->setPageOutCallback( array( $this, 'reportPage' ) ); $this->mOriginalLogCallback = $importer->setLogItemCallback( array( $this, 'reportLogItem' ) ); + $importer->setNoticeCallback( array( $this, 'reportNotice' ) ); $this->mPageCount = 0; $this->mIsUpload = $upload; $this->mInterwiki = $interwiki; @@ -325,8 +329,11 @@ class ImportReporter { } function open() { - global $wgOut; - $wgOut->addHTML( "
      \n" ); + $this->getOutput()->addHTML( "
        \n" ); + } + + function reportNotice( $msg, array $params ) { + $this->getOutput()->addHTML( Html::element( 'li', array(), $this->msg( $msg, $params )->text() ) ); } function reportLogItem( /* ... */ ) { @@ -345,18 +352,23 @@ class ImportReporter { * @return void */ function reportPage( $title, $origTitle, $revisionCount, $successCount, $pageInfo ) { - global $wgOut, $wgUser, $wgLang, $wgContLang; + global $wgContLang; $args = func_get_args(); call_user_func_array( $this->mOriginalPageOutCallback, $args ); + if ( $title === null ) { + # Invalid or non-importable title; a notice is already displayed + return; + } + $this->mPageCount++; - $localCount = $wgLang->formatNum( $successCount ); + $localCount = $this->getLanguage()->formatNum( $successCount ); $contentCount = $wgContLang->formatNum( $successCount ); if( $successCount > 0 ) { - $wgOut->addHTML( "
      • " . Linker::linkKnown( $title ) . " " . + $this->getOutput()->addHTML( "
      • " . Linker::linkKnown( $title ) . " " . wfMsgExt( 'import-revision-count', array( 'parsemag', 'escape' ), $localCount ) . "
      • \n" ); @@ -384,29 +396,30 @@ class ImportReporter { $dbw = wfGetDB( DB_MASTER ); $latest = $title->getLatestRevID(); $nullRevision = Revision::newNullRevision( $dbw, $title->getArticleId(), $comment, true ); - $nullRevision->insertOn( $dbw ); - $article = new Article( $title ); - # Update page record - $article->updateRevisionOn( $dbw, $nullRevision ); - wfRunHooks( 'NewRevisionFromEditComplete', array($article, $nullRevision, $latest, $wgUser) ); + if (!is_null($nullRevision)) { + $nullRevision->insertOn( $dbw ); + $page = WikiPage::factory( $title ); + # Update page record + $page->updateRevisionOn( $dbw, $nullRevision ); + wfRunHooks( 'NewRevisionFromEditComplete', array( $page, $nullRevision, $latest, $this->getUser() ) ); + } } else { - $wgOut->addHTML( "
      • " . Linker::linkKnown( $title ) . " " . + $this->getOutput()->addHTML( "
      • " . Linker::linkKnown( $title ) . " " . wfMsgHtml( 'import-nonewrevisions' ) . "
      • \n" ); } } function close() { - global $wgOut, $wgLang; - + $out = $this->getOutput(); if ( $this->mLogItemCount > 0 ) { $msg = wfMsgExt( 'imported-log-entries', 'parseinline', - $wgLang->formatNum( $this->mLogItemCount ) ); - $wgOut->addHTML( Xml::tags( 'li', null, $msg ) ); + $this->getLanguage()->formatNum( $this->mLogItemCount ) ); + $out->addHTML( Xml::tags( 'li', null, $msg ) ); } elseif( $this->mPageCount == 0 && $this->mLogItemCount == 0 ) { - $wgOut->addHTML( "
      \n" ); + $out->addHTML( "
    \n" ); return Status::newFatal( 'importnopages' ); } - $wgOut->addHTML( "\n" ); + $out->addHTML( "\n" ); return Status::newGood( $this->mPageCount ); } diff --git a/includes/specials/SpecialJavaScriptTest.php b/includes/specials/SpecialJavaScriptTest.php new file mode 100644 index 00000000..d7e1655f --- /dev/null +++ b/includes/specials/SpecialJavaScriptTest.php @@ -0,0 +1,142 @@ + 'initQUnitTesting', + ); + + public function __construct() { + parent::__construct( 'JavaScriptTest' ); + } + + public function execute( $par ) { + global $wgEnableJavaScriptTest; + + $out = $this->getOutput(); + + $this->setHeaders(); + $out->disallowUserJs(); + + // Abort early if we're disabled + if ( $wgEnableJavaScriptTest !== true ) { + $out->addWikiMsg( 'javascripttest-disabled' ); + return; + } + + $out->addModules( 'mediawiki.special.javaScriptTest' ); + + // Determine framework + $pars = explode( '/', $par ); + $framework = strtolower( $pars[0] ); + + // No framework specified + if ( $par == '' ) { + $out->setPagetitle( wfMsgHtml( 'javascripttest' ) ); + $summary = $this->wrapSummaryHtml( + wfMsgHtml( 'javascripttest-pagetext-noframework' ) . $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() + ); + $this->{self::$frameworks[$framework]}(); + + // Framework not found, display error + } else { + $out->setPagetitle( wfMsgHtml( 'javascripttest' ) ); + $summary = $this->wrapSummaryHtml( '

    ' + . wfMsgHtml( 'javascripttest-pagetext-unknownframework', $par ) + . '

    ' + . $this->getFrameworkListHtml(), + 'unknownframework' + ); + $out->addHtml( $summary ); + } + } + + /** + * Get a list of frameworks (including introduction paragraph and links to the framework run pages) + * @return String: HTML + */ + private function getFrameworkListHtml() { + $list = '
      '; + foreach( self::$frameworks as $framework => $initFn ) { + $list .= Html::rawElement( + 'li', + array(), + Linker::link( $this->getTitle( $framework ), wfMsgHtml( "javascripttest-$framework-name" ) ) + ); + } + $list .= '
    '; + $msg = wfMessage( 'javascripttest-pagetext-frameworks' )->rawParams( $list )->parseAsBlock(); + + return $msg; + } + + /** + * Function to wrap the summary. + * It must be given a valid state as a second parameter or an exception will + * be thrown. + * @param $html String: The raw HTML. + * @param $state String: State, one of 'noframework', 'unknownframework' or 'frameworkfound' + */ + private function wrapSummaryHtml( $html, $state ) { + $validStates = array( 'noframework', 'unknownframework', 'frameworkfound' ); + if( !in_array( $state, $validStates ) ) { + throw new MWException( __METHOD__ + . ' given an invalid state. Must be one of "' + . join( '", "', $validStates) . '".' + ); + } + return "
    $html
    "; + } + + /** + * Initialize the page for QUnit. + */ + private function initQUnitTesting() { + global $wgJavaScriptTestConfig, $wgLang; + + $out = $this->getOutput(); + + $out->addModules( 'mediawiki.tests.qunit.testrunner' ); + $qunitTestModules = $out->getResourceLoader()->getTestModuleNames( 'qunit' ); + $out->addModules( $qunitTestModules ); + + $summary = wfMessage( 'javascripttest-qunit-intro' ) + ->params( $wgJavaScriptTestConfig['qunit']['documentation'] ) + ->parseAsBlock(); + $header = wfMessage( 'javascripttest-qunit-heading' )->escaped(); + $userDir = $wgLang->getDir(); + + $baseHtml = << +
    $header
    +
    +
    +
    +
      +
      test markup, will be hidden
      +
      +HTML; + $out->addHtml( $this->wrapSummaryHtml( $summary, 'frameworkfound' ) . $baseHtml ); + + } + + public function isListed(){ + global $wgEnableJavaScriptTest; + return $wgEnableJavaScriptTest === true; + } + +} diff --git a/includes/specials/SpecialLinkSearch.php b/includes/specials/SpecialLinkSearch.php index 53db6f87..d3ab2f04 100644 --- a/includes/specials/SpecialLinkSearch.php +++ b/includes/specials/SpecialLinkSearch.php @@ -56,7 +56,6 @@ class LinkSearchPage extends QueryPage { $namespace = $request->getIntorNull( 'namespace', null ); $protocols_list = array(); - foreach( $wgUrlProtocols as $prot ) { if ( $prot !== '//' ) { $protocols_list[] = $prot; @@ -85,8 +84,7 @@ class LinkSearchPage extends QueryPage { $protocol = ''; } - $out->addWikiMsg( 'linksearch-text', '' . $this->getLang()->commaList( $wgUrlProtocols ) . '' ); - + $out->addWikiMsg( 'linksearch-text', '' . $this->getLanguage()->commaList( $protocols_list ) . '' ); $s = Xml::openElement( 'form', array( 'id' => 'mw-linksearch-form', 'method' => 'get', 'action' => $GLOBALS['wgScript'] ) ) . Html::hidden( 'title', $this->getTitle()->getPrefixedDbKey() ) . '
      ' . diff --git a/includes/specials/SpecialListfiles.php b/includes/specials/SpecialListfiles.php index 427de167..b5754991 100644 --- a/includes/specials/SpecialListfiles.php +++ b/includes/specials/SpecialListfiles.php @@ -28,7 +28,6 @@ class SpecialListFiles extends IncludableSpecialPage { } public function execute( $par ){ - global $wgOut, $wgRequest; $this->setHeaders(); $this->outputHeader(); @@ -36,11 +35,11 @@ class SpecialListFiles extends IncludableSpecialPage { $userName = $par; $search = ''; } else { - $userName = $wgRequest->getText( 'user', $par ); - $search = $wgRequest->getText( 'ilsearch', '' ); + $userName = $this->getRequest()->getText( 'user', $par ); + $search = $this->getRequest()->getText( 'ilsearch', '' ); } - $pager = new ImageListPager( $userName, $search, $this->including() ); + $pager = new ImageListPager( $this->getContext(), $userName, $search, $this->including() ); if ( $this->including() ) { $html = $pager->getBody(); @@ -50,7 +49,7 @@ class SpecialListFiles extends IncludableSpecialPage { $nav = $pager->getNavigationBar(); $html = "$form
      \n$body
      \n$nav"; } - $wgOut->addHTML( $html ); + $this->getOutput()->addHTML( $html ); } } @@ -64,8 +63,8 @@ class ImageListPager extends TablePager { var $mSearch = ''; var $mIncluding = false; - function __construct( $userName = null, $search = '', $including = false ) { - global $wgRequest, $wgMiserMode; + function __construct( IContextSource $context, $userName = null, $search = '', $including = false ) { + global $wgMiserMode; $this->mIncluding = $including; @@ -89,7 +88,7 @@ class ImageListPager extends TablePager { } if ( !$including ) { - if ( $wgRequest->getText( 'sort', 'img_date' ) == 'img_date' ) { + if ( $context->getRequest()->getText( 'sort', 'img_date' ) == 'img_date' ) { $this->mDefaultDirection = true; } else { $this->mDefaultDirection = false; @@ -98,11 +97,7 @@ class ImageListPager extends TablePager { $this->mDefaultDirection = true; } - parent::__construct(); - } - - function getTitle() { - return SpecialPage::getTitleFor( 'Listfiles' ); + parent::__construct( $context ); } /** @@ -197,14 +192,13 @@ class ImageListPager extends TablePager { } function formatValue( $field, $value ) { - global $wgLang; switch ( $field ) { case 'thumb': $file = wfLocalFile( $value ); $thumb = $file->transform( array( 'width' => 180, 'height' => 360 ) ); return $thumb->toHtml( array( 'desc-link' => true ) ); case 'img_timestamp': - return htmlspecialchars( $wgLang->timeanddate( $value, true ) ); + return htmlspecialchars( $this->getLanguage()->timeanddate( $value, true ) ); case 'img_name': static $imgfile = null; if ( $imgfile === null ) $imgfile = wfMsg( 'imgfile' ); @@ -212,7 +206,7 @@ class ImageListPager extends TablePager { // Weird files can maybe exist? Bug 22227 $filePage = Title::makeTitleSafe( NS_FILE, $value ); if( $filePage ) { - $link = $this->getSkin()->linkKnown( $filePage, htmlspecialchars( $filePage->getText() ) ); + $link = Linker::linkKnown( $filePage, htmlspecialchars( $filePage->getText() ) ); $download = Xml::element( 'a', array( 'href' => wfLocalFile( $filePage )->getURL() ), $imgfile @@ -223,7 +217,7 @@ class ImageListPager extends TablePager { } case 'img_user_text': if ( $this->mCurrentRow->img_user ) { - $link = $this->getSkin()->link( + $link = Linker::link( Title::makeTitle( NS_USER, $value ), htmlspecialchars( $value ) ); @@ -232,9 +226,9 @@ class ImageListPager extends TablePager { } return $link; case 'img_size': - return $this->getSkin()->formatSize( $value ); + return htmlspecialchars( $this->getLanguage()->formatSize( $value ) ); case 'img_description': - return $this->getSkin()->commentBlock( $value ); + return Linker::commentBlock( $value ); case 'count': return intval( $value ) + 1; } diff --git a/includes/specials/SpecialListgrouprights.php b/includes/specials/SpecialListgrouprights.php index 07e08e77..91d8ed87 100644 --- a/includes/specials/SpecialListgrouprights.php +++ b/includes/specials/SpecialListgrouprights.php @@ -44,10 +44,11 @@ class SpecialListGroupRights extends SpecialPage { global $wgImplicitGroups; global $wgGroupPermissions, $wgRevokePermissions, $wgAddGroups, $wgRemoveGroups; global $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf; - $out = $this->getOutput(); $this->setHeaders(); $this->outputHeader(); + + $out = $this->getOutput(); $out->addModuleStyles( 'mediawiki.special' ); $out->addHTML( @@ -96,20 +97,16 @@ class SpecialListGroupRights extends SpecialPage { if ( $group === 'user' ) { // Link to Special:listusers for implicit group 'user' - $grouplink = '
      ' . Linker::link( + $grouplink = '
      ' . Linker::linkKnown( SpecialPage::getTitleFor( 'Listusers' ), - wfMsgHtml( 'listgrouprights-members' ), - array(), - array(), - array( 'known', 'noclasses' ) + wfMsgHtml( 'listgrouprights-members' ) ); } elseif ( !in_array( $group, $wgImplicitGroups ) ) { - $grouplink = '
      ' . Linker::link( + $grouplink = '
      ' . Linker::linkKnown( SpecialPage::getTitleFor( 'Listusers' ), wfMsgHtml( 'listgrouprights-members' ), array(), - array( 'group' => $group ), - array( 'known', 'noclasses' ) + array( 'group' => $group ) ); } else { // No link to Special:listusers for other implicit groups as they are unlistable @@ -127,7 +124,8 @@ class SpecialListGroupRights extends SpecialPage { " $grouppage$grouplink " . - self::formatPermissions( $permissions, $revoke, $addgroups, $removegroups, $addgroupsSelf, $removegroupsSelf ) . + $this->formatPermissions( $permissions, $revoke, $addgroups, $removegroups, + $addgroupsSelf, $removegroupsSelf ) . ' ' ) ); @@ -149,9 +147,7 @@ class SpecialListGroupRights extends SpecialPage { * @param $removeSelf Array of group this group is allowed to remove from self or true * @return string List of all granted permissions, separated by comma separator */ - private static function formatPermissions( $permissions, $revoke, $add, $remove, $addSelf, $removeSelf ) { - global $wgLang; - + private function formatPermissions( $permissions, $revoke, $add, $remove, $addSelf, $removeSelf ) { $r = array(); foreach( $permissions as $permission => $granted ) { //show as granted only if it isn't revoked to prevent duplicate display of permissions @@ -173,29 +169,42 @@ class SpecialListGroupRights extends SpecialPage { } } sort( $r ); + $lang = $this->getLanguage(); if( $add === true ){ $r[] = wfMsgExt( 'listgrouprights-addgroup-all', array( 'escape' ) ); } elseif( is_array( $add ) && count( $add ) ) { $add = array_values( array_unique( $add ) ); - $r[] = wfMsgExt( 'listgrouprights-addgroup', array( 'parseinline' ), $wgLang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $add ) ), count( $add ) ); + $r[] = wfMsgExt( 'listgrouprights-addgroup', array( 'parseinline' ), + $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $add ) ), + count( $add ) + ); } if( $remove === true ){ $r[] = wfMsgExt( 'listgrouprights-removegroup-all', array( 'escape' ) ); } elseif( is_array( $remove ) && count( $remove ) ) { $remove = array_values( array_unique( $remove ) ); - $r[] = wfMsgExt( 'listgrouprights-removegroup', array( 'parseinline' ), $wgLang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $remove ) ), count( $remove ) ); + $r[] = wfMsgExt( 'listgrouprights-removegroup', array( 'parseinline' ), + $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $remove ) ), + count( $remove ) + ); } if( $addSelf === true ){ $r[] = wfMsgExt( 'listgrouprights-addgroup-self-all', array( 'escape' ) ); } elseif( is_array( $addSelf ) && count( $addSelf ) ) { $addSelf = array_values( array_unique( $addSelf ) ); - $r[] = wfMsgExt( 'listgrouprights-addgroup-self', array( 'parseinline' ), $wgLang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $addSelf ) ), count( $addSelf ) ); + $r[] = wfMsgExt( 'listgrouprights-addgroup-self', array( 'parseinline' ), + $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $addSelf ) ), + count( $addSelf ) + ); } if( $removeSelf === true ){ $r[] = wfMsgExt( 'listgrouprights-removegroup-self-all', array( 'escape' ) ); } elseif( is_array( $removeSelf ) && count( $removeSelf ) ) { $removeSelf = array_values( array_unique( $removeSelf ) ); - $r[] = wfMsgExt( 'listgrouprights-removegroup-self', array( 'parseinline' ), $wgLang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $removeSelf ) ), count( $removeSelf ) ); + $r[] = wfMsgExt( 'listgrouprights-removegroup-self', array( 'parseinline' ), + $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $removeSelf ) ), + count( $removeSelf ) + ); } if( empty( $r ) ) { return ''; diff --git a/includes/specials/SpecialListredirects.php b/includes/specials/SpecialListredirects.php index acf5fbd9..f9cf3e6e 100644 --- a/includes/specials/SpecialListredirects.php +++ b/includes/specials/SpecialListredirects.php @@ -43,6 +43,7 @@ class ListredirectsPage extends QueryPage { 'tables' => array( 'p1' => 'page', 'redirect', 'p2' => 'page' ), 'fields' => array( 'p1.page_namespace AS namespace', 'p1.page_title AS title', + 'p1.page_title AS value', 'rd_namespace', 'rd_title', 'rd_fragment', @@ -90,7 +91,7 @@ class ListredirectsPage extends QueryPage { ); } else { $title = Title::makeTitle( $row->namespace, $row->title ); - $article = new Article( $title ); + $article = WikiPage::factory( $title ); return $article->getRedirectTarget(); } } @@ -98,7 +99,7 @@ class ListredirectsPage extends QueryPage { function formatResult( $skin, $result ) { # Make a link to the redirect itself $rd_title = Title::makeTitle( $result->namespace, $result->title ); - $rd_link = $skin->link( + $rd_link = Linker::link( $rd_title, null, array(), @@ -108,10 +109,10 @@ class ListredirectsPage extends QueryPage { # Find out where the redirect leads $target = $this->getRedirectTarget( $result ); if( $target ) { - global $wgLang; # Make a link to the destination page - $arr = $wgLang->getArrow() . $wgLang->getDirMark(); - $targetLink = $skin->link( $target ); + $lang = $this->getLanguage(); + $arr = $lang->getArrow() . $lang->getDirMark(); + $targetLink = Linker::link( $target ); return "$rd_link $arr $targetLink"; } else { return "$rd_link"; diff --git a/includes/specials/SpecialListusers.php b/includes/specials/SpecialListusers.php index 0531444a..d743712d 100644 --- a/includes/specials/SpecialListusers.php +++ b/includes/specials/SpecialListusers.php @@ -3,7 +3,7 @@ * Implements Special:Listusers * * Copyright © 2004 Brion Vibber, lcrocker, Tim Starling, - * Domas Mituzas, Ashar Voultoiz, Jens Frank, Zhengzhu, + * Domas Mituzas, Antoine Musso, Jens Frank, Zhengzhu, * 2006 Rob Church * * This program is free software; you can redistribute it and/or modify @@ -34,25 +34,30 @@ */ class UsersPager extends AlphabeticPager { - function __construct( $par=null ) { - global $wgRequest; - $parms = explode( '/', ($par = ( $par !== null ) ? $par : '' ) ); + function __construct( IContextSource $context = null, $par = null ) { + if ( $context ) { + $this->setContext( $context ); + } + + $request = $this->getRequest(); + $par = ( $par !== null ) ? $par : ''; + $parms = explode( '/', $par ); $symsForAll = array( '*', 'user' ); if ( $parms[0] != '' && ( in_array( $par, User::getAllGroups() ) || in_array( $par, $symsForAll ) ) ) { $this->requestedGroup = $par; - $un = $wgRequest->getText( 'username' ); + $un = $request->getText( 'username' ); } elseif ( count( $parms ) == 2 ) { $this->requestedGroup = $parms[0]; $un = $parms[1]; } else { - $this->requestedGroup = $wgRequest->getVal( 'group' ); - $un = ( $par != '' ) ? $par : $wgRequest->getText( 'username' ); + $this->requestedGroup = $request->getVal( 'group' ); + $un = ( $par != '' ) ? $par : $request->getText( 'username' ); } if ( in_array( $this->requestedGroup, $symsForAll ) ) { $this->requestedGroup = ''; } - $this->editsOnly = $wgRequest->getBool( 'editsOnly' ); - $this->creationSort = $wgRequest->getBool( 'creationSort' ); + $this->editsOnly = $request->getBool( 'editsOnly' ); + $this->creationSort = $request->getBool( 'creationSort' ); $this->requestedUser = ''; if ( $un != '' ) { @@ -64,20 +69,15 @@ class UsersPager extends AlphabeticPager { parent::__construct(); } - function getTitle() { - return SpecialPage::getTitleFor( 'Listusers' ); - } - function getIndexField() { return $this->creationSort ? 'user_id' : 'user_name'; } function getQueryInfo() { - global $wgUser; $dbr = wfGetDB( DB_SLAVE ); $conds = array(); // Don't show hidden names - if( !$wgUser->isAllowed('hideuser') ) { + if( !$this->getUser()->isAllowed('hideuser') ) { $conds[] = 'ipb_deleted IS NULL'; } @@ -126,32 +126,32 @@ class UsersPager extends AlphabeticPager { } function formatRow( $row ) { - global $wgLang; - if ($row->user_id == 0) #Bug 16487 return ''; $userPage = Title::makeTitle( NS_USER, $row->user_name ); $name = Linker::link( $userPage, htmlspecialchars( $userPage->getText() ) ); + $lang = $this->getLanguage(); + $groups_list = self::getGroups( $row->user_id ); if( count( $groups_list ) > 0 ) { $list = array(); foreach( $groups_list as $group ) - $list[] = self::buildGroupLink( $group ); - $groups = $wgLang->commaList( $list ); + $list[] = self::buildGroupLink( $group, $userPage->getText() ); + $groups = $lang->commaList( $list ); } else { $groups = ''; } - $item = wfSpecialList( $name, $groups ); + $item = $lang->specialList( $name, $groups ); if( $row->ipb_deleted ) { $item = "$item"; } global $wgEdititis; if ( $wgEdititis ) { - $editCount = $wgLang->formatNum( $row->edits ); + $editCount = $lang->formatNum( $row->edits ); $edits = ' [' . wfMsgExt( 'usereditcount', array( 'parsemag', 'escape' ), $editCount ) . ']'; } else { $edits = ''; @@ -160,10 +160,9 @@ class UsersPager extends AlphabeticPager { $created = ''; # Some rows may be NULL if( $row->creation ) { - $d = $wgLang->date( wfTimestamp( TS_MW, $row->creation ), true ); - $t = $wgLang->time( wfTimestamp( TS_MW, $row->creation ), true ); - $created = ' (' . wfMsg( 'usercreated', $d, $t ) . ')'; - $created = htmlspecialchars( $created ); + $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 ) . ')'; } wfRunHooks( 'SpecialListusersFormatRow', array( &$item, $row ) ); @@ -186,12 +185,13 @@ class UsersPager extends AlphabeticPager { function getPageHeader( ) { global $wgScript; - $self = $this->getTitle(); + // @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' ) ) . - Html::hidden( 'title', $self->getPrefixedDbKey() ); + Html::hidden( 'title', $self ); # Username field $out .= Xml::label( wfMsg( 'listusersfrom' ), 'offset' ) . ' ' . @@ -264,13 +264,11 @@ class UsersPager extends AlphabeticPager { * Format a link to a group description page * * @param $group String: group name + * @param $username String Username * @return string */ - protected static function buildGroupLink( $group ) { - static $cache = array(); - if( !isset( $cache[$group] ) ) - $cache[$group] = User::makeGroupLinkHtml( $group, htmlspecialchars( User::getGroupMember( $group ) ) ); - return $cache[$group]; + protected static function buildGroupLink( $group, $username ) { + return User::makeGroupLinkHtml( $group, htmlspecialchars( User::getGroupMember( $group, $username ) ) ); } } @@ -292,12 +290,10 @@ class SpecialListUsers extends SpecialPage { * @param $par string (optional) A group to list users from */ public function execute( $par ) { - global $wgOut; - $this->setHeaders(); $this->outputHeader(); - $up = new UsersPager( $par ); + $up = new UsersPager( $this->getContext(), $par ); # getBody() first to check, if empty $usersbody = $up->getBody(); @@ -311,6 +307,6 @@ class SpecialListUsers extends SpecialPage { $s .= wfMessage( 'listusers-noresult' )->parseAsBlock(); } - $wgOut->addHTML( $s ); + $this->getOutput()->addHTML( $s ); } } diff --git a/includes/specials/SpecialLockdb.php b/includes/specials/SpecialLockdb.php index 5c861b31..c1453518 100644 --- a/includes/specials/SpecialLockdb.php +++ b/includes/specials/SpecialLockdb.php @@ -26,89 +26,53 @@ * * @ingroup SpecialPage */ -class SpecialLockdb extends SpecialPage { +class SpecialLockdb extends FormSpecialPage { var $reason = ''; public function __construct() { parent::__construct( 'Lockdb', 'siteadmin' ); } - public function execute( $par ) { - global $wgUser, $wgRequest; - - $this->setHeaders(); - - # Permission check - if( !$this->userCanExecute( $wgUser ) ) { - $this->displayRestrictionError(); - return; - } - - $this->outputHeader(); + public function requiresWrite() { + return false; + } - # If the lock file isn't writable, we can do sweet bugger all + public function checkExecutePermissions( User $user ) { global $wgReadOnlyFile; - if( !is_writable( dirname( $wgReadOnlyFile ) ) ) { - self::notWritable(); - return; - } - $action = $wgRequest->getVal( 'action' ); - $this->reason = $wgRequest->getVal( 'wpLockReason', '' ); - - if ( $action == 'success' ) { - $this->showSuccess(); - } elseif ( $action == 'submit' && $wgRequest->wasPosted() && - $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) { - $this->doSubmit(); - } else { - $this->showForm(); + parent::checkExecutePermissions( $user ); + # If the lock file isn't writable, we can do sweet bugger all + if ( !is_writable( dirname( $wgReadOnlyFile ) ) ) { + throw new ErrorPageError( 'lockdb', 'lockfilenotwritable' ); } } - private function showForm( $err = '' ) { - global $wgOut, $wgUser; - - $wgOut->addWikiMsg( 'lockdbtext' ); - - if ( $err != '' ) { - $wgOut->setSubtitle( wfMsg( 'formerror' ) ); - $wgOut->addHTML( '

      ' . htmlspecialchars( $err ) . "

      \n" ); - } - - $wgOut->addHTML( - Html::openElement( 'form', array( 'id' => 'lockdb', 'method' => 'POST', - 'action' => $this->getTitle()->getLocalURL( 'action=submit' ) ) ). "\n" . - wfMsgHtml( 'enterlockreason' ) . ":\n" . - Html::textarea( 'wpLockReason', $this->reason, array( 'rows' => 4 ) ). " - - - " . Html::openElement( 'td', array( 'style' => 'text-align:right' ) ) . " - " . Html::input( 'wpLockConfirm', null, 'checkbox' ) . " - - " . Html::openElement( 'td', array( 'style' => 'text-align:left' ) ) . - wfMsgHtml( 'lockconfirm' ) . " - - - - " . Html::openElement( 'td', array( 'style' => 'text-align:left' ) ) . " - " . Html::input( 'wpLock', wfMsg( 'lockbtn' ), 'submit' ) . " - - -
       
      \n" . - Html::hidden( 'wpEditToken', $wgUser->editToken() ) . "\n" . - Html::closeElement( 'form' ) + protected function getFormFields() { + return array( + 'Reason' => array( + 'type' => 'textarea', + 'rows' => 4, + 'vertical-label' => true, + 'label-message' => 'enterlockreason', + ), + 'Confirm' => array( + 'type' => 'toggle', + 'label-message' => 'lockconfirm', + ), ); + } + protected function alterForm( HTMLForm $form ) { + $form->setWrapperLegend( false ); + $form->setHeaderText( $this->msg( 'lockdbtext' )->parseAsBlock() ); + $form->setSubmitTextMsg( 'lockbtn' ); } - private function doSubmit() { - global $wgOut, $wgUser, $wgContLang, $wgRequest; - global $wgReadOnlyFile; + public function onSubmit( array $data ) { + global $wgContLang, $wgReadOnlyFile; - if ( ! $wgRequest->getCheck( 'wpLockConfirm' ) ) { - $this->showForm( wfMsg( 'locknoconfirm' ) ); - return; + if ( !$data['Confirm'] ) { + return Status::newFatal( 'locknoconfirm' ); } wfSuppressWarnings(); @@ -119,33 +83,25 @@ class SpecialLockdb extends SpecialPage { # This used to show a file not found error, but the likeliest reason for fopen() # to fail at this point is insufficient permission to write to the file...good old # is_writable() is plain wrong in some cases, it seems... - self::notWritable(); - return; + return Status::newFatal( 'lockfilenotwritable' ); } - fwrite( $fp, $this->reason ); + fwrite( $fp, $data['Reason'] ); $timestamp = wfTimestampNow(); fwrite( $fp, "\n

      " . wfMsgExt( 'lockedbyandtime', array( 'content', 'parsemag' ), - $wgUser->getName(), + $this->getUser()->getName(), $wgContLang->date( $timestamp ), $wgContLang->time( $timestamp ) ) . "

      \n" ); fclose( $fp ); - $wgOut->redirect( $this->getTitle()->getFullURL( 'action=success' ) ); - } - - private function showSuccess() { - global $wgOut; - - $wgOut->setPagetitle( wfMsg( 'lockdb' ) ); - $wgOut->setSubtitle( wfMsg( 'lockdbsuccesssub' ) ); - $wgOut->addWikiMsg( 'lockdbsuccesstext' ); + return Status::newGood(); } - public static function notWritable() { - global $wgOut; - $wgOut->showErrorPage( 'lockdb', 'lockfilenotwritable' ); + public function onSuccess() { + $out = $this->getOutput(); + $out->addSubtitle( $this->msg( 'lockdbsuccesssub' ) ); + $out->addWikiMsg( 'lockdbsuccesstext' ); } } diff --git a/includes/specials/SpecialLog.php b/includes/specials/SpecialLog.php index d8f6d8cf..64190df1 100644 --- a/includes/specials/SpecialLog.php +++ b/includes/specials/SpecialLog.php @@ -30,13 +30,24 @@ */ 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. + */ + private $typeOnUser = array( + 'block', + 'newusers', + 'rights', + ); + public function __construct() { parent::__construct( 'Log' ); } public function execute( $par ) { - global $wgRequest; - + global $wgLogRestrictions; + $this->setHeaders(); $this->outputHeader(); @@ -53,7 +64,7 @@ class SpecialLog extends SpecialPage { $opts->add( 'offender', '' ); // Set values - $opts->fetchValuesFromRequest( $wgRequest ); + $opts->fetchValuesFromRequest( $this->getRequest() ); if ( $par ) { $this->parseParams( $opts, (string)$par ); } @@ -64,6 +75,16 @@ class SpecialLog extends SpecialPage { $opts->setValue( 'month', '' ); } + // Reset the log type to default (nothing) if it's invalid or if the + // user does not possess the right to view it + $type = $opts->getValue( 'type' ); + if ( !LogPage::isLogType( $type ) + || ( isset( $wgLogRestrictions[$type] ) + && !$this->getUser()->isAllowed( $wgLogRestrictions[$type] ) ) + ) { + $opts->setValue( 'type', '' ); + } + # Handle type-specific inputs $qc = array(); if ( $opts->getValue( 'type' ) == 'suppress' ) { @@ -75,6 +96,20 @@ class SpecialLog extends SpecialPage { } } + # Some log types are only for a 'User:' title but we might have been given + # only the username instead of the full title 'User:username'. This part try + # to lookup for a user by that name and eventually fix user input. See bug 1697. + if( in_array( $opts->getValue( 'type' ), $this->typeOnUser ) ) { + # ok we have a type of log which expect a user title. + $target = Title::newFromText( $opts->getValue( 'page' ) ); + if( $target && $target->getNamespace() === NS_MAIN ) { + # User forgot to add 'User:', we are adding it for him + $opts->setValue( 'page', + Title::makeTitleSafe( NS_USER, $opts->getValue( 'page' ) ) + ); + } + } + $this->show( $opts, $qc ); } @@ -95,30 +130,27 @@ class SpecialLog extends SpecialPage { } private function show( FormOptions $opts, array $extraConds ) { - global $wgOut; - # Create a LogPager item to get the results and a LogEventsList item to format them... - $loglist = new LogEventsList( $this->getSkin(), $wgOut, 0 ); + $loglist = new LogEventsList( $this->getSkin(), $this->getOutput(), 0 ); $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' ) ); - # Set title and add header - $loglist->showHeader( $pager->getType() ); + $this->addHeader( $opts->getValue( 'type' ) ); # Set relevant user - if ( $pager->getUser() ) { - $this->getSkin()->setRelevantUser( User::newFromName( $pager->getUser() ) ); + if ( $pager->getPerformer() ) { + $this->getSkin()->setRelevantUser( User::newFromName( $pager->getPerformer() ) ); } # Show form options - $loglist->showOptions( $pager->getType(), $pager->getUser(), $pager->getPage(), $pager->getPattern(), + $loglist->showOptions( $pager->getType(), $opts->getValue( 'user' ), $pager->getPage(), $pager->getPattern(), $pager->getYear(), $pager->getMonth(), $pager->getFilterParams(), $opts->getValue( 'tagfilter' ) ); # Insert list $logBody = $pager->getBody(); if ( $logBody ) { - $wgOut->addHTML( + $this->getOutput()->addHTML( $pager->getNavigationBar() . $loglist->beginLogEventsList() . $logBody . @@ -126,7 +158,19 @@ class SpecialLog extends SpecialPage { $pager->getNavigationBar() ); } else { - $wgOut->addWikiMsg( 'logempty' ); + $this->getOutput()->addWikiMsg( 'logempty' ); } } + + /** + * Set page title and show header for this log type + * @param $type string + * @since 1.19 + */ + protected function addHeader( $type ) { + $page = new LogPage( $type ); + $this->getOutput()->setPageTitle( $page->getName()->text() ); + $this->getOutput()->addHTML( $page->getDescription()->parseAsBlock() ); + } + } diff --git a/includes/specials/SpecialMIMEsearch.php b/includes/specials/SpecialMIMEsearch.php index aefe7bf5..2213ffa4 100644 --- a/includes/specials/SpecialMIMEsearch.php +++ b/includes/specials/SpecialMIMEsearch.php @@ -59,12 +59,11 @@ class MIMEsearchPage extends QueryPage { } function execute( $par ) { - global $wgRequest, $wgOut; - $mime = $par ? $par : $wgRequest->getText( 'mime' ); + $mime = $par ? $par : $this->getRequest()->getText( 'mime' ); $this->setHeaders(); $this->outputHeader(); - $wgOut->addHTML( + $this->getOutput()->addHTML( Xml::openElement( 'form', array( 'id' => 'specialmimesearch', 'method' => 'get', 'action' => SpecialPage::getTitleFor( 'MIMEsearch' )->getLocalUrl() ) ) . Xml::openElement( 'fieldset' ) . Html::hidden( 'title', SpecialPage::getTitleFor( 'MIMEsearch' )->getPrefixedText() ) . @@ -85,24 +84,24 @@ class MIMEsearchPage extends QueryPage { function formatResult( $skin, $result ) { - global $wgContLang, $wgLang; + global $wgContLang; $nt = Title::makeTitle( $result->namespace, $result->title ); $text = $wgContLang->convert( $nt->getText() ); - $plink = $skin->link( + $plink = Linker::link( Title::newFromText( $nt->getPrefixedText() ), htmlspecialchars( $text ) ); - $download = $skin->makeMediaLinkObj( $nt, wfMsgHtml( 'download' ) ); - $bytes = wfMsgExt( 'nbytes', array( 'parsemag', 'escape' ), - $wgLang->formatNum( $result->img_size ) ); + $download = Linker::makeMediaLinkObj( $nt, wfMsgHtml( 'download' ) ); + $lang = $this->getLanguage(); + $bytes = htmlspecialchars( $lang->formatSize( $result->img_size ) ); $dimensions = htmlspecialchars( wfMsg( 'widthheight', - $wgLang->formatNum( $result->img_width ), - $wgLang->formatNum( $result->img_height ) + $lang->formatNum( $result->img_width ), + $lang->formatNum( $result->img_height ) ) ); - $user = $skin->link( Title::makeTitle( NS_USER, $result->img_user_text ), htmlspecialchars( $result->img_user_text ) ); - $time = htmlspecialchars( $wgLang->timeanddate( $result->img_timestamp ) ); + $user = Linker::link( Title::makeTitle( NS_USER, $result->img_user_text ), htmlspecialchars( $result->img_user_text ) ); + $time = htmlspecialchars( $lang->timeanddate( $result->img_timestamp ) ); return "($download) $plink . . $dimensions . . $bytes . . $user . . $time"; } diff --git a/includes/specials/SpecialMergeHistory.php b/includes/specials/SpecialMergeHistory.php index 88e90ee5..19650da9 100644 --- a/includes/specials/SpecialMergeHistory.php +++ b/includes/specials/SpecialMergeHistory.php @@ -40,12 +40,10 @@ class SpecialMergeHistory extends SpecialPage { } /** - * @param $request WebRequest * @return void */ - private function loadRequestParams( $request ) { - global $wgUser; - + private function loadRequestParams() { + $request = $this->getRequest(); $this->mAction = $request->getVal( 'action' ); $this->mTarget = $request->getVal( 'target' ); $this->mDest = $request->getVal( 'dest' ); @@ -59,7 +57,7 @@ class SpecialMergeHistory extends SpecialPage { } $this->mComment = $request->getText( 'wpComment' ); - $this->mMerge = $request->wasPosted() && $wgUser->matchEditToken( $request->getVal( 'wpEditToken' ) ); + $this->mMerge = $request->wasPosted() && $this->getUser()->matchEditToken( $request->getVal( 'wpEditToken' ) ); // target page if( $this->mSubmitted ) { $this->mTargetObj = Title::newFromURL( $this->mTarget ); @@ -83,19 +81,10 @@ class SpecialMergeHistory extends SpecialPage { } public function execute( $par ) { - global $wgOut, $wgRequest, $wgUser; - - if ( wfReadOnly() ) { - $wgOut->readOnlyPage(); - return; - } - - if( !$this->userCanExecute( $wgUser ) ) { - $this->displayRestrictionError(); - return; - } + $this->checkPermissions(); + $this->checkReadOnly(); - $this->loadRequestParams( $wgRequest ); + $this->loadRequestParams(); $this->setHeaders(); $this->outputHeader(); @@ -132,7 +121,7 @@ class SpecialMergeHistory extends SpecialPage { if ( count( $errors ) ) { $this->showMergeForm(); - $wgOut->addHTML( implode( "\n", $errors ) ); + $this->getOutput()->addHTML( implode( "\n", $errors ) ); } else { $this->showHistory(); } @@ -140,11 +129,11 @@ class SpecialMergeHistory extends SpecialPage { } function showMergeForm() { - global $wgOut, $wgScript; + global $wgScript; - $wgOut->addWikiMsg( 'mergehistory-header' ); + $this->getOutput()->addWikiMsg( 'mergehistory-header' ); - $wgOut->addHTML( + $this->getOutput()->addHTML( Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) . @@ -171,12 +160,6 @@ class SpecialMergeHistory extends SpecialPage { } private function showHistory() { - global $wgUser, $wgOut; - - $this->sk = $this->getSkin(); - - $wgOut->setPageTitle( wfMsg( 'mergehistory' ) ); - $this->showMergeForm(); # List all stored revisions @@ -185,6 +168,7 @@ class SpecialMergeHistory extends SpecialPage { ); $haveRevisions = $revisions && $revisions->getNumRows() > 0; + $out = $this->getOutput(); $titleObj = $this->getTitle(); $action = $titleObj->getLocalURL( array( 'action' => 'submit' ) ); # Start the form here @@ -196,7 +180,7 @@ class SpecialMergeHistory extends SpecialPage { 'id' => 'merge' ) ); - $wgOut->addHTML( $top ); + $out->addHTML( $top ); if( $haveRevisions ) { # Format the user-visible controls (comment field, submission button) @@ -223,27 +207,27 @@ class SpecialMergeHistory extends SpecialPage { Xml::closeElement( 'table' ) . Xml::closeElement( 'fieldset' ); - $wgOut->addHTML( $table ); + $out->addHTML( $table ); } - $wgOut->addHTML( + $out->addHTML( '

      ' . wfMsgHtml( 'mergehistory-list' ) . "

      \n" ); if( $haveRevisions ) { - $wgOut->addHTML( $revisions->getNavigationBar() ); - $wgOut->addHTML( '
        ' ); - $wgOut->addHTML( $revisions->getBody() ); - $wgOut->addHTML( '
      ' ); - $wgOut->addHTML( $revisions->getNavigationBar() ); + $out->addHTML( $revisions->getNavigationBar() ); + $out->addHTML( '
        ' ); + $out->addHTML( $revisions->getBody() ); + $out->addHTML( '
      ' ); + $out->addHTML( $revisions->getNavigationBar() ); } else { - $wgOut->addWikiMsg( 'mergehistory-empty' ); + $out->addWikiMsg( 'mergehistory-empty' ); } # Show relevant lines from the deletion log: - $wgOut->addHTML( '

      ' . htmlspecialchars( LogPage::logName( 'merge' ) ) . "

      \n" ); - LogEventsList::showLogExtract( $wgOut, 'merge', $this->mTargetObj->getPrefixedText() ); + $out->addHTML( '

      ' . htmlspecialchars( LogPage::logName( 'merge' ) ) . "

      \n" ); + LogEventsList::showLogExtract( $out, 'merge', $this->mTargetObj ); # When we submit, go by page ID to avoid some nasty but unlikely collisions. # Such would happen if a page was renamed after the form loaded, but before submit @@ -251,16 +235,14 @@ class SpecialMergeHistory extends SpecialPage { $misc .= Html::hidden( 'destID', $this->mDestObj->getArticleID() ); $misc .= Html::hidden( 'target', $this->mTarget ); $misc .= Html::hidden( 'dest', $this->mDest ); - $misc .= Html::hidden( 'wpEditToken', $wgUser->editToken() ); + $misc .= Html::hidden( 'wpEditToken', $this->getUser()->getEditToken() ); $misc .= Xml::closeElement( 'form' ); - $wgOut->addHTML( $misc ); + $out->addHTML( $misc ); return true; } function formatRevisionRow( $row ) { - global $wgLang; - $rev = new Revision( $row ); $stxt = ''; @@ -269,9 +251,9 @@ class SpecialMergeHistory extends SpecialPage { $ts = wfTimestamp( TS_MW, $row->rev_timestamp ); $checkBox = Xml::radio( 'mergepoint', $ts, false ); - $pageLink = $this->sk->linkKnown( + $pageLink = Linker::linkKnown( $rev->getTitle(), - htmlspecialchars( $wgLang->timeanddate( $ts ) ), + htmlspecialchars( $this->getLanguage()->timeanddate( $ts ) ), array(), array( 'oldid' => $rev->getId() ) ); @@ -280,10 +262,10 @@ class SpecialMergeHistory extends SpecialPage { } # Last link - if( !$rev->userCan( Revision::DELETED_TEXT ) ) { + if( !$rev->userCan( Revision::DELETED_TEXT, $this->getUser() ) ) { $last = $this->message['last']; } elseif( isset( $this->prevId[$row->rev_id] ) ) { - $last = $this->sk->linkKnown( + $last = Linker::linkKnown( $rev->getTitle(), $this->message['last'], array(), @@ -294,46 +276,18 @@ class SpecialMergeHistory extends SpecialPage { ); } - $userLink = $this->sk->revUserTools( $rev ); + $userLink = Linker::revUserTools( $rev ); $size = $row->rev_len; if( !is_null( $size ) ) { - $stxt = $this->sk->formatRevisionSize( $size ); + $stxt = Linker::formatRevisionSize( $size ); } - $comment = $this->sk->revComment( $rev ); + $comment = Linker::revComment( $rev ); return "
    1. $checkBox ($last) $pageLink . . $userLink $stxt $comment
    2. "; } - /** - * Fetch revision text link if it's available to all users - * @return string - */ - function getPageLink( $row, $titleObj, $ts, $target ) { - global $wgLang; - - if( !$this->userCan( $row, Revision::DELETED_TEXT ) ) { - return '' . - $wgLang->timeanddate( $ts, true ) . ''; - } else { - $link = $this->sk->linkKnown( - $titleObj, - $wgLang->timeanddate( $ts, true ), - array(), - array( - 'target' => $target, - 'timestamp' => $ts - ) - ); - if( $this->isDeleted( $row, Revision::DELETED_TEXT ) ) { - $link = '' . $link . ''; - } - return $link; - } - } - function merge() { - global $wgOut; # Get the titles directly from the IDs, in case the target page params # were spoofed. The queries are done based on the IDs, so it's best to # keep it consistent... @@ -359,7 +313,7 @@ class SpecialMergeHistory extends SpecialPage { ); # Destination page must exist with revisions if( !$maxtimestamp ) { - $wgOut->addWikiMsg( 'mergehistory-fail' ); + $this->getOutput()->addWikiMsg( 'mergehistory-fail' ); return false; } # Get the latest timestamp of the source @@ -371,7 +325,7 @@ class SpecialMergeHistory extends SpecialPage { ); # $this->mTimestamp must be older than $maxtimestamp if( $this->mTimestamp >= $maxtimestamp ) { - $wgOut->addWikiMsg( 'mergehistory-fail' ); + $this->getOutput()->addWikiMsg( 'mergehistory-fail' ); return false; } # Update the revisions @@ -416,13 +370,13 @@ class SpecialMergeHistory extends SpecialPage { } $mwRedir = MagicWord::get( 'redirect' ); $redirectText = $mwRedir->getSynonym( 0 ) . ' [[' . $destTitle->getPrefixedText() . "]]\n"; - $redirectArticle = new Article( $targetTitle ); + $redirectPage = WikiPage::factory( $targetTitle ); $redirectRevision = new Revision( array( 'page' => $this->mTargetID, 'comment' => $comment, 'text' => $redirectText ) ); $redirectRevision->insertOn( $dbw ); - $redirectArticle->updateRevisionOn( $dbw, $redirectRevision ); + $redirectPage->updateRevisionOn( $dbw, $redirectRevision ); # Now, we record the link from the redirect to the new title. # It should have no other outgoing links... @@ -440,7 +394,7 @@ class SpecialMergeHistory extends SpecialPage { $destTitle->invalidateCache(); // update histories # Check if this did anything if( !$count ) { - $wgOut->addWikiMsg( 'mergehistory-fail' ); + $this->getOutput()->addWikiMsg( 'mergehistory-fail' ); return false; } # Update our logs @@ -450,7 +404,7 @@ class SpecialMergeHistory extends SpecialPage { array( $destTitle->getPrefixedText(), $timestampLimit ) ); - $wgOut->addHTML( + $this->getOutput()->addHTML( wfMsgExt( 'mergehistory-success', array('parseinline'), $targetTitle->getPrefixedText(), $destTitle->getPrefixedText(), $count ) ); @@ -478,11 +432,7 @@ class MergeHistoryPager extends ReverseChronologicalPager { ); $this->maxTimestamp = $maxtimestamp; - parent::__construct(); - } - - function getTitle() { - return SpecialPage::getTitleFor( 'Contributions' ); + parent::__construct( $form->getContext() ); } function getStartBody() { @@ -493,8 +443,8 @@ class MergeHistoryPager extends ReverseChronologicalPager { # Give some pointers to make (last) links $this->mForm->prevId = array(); foreach ( $this->mResult as $row ) { - $batch->addObj( Title::makeTitleSafe( NS_USER, $row->rev_user_text ) ); - $batch->addObj( Title::makeTitleSafe( NS_USER_TALK, $row->rev_user_text ) ); + $batch->addObj( Title::makeTitleSafe( NS_USER, $row->user_name ) ); + $batch->addObj( Title::makeTitleSafe( NS_USER_TALK, $row->user_name ) ); $rev_id = isset( $rev_id ) ? $rev_id : $row->rev_id; if( $rev_id > $row->rev_id ) { @@ -520,16 +470,14 @@ class MergeHistoryPager extends ReverseChronologicalPager { function getQueryInfo() { $conds = $this->mConds; $conds['rev_page'] = $this->articleID; - $conds[] = 'page_id = rev_page'; $conds[] = "rev_timestamp < {$this->maxTimestamp}"; return array( - 'tables' => array( 'revision', 'page' ), - 'fields' => array( - 'rev_minor_edit', 'rev_timestamp', 'rev_user', 'rev_user_text', - 'rev_comment', 'rev_id', 'rev_page', 'rev_parent_id', - 'rev_text_id', 'rev_len', 'rev_deleted' - ), - 'conds' => $conds + 'tables' => array( 'revision', 'page', 'user' ), + 'fields' => array_merge( Revision::selectFields(), Revision::selectUserFields() ), + 'conds' => $conds, + 'join_conds' => array( + 'page' => Revision::pageJoinCond(), + 'user' => Revision::userJoinCond() ) ); } diff --git a/includes/specials/SpecialMostcategories.php b/includes/specials/SpecialMostcategories.php index 2e437196..98b73675 100644 --- a/includes/specials/SpecialMostcategories.php +++ b/includes/specials/SpecialMostcategories.php @@ -58,11 +58,10 @@ class MostcategoriesPage extends QueryPage { * @return string */ function formatResult( $skin, $result ) { - global $wgLang; $title = Title::makeTitleSafe( $result->namespace, $result->title ); - $count = wfMsgExt( 'ncategories', array( 'parsemag', 'escape' ), $wgLang->formatNum( $result->value ) ); - $link = $skin->link( $title ); - return wfSpecialList( $link, $count ); + $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 ac2b5206..7805e53e 100644 --- a/includes/specials/SpecialMostimages.php +++ b/includes/specials/SpecialMostimages.php @@ -50,9 +50,7 @@ class MostimagesPage extends ImageQueryPage { } function getCellHtml( $row ) { - global $wgLang; - return wfMsgExt( 'nimagelinks', array( 'parsemag', 'escape' ), - $wgLang->formatNum( $row->value ) ) . '
      '; + return $this->msg( 'nimagelinks' )->numParams( $row->value )->escaped() . '
      '; } } diff --git a/includes/specials/SpecialMostlinked.php b/includes/specials/SpecialMostlinked.php index 58f686e8..a16f0872 100644 --- a/includes/specials/SpecialMostlinked.php +++ b/includes/specials/SpecialMostlinked.php @@ -77,12 +77,11 @@ class MostlinkedPage extends QueryPage { * * @param $title Title being queried * @param $caption String: text to display on the link - * @param $skin Skin to use * @return String */ - function makeWlhLink( &$title, $caption, &$skin ) { + function makeWlhLink( $title, $caption ) { $wlh = SpecialPage::getTitleFor( 'Whatlinkshere', $title->getPrefixedDBkey() ); - return $skin->linkKnown( $wlh, $caption ); + return Linker::linkKnown( $wlh, $caption ); } /** @@ -93,15 +92,13 @@ class MostlinkedPage extends QueryPage { * @return string */ function formatResult( $skin, $result ) { - global $wgLang; $title = Title::makeTitleSafe( $result->namespace, $result->title ); if ( !$title ) { return ''; } - $link = $skin->link( $title ); + $link = Linker::link( $title ); $wlh = $this->makeWlhLink( $title, - wfMsgExt( 'nlinks', array( 'parsemag', 'escape'), - $wgLang->formatNum( $result->value ) ), $skin ); - return wfSpecialList( $link, $wlh ); + $this->msg( 'nlinks' )->numParams( $result->value )->escaped() ); + return $this->getLanguage()->specialList( $link, $wlh ); } } diff --git a/includes/specials/SpecialMostlinkedcategories.php b/includes/specials/SpecialMostlinkedcategories.php index 195282f7..7fb9dea9 100644 --- a/includes/specials/SpecialMostlinkedcategories.php +++ b/includes/specials/SpecialMostlinkedcategories.php @@ -25,7 +25,7 @@ */ /** - * A querypage to show categories ordered in descending order by the pages in them + * A querypage to show categories ordered in descending order by the pages in them * * @ingroup SpecialPage */ @@ -35,16 +35,14 @@ class MostlinkedCategoriesPage extends QueryPage { parent::__construct( $name ); } - function isExpensive() { return true; } function isSyndicated() { return false; } function getQueryInfo() { return array ( - 'tables' => array ( 'categorylinks' ), - 'fields' => array ( 'cl_to AS title', + 'tables' => array ( 'category' ), + 'fields' => array ( 'cat_title AS title', NS_CATEGORY . ' AS namespace', - 'COUNT(*) AS value' ), - 'options' => array ( 'GROUP BY' => 'cl_to' ) + 'cat_pages AS value' ), ); } @@ -76,15 +74,14 @@ class MostlinkedCategoriesPage extends QueryPage { * @return string */ function formatResult( $skin, $result ) { - global $wgLang, $wgContLang; + global $wgContLang; $nt = Title::makeTitle( NS_CATEGORY, $result->title ); $text = $wgContLang->convert( $nt->getText() ); - $plink = $skin->link( $nt, htmlspecialchars( $text ) ); + $plink = Linker::link( $nt, htmlspecialchars( $text ) ); - $nlinks = wfMsgExt( 'nmembers', array( 'parsemag', 'escape' ), - $wgLang->formatNum( $result->value ) ); - return wfSpecialList( $plink, $nlinks ); + $nlinks = $this->msg( 'nmembers' )->numParams( $result->value )->escaped(); + return $this->getLanguage()->specialList( $plink, $nlinks ); } } diff --git a/includes/specials/SpecialMostlinkedtemplates.php b/includes/specials/SpecialMostlinkedtemplates.php index 69771925..6fb09426 100644 --- a/includes/specials/SpecialMostlinkedtemplates.php +++ b/includes/specials/SpecialMostlinkedtemplates.php @@ -98,9 +98,9 @@ class MostlinkedTemplatesPage extends QueryPage { public function formatResult( $skin, $result ) { $title = Title::makeTitle( $result->namespace, $result->title ); - return wfSpecialList( - $skin->link( $title ), - $this->makeWlhLink( $title, $skin, $result ) + return $this->getLanguage()->specialList( + Linker::link( $title ), + $this->makeWlhLink( $title, $result ) ); } @@ -108,16 +108,13 @@ class MostlinkedTemplatesPage extends QueryPage { * Make a "what links here" link for a given title * * @param $title Title to make the link for - * @param $skin Skin to use * @param $result Result row * @return String */ - private function makeWlhLink( $title, $skin, $result ) { - global $wgLang; - $wlh = SpecialPage::getTitleFor( 'Whatlinkshere' ); - $label = wfMsgExt( 'ntransclusions', array( 'parsemag', 'escape' ), - $wgLang->formatNum( $result->value ) ); - return $skin->link( $wlh, $label, array(), array( 'target' => $title->getPrefixedText() ) ); + private function makeWlhLink( $title, $result ) { + $wlh = SpecialPage::getTitleFor( 'Whatlinkshere', $title->getPrefixedText() ); + $label = $this->msg( 'ntransclusions' )->numParams( $result->value )->escaped(); + return Linker::link( $wlh, $label ); } } diff --git a/includes/specials/SpecialMovepage.php b/includes/specials/SpecialMovepage.php index ec7f4024..d7ebd310 100644 --- a/includes/specials/SpecialMovepage.php +++ b/includes/specials/SpecialMovepage.php @@ -42,103 +42,104 @@ class MovePageForm extends UnlistedSpecialPage { } public function execute( $par ) { - global $wgUser, $wgOut, $wgRequest; - - # Check for database lock - if ( wfReadOnly() ) { - $wgOut->readOnlyPage(); - return; - } + $this->checkReadOnly(); $this->setHeaders(); $this->outputHeader(); - $target = !is_null( $par ) ? $par : $wgRequest->getVal( 'target' ); + $request = $this->getRequest(); + $target = !is_null( $par ) ? $par : $request->getVal( 'target' ); // Yes, the use of getVal() and getText() is wanted, see bug 20365 - $oldTitleText = $wgRequest->getVal( 'wpOldTitle', $target ); - $newTitleText = $wgRequest->getText( 'wpNewTitle' ); + $oldTitleText = $request->getVal( 'wpOldTitle', $target ); $this->oldTitle = Title::newFromText( $oldTitleText ); - $this->newTitle = Title::newFromText( $newTitleText ); + + $newTitleTextMain = $request->getText( 'wpNewTitleMain' ); + $newTitleTextNs = $request->getInt( 'wpNewTitleNs', $this->oldTitle->getNamespace() ); + // Backwards compatibility for forms submitting here from other sources + // which is more common than it should be.. + $newTitleText_bc = $request->getText( 'wpNewTitle' ); + $this->newTitle = strlen( $newTitleText_bc ) > 0 + ? Title::newFromText( $newTitleText_bc ) + : Title::makeTitleSafe( $newTitleTextNs, $newTitleTextMain ); if( is_null( $this->oldTitle ) ) { - $wgOut->showErrorPage( 'notargettitle', 'notargettext' ); - return; + throw new ErrorPageError( 'notargettitle', 'notargettext' ); } if( !$this->oldTitle->exists() ) { - $wgOut->showErrorPage( 'nopagetitle', 'nopagetext' ); - return; + throw new ErrorPageError( 'nopagetitle', 'nopagetext' ); } + $user = $this->getUser(); + # Check rights - $permErrors = $this->oldTitle->getUserPermissionsErrors( 'move', $wgUser ); - if( !empty( $permErrors ) ) { + $permErrors = $this->oldTitle->getUserPermissionsErrors( 'move', $user ); + if ( count( $permErrors ) ) { // Auto-block user's IP if the account was "hard" blocked - $wgUser->spreadAnyEditBlock(); - $this->getOutput()->showPermissionsErrorPage( $permErrors ); - return; + $user->spreadAnyEditBlock(); + throw new PermissionsError( 'move', $permErrors ); } - $def = !$wgRequest->wasPosted(); + $def = !$request->wasPosted(); - $this->reason = $wgRequest->getText( 'wpReason' ); - $this->moveTalk = $wgRequest->getBool( 'wpMovetalk', $def ); - $this->fixRedirects = $wgRequest->getBool( 'wpFixRedirects', $def ); - $this->leaveRedirect = $wgRequest->getBool( 'wpLeaveRedirect', $def ); - $this->moveSubpages = $wgRequest->getBool( 'wpMovesubpages', false ); - $this->deleteAndMove = $wgRequest->getBool( 'wpDeleteAndMove' ) && $wgRequest->getBool( 'wpConfirm' ); - $this->moveOverShared = $wgRequest->getBool( 'wpMoveOverSharedFile', false ); - $this->watch = $wgRequest->getCheck( 'wpWatch' ) && $wgUser->isLoggedIn(); + $this->reason = $request->getText( 'wpReason' ); + $this->moveTalk = $request->getBool( 'wpMovetalk', $def ); + $this->fixRedirects = $request->getBool( 'wpFixRedirects', $def ); + $this->leaveRedirect = $request->getBool( 'wpLeaveRedirect', $def ); + $this->moveSubpages = $request->getBool( 'wpMovesubpages', false ); + $this->deleteAndMove = $request->getBool( 'wpDeleteAndMove' ) && $request->getBool( 'wpConfirm' ); + $this->moveOverShared = $request->getBool( 'wpMoveOverSharedFile', false ); + $this->watch = $request->getCheck( 'wpWatch' ) && $user->isLoggedIn(); - if ( 'submit' == $wgRequest->getVal( 'action' ) && $wgRequest->wasPosted() - && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) { + if ( 'submit' == $request->getVal( 'action' ) && $request->wasPosted() + && $user->matchEditToken( $request->getVal( 'wpEditToken' ) ) ) { $this->doSubmit(); } else { - $this->showForm( '' ); + $this->showForm( array() ); } } /** * Show the form * - * @param $err Mixed: error message. May either be a string message name or - * array message name and parameters, like the second argument to - * OutputPage::wrapWikiMsg(). + * @param $err Array: error messages. Each item is an error message. + * It may either be a string message name or array message name and + * parameters, like the second argument to OutputPage::wrapWikiMsg(). */ function showForm( $err ) { - global $wgOut, $wgUser, $wgContLang, $wgFixDoubleRedirects; - - $skin = $this->getSkin(); + global $wgContLang, $wgFixDoubleRedirects, $wgMaximumMovedPages; - $oldTitleLink = $skin->link( $this->oldTitle ); + $this->getSkin()->setRelevantTitle( $this->oldTitle ); - $wgOut->setPagetitle( wfMsg( 'move-page', $this->oldTitle->getPrefixedText() ) ); - $skin->setRelevantTitle( $this->oldTitle ); + $oldTitleLink = Linker::link( $this->oldTitle ); - $wgOut->addModules( 'mediawiki.special.movePage' ); + $out = $this->getOutput(); + $out->setPageTitle( $this->msg( 'move-page', $this->oldTitle->getPrefixedText() ) ); + $out->addModules( 'mediawiki.special.movePage' ); $newTitle = $this->newTitle; - if( !$newTitle ) { + if ( !$newTitle ) { # Show the current title as a default # when the form is first opened. $newTitle = $this->oldTitle; - } - else { - if( empty($err) ) { - # If a title was supplied, probably from the move log revert - # link, check for validity. We can then show some diagnostic - # information and save a click. - $newerr = $this->oldTitle->isValidMoveOperation( $newTitle ); - if( $newerr ) { - $err = $newerr[0]; - } + } elseif ( !count( $err ) ) { + # If a title was supplied, probably from the move log revert + # link, check for validity. We can then show some diagnostic + # information and save a click. + $newerr = $this->oldTitle->isValidMoveOperation( $newTitle ); + if( is_array( $newerr ) ) { + $err = $newerr; } } - if ( !empty($err) && $err[0] == 'articleexists' && $wgUser->isAllowed( 'delete' ) ) { - $wgOut->addWikiMsg( 'delete_and_move_text', $newTitle->getPrefixedText() ); + $user = $this->getUser(); + + if ( count( $err ) == 1 && isset( $err[0][0] ) && $err[0][0] == 'articleexists' + && $newTitle->quickUserCan( 'delete', $user ) + ) { + $out->addWikiMsg( 'delete_and_move_text', $newTitle->getPrefixedText() ); $movepagebtn = wfMsg( 'delete_and_move' ); $submitVar = 'wpDeleteAndMove'; $confirm = " @@ -148,26 +149,38 @@ class MovePageForm extends UnlistedSpecialPage { Xml::checkLabel( wfMsg( 'delete_and_move_confirm' ), 'wpConfirm', 'wpConfirm' ) . " "; - $err = ''; + $err = array(); } else { if ($this->oldTitle->getNamespace() == NS_USER && !$this->oldTitle->isSubpage() ) { - $wgOut->wrapWikiMsg( "
      \n$1\n
      ", 'moveuserpage-warning' ); + $out->wrapWikiMsg( "
      \n$1\n
      ", 'moveuserpage-warning' ); } - $wgOut->addWikiMsg( $wgFixDoubleRedirects ? 'movepagetext' : + $out->addWikiMsg( $wgFixDoubleRedirects ? 'movepagetext' : 'movepagetext-noredirectfixer' ); $movepagebtn = wfMsg( 'movepagebtn' ); $submitVar = 'wpMove'; $confirm = false; } - if ( !empty($err) && $err[0] == 'file-exists-sharedrepo' && $wgUser->isAllowed( 'reupload-shared' ) ) { - $wgOut->addWikiMsg( 'move-over-sharedrepo', $newTitle->getPrefixedText() ); + if ( count( $err ) == 1 && isset( $err[0][0] ) && $err[0][0] == 'file-exists-sharedrepo' + && $user->isAllowed( 'reupload-shared' ) + ) { + $out->addWikiMsg( 'move-over-sharedrepo', $newTitle->getPrefixedText() ); $submitVar = 'wpMoveOverSharedFile'; - $err = ''; + $err = array(); } $oldTalk = $this->oldTitle->getTalkPage(); - $considerTalk = ( !$this->oldTitle->isTalkPage() && $oldTalk->exists() ); + $oldTitleSubpages = $this->oldTitle->hasSubpages(); + $oldTitleTalkSubpages = $this->oldTitle->getTalkPage()->hasSubpages(); + + $canMoveSubpage = ( $oldTitleSubpages || $oldTitleTalkSubpages ) && + !count( $this->oldTitle->getUserPermissionsErrors( 'move-subpages', $user ) ); + + # We also want to be able to move assoc. subpage talk-pages even if base page + # has no associated talk page, so || with $oldTitleTalkSubpages. + $considerTalk = !$this->oldTitle->isTalkPage() && + ( $oldTalk->exists() + || ( $oldTitleTalkSubpages && $canMoveSubpage ) ); $dbr = wfGetDB( DB_SLAVE ); if ( $wgFixDoubleRedirects ) { @@ -181,20 +194,36 @@ class MovePageForm extends UnlistedSpecialPage { } if ( $considerTalk ) { - $wgOut->addWikiMsg( 'movepagetalktext' ); + $out->addWikiMsg( 'movepagetalktext' ); } - $token = htmlspecialchars( $wgUser->editToken() ); + if ( count( $err ) ) { + $out->addHTML( "
      \n" ); + $action_desc = $this->msg( 'action-move' )->plain(); + $out->addWikiMsg( 'permissionserrorstext-withaction', count( $err ), $action_desc ); - if ( !empty($err) ) { - $wgOut->setSubtitle( wfMsg( 'formerror' ) ); - if( $err[0] == 'hookaborted' ) { - $hookErr = $err[1]; - $errMsg = "

      $hookErr

      \n"; - $wgOut->addHTML( $errMsg ); + if ( count( $err ) == 1 ) { + $errMsg = $err[0]; + $errMsgName = array_shift( $errMsg ); + if ( $errMsgName == 'hookaborted' ) { + $out->addHTML( "

      {$errMsg[0]}

      \n" ); + } else { + $out->addWikiMsgArray( $errMsgName, $errMsg ); + } } else { - $wgOut->wrapWikiMsg( "

      \n$1\n

      ", $err ); + $errStr = array(); + foreach( $err as $errMsg ) { + if( $errMsg[0] == 'hookaborted' ) { + $errStr[] = $errMsg[1]; + } else { + $errMsgName = array_shift( $errMsg ); + $errStr[] = $this->msg( $errMsgName, $errMsg )->parse(); + } + } + + $out->addHTML( '
      • ' . implode( "
      • \n
      • ", $errStr ) . "
      \n" ); } + $out->addHTML( "
      \n" ); } if ( $this->oldTitle->isProtected( 'move' ) ) { @@ -207,13 +236,16 @@ class MovePageForm extends UnlistedSpecialPage { $noticeMsg = 'protectedpagemovewarning'; $classes[] = 'mw-textarea-protected'; } - $wgOut->addHTML( "
      \n" ); - $wgOut->addWikiMsg( $noticeMsg ); - LogEventsList::showLogExtract( $wgOut, 'protect', $this->oldTitle->getPrefixedText(), '', array( 'lim' => 1 ) ); - $wgOut->addHTML( "
      \n" ); + $out->addHTML( "
      \n" ); + $out->addWikiMsg( $noticeMsg ); + LogEventsList::showLogExtract( $out, 'protect', $this->oldTitle, '', array( 'lim' => 1 ) ); + $out->addHTML( "
      \n" ); } - $wgOut->addHTML( + // Byte limit (not string length limit) for wpReason and wpNewTitleMain + // is enforced in the mediawiki.special.movePage module + + $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' ) ) . @@ -228,10 +260,18 @@ class MovePageForm extends UnlistedSpecialPage { " . - Xml::label( wfMsg( 'newtitle' ), 'wpNewTitle' ) . + Xml::label( wfMsg( 'newtitle' ), 'wpNewTitleMain' ) . " " . - Xml::input( 'wpNewTitle', 40, $wgContLang->recodeForEdit( $newTitle->getPrefixedText() ), array( 'type' => 'text', 'id' => 'wpNewTitle' ) ) . + Html::namespaceSelector( + array( 'selected' => $newTitle->getNamespace() ), + array( 'name' => 'wpNewTitleNs', 'id' => 'wpNewTitleNs' ) + ) . + Xml::input( 'wpNewTitleMain', 60, $wgContLang->recodeForEdit( $newTitle->getText() ), array( + 'type' => 'text', + 'id' => 'wpNewTitleMain', + 'maxlength' => 255, + ) ) . Html::hidden( 'wpOldTitle', $this->oldTitle->getPrefixedText() ) . " @@ -241,13 +281,13 @@ class MovePageForm extends UnlistedSpecialPage { " " . Html::element( 'textarea', array( 'name' => 'wpReason', 'id' => 'wpReason', 'cols' => 60, 'rows' => 2, - 'maxlength' => 200 ), $this->reason ) . // maxlength byte limit is enforce in mediawiki.special.movePage.js + 'maxlength' => 200 ), $this->reason ) . " " ); if( $considerTalk ) { - $wgOut->addHTML( " + $out->addHTML( " " . @@ -257,8 +297,8 @@ class MovePageForm extends UnlistedSpecialPage { ); } - if ( $wgUser->isAllowed( 'suppressredirect' ) ) { - $wgOut->addHTML( " + if ( $user->isAllowed( 'suppressredirect' ) ) { + $out->addHTML( " " . @@ -270,7 +310,7 @@ class MovePageForm extends UnlistedSpecialPage { } if ( $hasRedirects ) { - $wgOut->addHTML( " + $out->addHTML( " " . @@ -281,12 +321,8 @@ class MovePageForm extends UnlistedSpecialPage { ); } - if( ($this->oldTitle->hasSubpages() || $this->oldTitle->getTalkPage()->hasSubpages()) - && $this->oldTitle->userCan( 'move-subpages' ) ) - { - global $wgMaximumMovedPages, $wgLang; - - $wgOut->addHTML( " + if( $canMoveSubpage ) { + $out->addHTML( " " . @@ -303,7 +339,7 @@ class MovePageForm extends UnlistedSpecialPage { ? 'move-subpages' : 'move-talk-subpages' ), array( 'parseinline' ), - $wgLang->formatNum( $wgMaximumMovedPages ), + $this->getLanguage()->formatNum( $wgMaximumMovedPages ), # $2 to allow use of PLURAL in message. $wgMaximumMovedPages ) @@ -313,11 +349,11 @@ class MovePageForm extends UnlistedSpecialPage { ); } - $watchChecked = $wgUser->isLoggedIn() && ($this->watch || $wgUser->getBoolOption( 'watchmoves' ) + $watchChecked = $user->isLoggedIn() && ($this->watch || $user->getBoolOption( 'watchmoves' ) || $this->oldTitle->userIsWatching()); # Don't allow watching if user is not logged in - if( $wgUser->isLoggedIn() ) { - $wgOut->addHTML( " + if( $user->isLoggedIn() ) { + $out->addHTML( " " . @@ -326,7 +362,7 @@ class MovePageForm extends UnlistedSpecialPage { "); } - $wgOut->addHTML( " + $out->addHTML( " {$confirm}   @@ -335,69 +371,74 @@ class MovePageForm extends UnlistedSpecialPage { " " . Xml::closeElement( 'table' ) . - Html::hidden( 'wpEditToken', $token ) . + Html::hidden( 'wpEditToken', $user->getEditToken() ) . Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' ) . "\n" ); - $this->showLogFragment( $this->oldTitle, $wgOut ); - $this->showSubpages( $this->oldTitle, $wgOut ); + $this->showLogFragment( $this->oldTitle ); + $this->showSubpages( $this->oldTitle ); } function doSubmit() { - global $wgOut, $wgUser, $wgMaximumMovedPages, $wgLang; - global $wgFixDoubleRedirects; + global $wgMaximumMovedPages, $wgFixDoubleRedirects, $wgDeleteRevisionsLimit; - if ( $wgUser->pingLimiter( 'move' ) ) { - $wgOut->rateLimited(); - return; + $user = $this->getUser(); + + if ( $user->pingLimiter( 'move' ) ) { + throw new ThrottledError; } $ot = $this->oldTitle; $nt = $this->newTitle; - # Delete to make way if requested - if ( $wgUser->isAllowed( 'delete' ) && $this->deleteAndMove ) { - $article = new Article( $nt ); - - # Disallow deletions of big articles - $bigHistory = $article->isBigDeletion(); - if( $bigHistory && !$nt->userCan( 'bigdelete' ) ) { - global $wgDeleteRevisionsLimit; - $this->showForm( array('delete-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) ); - return; - } - - // Delete an associated image if there is - $file = wfLocalFile( $nt ); - if( $file->exists() ) { - $file->delete( wfMsgForContent( 'delete_and_move_reason' ), false ); - } - - // This may output an error message and exit - $article->doDelete( wfMsgForContent( 'delete_and_move_reason' ) ); - } - # don't allow moving to pages with # in if ( !$nt || $nt->getFragment() != '' ) { - $this->showForm( 'badtitletext' ); + $this->showForm( array( array( 'badtitletext' ) ) ); return; } # Show a warning if the target file exists on a shared repo if ( $nt->getNamespace() == NS_FILE - && !( $this->moveOverShared && $wgUser->isAllowed( 'reupload-shared' ) ) + && !( $this->moveOverShared && $user->isAllowed( 'reupload-shared' ) ) && !RepoGroup::singleton()->getLocalRepo()->findFile( $nt ) && wfFindFile( $nt ) ) { - $this->showForm( array('file-exists-sharedrepo') ); + $this->showForm( array( array( 'file-exists-sharedrepo' ) ) ); return; } - if ( $wgUser->isAllowed( 'suppressredirect' ) ) { + # Delete to make way if requested + if ( $this->deleteAndMove ) { + $permErrors = $nt->getUserPermissionsErrors( 'delete', $user ); + if ( count( $permErrors ) ) { + # Only show the first error + $this->showForm( $permErrors ); + return; + } + + $reason = wfMessage( 'delete_and_move_reason', $ot )->inContentLanguage()->text(); + + // Delete an associated image if there is + if ( $nt->getNamespace() == NS_FILE ) { + $file = wfLocalFile( $nt ); + if ( $file->exists() ) { + $file->delete( $reason, false ); + } + } + + $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() ) ) ) ); + return; + } + } + + if ( $user->isAllowed( 'suppressredirect' ) ) { $createRedirect = $this->leaveRedirect; } else { $createRedirect = true; @@ -406,8 +447,7 @@ class MovePageForm extends UnlistedSpecialPage { # Do the actual move. $error = $ot->moveTo( $nt, true, $this->reason, $createRedirect ); if ( $error !== true ) { - # @todo FIXME: Show all the errors in a list, not just the first one - $this->showForm( reset( $error ) ); + $this->showForm( $error ); return; } @@ -417,18 +457,23 @@ class MovePageForm extends UnlistedSpecialPage { wfRunHooks( 'SpecialMovepageAfterMove', array( &$this, &$ot, &$nt ) ); - $wgOut->setPagetitle( wfMsg( 'pagemovedsub' ) ); + $out = $this->getOutput(); + $out->setPagetitle( wfMsg( 'pagemovedsub' ) ); - $oldUrl = $ot->getFullUrl( 'redirect=no' ); - $newUrl = $nt->getFullUrl(); + $oldLink = Linker::link( + $ot, + null, + array(), + array( 'redirect' => 'no' ) + ); + $newLink = Linker::linkKnown( $nt ); $oldText = $ot->getPrefixedText(); $newText = $nt->getPrefixedText(); - $oldLink = "[$oldUrl $oldText]"; - $newLink = "[$newUrl $newText]"; $msgName = $createRedirect ? 'movepage-moved-redirect' : 'movepage-moved-noredirect'; - $wgOut->addWikiMsg( 'movepage-moved', $oldLink, $newLink, $oldText, $newText ); - $wgOut->addWikiMsg( $msgName ); + $out->addHTML( wfMessage( 'movepage-moved' )->rawParams( $oldLink, + $newLink )->params( $oldText, $newText )->parseAsBlock() ); + $out->addWikiMsg( $msgName ); # Now we move extra pages we've been asked to move: subpages and talk # pages. First, if the old page or the new page is a talk page, we @@ -437,7 +482,7 @@ class MovePageForm extends UnlistedSpecialPage { $this->moveTalk = false; } - if( !$ot->userCan( 'move-subpages' ) ) { + if ( count( $ot->getUserPermissionsErrors( 'move-subpages', $user ) ) ) { $this->moveSubpages = false; } @@ -494,7 +539,6 @@ class MovePageForm extends UnlistedSpecialPage { } $extraOutput = array(); - $skin = $this->getSkin(); $count = 1; foreach( $extraPages as $oldSubpage ) { if( $ot->equals( $oldSubpage ) ) { @@ -516,7 +560,7 @@ class MovePageForm extends UnlistedSpecialPage { # be longer than 255 characters. $newSubpage = Title::makeTitleSafe( $newNs, $newPageName ); if( !$newSubpage ) { - $oldLink = $skin->linkKnown( $oldSubpage ); + $oldLink = Linker::linkKnown( $oldSubpage ); $extraOutput []= wfMsgHtml( 'movepage-page-unmoved', $oldLink, htmlspecialchars(Title::makeName( $newNs, $newPageName ))); continue; @@ -524,7 +568,7 @@ class MovePageForm extends UnlistedSpecialPage { # This was copy-pasted from Renameuser, bleh. if ( $newSubpage->exists() && !$oldSubpage->isValidMoveTarget( $newSubpage ) ) { - $link = $skin->linkKnown( $newSubpage ); + $link = Linker::linkKnown( $newSubpage ); $extraOutput []= wfMsgHtml( 'movepage-page-exists', $link ); } else { $success = $oldSubpage->moveTo( $newSubpage, true, $this->reason, $createRedirect ); @@ -532,22 +576,22 @@ class MovePageForm extends UnlistedSpecialPage { if ( $this->fixRedirects ) { DoubleRedirectJob::fixRedirects( 'move', $oldSubpage, $newSubpage ); } - $oldLink = $skin->linkKnown( + $oldLink = Linker::link( $oldSubpage, null, array(), array( 'redirect' => 'no' ) ); - $newLink = $skin->linkKnown( $newSubpage ); + $newLink = Linker::linkKnown( $newSubpage ); $extraOutput []= wfMsgHtml( 'movepage-page-moved', $oldLink, $newLink ); ++$count; if( $count >= $wgMaximumMovedPages ) { - $extraOutput []= wfMsgExt( 'movepage-max-pages', array( 'parsemag', 'escape' ), $wgLang->formatNum( $wgMaximumMovedPages ) ); + $extraOutput []= wfMsgExt( 'movepage-max-pages', array( 'parsemag', 'escape' ), $this->getLanguage()->formatNum( $wgMaximumMovedPages ) ); break; } } else { - $oldLink = $skin->linkKnown( $oldSubpage ); - $newLink = $skin->link( $newSubpage ); + $oldLink = Linker::linkKnown( $oldSubpage ); + $newLink = Linker::link( $newSubpage ); $extraOutput []= wfMsgHtml( 'movepage-page-unmoved', $oldLink, $newLink ); } } @@ -555,16 +599,16 @@ class MovePageForm extends UnlistedSpecialPage { } if( $extraOutput !== array() ) { - $wgOut->addHTML( "
        \n
      • " . implode( "
      • \n
      • ", $extraOutput ) . "
      • \n
      " ); + $out->addHTML( "
        \n
      • " . implode( "
      • \n
      • ", $extraOutput ) . "
      • \n
      " ); } # Deal with watches (we don't watch subpages) - if( $this->watch && $wgUser->isLoggedIn() ) { - $wgUser->addWatch( $ot ); - $wgUser->addWatch( $nt ); + if( $this->watch && $user->isLoggedIn() ) { + $user->addWatch( $ot ); + $user->addWatch( $nt ); } else { - $wgUser->removeWatch( $ot ); - $wgUser->removeWatch( $nt ); + $user->removeWatch( $ot ); + $user->removeWatch( $nt ); } # Re-clear the file redirect cache, which may have been polluted by @@ -575,20 +619,20 @@ class MovePageForm extends UnlistedSpecialPage { } } - function showLogFragment( $title, &$out ) { + function showLogFragment( $title ) { + $out = $this->getOutput(); $out->addHTML( Xml::element( 'h2', null, LogPage::logName( 'move' ) ) ); - LogEventsList::showLogExtract( $out, 'move', $title->getPrefixedText() ); + LogEventsList::showLogExtract( $out, 'move', $title ); } - function showSubpages( $title, $out ) { - global $wgLang; - + function showSubpages( $title ) { if( !MWNamespace::hasSubpages( $title->getNamespace() ) ) return; $subpages = $title->getSubpages(); $count = $subpages instanceof TitleArray ? $subpages->count() : 0; + $out = $this->getOutput(); $out->wrapWikiMsg( '== $1 ==', array( 'movesubpage', $count ) ); # No subpages. @@ -597,15 +641,13 @@ class MovePageForm extends UnlistedSpecialPage { return; } - $out->addWikiMsg( 'movesubpagetext', $wgLang->formatNum( $count ) ); - $skin = $this->getSkin(); + $out->addWikiMsg( 'movesubpagetext', $this->getLanguage()->formatNum( $count ) ); $out->addHTML( "
        \n" ); foreach( $subpages as $subpage ) { - $link = $skin->link( $subpage ); + $link = Linker::link( $subpage ); $out->addHTML( "
      • $link
      • \n" ); } $out->addHTML( "
      \n" ); } } - diff --git a/includes/specials/SpecialNewimages.php b/includes/specials/SpecialNewimages.php index ea20c2f7..b88123dc 100644 --- a/includes/specials/SpecialNewimages.php +++ b/includes/specials/SpecialNewimages.php @@ -30,7 +30,7 @@ class SpecialNewFiles extends IncludableSpecialPage { $this->setHeaders(); $this->outputHeader(); - $pager = new NewFilesPager( $par ); + $pager = new NewFilesPager( $this->getContext(), $par ); if ( !$this->including() ) { $form = $pager->getForm(); @@ -50,18 +50,16 @@ class SpecialNewFiles extends IncludableSpecialPage { */ class NewFilesPager extends ReverseChronologicalPager { - function __construct( $par = null ) { - global $wgRequest; + /** + * @var ImageGallery + */ + var $gallery; - $this->like = $wgRequest->getText( 'like' ); - $this->showbots = $wgRequest->getBool( 'showbots' , 0 ); - $this->skin = $this->getSkin(); + function __construct( IContextSource $context, $par = null ) { + $this->like = $context->getRequest()->getText( 'like' ); + $this->showbots = $context->getRequest()->getBool( 'showbots' , 0 ); - parent::__construct(); - } - - function getTitle() { - return SpecialPage::getTitleFor( 'Newimages' ); + parent::__construct( $context ); } function getQueryInfo() { @@ -105,7 +103,10 @@ class NewFilesPager extends ReverseChronologicalPager { } function getStartBody(){ - $this->gallery = new ImageGallery(); + if ( !$this->gallery ) { + $this->gallery = new ImageGallery(); + } + return ''; } function getEndBody(){ @@ -113,24 +114,22 @@ class NewFilesPager extends ReverseChronologicalPager { } function formatRow( $row ) { - global $wgLang; - $name = $row->img_name; $user = User::newFromId( $row->img_user ); $title = Title::makeTitle( NS_FILE, $name ); - $ul = $this->skin->link( $user->getUserpage(), $user->getName() ); + $ul = Linker::link( $user->getUserpage(), $user->getName() ); $this->gallery->add( $title, "$ul
      \n" - . htmlspecialchars( $wgLang->timeanddate( $row->img_timestamp, true ) ) + . htmlspecialchars( $this->getLanguage()->timeanddate( $row->img_timestamp, true ) ) . "
      \n" ); } function getForm() { - global $wgRequest, $wgMiserMode; + global $wgMiserMode; $fields = array( 'like' => array( @@ -142,16 +141,16 @@ class NewFilesPager extends ReverseChronologicalPager { 'type' => 'check', 'label' => wfMessage( 'showhidebots', wfMsg( 'show' ) ), 'name' => 'showbots', - # 'default' => $wgRequest->getBool( 'showbots', 0 ), + # 'default' => $this->getRequest()->getBool( 'showbots', 0 ), ), 'limit' => array( 'type' => 'hidden', - 'default' => $wgRequest->getText( 'limit' ), + 'default' => $this->getRequest()->getText( 'limit' ), 'name' => 'limit', ), 'offset' => array( 'type' => 'hidden', - 'default' => $wgRequest->getText( 'offset' ), + 'default' => $this->getRequest()->getText( 'offset' ), 'name' => 'offset', ), ); @@ -160,7 +159,7 @@ class NewFilesPager extends ReverseChronologicalPager { unset( $fields['like'] ); } - $form = new HTMLForm( $fields ); + $form = new HTMLForm( $fields, $this->getContext() ); $form->setTitle( $this->getTitle() ); $form->setSubmitText( wfMsg( 'ilsubmit' ) ); $form->setMethod( 'get' ); diff --git a/includes/specials/SpecialNewpages.php b/includes/specials/SpecialNewpages.php index bf9fb9f7..54bcb97f 100644 --- a/includes/specials/SpecialNewpages.php +++ b/includes/specials/SpecialNewpages.php @@ -78,7 +78,6 @@ class SpecialNewpages extends IncludableSpecialPage { } protected function parseParams( $par ) { - global $wgLang; $bits = preg_split( '/\s*,\s*/', trim( $par ) ); foreach ( $bits as $bit ) { if ( 'shownav' == $bit ) { @@ -112,7 +111,7 @@ class SpecialNewpages extends IncludableSpecialPage { $this->opts->setValue( 'username', $m[1] ); } if ( preg_match( '/^namespace=(.*)$/', $bit, $m ) ) { - $ns = $wgLang->getNsIndex( $m[1] ); + $ns = $this->getLanguage()->getNsIndex( $m[1] ); if( $ns !== false ) { $this->opts->setValue( 'namespace', $ns ); } @@ -139,11 +138,12 @@ class SpecialNewpages extends IncludableSpecialPage { // Settings $this->form(); - $this->setSyndicated(); $feedType = $this->opts->getValue( 'feed' ); if( $feedType ) { return $this->feed( $feedType ); } + + $out->setFeedAppendQuery( wfArrayToCGI( $this->opts->getAllValues() ) ); } $pager = new NewPagesPager( $this, $this->opts ); @@ -162,7 +162,7 @@ class SpecialNewpages extends IncludableSpecialPage { } protected function filterLinks() { - global $wgGroupPermissions, $wgLang; + global $wgGroupPermissions; // show/hide links $showhide = array( wfMsgHtml( 'show' ), wfMsgHtml( 'hide' ) ); @@ -194,13 +194,13 @@ class SpecialNewpages extends IncludableSpecialPage { $self = $this->getTitle(); foreach ( $filters as $key => $msg ) { $onoff = 1 - $this->opts->getValue( $key ); - $link = $this->getSkin()->link( $self, $showhide[$onoff], array(), + $link = Linker::link( $self, $showhide[$onoff], array(), array( $key => $onoff ) + $changed ); $links[$key] = wfMsgHtml( $msg, $link ); } - return $wgLang->pipeList( $links ); + return $this->getLanguage()->pipeList( $links ); } protected function form() { @@ -276,12 +276,6 @@ class SpecialNewpages extends IncludableSpecialPage { $this->getOutput()->addHTML( $form ); } - protected function setSyndicated() { - $out = $this->getOutput(); - $out->setSyndicated( true ); - $out->setFeedAppendQuery( wfArrayToCGI( $this->opts->getAllValues() ) ); - } - /** * Format a row, providing the timestamp, links to the page/history, size, user links, and a comment * @@ -289,8 +283,6 @@ class SpecialNewpages extends IncludableSpecialPage { * @return String */ public function formatRow( $result ) { - global $wgLang; - # Revision deletion works on revisions, so we should cast one $row = array( 'comment' => $result->rc_comment, @@ -302,11 +294,19 @@ class SpecialNewpages extends IncludableSpecialPage { $classes = array(); - $dm = $wgLang->getDirMark(); + $lang = $this->getLanguage(); + $dm = $lang->getDirMark(); - $title = Title::makeTitleSafe( $result->rc_namespace, $result->rc_title ); - $time = Html::element( 'span', array( 'class' => 'mw-newpages-time' ), - $wgLang->timeAndDate( $result->rc_timestamp, true ) + $title = Title::newFromRow( $result ); + $spanTime = Html::element( 'span', array( 'class' => 'mw-newpages-time' ), + $lang->timeanddate( $result->rc_timestamp, true ) + ); + $time = Linker::linkKnown( + $title, + $spanTime, + array(), + array( 'oldid' => $result->rc_this_oldid ), + array() ); $query = array( 'redirect' => 'no' ); @@ -315,14 +315,14 @@ class SpecialNewpages extends IncludableSpecialPage { $query['rcid'] = $result->rc_id; } - $plink = $this->getSkin()->linkKnown( + $plink = Linker::linkKnown( $title, null, array( 'class' => 'mw-newpages-pagename' ), $query, array( 'known' ) // Set explicitly to avoid the default of 'known','noclasses'. This breaks the colouration for stubs ); - $histLink = $this->getSkin()->linkKnown( + $histLink = Linker::linkKnown( $title, wfMsgHtml( 'hist' ), array(), @@ -330,13 +330,12 @@ class SpecialNewpages extends IncludableSpecialPage { ); $hist = Html::rawElement( 'span', array( 'class' => 'mw-newpages-history' ), wfMsg( 'parentheses', $histLink ) ); - $length = Html::rawElement( 'span', array( 'class' => 'mw-newpages-length' ), - '[' . wfMsgExt( 'nbytes', array( 'parsemag', 'escape' ), $wgLang->formatNum( $result->length ) ) . - ']' + $length = Html::element( 'span', array( 'class' => 'mw-newpages-length' ), + '[' . $this->msg( 'nbytes' )->numParams( $result->length )->text() . ']' ); - $ulink = $this->getSkin()->revUserTools( $rev ); - $comment = $this->getSkin()->revComment( $rev ); + $ulink = Linker::revUserTools( $rev ); + $comment = Linker::revComment( $rev ); if ( $this->patrollable( $result ) ) { $classes[] = 'not-patrolled'; @@ -357,7 +356,14 @@ class SpecialNewpages extends IncludableSpecialPage { $css = count( $classes ) ? ' class="' . implode( ' ', $classes ) . '"' : ''; - return "{$time} {$dm}{$plink} {$hist} {$dm}{$length} {$dm}{$ulink} {$comment} {$tagDisplay}\n"; + # Display the old title if the namespace 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(); + } + + return "{$time} {$dm}{$plink} {$hist} {$dm}{$length} {$dm}{$ulink} {$comment} {$tagDisplay} {$oldTitleText}\n"; } /** @@ -461,33 +467,11 @@ class NewPagesPager extends ReverseChronologicalPager { protected $mForm; function __construct( $form, FormOptions $opts ) { - parent::__construct(); + parent::__construct( $form->getContext() ); $this->mForm = $form; $this->opts = $opts; } - /** - * @return Title - */ - function getTitle() { - static $title = null; - if ( $title === null ) { - $title = $this->mForm->getTitle(); - } - return $title; - } - - /** - * @return User - */ - function getUser() { - static $user = null; - if ( $user === null ) { - $user = $this->mForm->getUser(); - } - return $user; - } - function getQueryInfo() { global $wgEnableNewpagesUserFilter, $wgGroupPermissions; $conds = array(); @@ -531,7 +515,8 @@ 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' + 'page_len AS length', 'page_latest AS rev_id', 'ts_tags', 'rc_this_oldid', + 'page_namespace', 'page_title' ); $join_conds = array( 'page' => array( 'INNER JOIN', 'page_id=rc_cur_id' ) ); diff --git a/includes/specials/SpecialPasswordReset.php b/includes/specials/SpecialPasswordReset.php index db5268d6..62731e98 100644 --- a/includes/specials/SpecialPasswordReset.php +++ b/includes/specials/SpecialPasswordReset.php @@ -1,6 +1,6 @@ canChangePassword( $user ) === true && parent::userCanExecute( $user ); + } + + public function checkExecutePermissions( User $user ) { $error = $this->canChangePassword( $user ); if ( is_string( $error ) ) { throw new ErrorPageError( 'internalerror', $error ); - } else if ( !$error ) { + } elseif ( !$error ) { throw new ErrorPageError( 'internalerror', 'resetpass_forbidden' ); } - return parent::userCanExecute( $user ); + return parent::checkExecutePermissions( $user ); } protected function getFormFields() { @@ -69,6 +83,14 @@ class SpecialPasswordReset extends FormSpecialPage { ); } + if( $this->getUser()->isAllowed( 'passwordreset' ) ){ + $a['Capture'] = array( + 'type' => 'check', + 'label-message' => 'passwordreset-capture', + 'help-message' => 'passwordreset-capture-help', + ); + } + return $a; } @@ -109,6 +131,16 @@ class SpecialPasswordReset extends FormSpecialPage { } } + if( isset( $data['Capture'] ) && !$this->getUser()->isAllowed( 'passwordreset' ) ){ + // The user knows they don't have the passwordreset permission, but they tried to spoof the form. That's naughty + throw new PermissionsError( 'passwordreset' ); + } + + /** + * @var $firstUser User + * @var $users User[] + */ + if ( isset( $data['Username'] ) && $data['Username'] !== '' ) { $method = 'username'; $users = array( User::newFromName( $data['Username'] ) ); @@ -183,7 +215,7 @@ class SpecialPasswordReset extends FormSpecialPage { // We need to have a valid IP address for the hook, but per bug 18347, we should // send the user's name if they're logged in. - $ip = wfGetIP(); + $ip = $this->getRequest()->getIP(); if ( !$ip ) { return array( 'badipaddress' ); } @@ -207,8 +239,8 @@ class SpecialPasswordReset extends FormSpecialPage { } $passwordBlock = implode( "\n\n", $passwords ); - $body = wfMessage( $msg )->inLanguage( $userLanguage ); - $body->params( + $this->email = wfMessage( $msg )->inLanguage( $userLanguage ); + $this->email->params( $username, $passwordBlock, count( $passwords ), @@ -218,28 +250,49 @@ class SpecialPasswordReset extends FormSpecialPage { $title = wfMessage( 'passwordreset-emailtitle' ); - $result = $firstUser->sendMail( $title->text(), $body->text() ); + $this->result = $firstUser->sendMail( $title->escaped(), $this->email->escaped() ); + + // Blank the email if the user is not supposed to see it + if( !isset( $data['Capture'] ) || !$data['Capture'] ) { + $this->email = null; + } - if ( $result->isGood() ) { + if ( $this->result->isGood() ) { + return true; + } elseif( isset( $data['Capture'] ) && $data['Capture'] ){ + // The email didn't send, but maybe they knew that and that's why they captured it return true; } else { // @todo FIXME: The email didn't send, but we have already set the password throttle // timestamp, so they won't be able to try again until it expires... :( - return array( array( 'mailerror', $result->getMessage() ) ); + return array( array( 'mailerror', $this->result->getMessage() ) ); } } public function onSuccess() { + if( $this->getUser()->isAllowed( 'passwordreset' ) && $this->email != null ){ + // @todo: Logging + + if( $this->result->isGood() ){ + $this->getOutput()->addWikiMsg( 'passwordreset-emailsent-capture' ); + } else { + $this->getOutput()->addWikiMsg( 'passwordreset-emailerror-capture', $this->result->getMessage() ); + } + + $this->getOutput()->addHTML( Html::rawElement( 'pre', array(), $this->email->escaped() ) ); + } + $this->getOutput()->addWikiMsg( 'passwordreset-emailsent' ); $this->getOutput()->returnToMain(); } - function canChangePassword(User $user) { + protected function canChangePassword( User $user ) { global $wgPasswordResetRoutes, $wgAuth; // Maybe password resets are disabled, or there are no allowable routes if ( !is_array( $wgPasswordResetRoutes ) || - !in_array( true, array_values( $wgPasswordResetRoutes ) ) ) { + !in_array( true, array_values( $wgPasswordResetRoutes ) ) ) + { return 'passwordreset-disabled'; } @@ -257,15 +310,12 @@ class SpecialPasswordReset extends FormSpecialPage { return true; } - /** * Hide the password reset page if resets are disabled. * @return Bool */ function isListed() { - global $wgUser; - - if ( $this->canChangePassword( $wgUser ) === true ) { + if ( $this->canChangePassword( $this->getUser() ) === true ) { return parent::isListed(); } diff --git a/includes/specials/SpecialPopularpages.php b/includes/specials/SpecialPopularpages.php index 7c7190ad..803f03e7 100644 --- a/includes/specials/SpecialPopularpages.php +++ b/includes/specials/SpecialPopularpages.php @@ -36,6 +36,7 @@ class PopularPagesPage extends QueryPage { # page_counter is not indexed return true; } + function isSyndicated() { return false; } function getQueryInfo() { @@ -54,17 +55,13 @@ class PopularPagesPage extends QueryPage { * @return string */ function formatResult( $skin, $result ) { - global $wgLang, $wgContLang; + global $wgContLang; $title = Title::makeTitle( $result->namespace, $result->title ); - $link = $skin->linkKnown( + $link = Linker::linkKnown( $title, htmlspecialchars( $wgContLang->convert( $title->getPrefixedText() ) ) ); - $nv = wfMsgExt( - 'nviews', - array( 'parsemag', 'escape'), - $wgLang->formatNum( $result->value ) - ); - return wfSpecialList($link, $nv); + $nv = $this->msg( 'nviews' )->numParams( $result->value )->escaped(); + return $this->getLanguage()->specialList( $link, $nv ); } } diff --git a/includes/specials/SpecialPreferences.php b/includes/specials/SpecialPreferences.php index edc26bc1..946112bf 100644 --- a/includes/specials/SpecialPreferences.php +++ b/includes/specials/SpecialPreferences.php @@ -31,70 +31,60 @@ class SpecialPreferences extends SpecialPage { parent::__construct( 'Preferences' ); } - function execute( $par ) { - global $wgOut, $wgUser, $wgRequest; - + public function execute( $par ) { $this->setHeaders(); $this->outputHeader(); - $wgOut->disallowUserJs(); # Prevent hijacked user scripts from sniffing passwords etc. + $out = $this->getOutput(); + $out->disallowUserJs(); # Prevent hijacked user scripts from sniffing passwords etc. - if ( $wgUser->isAnon() ) { - $wgOut->showErrorPage( 'prefsnologin', 'prefsnologintext', array( $this->getTitle()->getPrefixedDBkey() ) ); - return; - } - if ( wfReadOnly() ) { - $wgOut->readOnlyPage(); + $user = $this->getUser(); + if ( $user->isAnon() ) { + $out->showErrorPage( 'prefsnologin', 'prefsnologintext', array( $this->getTitle()->getPrefixedDBkey() ) ); return; } + $this->checkReadOnly(); if ( $par == 'reset' ) { $this->showResetForm(); return; } - $wgOut->addModules( 'mediawiki.special.preferences' ); + $out->addModules( 'mediawiki.special.preferences' ); - if ( $wgRequest->getCheck( 'success' ) ) { - $wgOut->wrapWikiMsg( + if ( $this->getRequest()->getCheck( 'success' ) ) { + $out->wrapWikiMsg( "
      \n$1\n
      ", 'savedprefs' ); } - if ( $wgRequest->getCheck( 'eauth' ) ) { - $wgOut->wrapWikiMsg( "
      \n$1\n
      ", - 'eauthentsent', $wgUser->getName() ); - } - - $htmlForm = Preferences::getFormObject( $wgUser ); + $htmlForm = Preferences::getFormObject( $user, $this->getContext() ); $htmlForm->setSubmitCallback( array( 'Preferences', 'tryUISubmit' ) ); $htmlForm->show(); } - function showResetForm() { - global $wgOut; - - $wgOut->addWikiMsg( 'prefs-reset-intro' ); + private function showResetForm() { + $this->getOutput()->addWikiMsg( 'prefs-reset-intro' ); $htmlForm = new HTMLForm( array(), $this->getContext(), 'prefs-restore' ); $htmlForm->setSubmitText( wfMsg( 'restoreprefs' ) ); $htmlForm->setTitle( $this->getTitle( 'reset' ) ); - $htmlForm->setSubmitCallback( array( __CLASS__, 'submitReset' ) ); + $htmlForm->setSubmitCallback( array( $this, 'submitReset' ) ); $htmlForm->suppressReset(); $htmlForm->show(); } - static function submitReset( $formData ) { - global $wgUser, $wgOut; - $wgUser->resetOptions(); - $wgUser->saveSettings(); + public function submitReset( $formData ) { + $user = $this->getUser(); + $user->resetOptions(); + $user->saveSettings(); $url = SpecialPage::getTitleFor( 'Preferences' )->getFullURL( 'success' ); - $wgOut->redirect( $url ); + $this->getOutput()->redirect( $url ); return true; } diff --git a/includes/specials/SpecialPrefixindex.php b/includes/specials/SpecialPrefixindex.php index 28be4daf..495f15f7 100644 --- a/includes/specials/SpecialPrefixindex.php +++ b/includes/specials/SpecialPrefixindex.php @@ -38,23 +38,26 @@ class SpecialPrefixindex extends SpecialAllpages { * @param $par String: becomes "FOO" when called like Special:Prefixindex/FOO (default null) */ function execute( $par ) { - global $wgRequest, $wgOut, $wgContLang; + global $wgContLang; $this->setHeaders(); $this->outputHeader(); - $wgOut->addModuleStyles( 'mediawiki.special' ); + + $out = $this->getOutput(); + $out->addModuleStyles( 'mediawiki.special' ); # GET values - $from = $wgRequest->getVal( 'from', '' ); - $prefix = $wgRequest->getVal( 'prefix', '' ); - $ns = $wgRequest->getIntOrNull( 'namespace' ); + $request = $this->getRequest(); + $from = $request->getVal( 'from', '' ); + $prefix = $request->getVal( 'prefix', '' ); + $ns = $request->getIntOrNull( 'namespace' ); $namespace = (int)$ns; // if no namespace given, use 0 (NS_MAIN). $namespaces = $wgContLang->getNamespaces(); - $wgOut->setPagetitle( + $out->setPageTitle( ( $namespace > 0 && in_array( $namespace, array_keys( $namespaces ) ) ) - ? wfMsg( 'allinnamespace', str_replace( '_', ' ', $namespaces[$namespace] ) ) - : wfMsg( 'prefixindex' ) + ? $this->msg( 'prefixindex-namespace', str_replace( '_', ' ', $namespaces[$namespace] ) ) + : $this->msg( 'prefixindex' ) ); $showme = ''; @@ -62,8 +65,9 @@ class SpecialPrefixindex extends SpecialAllpages { $showme = $par; } elseif( $prefix != '' ) { $showme = $prefix; - } elseif( $from != '' ) { + } elseif( $from != '' && $ns === null ) { // For back-compat with Special:Allpages + // Don't do this if namespace is passed, so paging works when doing NS views. $showme = $from; } @@ -71,7 +75,7 @@ class SpecialPrefixindex extends SpecialAllpages { if ( $this->including() || $showme != '' || $ns !== null ) { $this->showPrefixChunk( $namespace, $showme, $from ); } else { - $wgOut->addHTML( $this->namespacePrefixForm( $namespace, null ) ); + $out->addHTML( $this->namespacePrefixForm( $namespace, null ) ); } } @@ -82,11 +86,10 @@ class SpecialPrefixindex extends SpecialAllpages { */ function namespacePrefixForm( $namespace = NS_MAIN, $from = '' ) { global $wgScript; - $t = $this->getTitle(); $out = Xml::openElement( 'div', array( 'class' => 'namespaceoptions' ) ); $out .= Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ); - $out .= Html::hidden( 'title', $t->getPrefixedText() ); + $out .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ); $out .= Xml::openElement( 'fieldset' ); $out .= Xml::element( 'legend', null, wfMsg( 'allpages' ) ); $out .= Xml::openElement( 'table', array( 'id' => 'nsselect', 'class' => 'allpages' ) ); @@ -120,11 +123,11 @@ class SpecialPrefixindex extends SpecialAllpages { * @param $from String: list all pages from this name (default FALSE) */ function showPrefixChunk( $namespace = NS_MAIN, $prefix, $from = null ) { - global $wgOut, $wgContLang, $wgLang; - - $sk = $this->getSkin(); + global $wgContLang; - if (!isset($from)) $from = $prefix; + if ( $from === null ) { + $from = $prefix; + } $fromList = $this->getNamespaceKeyAndText($namespace, $from); $prefixList = $this->getNamespaceKeyAndText($namespace, $prefix); @@ -169,7 +172,7 @@ class SpecialPrefixindex extends SpecialAllpages { $t = Title::makeTitle( $s->page_namespace, $s->page_title ); if( $t ) { $link = ($s->page_is_redirect ? '
      ' : '' ) . - $sk->linkKnown( + Linker::linkKnown( $t, htmlspecialchars( $t->getText() ) ) . @@ -214,10 +217,11 @@ class SpecialPrefixindex extends SpecialAllpages { 'prefix' => $prefix ); - if( $namespace ) { + if( $namespace || ($prefix == '')) { + // Keep the namespace even if it's 0 for empty prefixes. + // This tells us we're not just a holdover from old links. $query['namespace'] = $namespace; } - $nextLink = Linker::linkKnown( $self, wfMsgHtml( 'nextpage', str_replace( '_',' ', htmlspecialchars( $s->page_title ) ) ), diff --git a/includes/specials/SpecialProtectedpages.php b/includes/specials/SpecialProtectedpages.php index b1f61f09..eec974fe 100644 --- a/includes/specials/SpecialProtectedpages.php +++ b/includes/specials/SpecialProtectedpages.php @@ -36,8 +36,6 @@ class SpecialProtectedpages extends SpecialPage { } public function execute( $par ) { - global $wgOut, $wgRequest; - $this->setHeaders(); $this->outputHeader(); @@ -46,17 +44,18 @@ class SpecialProtectedpages extends SpecialPage { Title::purgeExpiredRestrictions(); } - $type = $wgRequest->getVal( $this->IdType ); - $level = $wgRequest->getVal( $this->IdLevel ); - $sizetype = $wgRequest->getVal( 'sizetype' ); - $size = $wgRequest->getIntOrNull( 'size' ); - $NS = $wgRequest->getIntOrNull( 'namespace' ); - $indefOnly = $wgRequest->getBool( 'indefonly' ) ? 1 : 0; - $cascadeOnly = $wgRequest->getBool('cascadeonly') ? 1 : 0; + $request = $this->getRequest(); + $type = $request->getVal( $this->IdType ); + $level = $request->getVal( $this->IdLevel ); + $sizetype = $request->getVal( 'sizetype' ); + $size = $request->getIntOrNull( 'size' ); + $NS = $request->getIntOrNull( 'namespace' ); + $indefOnly = $request->getBool( 'indefonly' ) ? 1 : 0; + $cascadeOnly = $request->getBool('cascadeonly') ? 1 : 0; $pager = new ProtectedPagesPager( $this, array(), $type, $level, $NS, $sizetype, $size, $indefOnly, $cascadeOnly ); - $wgOut->addHTML( $this->showOptions( $NS, $type, $level, $sizetype, $size, $indefOnly, $cascadeOnly ) ); + $this->getOutput()->addHTML( $this->showOptions( $NS, $type, $level, $sizetype, $size, $indefOnly, $cascadeOnly ) ); if( $pager->getNumRows() ) { $s = $pager->getNavigationBar(); @@ -67,7 +66,7 @@ class SpecialProtectedpages extends SpecialPage { } else { $s = '

      ' . wfMsgHtml( 'protectedpagesempty' ) . '

      '; } - $wgOut->addHTML( $s ); + $this->getOutput()->addHTML( $s ); } /** @@ -76,19 +75,16 @@ class SpecialProtectedpages extends SpecialPage { * @return string Formatted
    3. element */ public function formatRow( $row ) { - global $wgUser, $wgLang; - wfProfileIn( __METHOD__ ); - static $skin = null, $infinity = null; + static $infinity = null; - if( is_null( $skin ) ){ - $skin = $wgUser->getSkin(); + if( is_null( $infinity ) ){ $infinity = wfGetDB( DB_SLAVE )->getInfinity(); } $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title ); - $link = $skin->link( $title ); + $link = Linker::link( $title ); $description_items = array (); @@ -101,27 +97,28 @@ class SpecialProtectedpages extends SpecialPage { } $stxt = ''; + $lang = $this->getLanguage(); - $expiry = $wgLang->formatExpiry( $row->pr_expiry, TS_MW ); + $expiry = $lang->formatExpiry( $row->pr_expiry, TS_MW ); if( $expiry != $infinity ) { $expiry_description = wfMsg( - 'protect-expiring', - $wgLang->timeanddate( $expiry ), - $wgLang->date( $expiry ), - $wgLang->time( $expiry ) + 'protect-expiring-local', + $lang->timeanddate( $expiry, true ), + $lang->date( $expiry, true ), + $lang->time( $expiry, true ) ); $description_items[] = htmlspecialchars($expiry_description); } if(!is_null($size = $row->page_len)) { - $stxt = $wgLang->getDirMark() . ' ' . $skin->formatRevisionSize( $size ); + $stxt = $lang->getDirMark() . ' ' . Linker::formatRevisionSize( $size ); } # Show a link to the change protection form for allowed users otherwise a link to the protection log - if( $wgUser->isAllowed( 'protect' ) ) { - $changeProtection = ' (' . $skin->linkKnown( + if( $this->getUser()->isAllowed( 'protect' ) ) { + $changeProtection = ' (' . Linker::linkKnown( $title, wfMsgHtml( 'protect_change' ), array(), @@ -129,7 +126,7 @@ class SpecialProtectedpages extends SpecialPage { ) . ')'; } else { $ltitle = SpecialPage::getTitleFor( 'Log' ); - $changeProtection = ' (' . $skin->linkKnown( + $changeProtection = ' (' . Linker::linkKnown( $ltitle, wfMsgHtml( 'protectlogpage' ), array(), @@ -145,7 +142,7 @@ class SpecialProtectedpages extends SpecialPage { return Html::rawElement( 'li', array(), - wfSpecialList( $link . $stxt, $wgLang->commaList( $description_items ), false ) . $changeProtection ) . "\n"; + $lang->specialList( $link . $stxt, $lang->commaList( $description_items ), false ) . $changeProtection ) . "\n"; } /** @@ -160,7 +157,7 @@ class SpecialProtectedpages extends SpecialPage { */ protected function showOptions( $namespace, $type='edit', $level, $sizetype, $size, $indefOnly, $cascadeOnly ) { global $wgScript; - $title = SpecialPage::getTitleFor( 'Protectedpages' ); + $title = $this->getTitle(); return Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) . Xml::openElement( 'fieldset' ) . Xml::element( 'legend', array(), wfMsg( 'protectedpages' ) ) . @@ -306,7 +303,7 @@ class ProtectedPagesPager extends AlphabeticPager { $this->size = intval($size); $this->indefonly = (bool)$indefonly; $this->cascadeonly = (bool)$cascadeonly; - parent::__construct(); + parent::__construct( $form->getContext() ); } function getStartBody() { @@ -319,10 +316,6 @@ class ProtectedPagesPager extends AlphabeticPager { return ''; } - function getTitle() { - return SpecialPage::getTitleFor( 'Protectedpages' ); - } - function formatRow( $row ) { return $this->mForm->formatRow( $row ); } diff --git a/includes/specials/SpecialProtectedtitles.php b/includes/specials/SpecialProtectedtitles.php index 5fb91af7..982feb66 100644 --- a/includes/specials/SpecialProtectedtitles.php +++ b/includes/specials/SpecialProtectedtitles.php @@ -36,8 +36,6 @@ class SpecialProtectedtitles extends SpecialPage { } function execute( $par ) { - global $wgOut, $wgRequest; - $this->setHeaders(); $this->outputHeader(); @@ -46,15 +44,16 @@ class SpecialProtectedtitles extends SpecialPage { Title::purgeExpiredRestrictions(); } - $type = $wgRequest->getVal( $this->IdType ); - $level = $wgRequest->getVal( $this->IdLevel ); - $sizetype = $wgRequest->getVal( 'sizetype' ); - $size = $wgRequest->getIntOrNull( 'size' ); - $NS = $wgRequest->getIntOrNull( 'namespace' ); + $request = $this->getRequest(); + $type = $request->getVal( $this->IdType ); + $level = $request->getVal( $this->IdLevel ); + $sizetype = $request->getVal( 'sizetype' ); + $size = $request->getIntOrNull( 'size' ); + $NS = $request->getIntOrNull( 'namespace' ); $pager = new ProtectedTitlesPager( $this, array(), $type, $level, $NS, $sizetype, $size ); - $wgOut->addHTML( $this->showOptions( $NS, $type, $level ) ); + $this->getOutput()->addHTML( $this->showOptions( $NS, $type, $level ) ); if ( $pager->getNumRows() ) { $s = $pager->getNavigationBar(); @@ -65,7 +64,7 @@ class SpecialProtectedtitles extends SpecialPage { } else { $s = '

      ' . wfMsgHtml( 'protectedtitlesempty' ) . '

      '; } - $wgOut->addHTML( $s ); + $this->getOutput()->addHTML( $s ); } /** @@ -74,19 +73,16 @@ class SpecialProtectedtitles extends SpecialPage { * @return string */ function formatRow( $row ) { - global $wgLang; - wfProfileIn( __METHOD__ ); - static $skin = null, $infinity = null; + static $infinity = null; - if( is_null( $skin ) ){ - $skin = $this->getSkin(); + if( is_null( $infinity ) ){ $infinity = wfGetDB( DB_SLAVE )->getInfinity(); } $title = Title::makeTitleSafe( $row->pt_namespace, $row->pt_title ); - $link = $skin->link( $title ); + $link = Linker::link( $title ); $description_items = array (); @@ -94,17 +90,22 @@ class SpecialProtectedtitles extends SpecialPage { $description_items[] = $protType; - $expiry = strlen( $row->pt_expiry ) ? $wgLang->formatExpiry( $row->pt_expiry, TS_MW ) : $infinity; + $lang = $this->getLanguage(); + $expiry = strlen( $row->pt_expiry ) ? $lang->formatExpiry( $row->pt_expiry, TS_MW ) : $infinity; if( $expiry != $infinity ) { - - $expiry_description = wfMsg( 'protect-expiring', $wgLang->timeanddate( $expiry ) , $wgLang->date( $expiry ) , $wgLang->time( $expiry ) ); + $expiry_description = wfMsg( + 'protect-expiring-local', + $lang->timeanddate( $expiry, true ), + $lang->date( $expiry, true ), + $lang->time( $expiry, true ) + ); $description_items[] = htmlspecialchars($expiry_description); } wfProfileOut( __METHOD__ ); - return '
    4. ' . wfSpecialList( $link, implode( $description_items, ', ' ) ) . "
    5. \n"; + return '
    6. ' . $lang->specialList( $link, implode( $description_items, ', ' ) ) . "
    7. \n"; } /** @@ -116,7 +117,7 @@ class SpecialProtectedtitles extends SpecialPage { function showOptions( $namespace, $type='edit', $level ) { global $wgScript; $action = htmlspecialchars( $wgScript ); - $title = SpecialPage::getTitleFor( 'Protectedtitles' ); + $title = $this->getTitle(); $special = htmlspecialchars( $title->getPrefixedDBkey() ); return "
      \n" . '
      ' . @@ -189,7 +190,7 @@ class ProtectedTitlesPager extends AlphabeticPager { $this->level = $level; $this->namespace = $namespace; $this->size = intval($size); - parent::__construct(); + parent::__construct( $form->getContext() ); } function getStartBody() { @@ -207,6 +208,9 @@ class ProtectedTitlesPager extends AlphabeticPager { return ''; } + /** + * @return Title + */ function getTitle() { return SpecialPage::getTitleFor( 'Protectedtitles' ); } @@ -215,6 +219,9 @@ class ProtectedTitlesPager extends AlphabeticPager { return $this->mForm->formatRow( $row ); } + /** + * @return array + */ function getQueryInfo() { $conds = $this->mConds; $conds[] = 'pt_expiry>' . $this->mDb->addQuotes( $this->mDb->timestamp() ); diff --git a/includes/specials/SpecialRandompage.php b/includes/specials/SpecialRandompage.php index e299dc77..0b6239bb 100644 --- a/includes/specials/SpecialRandompage.php +++ b/includes/specials/SpecialRandompage.php @@ -33,8 +33,7 @@ class RandomPage extends SpecialPage { protected $extra = array(); // Extra SQL statements public function __construct( $name = 'Randompage' ){ - global $wgContentNamespaces; - $this->namespaces = $wgContentNamespaces; + $this->namespaces = MWNamespace::getContentNamespaces(); parent::__construct( $name ); } @@ -55,9 +54,9 @@ class RandomPage extends SpecialPage { } public function execute( $par ) { - global $wgOut, $wgContLang, $wgRequest; + global $wgContLang; - if ($par) { + if ( $par ) { $this->setNamespace( $wgContLang->getNsIndex( $par ) ); } @@ -65,15 +64,15 @@ class RandomPage extends SpecialPage { if( is_null( $title ) ) { $this->setHeaders(); - $wgOut->addWikiMsg( strtolower( $this->mName ) . '-nopages', + $this->getOutput()->addWikiMsg( strtolower( $this->getName() ) . '-nopages', $this->getNsList(), count( $this->namespaces ) ); return; } $redirectParam = $this->isRedirect() ? array( 'redirect' => 'no' ) : array(); - $query = array_merge( $wgRequest->getValues(), $redirectParam ); + $query = array_merge( $this->getRequest()->getValues(), $redirectParam ); unset( $query['title'] ); - $wgOut->redirect( $title->getFullUrl( $query ) ); + $this->getOutput()->redirect( $title->getFullUrl( $query ) ); } /** diff --git a/includes/specials/SpecialRecentchanges.php b/includes/specials/SpecialRecentchanges.php index 6c78ced0..daf47f62 100644 --- a/includes/specials/SpecialRecentchanges.php +++ b/includes/specials/SpecialRecentchanges.php @@ -73,9 +73,7 @@ class SpecialRecentChanges extends IncludableSpecialPage { public function setup( $parameters ) { $opts = $this->getDefaultOptions(); - $this->customFilters = array(); - wfRunHooks( 'SpecialRecentChangesFilters', array( $this, &$this->customFilters ) ); - foreach( $this->customFilters as $key => $params ) { + foreach( $this->getCustomFilters() as $key => $params ) { $opts->add( $key, $params['default'] ); } @@ -90,6 +88,19 @@ class SpecialRecentChanges extends IncludableSpecialPage { return $opts; } + /** + * Get custom show/hide filters + * + * @return Array Map of filter URL param names to properties (msg/default) + */ + protected function getCustomFilters() { + if ( $this->customFilters === null ) { + $this->customFilters = array(); + wfRunHooks( 'SpecialRecentChangesFilters', array( $this, &$this->customFilters ) ); + } + return $this->customFilters; + } + /** * Create a FormOptions object specific for feed requests and return it * @@ -232,6 +243,9 @@ class SpecialRecentChanges extends IncludableSpecialPage { if( preg_match( '/^days=(\d+)$/', $bit, $m ) ) { $opts['days'] = $m[1]; } + if( preg_match( '/^namespace=(\d+)$/', $bit, $m ) ) { + $opts['namespace'] = $m[1]; + } } } @@ -617,7 +631,15 @@ class SpecialRecentChanges extends IncludableSpecialPage { * @param $opts FormOptions */ function setTopText( FormOptions $opts ) { - $this->getOutput()->addWikiText( wfMsgForContentNoTrans( 'recentchangestext' ) ); + global $wgContLang; + $this->getOutput()->addWikiText( + Html::rawElement( 'p', + array( 'lang' => $wgContLang->getCode(), 'dir' => $wgContLang->getDir() ), + "\n" . wfMsgForContentNoTrans( 'recentchangestext' ) . "\n" + ), + /* $lineStart */ false, + /* $interface */ false + ); } /** @@ -636,7 +658,10 @@ class SpecialRecentChanges extends IncludableSpecialPage { * @return String */ protected function namespaceFilterForm( FormOptions $opts ) { - $nsSelect = Xml::namespaceSelector( $opts['namespace'], '' ); + $nsSelect = Html::namespaceSelector( + array( 'selected' => $opts['namespace'], 'all' => '' ), + array( 'name' => 'namespace', 'id' => 'namespace' ) + ); $nsLabel = Xml::label( wfMsg( 'namespace' ), 'namespace' ); $invert = Xml::checkLabel( wfMsg( 'invert' ), 'invert', 'nsinvert', @@ -766,10 +791,10 @@ class SpecialRecentChanges extends IncludableSpecialPage { } if( $options['from'] ) { $note .= wfMsgExt( 'rcnotefrom', array( 'parseinline' ), - $this->getLang()->formatNum( $options['limit'] ), - $this->getLang()->timeanddate( $options['from'], true ), - $this->getLang()->date( $options['from'], true ), - $this->getLang()->time( $options['from'], true ) ) . '
      '; + $this->getLanguage()->formatNum( $options['limit'] ), + $this->getLanguage()->timeanddate( $options['from'], true ), + $this->getLanguage()->date( $options['from'], true ), + $this->getLanguage()->time( $options['from'], true ) ) . '
      '; } # Sort data for display and make sure it's unique after we've added user data. @@ -782,30 +807,30 @@ class SpecialRecentChanges extends IncludableSpecialPage { // limit links foreach( $wgRCLinkLimits as $value ) { - $cl[] = $this->makeOptionsLink( $this->getLang()->formatNum( $value ), + $cl[] = $this->makeOptionsLink( $this->getLanguage()->formatNum( $value ), array( 'limit' => $value ), $nondefaults, $value == $options['limit'] ); } - $cl = $this->getLang()->pipeList( $cl ); + $cl = $this->getLanguage()->pipeList( $cl ); // day links, reset 'from' to none foreach( $wgRCLinkDays as $value ) { - $dl[] = $this->makeOptionsLink( $this->getLang()->formatNum( $value ), + $dl[] = $this->makeOptionsLink( $this->getLanguage()->formatNum( $value ), array( 'days' => $value, 'from' => '' ), $nondefaults, $value == $options['days'] ); } - $dl = $this->getLang()->pipeList( $dl ); + $dl = $this->getLanguage()->pipeList( $dl ); // show/hide links $showhide = array( wfMsg( 'show' ), wfMsg( 'hide' ) ); $filters = array( - 'hideminor' => 'rcshowhideminor', - 'hidebots' => 'rcshowhidebots', - 'hideanons' => 'rcshowhideanons', - 'hideliu' => 'rcshowhideliu', + 'hideminor' => 'rcshowhideminor', + 'hidebots' => 'rcshowhidebots', + 'hideanons' => 'rcshowhideanons', + 'hideliu' => 'rcshowhideliu', 'hidepatrolled' => 'rcshowhidepatr', - 'hidemyself' => 'rcshowhidemine' + 'hidemyself' => 'rcshowhidemine' ); - foreach ( $this->customFilters as $key => $params ) { + foreach ( $this->getCustomFilters() as $key => $params ) { $filters[$key] = $params['msg']; } // Disable some if needed @@ -822,13 +847,13 @@ class SpecialRecentChanges extends IncludableSpecialPage { // show from this onward link $timestamp = wfTimestampNow(); - $now = $this->getLang()->timeanddate( $timestamp, true ); + $now = $this->getLanguage()->timeanddate( $timestamp, true ); $tl = $this->makeOptionsLink( $now, array( 'from' => $timestamp ), $nondefaults ); $rclinks = wfMsgExt( 'rclinks', array( 'parseinline', 'replaceafter' ), - $cl, $dl, $this->getLang()->pipeList( $links ) ); + $cl, $dl, $this->getLanguage()->pipeList( $links ) ); $rclistfrom = wfMsgExt( 'rclistfrom', array( 'parseinline', 'replaceafter' ), $tl ); return "{$note}$rclinks
      $rclistfrom"; } diff --git a/includes/specials/SpecialRecentchangeslinked.php b/includes/specials/SpecialRecentchangeslinked.php index 8b8369b5..1f556f89 100644 --- a/includes/specials/SpecialRecentchangeslinked.php +++ b/includes/specials/SpecialRecentchangeslinked.php @@ -69,13 +69,14 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges { if ( $target === '' ) { return false; } + $outputPage = $this->getOutput(); $title = Title::newFromURL( $target ); if( !$title || $title->getInterwiki() != '' ){ - $this->getOutput()->wrapWikiMsg( "
      \n$1\n

      ", 'allpagesbadtitle' ); + $outputPage->wrapWikiMsg( "
      \n$1\n

      ", 'allpagesbadtitle' ); return false; } - $this->getOutput()->setPageTitle( wfMsg( 'recentchangeslinked-title', $title->getPrefixedText() ) ); + $outputPage->setPageTitle( $this->msg( 'recentchangeslinked-title', $title->getPrefixedText() ) ); /* * Ordinary links are in the pagelinks table, while transclusions are @@ -113,8 +114,9 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges { $query_options, $opts['tagfilter'] ); } - if ( !wfRunHooks( 'SpecialRecentChangesQuery', array( &$conds, &$tables, &$join_conds, $opts, &$query_options, &$select ) ) ) + if ( !wfRunHooks( 'SpecialRecentChangesQuery', array( &$conds, &$tables, &$join_conds, $opts, &$query_options, &$select ) ) ) { return false; + } if( $ns == NS_CATEGORY && !$showlinkedto ) { // special handling for categories @@ -125,11 +127,14 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges { // for now, always join on these tables; really should be configurable as in whatlinkshere $link_tables = array( 'pagelinks', 'templatelinks' ); // imagelinks only contains links to pages in NS_FILE - if( $ns == NS_FILE || !$showlinkedto ) $link_tables[] = 'imagelinks'; + if( $ns == NS_FILE || !$showlinkedto ) { + $link_tables[] = 'imagelinks'; + } } - if( $id == 0 && !$showlinkedto ) + if( $id == 0 && !$showlinkedto ) { return false; // nonexistent pages can't link to any pages + } // field name prefixes for all the various tables we might want to join with $prefix = array( 'pagelinks' => 'pl', 'templatelinks' => 'tl', 'categorylinks' => 'cl', 'imagelinks' => 'il' ); @@ -140,14 +145,20 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges { $pfx = $prefix[$link_table]; // imagelinks and categorylinks tables have no xx_namespace field, and have xx_to instead of xx_title - if( $link_table == 'imagelinks' ) $link_ns = NS_FILE; - elseif( $link_table == 'categorylinks' ) $link_ns = NS_CATEGORY; - else $link_ns = 0; + if( $link_table == 'imagelinks' ) { + $link_ns = NS_FILE; + } elseif( $link_table == 'categorylinks' ) { + $link_ns = NS_CATEGORY; + } else { + $link_ns = 0; + } if( $showlinkedto ) { // find changes to pages linking to this page if( $link_ns ) { - if( $ns != $link_ns ) continue; // should never happen, but check anyway + if( $ns != $link_ns ) { + continue; + } // should never happen, but check anyway $subconds = array( "{$pfx}_to" => $dbkey ); } else { $subconds = array( "{$pfx}_namespace" => $ns, "{$pfx}_title" => $dbkey ); @@ -164,11 +175,11 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges { } } - if( $dbr->unionSupportsOrderAndLimit()) + if( $dbr->unionSupportsOrderAndLimit()) { $order = array( 'ORDER BY' => 'rc_timestamp DESC' ); - else + } else { $order = array(); - + } $query = $dbr->selectSQLText( array_merge( $tables, array( $link_table ) ), @@ -185,11 +196,12 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges { $subsql[] = $query; } - if( count($subsql) == 0 ) + if( count($subsql) == 0 ) { return false; // should never happen - if( count($subsql) == 1 && $dbr->unionSupportsOrderAndLimit() ) + } + if( count($subsql) == 1 && $dbr->unionSupportsOrderAndLimit() ) { $sql = $subsql[0]; - else { + } else { // need to resort and relimit after union $sql = $dbr->unionQueries($subsql, false).' ORDER BY rc_timestamp DESC'; $sql = $dbr->limitResult($sql, $limit, false); @@ -197,12 +209,17 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges { $res = $dbr->query( $sql, __METHOD__ ); - if( $res->numRows() == 0 ) + if( $res->numRows() == 0 ) { $this->mResultEmpty = true; + } return $res; } + /** + * @param $opts FormOptions + * @return array + */ function getExtraOptions( $opts ){ $opts->consumeValues( array( 'showlinkedto', 'target', 'tagfilter' ) ); $extraOpts = array(); @@ -212,8 +229,9 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges { Xml::check( 'showlinkedto', $opts['showlinkedto'], array('id' => 'showlinkedto') ) . ' ' . Xml::label( wfMsg("recentchangeslinked-to"), 'showlinkedto' ) ); $tagFilter = ChangeTags::buildTagFilterSelector( $opts['tagfilter'] ); - if ($tagFilter) + if ($tagFilter) { $extraOpts['tagfilter'] = $tagFilter; + } return $extraOpts; } @@ -235,8 +253,7 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges { function setTopText( FormOptions $opts ) { $target = $this->getTargetTitle(); if( $target ) { - $this->getOutput()->setSubtitle( wfMsg( 'recentchangeslinked-backlink', Linker::link( $target, - $target->getPrefixedText(), array(), array( 'redirect' => 'no' ) ) ) ); + $this->getOutput()->addBacklinkSubtitle( $target ); } } diff --git a/includes/specials/SpecialRevisiondelete.php b/includes/specials/SpecialRevisiondelete.php index 3c643253..df60a26a 100644 --- a/includes/specials/SpecialRevisiondelete.php +++ b/includes/specials/SpecialRevisiondelete.php @@ -111,15 +111,12 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { } public function execute( $par ) { + $this->checkPermissions(); + $this->checkReadOnly(); + $output = $this->getOutput(); $user = $this->getUser(); - if( !$user->isAllowed( 'deletedhistory' ) ) { - $output->permissionRequired( 'deletedhistory' ); - return; - } elseif( wfReadOnly() ) { - $output->readOnlyPage(); - return; - } + $this->mIsAllowed = $user->isAllowed('deleterevision'); // for changes $this->setHeaders(); $this->outputHeader(); @@ -137,7 +134,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { // $this->ids = array_map( 'intval', $this->ids ); $this->ids = array_unique( array_filter( $this->ids ) ); - if ( $request->getVal( 'action' ) == 'historysubmit' ) { + if ( $request->getVal( 'action' ) == 'historysubmit' || $request->getVal( 'action' ) == 'revisiondelete' ) { // For show/hide form submission from history page // Since we are access through index.php?title=XXX&action=historysubmit // getFullTitle() will contain the target title and not our title @@ -206,12 +203,12 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { # Show relevant lines from the deletion log $output->addHTML( "

      " . htmlspecialchars( LogPage::logName( 'delete' ) ) . "

      \n" ); LogEventsList::showLogExtract( $output, 'delete', - $this->targetObj->getPrefixedText(), '', array( 'lim' => 25, 'conds' => $qc ) ); + $this->targetObj, '', array( 'lim' => 25, 'conds' => $qc ) ); # Show relevant lines from the suppression log if( $user->isAllowed( 'suppressionlog' ) ) { $output->addHTML( "

      " . htmlspecialchars( LogPage::logName( 'suppress' ) ) . "

      \n" ); LogEventsList::showLogExtract( $output, 'suppress', - $this->targetObj->getPrefixedText(), '', array( 'lim' => 25, 'conds' => $qc ) ); + $this->targetObj, '', array( 'lim' => 25, 'conds' => $qc ) ); } } @@ -228,7 +225,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { array(), array( 'page' => $this->targetObj->getPrefixedText() ) ); - if ( $this->targetObj->getNamespace() != NS_SPECIAL ) { + if ( !$this->targetObj->isSpecialPage() ) { # Give a link to the page history $links[] = Linker::linkKnown( $this->targetObj, @@ -248,7 +245,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { } } # Logs themselves don't have histories or archived revisions - $this->getOutput()->setSubtitle( '

      ' . $this->getLang()->pipeList( $links ) . '

      ' ); + $this->getOutput()->addSubtitle( $this->getLanguage()->pipeList( $links ) ); } } @@ -278,7 +275,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { $this->getOutput()->addWikiMsg( 'revdelete-no-file' ); return; } - if( !$oimage->userCan(File::DELETED_FILE) ) { + if( !$oimage->userCan( File::DELETED_FILE, $this->getUser() ) ) { if( $oimage->isDeleted( File::DELETED_RESTRICTED ) ) { $this->getOutput()->permissionRequired( 'suppressrevision' ); } else { @@ -289,15 +286,15 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { if ( !$this->getUser()->matchEditToken( $this->token, $archiveName ) ) { $this->getOutput()->addWikiMsg( 'revdelete-show-file-confirm', $this->targetObj->getText(), - $this->getLang()->date( $oimage->getTimestamp() ), - $this->getLang()->time( $oimage->getTimestamp() ) ); + $this->getLanguage()->date( $oimage->getTimestamp() ), + $this->getLanguage()->time( $oimage->getTimestamp() ) ); $this->getOutput()->addHTML( Xml::openElement( 'form', array( 'method' => 'POST', 'action' => $this->getTitle()->getLocalUrl( 'target=' . urlencode( $oimage->getName() ) . '&file=' . urlencode( $archiveName ) . - '&token=' . urlencode( $this->getUser()->editToken( $archiveName ) ) ) + '&token=' . urlencode( $this->getUser()->getEditToken( $archiveName ) ) ) ) ) . Xml::submitButton( wfMsg( 'revdelete-show-file-submit' ) ) . @@ -314,12 +311,9 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { $this->getRequest()->response()->header( 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate' ); $this->getRequest()->response()->header( 'Pragma: no-cache' ); - # Stream the file to the client - global $IP; - require_once( "$IP/includes/StreamFile.php" ); $key = $oimage->getStorageKey(); $path = $repo->getZonePath( 'deleted' ) . '/' . $repo->getDeletedHashPath( $key ) . $key; - wfStreamFile( $path ); + $repo->streamFile( $path ); } /** @@ -341,7 +335,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { $UserAllowed = true; if ( $this->typeName == 'logging' ) { - $this->getOutput()->addWikiMsg( 'logdelete-selected', $this->getLang()->formatNum( count($this->ids) ) ); + $this->getOutput()->addWikiMsg( 'logdelete-selected', $this->getLanguage()->formatNum( count($this->ids) ) ); } else { $this->getOutput()->addWikiMsg( 'revdelete-selected', $this->targetObj->getPrefixedText(), count( $this->ids ) ); @@ -410,7 +404,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { '' . "\n" . Xml::closeElement( 'table' ) . - Html::hidden( 'wpEditToken', $this->getUser()->editToken() ) . + Html::hidden( 'wpEditToken', $this->getUser()->getEditToken() ) . Html::hidden( 'target', $this->targetObj->getPrefixedText() ) . Html::hidden( 'type', $this->typeName ) . Html::hidden( 'ids', implode( ',', $this->ids ) ) . @@ -541,7 +535,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { * Report that the submit operation succeeded */ protected function success() { - $this->getOutput()->setPagetitle( wfMsg( 'actioncomplete' ) ); + $this->getOutput()->setPageTitle( $this->msg( 'actioncomplete' ) ); $this->getOutput()->wrapWikiMsg( "\n$1\n", $this->typeInfo['success'] ); $this->list->reloadFromMaster(); $this->showForm(); @@ -551,7 +545,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage { * Report that the submit operation failed */ protected function failure( $status ) { - $this->getOutput()->setPagetitle( wfMsg( 'actionfailed' ) ); + $this->getOutput()->setPageTitle( $this->msg( 'actionfailed' ) ); $this->getOutput()->addWikiText( $status->getWikiText( $this->typeInfo['failure'] ) ); $this->showForm(); } diff --git a/includes/specials/SpecialSearch.php b/includes/specials/SpecialSearch.php index ba9d378a..3fa86875 100644 --- a/includes/specials/SpecialSearch.php +++ b/includes/specials/SpecialSearch.php @@ -35,8 +35,9 @@ class SpecialSearch extends SpecialPage { * string when applicable. Extensions can add new profiles with hooks * with custom search options just for that profile. * null|string - */ + */ protected $profile; + function getProfile() { return $this->profile; } /// Search engine protected $searchEngine; @@ -47,6 +48,27 @@ class SpecialSearch extends SpecialPage { /// No idea, apparently used by some other classes protected $mPrefix; + /** + * @var int + */ + protected $limit, $offset; + + /** + * @var array + */ + protected $namespaces; + function getNamespaces() { return $this->namespaces; } + + /** + * @var bool + */ + protected $searchRedirects; + + /** + * @var string + */ + protected $didYouMeanHtml, $fulltext; + const NAMESPACES_CURRENT = 'sense'; public function __construct() { @@ -59,25 +81,26 @@ class SpecialSearch extends SpecialPage { * @param $par String or null */ public function execute( $par ) { - global $wgRequest, $wgUser, $wgOut; - $this->setHeaders(); $this->outputHeader(); - $wgOut->allowClickjacking(); - $wgOut->addModuleStyles( 'mediawiki.special' ); + $out = $this->getOutput(); + $out->allowClickjacking(); + $out->addModuleStyles( 'mediawiki.special' ); // Strip underscores from title parameter; most of the time we'll want // text form here. But don't strip underscores from actual text params! $titleParam = str_replace( '_', ' ', $par ); + $request = $this->getRequest(); + // Fetch the search term - $search = str_replace( "\n", " ", $wgRequest->getText( 'search', $titleParam ) ); + $search = str_replace( "\n", " ", $request->getText( 'search', $titleParam ) ); - $this->load( $wgRequest, $wgUser ); + $this->load(); - if ( $wgRequest->getVal( 'fulltext' ) - || !is_null( $wgRequest->getVal( 'offset' ) ) - || !is_null( $wgRequest->getVal( 'searchx' ) ) ) + if ( $request->getVal( 'fulltext' ) + || !is_null( $request->getVal( 'offset' ) ) + || !is_null( $request->getVal( 'searchx' ) ) ) { $this->showResults( $search ); } else { @@ -87,33 +110,39 @@ class SpecialSearch extends SpecialPage { /** * Set up basic search parameters from the request and user settings. - * Typically you'll pass $wgRequest and $wgUser. * - * @param $request WebRequest - * @param $user User + * @see tests/phpunit/includes/specials/SpecialSearchTest.php */ - public function load( &$request, &$user ) { + public function load() { + $request = $this->getRequest(); list( $this->limit, $this->offset ) = $request->getLimitOffset( 20, 'searchlimit' ); $this->mPrefix = $request->getVal( 'prefix', '' ); + $user = $this->getUser(); # Extract manually requested namespaces $nslist = $this->powerSearch( $request ); - $this->profile = $profile = $request->getVal( 'profile', null ); + if ( !count( $nslist ) ) { + # Fallback to user preference + $nslist = SearchEngine::userNamespaces( $user ); + } + + $profile = null; + if ( !count( $nslist ) ) { + $profile = 'default'; + } + + $profile = $request->getVal( 'profile', $profile ); $profiles = $this->getSearchProfiles(); - if ( $profile === null) { + if ( $profile === null ) { // BC with old request format - $this->profile = 'advanced'; - if ( count( $nslist ) ) { - foreach( $profiles as $key => $data ) { - if ( $nslist === $data['namespaces'] && $key !== 'advanced') { - $this->profile = $key; - } + $profile = 'advanced'; + foreach( $profiles as $key => $data ) { + if ( $nslist === $data['namespaces'] && $key !== 'advanced') { + $profile = $key; } - $this->namespaces = $nslist; - } else { - $this->namespaces = SearchEngine::userNamespaces( $user ); } + $this->namespaces = $nslist; } elseif ( $profile === 'advanced' ) { $this->namespaces = $nslist; } else { @@ -121,7 +150,7 @@ class SpecialSearch extends SpecialPage { $this->namespaces = $profiles[$profile]['namespaces']; } else { // Unknown profile requested - $this->profile = 'default'; + $profile = 'default'; $this->namespaces = $profiles['default']['namespaces']; } } @@ -129,9 +158,9 @@ class SpecialSearch extends SpecialPage { // Redirects defaults to true, but we don't know whether it was ticked of or just missing $default = $request->getBool( 'profile' ) ? 0 : 1; $this->searchRedirects = $request->getBool( 'redirs', $default ) ? 1 : 0; - $this->sk = $this->getSkin(); $this->didYouMeanHtml = ''; # html of did you mean... link $this->fulltext = $request->getVal('fulltext'); + $this->profile = $profile; } /** @@ -140,7 +169,6 @@ class SpecialSearch extends SpecialPage { * @param $term String */ public function goResult( $term ) { - global $wgOut; $this->setupPage( $term ); # Try to go to page as entered. $t = Title::newFromText( $term ); @@ -157,7 +185,7 @@ class SpecialSearch extends SpecialPage { } if( !is_null( $t ) ) { - $wgOut->redirect( $t->getFullURL() ); + $this->getOutput()->redirect( $t->getFullURL() ); return; } # No match, generate an edit URL @@ -169,7 +197,7 @@ class SpecialSearch extends SpecialPage { # If the feature is enabled, go straight to the edit page if( $wgGoToEdit ) { - $wgOut->redirect( $t->getFullURL( array( 'action' => 'edit' ) ) ); + $this->getOutput()->redirect( $t->getFullURL( array( 'action' => 'edit' ) ) ); return; } } @@ -180,11 +208,9 @@ class SpecialSearch extends SpecialPage { * @param $term String */ public function showResults( $term ) { - global $wgOut, $wgDisableTextSearch, $wgContLang, $wgScript; + global $wgDisableTextSearch, $wgSearchForwardUrl, $wgContLang, $wgScript; wfProfileIn( __METHOD__ ); - $sk = $this->getSkin(); - $search = $this->getSearchEngine(); $search->setLimitOffset( $this->limit, $this->offset ); $search->setNamespaces( $this->namespaces ); @@ -197,25 +223,25 @@ class SpecialSearch extends SpecialPage { $this->setupPage( $term ); - if( $wgDisableTextSearch ) { - global $wgSearchForwardUrl; - if( $wgSearchForwardUrl ) { + $out = $this->getOutput(); + + if ( $wgDisableTextSearch ) { + if ( $wgSearchForwardUrl ) { $url = str_replace( '$1', urlencode( $term ), $wgSearchForwardUrl ); - $wgOut->redirect( $url ); - wfProfileOut( __METHOD__ ); - return; + $out->redirect( $url ); + } else { + $out->addHTML( + Xml::openElement( 'fieldset' ) . + Xml::element( 'legend', null, wfMsg( 'search-external' ) ) . + Xml::element( 'p', array( 'class' => 'mw-searchdisabled' ), wfMsg( 'searchdisabled' ) ) . + wfMsg( 'googlesearch', + htmlspecialchars( $term ), + htmlspecialchars( 'UTF-8' ), + htmlspecialchars( wfMsg( 'searchbutton' ) ) + ) . + Xml::closeElement( 'fieldset' ) + ); } - $wgOut->addHTML( - Xml::openElement( 'fieldset' ) . - Xml::element( 'legend', null, wfMsg( 'search-external' ) ) . - Xml::element( 'p', array( 'class' => 'mw-searchdisabled' ), wfMsg( 'searchdisabled' ) ) . - wfMsg( 'googlesearch', - htmlspecialchars( $term ), - htmlspecialchars( 'UTF-8' ), - htmlspecialchars( wfMsg( 'searchbutton' ) ) - ) . - Xml::closeElement( 'fieldset' ) - ); wfProfileOut( __METHOD__ ); return; } @@ -226,8 +252,9 @@ class SpecialSearch extends SpecialPage { $rewritten = $search->replacePrefixes($term); $titleMatches = $search->searchTitle( $rewritten ); - if( !($titleMatches instanceof SearchResultTooMany)) + if( !( $titleMatches instanceof SearchResultTooMany ) ) { $textMatches = $search->searchText( $rewritten ); + } // did you mean... suggestions if( $textMatches && $textMatches->hasSuggestion() ) { @@ -236,8 +263,9 @@ class SpecialSearch extends SpecialPage { # mirror Go/Search behaviour of original request .. $didYouMeanParams = array( 'search' => $textMatches->getSuggestionQuery() ); - if($this->fulltext != null) + if( $this->fulltext != null ) { $didYouMeanParams['fulltext'] = $this->fulltext; + } $stParams = array_merge( $didYouMeanParams, @@ -246,10 +274,11 @@ class SpecialSearch extends SpecialPage { $suggestionSnippet = $textMatches->getSuggestionSnippet(); - if( $suggestionSnippet == '' ) + if( $suggestionSnippet == '' ) { $suggestionSnippet = null; + } - $suggestLink = $sk->linkKnown( + $suggestLink = Linker::linkKnown( $st, $suggestionSnippet, array(), @@ -259,7 +288,7 @@ class SpecialSearch extends SpecialPage { $this->didYouMeanHtml = '
      '.wfMsg('search-suggest',$suggestLink).'
      '; } // start rendering the page - $wgOut->addHtml( + $out->addHtml( Xml::openElement( 'form', array( @@ -269,7 +298,7 @@ class SpecialSearch extends SpecialPage { ) ) ); - $wgOut->addHtml( + $out->addHtml( Xml::openElement( 'table', array( 'id'=>'mw-search-top-table', 'border'=>0, 'cellpadding'=>0, 'cellspacing'=>0 ) ) . Xml::openElement( 'tr' ) . Xml::openElement( 'td' ) . "\n" . @@ -281,16 +310,16 @@ class SpecialSearch extends SpecialPage { // Sometimes the search engine knows there are too many hits if( $titleMatches instanceof SearchResultTooMany ) { - $wgOut->wrapWikiMsg( "==$1==\n", 'toomanymatches' ); + $out->wrapWikiMsg( "==$1==\n", 'toomanymatches' ); wfProfileOut( __METHOD__ ); return; } $filePrefix = $wgContLang->getFormattedNsText(NS_FILE).':'; if( trim( $term ) === '' || $filePrefix === trim( $term ) ) { - $wgOut->addHTML( $this->formHeader( $term, 0, 0 ) ); - $wgOut->addHtml( $this->getProfileForm( $this->profile, $term ) ); - $wgOut->addHTML( '' ); + $out->addHTML( $this->formHeader( $term, 0, 0 ) ); + $out->addHtml( $this->getProfileForm( $this->profile, $term ) ); + $out->addHTML( '' ); // Empty query -- straight view of search form wfProfileOut( __METHOD__ ); return; @@ -316,33 +345,32 @@ class SpecialSearch extends SpecialPage { $totalRes += $textMatches->getTotalHits(); // show number of results and current offset - $wgOut->addHTML( $this->formHeader( $term, $num, $totalRes ) ); - $wgOut->addHtml( $this->getProfileForm( $this->profile, $term ) ); + $out->addHTML( $this->formHeader( $term, $num, $totalRes ) ); + $out->addHtml( $this->getProfileForm( $this->profile, $term ) ); - $wgOut->addHtml( Xml::closeElement( 'form' ) ); - $wgOut->addHtml( "
      " ); + $out->addHtml( Xml::closeElement( 'form' ) ); + $out->addHtml( "
      " ); // prev/next links if( $num || $this->offset ) { // Show the create link ahead $this->showCreateLink( $t ); - $prevnext = wfViewPrevNext( $this->offset, $this->limit, - SpecialPage::getTitleFor( 'Search' ), - wfArrayToCGI( $this->powerSearchOptions(), array( 'search' => $term ) ), + $prevnext = $this->getLanguage()->viewPrevNext( $this->getTitle(), $this->offset, $this->limit, + $this->powerSearchOptions() + array( 'search' => $term ), max( $titleMatchesNum, $textMatchesNum ) < $this->limit ); - //$wgOut->addHTML( "

      {$prevnext}

      \n" ); + //$out->addHTML( "

      {$prevnext}

      \n" ); wfRunHooks( 'SpecialSearchResults', array( $term, &$titleMatches, &$textMatches ) ); } else { wfRunHooks( 'SpecialSearchNoResults', array( $term ) ); } - $wgOut->parserOptions()->setEditSection( false ); + $out->parserOptions()->setEditSection( false ); if( $titleMatches ) { if( $numTitleMatches > 0 ) { - $wgOut->wrapWikiMsg( "==$1==\n", 'titlematches' ); - $wgOut->addHTML( $this->showMatches( $titleMatches ) ); + $out->wrapWikiMsg( "==$1==\n", 'titlematches' ); + $out->addHTML( $this->showMatches( $titleMatches ) ); } $titleMatches->free(); } @@ -350,37 +378,38 @@ class SpecialSearch extends SpecialPage { // output appropriate heading if( $numTextMatches > 0 && $numTitleMatches > 0 ) { // if no title matches the heading is redundant - $wgOut->wrapWikiMsg( "==$1==\n", 'textmatches' ); + $out->wrapWikiMsg( "==$1==\n", 'textmatches' ); } elseif( $totalRes == 0 ) { # Don't show the 'no text matches' if we received title matches - # $wgOut->wrapWikiMsg( "==$1==\n", 'notextmatches' ); + # $out->wrapWikiMsg( "==$1==\n", 'notextmatches' ); } // show interwiki results if any if( $textMatches->hasInterwikiResults() ) { - $wgOut->addHTML( $this->showInterwiki( $textMatches->getInterwikiResults(), $term ) ); + $out->addHTML( $this->showInterwiki( $textMatches->getInterwikiResults(), $term ) ); } // show results if( $numTextMatches > 0 ) { - $wgOut->addHTML( $this->showMatches( $textMatches ) ); + $out->addHTML( $this->showMatches( $textMatches ) ); } $textMatches->free(); } if( $num === 0 ) { - $wgOut->wrapWikiMsg( "

      \n$1

      ", array( 'search-nonefound', wfEscapeWikiText( $term ) ) ); + $out->wrapWikiMsg( "

      \n$1

      ", array( 'search-nonefound', wfEscapeWikiText( $term ) ) ); $this->showCreateLink( $t ); } - $wgOut->addHtml( "
      " ); + $out->addHtml( "
      " ); if( $num || $this->offset ) { - $wgOut->addHTML( "

      {$prevnext}

      \n" ); + $out->addHTML( "

      {$prevnext}

      \n" ); } wfProfileOut( __METHOD__ ); } + /** + * @param $t Title + */ protected function showCreateLink( $t ) { - global $wgOut; - // show direct page/create link if applicable // Check DBkey !== '' in case of fragment link only. @@ -390,7 +419,7 @@ class SpecialSearch extends SpecialPage { $this->getOutput()->addHtml( '

      ' ); return; } - $messageName = ''; + if( $t->isKnown() ) { $messageName = 'searchmenu-exists'; } elseif( $t->userCan( 'create' ) ) { @@ -406,24 +435,23 @@ class SpecialSearch extends SpecialPage { $this->getOutput()->wrapWikiMsg( "

      \n$1

      ", $params ); } else { // preserve the paragraph for margins etc... - $wgOut->addHtml( '

      ' ); + $this->getOutput()->addHtml( '

      ' ); } } /** - * + * @param $term string */ protected function setupPage( $term ) { - global $wgOut; - # Should advanced UI be used? $this->searchAdvanced = ($this->profile === 'advanced'); + $out = $this->getOutput(); if( strval( $term ) !== '' ) { - $wgOut->setPageTitle( wfMsg( 'searchresults') ); - $wgOut->setHTMLTitle( wfMsg( 'pagetitle', wfMsg( 'searchresults-title', $term ) ) ); + $out->setPageTitle( $this->msg( 'searchresults' ) ); + $out->setHTMLTitle( $this->msg( 'pagetitle', $this->msg( 'searchresults-title', $term )->plain() ) ); } // add javascript specific to special:search - $wgOut->addModules( 'mediawiki.special.search' ); + $out->addModules( 'mediawiki.special.search' ); } /** @@ -466,6 +494,8 @@ class SpecialSearch extends SpecialPage { * Show whole set of results * * @param $matches SearchResultSet + * + * @return string */ protected function showMatches( &$matches ) { global $wgContLang; @@ -479,8 +509,10 @@ class SpecialSearch extends SpecialPage { $out .= "\n\n"; } $out .= "
        \n"; - while( $result = $matches->next() ) { + $result = $matches->next(); + while( $result ) { $out .= $this->showHit( $result, $terms ); + $result = $matches->next(); } $out .= "
      \n"; @@ -495,9 +527,10 @@ class SpecialSearch extends SpecialPage { * * @param $result SearchResult * @param $terms Array: terms to highlight + * + * @return string */ protected function showHit( $result, $terms ) { - global $wgLang; wfProfileIn( __METHOD__ ); if( $result->isBrokenTitle() ) { @@ -505,7 +538,6 @@ class SpecialSearch extends SpecialPage { return "\n"; } - $sk = $this->getSkin(); $t = $result->getTitle(); $titleSnippet = $result->getTitleSnippet($terms); @@ -518,7 +550,7 @@ class SpecialSearch extends SpecialPage { wfRunHooks( 'ShowSearchHitTitle', array( &$link_t, &$titleSnippet, $result, $terms, $this ) ); - $link = $this->sk->linkKnown( + $link = Linker::linkKnown( $link_t, $titleSnippet ); @@ -526,7 +558,7 @@ class SpecialSearch extends SpecialPage { //If page content is not readable, just return the title. //This is not quite safe, but better than showing excerpts from non-readable pages //Note that hiding the entry entirely would screw up paging. - if( !$t->userCanRead() ) { + if( !$t->userCan( 'read' ) ) { wfProfileOut( __METHOD__ ); return "
    8. {$link}
    9. \n"; } @@ -553,7 +585,7 @@ class SpecialSearch extends SpecialPage { $redirect = "" . wfMsg( 'search-redirect', - $this->sk->linkKnown( + Linker::linkKnown( $redirectTitle, $redirectText ) @@ -569,7 +601,7 @@ class SpecialSearch extends SpecialPage { $section = "" . wfMsg( - 'search-section', $this->sk->linkKnown( + 'search-section', Linker::linkKnown( $sectionTitle, $sectionText ) @@ -580,13 +612,15 @@ class SpecialSearch extends SpecialPage { // format text extract $extract = "
      ".$result->getTextSnippet($terms)."
      "; + $lang = $this->getLanguage(); + // format score if( is_null( $result->getScore() ) ) { // Search engine doesn't report scoring info $score = ''; } else { $percent = sprintf( '%2.1f', $result->getScore() * 100 ); - $score = wfMsg( 'search-result-score', $wgLang->formatNum( $percent ) ) + $score = wfMsg( 'search-result-score', $lang->formatNum( $percent ) ) . ' - '; } @@ -597,8 +631,8 @@ class SpecialSearch extends SpecialPage { $size = wfMsgExt( 'search-result-size', array( 'parsemag', 'escape' ), - $wgLang->formatSize( $byteSize ), - $wgLang->formatNum( $wordCount ) + $lang->formatSize( $byteSize ), + $lang->formatNum( $wordCount ) ); if( $t->getNamespace() == NS_CATEGORY ) { @@ -606,13 +640,13 @@ class SpecialSearch extends SpecialPage { $size = wfMsgExt( 'search-result-category-size', array( 'parsemag', 'escape' ), - $wgLang->formatNum( $cat->getPageCount() ), - $wgLang->formatNum( $cat->getSubcatCount() ), - $wgLang->formatNum( $cat->getFileCount() ) + $lang->formatNum( $cat->getPageCount() ), + $lang->formatNum( $cat->getSubcatCount() ), + $lang->formatNum( $cat->getFileCount() ) ); } - $date = $wgLang->timeanddate( $timestamp ); + $date = $lang->timeanddate( $timestamp ); // link to related articles if supported $related = ''; @@ -626,7 +660,7 @@ class SpecialSearch extends SpecialPage { ) ); - $related = ' -- ' . $sk->linkKnown( + $related = ' -- ' . Linker::linkKnown( $st, wfMsg('search-relatedarticle'), array(), @@ -675,6 +709,8 @@ class SpecialSearch extends SpecialPage { * * @param $matches SearchResultSet * @param $query String + * + * @return string */ protected function showInterwiki( &$matches, $query ) { global $wgContLang; @@ -695,9 +731,11 @@ class SpecialSearch extends SpecialPage { } $prev = null; - while( $result = $matches->next() ) { + $result = $matches->next(); + while( $result ) { $out .= $this->showInterwikiHit( $result, $prev, $terms, $query, $customCaptions ); $prev = $result->getInterwikiPrefix(); + $result = $matches->next(); } // TODO: should support paging in a non-confusing way (not sure how though, maybe via ajax).. $out .= "
      \n"; @@ -716,6 +754,8 @@ class SpecialSearch extends SpecialPage { * @param $terms Array * @param $query String * @param $customCaptions Array: iw prefix -> caption + * + * @return string */ protected function showInterwikiHit( $result, $lastInterwiki, $terms, $query, $customCaptions) { wfProfileIn( __METHOD__ ); @@ -732,7 +772,7 @@ class SpecialSearch extends SpecialPage { if( $titleSnippet == '' ) $titleSnippet = null; - $link = $this->sk->linkKnown( + $link = Linker::linkKnown( $t, $titleSnippet ); @@ -748,7 +788,7 @@ class SpecialSearch extends SpecialPage { $redirect = "" . wfMsg( 'search-redirect', - $this->sk->linkKnown( + Linker::linkKnown( $redirectTitle, $redirectText ) @@ -770,7 +810,7 @@ class SpecialSearch extends SpecialPage { } // "more results" link (special page stuff could be localized, but we might not know target lang) $searchTitle = Title::newFromText($t->getInterwiki().":Special:Search"); - $searchLink = $this->sk->linkKnown( + $searchLink = Linker::linkKnown( $searchTitle, wfMsg('search-interwiki-more'), array(), @@ -788,6 +828,11 @@ class SpecialSearch extends SpecialPage { return $out; } + /** + * @param $profile + * @param $term + * @return String + */ protected function getProfileForm( $profile, $term ) { // Hidden stuff $opts = array(); @@ -807,6 +852,7 @@ class SpecialSearch extends SpecialPage { * Generates the power search box at [[Special:Search]] * * @param $term String: search term + * @param $opts array * @return String: HTML form */ protected function powerSearchBox( $term, $opts ) { @@ -900,6 +946,9 @@ class SpecialSearch extends SpecialPage { Xml::closeElement( 'fieldset' ); } + /** + * @return array + */ protected function getSearchProfiles() { // Builds list of Search Types (profiles) $nsAllSet = array_keys( SearchEngine::searchableNamespaces() ); @@ -948,9 +997,13 @@ class SpecialSearch extends SpecialPage { return $profiles; } + /** + * @param $term + * @param $resultsShown + * @param $totalNum + * @return string + */ protected function formHeader( $term, $resultsShown, $totalNum ) { - global $wgLang; - $out = Xml::openElement('div', array( 'class' => 'mw-search-formheader' ) ); $bareterm = $term; @@ -960,6 +1013,7 @@ class SpecialSearch extends SpecialPage { } $profiles = $this->getSearchProfiles(); + $lang = $this->getLanguage(); // Outputs XML for Search Types $out .= Xml::openElement( 'div', array( 'class' => 'search-types' ) ); @@ -971,7 +1025,7 @@ class SpecialSearch extends SpecialPage { $profile['parameters']['profile'] = $id; $tooltipParam = isset( $profile['namespace-messages'] ) ? - $wgLang->commaList( $profile['namespace-messages'] ) : null; + $lang->commaList( $profile['namespace-messages'] ) : null; $out .= Xml::tags( 'li', array( @@ -993,19 +1047,22 @@ class SpecialSearch extends SpecialPage { if ( $resultsShown > 0 ) { if ( $totalNum > 0 ){ $top = wfMsgExt( 'showingresultsheader', array( 'parseinline' ), - $wgLang->formatNum( $this->offset + 1 ), - $wgLang->formatNum( $this->offset + $resultsShown ), - $wgLang->formatNum( $totalNum ), + $lang->formatNum( $this->offset + 1 ), + $lang->formatNum( $this->offset + $resultsShown ), + $lang->formatNum( $totalNum ), wfEscapeWikiText( $term ), - $wgLang->formatNum( $resultsShown ) + $lang->formatNum( $resultsShown ) ); } elseif ( $resultsShown >= $this->limit ) { - $top = wfShowingResults( $this->offset, $this->limit ); + $top = wfMsgExt( 'showingresults', array( 'parseinline' ), + $lang->formatNum( $this->limit ), + $lang->formatNum( $this->offset + 1 ) + ); } else { $top = wfMsgExt( 'showingresultsnum', array( 'parseinline' ), - $wgLang->formatNum( $this->limit ), - $wgLang->formatNum( $this->offset + 1 ), - $wgLang->formatNum( $resultsShown ) + $lang->formatNum( $this->limit ), + $lang->formatNum( $this->offset + 1 ), + $lang->formatNum( $resultsShown ) ); } $out .= Xml::tags( 'div', array( 'class' => 'results-info' ), @@ -1019,6 +1076,10 @@ class SpecialSearch extends SpecialPage { return $out; } + /** + * @param $term string + * @return string + */ protected function shortDialog( $term ) { $out = Html::hidden( 'title', $this->getTitle()->getPrefixedText() ); $out .= Html::hidden( 'profile', $this->profile ) . "\n"; @@ -1102,6 +1163,8 @@ class SpecialSearch extends SpecialPage { /** * @since 1.18 + * + * @return SearchEngine */ public function getSearchEngine() { if ( $this->searchEngine === null ) { @@ -1115,6 +1178,9 @@ class SpecialSearch extends SpecialPage { * add more params to links to not lose selection when * user navigates search results. * @since 1.18 + * + * @param $key + * @param $value */ public function setExtraParam( $key, $value ) { $this->extraParams[$key] = $value; diff --git a/includes/specials/SpecialShortpages.php b/includes/specials/SpecialShortpages.php index 3b785018..c176f913 100644 --- a/includes/specials/SpecialShortpages.php +++ b/includes/specials/SpecialShortpages.php @@ -33,14 +33,6 @@ class ShortPagesPage extends QueryPage { parent::__construct( $name ); } - // inexpensive? - /** - * This query is indexed as of 1.5 - */ - function isExpensive() { - return true; - } - function isSyndicated() { return false; } @@ -51,9 +43,9 @@ class ShortPagesPage extends QueryPage { 'fields' => array ( 'page_namespace AS namespace', 'page_title AS title', 'page_len AS value' ), - 'conds' => array ( 'page_namespace' => MWNamespace::getContentNamespaces(), + 'conds' => array ( 'page_namespace' => NS_MAIN, 'page_is_redirect' => 0 ), - 'options' => array ( 'USE INDEX' => 'page_len' ) + 'options' => array ( 'USE INDEX' => 'page_redirect_namespace_len' ) ); } @@ -86,23 +78,22 @@ class ShortPagesPage extends QueryPage { } function formatResult( $skin, $result ) { - global $wgLang; - $dm = $wgLang->getDirMark(); + $dm = $this->getLanguage()->getDirMark(); $title = Title::makeTitle( $result->namespace, $result->title ); if ( !$title ) { return ''; } - $hlink = $skin->linkKnown( + $hlink = Linker::linkKnown( $title, wfMsgHtml( 'hist' ), array(), array( 'action' => 'history' ) ); $plink = $this->isCached() - ? $skin->link( $title ) - : $skin->linkKnown( $title ); - $size = wfMessage( 'nbytes', $wgLang->formatNum( $result->value ) )->escaped(); + ? Linker::link( $title ) + : Linker::linkKnown( $title ); + $size = $this->msg( 'nbytes' )->numParams( $result->value )->escaped(); return $title->exists() ? "({$hlink}) {$dm}{$plink} {$dm}[{$size}]" diff --git a/includes/specials/SpecialSpecialpages.php b/includes/specials/SpecialSpecialpages.php index 13bc4c2b..e973ddc8 100644 --- a/includes/specials/SpecialSpecialpages.php +++ b/includes/specials/SpecialSpecialpages.php @@ -51,7 +51,7 @@ class SpecialSpecialpages extends UnlistedSpecialPage { private function getPageGroups() { global $wgSortSpecialPages; - $pages = SpecialPageFactory::getUsablePages(); + $pages = SpecialPageFactory::getUsablePages( $this->getUser() ); if( !count( $pages ) ) { # Yeah, that was pointless. Thanks for coming. diff --git a/includes/specials/SpecialStatistics.php b/includes/specials/SpecialStatistics.php index 5def4da5..b9c092b6 100644 --- a/includes/specials/SpecialStatistics.php +++ b/includes/specials/SpecialStatistics.php @@ -138,15 +138,17 @@ class SpecialStatistics extends SpecialPage { return Xml::openElement( 'tr' ) . Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-pages', array( 'parseinline' ) ) ) . Xml::closeElement( 'tr' ) . - $this->formatRow( wfMsgExt( 'statistics-articles', array( 'parseinline' ) ), - $this->getLang()->formatNum( $this->good ), + $this->formatRow( Linker::linkKnown( SpecialPage::getTitleFor( 'Allpages' ), + wfMsgExt( 'statistics-articles', array( 'parseinline' ) ) ), + $this->getLanguage()->formatNum( $this->good ), array( 'class' => 'mw-statistics-articles' ) ) . $this->formatRow( wfMsgExt( 'statistics-pages', array( 'parseinline' ) ), - $this->getLang()->formatNum( $this->total ), + $this->getLanguage()->formatNum( $this->total ), array( 'class' => 'mw-statistics-pages' ), 'statistics-pages-desc' ) . - $this->formatRow( wfMsgExt( 'statistics-files', array( 'parseinline' ) ), - $this->getLang()->formatNum( $this->images ), + $this->formatRow( Linker::linkKnown( SpecialPage::getTitleFor( 'Listfiles' ), + wfMsgExt( 'statistics-files', array( 'parseinline' ) ) ), + $this->getLanguage()->formatNum( $this->images ), array( 'class' => 'mw-statistics-files' ) ); } private function getEditStats() { @@ -154,10 +156,10 @@ class SpecialStatistics extends SpecialPage { Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-edits', array( 'parseinline' ) ) ) . Xml::closeElement( 'tr' ) . $this->formatRow( wfMsgExt( 'statistics-edits', array( 'parseinline' ) ), - $this->getLang()->formatNum( $this->edits ), + $this->getLanguage()->formatNum( $this->edits ), array( 'class' => 'mw-statistics-edits' ) ) . $this->formatRow( wfMsgExt( 'statistics-edits-average', array( 'parseinline' ) ), - $this->getLang()->formatNum( sprintf( '%.2f', $this->total ? $this->edits / $this->total : 0 ) ), + $this->getLanguage()->formatNum( sprintf( '%.2f', $this->total ? $this->edits / $this->total : 0 ) ), array( 'class' => 'mw-statistics-edits-average' ) ); } @@ -167,17 +169,17 @@ class SpecialStatistics extends SpecialPage { Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-users', array( 'parseinline' ) ) ) . Xml::closeElement( 'tr' ) . $this->formatRow( wfMsgExt( 'statistics-users', array( 'parseinline' ) ), - $this->getLang()->formatNum( $this->users ), + $this->getLanguage()->formatNum( $this->users ), array( 'class' => 'mw-statistics-users' ) ) . $this->formatRow( wfMsgExt( 'statistics-users-active', array( 'parseinline' ) ) . ' ' . Linker::linkKnown( SpecialPage::getTitleFor( 'Activeusers' ), wfMsgHtml( 'listgrouprights-members' ) ), - $this->getLang()->formatNum( $this->activeUsers ), + $this->getLanguage()->formatNum( $this->activeUsers ), array( 'class' => 'mw-statistics-users-active' ), 'statistics-users-active-desc', - $this->getLang()->formatNum( $wgActiveUserDays ) ); + $this->getLanguage()->formatNum( $wgActiveUserDays ) ); } private function getGroupStats() { @@ -219,7 +221,7 @@ class SpecialStatistics extends SpecialPage { $classZero = ' statistics-group-zero'; } $text .= $this->formatRow( $grouppage . ' ' . $grouplink, - $this->getLang()->formatNum( $countUsers ), + $this->getLanguage()->formatNum( $countUsers ), array( 'class' => 'statistics-group-' . Sanitizer::escapeClass( $group ) . $classZero ) ); } return $text; @@ -230,10 +232,10 @@ class SpecialStatistics extends SpecialPage { Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-views', array( 'parseinline' ) ) ) . Xml::closeElement( 'tr' ) . $this->formatRow( wfMsgExt( 'statistics-views-total', array( 'parseinline' ) ), - $this->getLang()->formatNum( $this->views ), + $this->getLanguage()->formatNum( $this->views ), array ( 'class' => 'mw-statistics-views-total' ), 'statistics-views-total-desc' ) . $this->formatRow( wfMsgExt( 'statistics-views-peredit', array( 'parseinline' ) ), - $this->getLang()->formatNum( sprintf( '%.2f', $this->edits ? + $this->getLanguage()->formatNum( sprintf( '%.2f', $this->edits ? $this->views / $this->edits : 0 ) ), array ( 'class' => 'mw-statistics-views-peredit' ) ); } @@ -266,7 +268,7 @@ class SpecialStatistics extends SpecialPage { $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title ); if( $title instanceof Title ) { $text .= $this->formatRow( Linker::link( $title ), - $this->getLang()->formatNum( $row->page_counter ) ); + $this->getLanguage()->formatNum( $row->page_counter ) ); } } @@ -287,7 +289,7 @@ class SpecialStatistics extends SpecialPage { $name = htmlspecialchars( $name ); $number = htmlspecialchars( $number ); - $return .= $this->formatRow( $name, $this->getLang()->formatNum( $number ), array( 'class' => 'mw-statistics-hook' ) ); + $return .= $this->formatRow( $name, $this->getLanguage()->formatNum( $number ), array( 'class' => 'mw-statistics-hook' ) ); } return $return; diff --git a/includes/specials/SpecialTags.php b/includes/specials/SpecialTags.php index 66a89e94..adfc7441 100644 --- a/includes/specials/SpecialTags.php +++ b/includes/specials/SpecialTags.php @@ -36,10 +36,12 @@ class SpecialTags extends SpecialPage { } function execute( $par ) { - global $wgOut; + $this->setHeaders(); + $this->outputHeader(); - $wgOut->setPageTitle( wfMsg( 'tags-title' ) ); - $wgOut->wrapWikiMsg( "
      \n$1\n
      ", 'tags-intro' ); + $out = $this->getOutput(); + $out->setPageTitle( $this->msg( 'tags-title' ) ); + $out->wrapWikiMsg( "
      \n$1\n
      ", 'tags-intro' ); // Write the headers $html = Xml::tags( 'tr', null, Xml::tags( 'th', null, wfMsgExt( 'tags-tag', 'parseinline' ) ) . @@ -59,35 +61,30 @@ class SpecialTags extends SpecialPage { $html .= $this->doTagRow( $tag, 0 ); } - $wgOut->addHTML( Xml::tags( 'table', array( 'class' => 'wikitable mw-tags-table' ), $html ) ); + $out->addHTML( Xml::tags( 'table', array( 'class' => 'wikitable mw-tags-table' ), $html ) ); } function doTagRow( $tag, $hitcount ) { - static $sk = null, $doneTags = array(); - if ( !$sk ) { - $sk = $this->getSkin(); - } + static $doneTags = array(); if ( in_array( $tag, $doneTags ) ) { return ''; } - global $wgLang; - $newRow = ''; $newRow .= Xml::tags( 'td', null, Xml::element( 'tt', null, $tag ) ); $disp = ChangeTags::tagDescription( $tag ); - $disp .= ' (' . $sk->link( Title::makeTitle( NS_MEDIAWIKI, "Tag-$tag" ), wfMsgHtml( 'tags-edit' ) ) . ')'; + $disp .= ' (' . Linker::link( Title::makeTitle( NS_MEDIAWIKI, "Tag-$tag" ), wfMsgHtml( 'tags-edit' ) ) . ')'; $newRow .= Xml::tags( 'td', null, $disp ); $msg = wfMessage( "tag-$tag-description" ); $desc = !$msg->exists() ? '' : $msg->parse(); - $desc .= ' (' . $sk->link( Title::makeTitle( NS_MEDIAWIKI, "Tag-$tag-description" ), wfMsgHtml( 'tags-edit' ) ) . ')'; + $desc .= ' (' . Linker::link( Title::makeTitle( NS_MEDIAWIKI, "Tag-$tag-description" ), wfMsgHtml( 'tags-edit' ) ) . ')'; $newRow .= Xml::tags( 'td', null, $desc ); - $hitcount = wfMsgExt( 'tags-hitcount', array( 'parsemag' ), $wgLang->formatNum( $hitcount ) ); - $hitcount = $sk->link( SpecialPage::getTitleFor( 'Recentchanges' ), $hitcount, array(), array( 'tagfilter' => $tag ) ); + $hitcount = wfMsgExt( 'tags-hitcount', array( 'parsemag' ), $this->getLanguage()->formatNum( $hitcount ) ); + $hitcount = Linker::link( SpecialPage::getTitleFor( 'Recentchanges' ), $hitcount, array(), array( 'tagfilter' => $tag ) ); $newRow .= Xml::tags( 'td', null, $hitcount ); $doneTags[] = $tag; diff --git a/includes/specials/SpecialUnblock.php b/includes/specials/SpecialUnblock.php index 521c1775..47944309 100644 --- a/includes/specials/SpecialUnblock.php +++ b/includes/specials/SpecialUnblock.php @@ -35,35 +35,22 @@ class SpecialUnblock extends SpecialPage { } public function execute( $par ){ - global $wgUser, $wgOut, $wgRequest; + $this->checkPermissions(); + $this->checkReadOnly(); - # Check permissions - if( !$this->userCanExecute( $wgUser ) ) { - $this->displayRestrictionError(); - return; - } - - # Check for database lock - if( wfReadOnly() ) { - throw new ReadOnlyError; - } - - list( $this->target, $this->type ) = SpecialBlock::getTargetAndType( $par, $wgRequest ); + list( $this->target, $this->type ) = SpecialBlock::getTargetAndType( $par, $this->getRequest() ); $this->block = Block::newFromTarget( $this->target ); - # bug 15810: blocked admins should have limited access here. This won't allow sysops - # to remove autoblocks on themselves, but they should have ipblock-exempt anyway - $status = SpecialBlock::checkUnblockSelf( $this->target ); - if ( $status !== true ) { - throw new ErrorPageError( 'badaccess', $status ); - } + $this->setHeaders(); + $this->outputHeader(); - $wgOut->setPageTitle( wfMsg( 'unblockip' ) ); - $wgOut->addModules( 'mediawiki.special' ); + $out = $this->getOutput(); + $out->setPageTitle( $this->msg( 'unblockip' ) ); + $out->addModules( 'mediawiki.special' ); $form = new HTMLForm( $this->getFields(), $this->getContext() ); $form->setWrapperLegend( wfMsg( 'unblockip' ) ); - $form->setSubmitCallback( array( __CLASS__, 'processUnblock' ) ); + $form->setSubmitCallback( array( __CLASS__, 'processUIUnblock' ) ); $form->setSubmitText( wfMsg( 'ipusubmit' ) ); $form->addPreText( wfMsgExt( 'unblockiptext', 'parse' ) ); @@ -71,14 +58,14 @@ class SpecialUnblock extends SpecialPage { switch( $this->type ){ case Block::TYPE_USER: case Block::TYPE_IP: - $wgOut->addWikiMsg( 'unblocked', $this->target ); + $out->addWikiMsg( 'unblocked', $this->target ); break; case Block::TYPE_RANGE: - $wgOut->addWikiMsg( 'unblocked-range', $this->target ); + $out->addWikiMsg( 'unblocked-range', $this->target ); break; case Block::TYPE_ID: case Block::TYPE_AUTO: - $wgOut->addWikiMsg( 'unblocked-id', $this->target ); + $out->addWikiMsg( 'unblocked-id', $this->target ); break; } } @@ -120,8 +107,7 @@ class SpecialUnblock extends SpecialPage { switch( $type ){ case Block::TYPE_USER: case Block::TYPE_IP: - $skin = $this->getSkin(); - $fields['Name']['default'] = $skin->link( + $fields['Name']['default'] = Linker::link( $target->getUserPage(), $target->getName() ); @@ -148,13 +134,22 @@ class SpecialUnblock extends SpecialPage { return $fields; } + /** + * Submit callback for an HTMLForm object + */ + public static function processUIUnblock( array $data, HTMLForm $form ) { + return self::processUnblock( $data, $form->getContext() ); + } + /** * Process the form + * + * @param $data Array + * @param $context IContextSource * @return Array( Array(message key, parameters) ) on failure, True on success */ - public static function processUnblock( array $data ){ - global $wgUser; - + public static function processUnblock( array $data, IContextSource $context ){ + $performer = $context->getUser(); $target = $data['Target']; $block = Block::newFromTarget( $data['Target'] ); @@ -162,6 +157,14 @@ class SpecialUnblock extends SpecialPage { return array( array( 'ipb_cant_unblock', $target ) ); } + # bug 15810: blocked admins should have limited access here. This + # won't allow sysops to remove autoblocks on themselves, but they + # should have ipblock-exempt anyway + $status = SpecialBlock::checkUnblockSelf( $target, $performer ); + if ( $status !== true ) { + throw new ErrorPageError( 'badaccess', $status ); + } + # If the specified IP is a single address, and the block is a range block, don't # unblock the whole range. list( $target, $type ) = SpecialBlock::getTargetAndType( $target ); @@ -172,7 +175,7 @@ class SpecialUnblock extends SpecialPage { # If the name was hidden and the blocking user cannot hide # names, then don't allow any block removals... - if( !$wgUser->isAllowed( 'hideuser' ) && $block->mHideName ) { + if( !$performer->isAllowed( 'hideuser' ) && $block->mHideName ) { return array( 'unblock-hideuser' ); } diff --git a/includes/specials/SpecialUndelete.php b/includes/specials/SpecialUndelete.php index d4636e74..5d8b17b7 100644 --- a/includes/specials/SpecialUndelete.php +++ b/includes/specials/SpecialUndelete.php @@ -116,7 +116,7 @@ class PageArchive { $res = $dbr->select( 'archive', array( 'ar_minor_edit', 'ar_timestamp', 'ar_user', 'ar_user_text', - 'ar_comment', 'ar_len', 'ar_deleted', 'ar_rev_id' + 'ar_comment', 'ar_len', 'ar_deleted', 'ar_rev_id', 'ar_sha1' ), array( 'ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey() ), @@ -187,10 +187,12 @@ class PageArchive { 'ar_flags', 'ar_text_id', 'ar_deleted', - 'ar_len' ), + 'ar_len', + 'ar_sha1', + ), array( 'ar_namespace' => $this->title->getNamespace(), - 'ar_title' => $this->title->getDBkey(), - 'ar_timestamp' => $dbr->timestamp( $timestamp ) ), + 'ar_title' => $this->title->getDBkey(), + 'ar_timestamp' => $dbr->timestamp( $timestamp ) ), __METHOD__ ); if( $row ) { return Revision::newFromArchiveRow( $row, array( 'page' => $this->title->getArticleId() ) ); @@ -398,18 +400,17 @@ class PageArchive { $dbw = wfGetDB( DB_MASTER ); # Does this page already exist? We'll have to update it... - $article = new Article( $this->title ); + $article = WikiPage::factory( $this->title ); # Load latest data for the current page (bug 31179) $article->loadPageData( 'fromdbmaster' ); $oldcountable = $article->isCountable(); - $options = 'FOR UPDATE'; // lock page $page = $dbw->selectRow( 'page', array( 'page_id', 'page_latest' ), array( 'page_namespace' => $this->title->getNamespace(), 'page_title' => $this->title->getDBkey() ), __METHOD__, - $options + array( 'FOR UPDATE' ) // lock page ); if( $page ) { $makepage = false; @@ -460,7 +461,8 @@ class PageArchive { 'ar_text_id', 'ar_deleted', 'ar_page_id', - 'ar_len' ), + 'ar_len', + 'ar_sha1' ), /* WHERE */ array( 'ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), @@ -580,12 +582,20 @@ class SpecialUndelete extends SpecialPage { parent::__construct( 'Undelete', 'deletedhistory' ); } - function loadRequest() { + function loadRequest( $par ) { $request = $this->getRequest(); $user = $this->getUser(); $this->mAction = $request->getVal( 'action' ); - $this->mTarget = $request->getVal( 'target' ); + if ( $par !== null && $par !== '' ) { + $this->mTarget = $par; + } else { + $this->mTarget = $request->getVal( 'target' ); + } + $this->mTargetObj = null; + if ( $this->mTarget !== null && $this->mTarget !== '' ) { + $this->mTargetObj = Title::newFromURL( $this->mTarget ); + } $this->mSearchPrefix = $request->getText( 'prefix' ); $time = $request->getVal( 'timestamp' ); $this->mTimestamp = $time ? wfTimestamp( TS_MW, $time ) : ''; @@ -597,6 +607,7 @@ class SpecialUndelete extends SpecialPage { $this->mInvert = $request->getCheck( 'invert' ) && $posted; $this->mPreview = $request->getCheck( 'preview' ) && $posted; $this->mDiff = $request->getCheck( 'diff' ); + $this->mDiffOnly = $request->getBool( 'diffonly', $this->getUser()->getOption( 'diffonly' ) ); $this->mComment = $request->getText( 'wpComment' ); $this->mUnsuppress = $request->getVal( 'wpUnsuppress' ) && $user->isAllowed( 'suppressrevision' ); $this->mToken = $request->getVal( 'token' ); @@ -607,6 +618,7 @@ class SpecialUndelete extends SpecialPage { } elseif ( $user->isAllowed( 'deletedtext' ) ) { $this->mAllowed = false; // user cannot restore $this->mCanView = true; // user can view content + $this->mRestore = false; } else { // user can only view the list of revisions $this->mAllowed = false; $this->mCanView = false; @@ -633,104 +645,84 @@ class SpecialUndelete extends SpecialPage { } function execute( $par ) { + $this->checkPermissions(); + $user = $this->getUser(); + $this->setHeaders(); - if ( !$this->userCanExecute( $this->getUser() ) ) { - $this->displayRestrictionError(); - return; - } $this->outputHeader(); - $this->loadRequest(); + $this->loadRequest( $par ); $out = $this->getOutput(); - if ( $this->mAllowed ) { - $out->setPageTitle( wfMsg( 'undeletepage' ) ); - } else { - $out->setPageTitle( wfMsg( 'viewdeletedpage' ) ); - } + if ( is_null( $this->mTargetObj ) ) { + $out->addWikiMsg( 'undelete-header' ); - if( $par != '' ) { - $this->mTarget = $par; - } - if ( $this->mTarget !== '' ) { - $this->mTargetObj = Title::newFromURL( $this->mTarget ); - $this->getSkin()->setRelevantTitle( $this->mTargetObj ); - } else { - $this->mTargetObj = null; - } - - if( is_null( $this->mTargetObj ) ) { # Not all users can just browse every deleted page from the list - if( $this->getUser()->isAllowed( 'browsearchive' ) ) { + if ( $user->isAllowed( 'browsearchive' ) ) { $this->showSearchForm(); - - # List undeletable articles - if( $this->mSearchPrefix ) { - $result = PageArchive::listPagesByPrefix( $this->mSearchPrefix ); - $this->showList( $result ); - } - } else { - $out->addWikiMsg( 'undelete-header' ); } return; } - if( $this->mTimestamp !== '' ) { - return $this->showRevision( $this->mTimestamp ); + + if ( $this->mAllowed ) { + $out->setPageTitle( $this->msg( 'undeletepage' ) ); + } else { + $out->setPageTitle( $this->msg( 'viewdeletedpage' ) ); } - if( $this->mFilename !== null ) { + + $this->getSkin()->setRelevantTitle( $this->mTargetObj ); + + if ( $this->mTimestamp !== '' ) { + $this->showRevision( $this->mTimestamp ); + } elseif ( $this->mFilename !== null ) { $file = new ArchivedFile( $this->mTargetObj, '', $this->mFilename ); // Check if user is allowed to see this file if ( !$file->exists() ) { $out->addWikiMsg( 'filedelete-nofile', $this->mFilename ); - return; - } elseif( !$file->userCan( File::DELETED_FILE ) ) { + } elseif ( !$file->userCan( File::DELETED_FILE, $user ) ) { if( $file->isDeleted( File::DELETED_RESTRICTED ) ) { - $out->permissionRequired( 'suppressrevision' ); + throw new PermissionsError( 'suppressrevision' ); } else { - $out->permissionRequired( 'deletedtext' ); + throw new PermissionsError( 'deletedtext' ); } - return false; - } elseif ( !$this->getUser()->matchEditToken( $this->mToken, $this->mFilename ) ) { + } elseif ( !$user->matchEditToken( $this->mToken, $this->mFilename ) ) { $this->showFileConfirmationForm( $this->mFilename ); - return false; } else { - return $this->showFile( $this->mFilename ); - } - } - if( $this->mRestore && $this->mAction == 'submit' ) { - global $wgUploadMaintenance; - if( $wgUploadMaintenance && $this->mTargetObj && $this->mTargetObj->getNamespace() == NS_FILE ) { - $out->wrapWikiMsg( "
      \n$1\n
      \n", array( 'filedelete-maintenance' ) ); - return; + $this->showFile( $this->mFilename ); } - return $this->undelete(); - } - if( $this->mInvert && $this->mAction == 'submit' ) { - return $this->showHistory(); + } elseif ( $this->mRestore && $this->mAction == 'submit' ) { + $this->undelete(); + } else { + $this->showHistory(); } - return $this->showHistory(); } function showSearchForm() { global $wgScript; - $this->getOutput()->addWikiMsg( 'undelete-header' ); - - $this->getOutput()->addHTML( + $out = $this->getOutput(); + $out->setPageTitle( $this->msg( 'undelete-search-title' ) ); + $out->addHTML( Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) . - Xml::fieldset( wfMsg( 'undelete-search-box' ) ) . + Xml::fieldset( $this->msg( 'undelete-search-box' )->text() ) . Html::hidden( 'title', $this->getTitle()->getPrefixedDbKey() ) . - Xml::inputLabel( wfMsg( 'undelete-search-prefix' ), + Xml::inputLabel( $this->msg( 'undelete-search-prefix' )->text(), 'prefix', 'prefix', 20, $this->mSearchPrefix ) . ' ' . - Xml::submitButton( wfMsg( 'undelete-search-submit' ) ) . + Xml::submitButton( $this->msg( 'undelete-search-submit' )->text() ) . Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' ) ); + + # List undeletable articles + if( $this->mSearchPrefix ) { + $result = PageArchive::listPagesByPrefix( $this->mSearchPrefix ); + $this->showList( $result ); + } } /** @@ -747,7 +739,7 @@ class SpecialUndelete extends SpecialPage { return; } - $out->addWikiMsg( 'undeletepagetext', $this->getLang()->formatNum( $result->numRows() ) ); + $out->addWikiMsg( 'undeletepagetext', $this->getLanguage()->formatNum( $result->numRows() ) ); $undelete = $this->getTitle(); $out->addHTML( "
        \n" ); @@ -759,9 +751,7 @@ class SpecialUndelete extends SpecialPage { array(), array( 'target' => $title->getPrefixedText() ) ); - $revs = wfMsgExt( 'undeleterevisions', - array( 'parseinline' ), - $this->getLang()->formatNum( $row->count ) ); + $revs = $this->msg( 'undeleterevisions' )->numParams( $row->count )->parse(); $out->addHTML( "
      • {$link} ({$revs})
      • \n" ); } $result->free(); @@ -771,8 +761,6 @@ class SpecialUndelete extends SpecialPage { } private function showRevision( $timestamp ) { - $out = $this->getOutput(); - if( !preg_match( '/[0-9]{14}/', $timestamp ) ) { return 0; } @@ -781,13 +769,16 @@ class SpecialUndelete extends SpecialPage { wfRunHooks( 'UndeleteForm::showRevision', array( &$archive, $this->mTargetObj ) ); $rev = $archive->getRevision( $timestamp ); + $out = $this->getOutput(); + $user = $this->getUser(); + if( !$rev ) { $out->addWikiMsg( 'undeleterevision-missing' ); return; } if( $rev->isDeleted( Revision::DELETED_TEXT ) ) { - if( !$rev->userCan( Revision::DELETED_TEXT ) ) { + if( !$rev->userCan( Revision::DELETED_TEXT, $user ) ) { $out->wrapWikiMsg( "\n", 'rev-deleted-text-permission' ); return; } else { @@ -797,13 +788,11 @@ class SpecialUndelete extends SpecialPage { } } - $out->setPageTitle( wfMsg( 'undeletepage' ) ); - if( $this->mDiff ) { $previousRev = $archive->getPreviousRevision( $timestamp ); if( $previousRev ) { $this->showDiff( $previousRev, $rev ); - if( $this->getUser()->getOption( 'diffonly' ) ) { + if( $this->mDiffOnly ) { return; } else { $out->addHTML( '
        ' ); @@ -818,12 +807,14 @@ class SpecialUndelete extends SpecialPage { htmlspecialchars( $this->mTargetObj->getPrefixedText() ) ); + $lang = $this->getLanguage(); + // date and time are separate parameters to facilitate localisation. // $time is kept for backward compat reasons. - $time = $this->getLang()->timeAndDate( $timestamp, true ); - $d = $this->getLang()->date( $timestamp, true ); - $t = $this->getLang()->time( $timestamp, true ); - $user = Linker::revUserTools( $rev ); + $time = $lang->userTimeAndDate( $timestamp, $user ); + $d = $lang->userDate( $timestamp, $user ); + $t = $lang->userTime( $timestamp, $user ); + $userLink = Linker::revUserTools( $rev ); if( $this->mPreview ) { $openDiv = '
        '; @@ -834,14 +825,14 @@ class SpecialUndelete extends SpecialPage { // Revision delete links if ( !$this->mDiff ) { - $revdel = $this->revDeleteLink( $rev ); + $revdel = Linker::getRevDeleteLink( $user, $rev, $this->mTargetObj ); if ( $revdel ) { - $out->addHTML( $revdel ); + $out->addHTML( "$revdel " ); } } - $out->addHTML( wfMessage( 'undelete-revision' )->rawParams( $link )->params( - $time )->rawParams( $user )->params( $d, $t )->parse() . '
        ' ); + $out->addHTML( $this->msg( 'undelete-revision' )->rawParams( $link )->params( + $time )->rawParams( $userLink )->params( $d, $t )->parse() . '' ); wfRunHooks( 'UndeleteShowRevision', array( $this->mTargetObj, $rev ) ); if( $this->mPreview ) { @@ -849,15 +840,15 @@ class SpecialUndelete extends SpecialPage { $popts = $out->parserOptions(); $popts->setEditSection( false ); $out->parserOptions( $popts ); - $out->addWikiTextTitleTidy( $rev->getText( Revision::FOR_THIS_USER ), $this->mTargetObj, true ); + $out->addWikiTextTitleTidy( $rev->getText( Revision::FOR_THIS_USER, $user ), $this->mTargetObj, true ); } $out->addHTML( Xml::element( 'textarea', array( 'readonly' => 'readonly', - 'cols' => intval( $this->getUser()->getOption( 'cols' ) ), - 'rows' => intval( $this->getUser()->getOption( 'rows' ) ) ), - $rev->getText( Revision::FOR_THIS_USER ) . "\n" ) . + 'cols' => intval( $user->getOption( 'cols' ) ), + 'rows' => intval( $user->getOption( 'rows' ) ) ), + $rev->getText( Revision::FOR_THIS_USER, $user ) . "\n" ) . Xml::openElement( 'div' ) . Xml::openElement( 'form', array( 'method' => 'post', @@ -873,61 +864,19 @@ class SpecialUndelete extends SpecialPage { Xml::element( 'input', array( 'type' => 'hidden', 'name' => 'wpEditToken', - 'value' => $this->getUser()->editToken() ) ) . + 'value' => $user->getEditToken() ) ) . Xml::element( 'input', array( 'type' => 'submit', 'name' => 'preview', - 'value' => wfMsg( 'showpreview' ) ) ) . + 'value' => $this->msg( 'showpreview' )->text() ) ) . Xml::element( 'input', array( 'name' => 'diff', 'type' => 'submit', - 'value' => wfMsg( 'showdiff' ) ) ) . + 'value' => $this->msg( 'showdiff' )->text() ) ) . Xml::closeElement( 'form' ) . Xml::closeElement( 'div' ) ); } - /** - * Get a revision-deletion link, or disabled link, or nothing, depending - * on user permissions & the settings on the revision. - * - * Will use forward-compatible revision ID in the Special:RevDelete link - * if possible, otherwise the timestamp-based ID which may break after - * undeletion. - * - * @param Revision $rev - * @return string HTML fragment - */ - function revDeleteLink( $rev ) { - $canHide = $this->getUser()->isAllowed( 'deleterevision' ); - if( $canHide || ( $rev->getVisibility() && $this->getUser()->isAllowed( 'deletedhistory' ) ) ) { - if( !$rev->userCan( Revision::DELETED_RESTRICTED ) ) { - $revdlink = Linker::revDeleteLinkDisabled( $canHide ); // revision was hidden from sysops - } else { - if ( $rev->getId() ) { - // RevDelete links using revision ID are stable across - // page deletion and undeletion; use when possible. - $query = array( - 'type' => 'revision', - 'target' => $this->mTargetObj->getPrefixedDBkey(), - 'ids' => $rev->getId() - ); - } else { - // Older deleted entries didn't save a revision ID. - // We have to refer to these by timestamp, ick! - $query = array( - 'type' => 'archive', - 'target' => $this->mTargetObj->getPrefixedDBkey(), - 'ids' => $rev->getTimestamp() - ); - } - return Linker::revDeleteLink( $query, - $rev->isDeleted( File::DELETED_RESTRICTED ), $canHide ); - } - } else { - return ''; - } - } - /** * Build a diff display between this and the previous either deleted * or non-deleted edit. @@ -937,7 +886,7 @@ class SpecialUndelete extends SpecialPage { * @return String: HTML */ function showDiff( $previousRev, $currentRev ) { - $diffEngine = new DifferenceEngine( $previousRev->getTitle() ); + $diffEngine = new DifferenceEngine( $this->getContext() ); $diffEngine->showDiffStyle(); $this->getOutput()->addHTML( "
        " . @@ -981,18 +930,20 @@ class SpecialUndelete extends SpecialPage { $targetQuery = array( 'oldid' => $rev->getId() ); } // Add show/hide deletion links if available - $del = $this->revDeleteLink( $rev ); + $user = $this->getUser(); + $lang = $this->getLanguage(); + $rdel = Linker::getRevDeleteLink( $user, $rev, $this->mTargetObj ); + if ( $rdel ) $rdel = " $rdel"; return '
        ' . Linker::link( $targetPage, - wfMsgExt( + $this->msg( 'revisionasof', - array( 'escape' ), - $this->getLang()->timeanddate( $rev->getTimestamp(), true ), - $this->getLang()->date( $rev->getTimestamp(), true ), - $this->getLang()->time( $rev->getTimestamp(), true ) - ), + $lang->userTimeAndDate( $rev->getTimestamp(), $user ), + $lang->userDate( $rev->getTimestamp(), $user ), + $lang->userTime( $rev->getTimestamp(), $user ) + )->escaped(), array(), $targetQuery ) . @@ -1001,7 +952,7 @@ class SpecialUndelete extends SpecialPage { Linker::revUserTools( $rev ) . '
        ' . '
        ' . '
        ' . - Linker::revComment( $rev ) . $del . '
        ' . + Linker::revComment( $rev ) . $rdel . '
        ' . '
        '; } @@ -1009,21 +960,24 @@ class SpecialUndelete extends SpecialPage { * Show a form confirming whether a tokenless user really wants to see a file */ private function showFileConfirmationForm( $key ) { + $out = $this->getOutput(); + $lang = $this->getLanguage(); + $user = $this->getUser(); $file = new ArchivedFile( $this->mTargetObj, '', $this->mFilename ); - $this->getOutput()->addWikiMsg( 'undelete-show-file-confirm', + $out->addWikiMsg( 'undelete-show-file-confirm', $this->mTargetObj->getText(), - $this->getLang()->date( $file->getTimestamp() ), - $this->getLang()->time( $file->getTimestamp() ) ); - $this->getOutput()->addHTML( + $lang->userDate( $file->getTimestamp(), $user ), + $lang->userTime( $file->getTimestamp(), $user ) ); + $out->addHTML( Xml::openElement( 'form', array( 'method' => 'POST', 'action' => $this->getTitle()->getLocalURL( 'target=' . urlencode( $this->mTarget ) . '&file=' . urlencode( $key ) . - '&token=' . urlencode( $this->getUser()->editToken( $key ) ) ) + '&token=' . urlencode( $user->getEditToken( $key ) ) ) ) ) . - Xml::submitButton( wfMsg( 'undelete-show-file-submit' ) ) . + Xml::submitButton( $this->msg( 'undelete-show-file-submit' )->text() ) . '' ); } @@ -1043,20 +997,15 @@ class SpecialUndelete extends SpecialPage { $response->header( 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate' ); $response->header( 'Pragma: no-cache' ); - global $IP; - require_once( "$IP/includes/StreamFile.php" ); $repo = RepoGroup::singleton()->getLocalRepo(); $path = $repo->getZonePath( 'deleted' ) . '/' . $repo->getDeletedHashPath( $key ) . $key; - wfStreamFile( $path ); + $repo->streamFile( $path ); } private function showHistory() { $out = $this->getOutput(); if( $this->mAllowed ) { $out->addModules( 'mediawiki.special.undelete' ); - $out->setPageTitle( wfMsg( 'undeletepage' ) ); - } else { - $out->setPageTitle( wfMsg( 'viewdeletedpage' ) ); } $out->wrapWikiMsg( "
        \n$1\n
        \n", @@ -1117,11 +1066,11 @@ class SpecialUndelete extends SpecialPage { # Show relevant lines from the deletion log: $out->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) . "\n" ); - LogEventsList::showLogExtract( $out, 'delete', $this->mTargetObj->getPrefixedText() ); + LogEventsList::showLogExtract( $out, 'delete', $this->mTargetObj ); # Show relevant lines from the suppression log: if( $this->getUser()->isAllowed( 'suppressionlog' ) ) { $out->addHTML( Xml::element( 'h2', null, LogPage::logName( 'suppress' ) ) . "\n" ); - LogEventsList::showLogExtract( $out, 'suppress', $this->mTargetObj->getPrefixedText() ); + LogEventsList::showLogExtract( $out, 'suppress', $this->mTargetObj ); } if( $this->mAllowed && ( $haveRevisions || $haveFiles ) ) { @@ -1132,24 +1081,24 @@ class SpecialUndelete extends SpecialPage { "   " . - Xml::checkLabel( wfMsg( 'revdelete-unsuppress' ), 'wpUnsuppress', - 'mw-undelete-unsuppress', $this->mUnsuppress ). + Xml::checkLabel( $this->msg( 'revdelete-unsuppress' )->text(), + 'wpUnsuppress', 'mw-undelete-unsuppress', $this->mUnsuppress ). " "; } else { $unsuppressBox = ''; } $table = - Xml::fieldset( wfMsg( 'undelete-fieldset-title' ) ) . + Xml::fieldset( $this->msg( 'undelete-fieldset-title' )->text() ) . Xml::openElement( 'table', array( 'id' => 'mw-undelete-table' ) ) . " " . - wfMsgExt( 'undeleteextrahelp', 'parse' ) . + $this->msg( 'undeleteextrahelp' )->parseAsBlock() . " " . - Xml::label( wfMsg( 'undeletecomment' ), 'wpComment' ) . + Xml::label( $this->msg( 'undeletecomment' )->text(), 'wpComment' ) . " " . Xml::input( 'wpComment', 50, $this->mComment, array( 'id' => 'wpComment' ) ) . @@ -1158,8 +1107,8 @@ class SpecialUndelete extends SpecialPage {   " . - Xml::submitButton( wfMsg( 'undeletebtn' ), array( 'name' => 'restore', 'id' => 'mw-undelete-submit' ) ) . ' ' . - Xml::submitButton( wfMsg( 'undeleteinvert' ), array( 'name' => 'invert', 'id' => 'mw-undelete-invert' ) ) . + Xml::submitButton( $this->msg( 'undeletebtn' )->text(), array( 'name' => 'restore', 'id' => 'mw-undelete-submit' ) ) . ' ' . + Xml::submitButton( $this->msg( 'undeleteinvert' )->text(), array( 'name' => 'invert', 'id' => 'mw-undelete-invert' ) ) . " " . $unsuppressBox . @@ -1169,7 +1118,7 @@ class SpecialUndelete extends SpecialPage { $out->addHTML( $table ); } - $out->addHTML( Xml::element( 'h2', null, wfMsg( 'history' ) ) . "\n" ); + $out->addHTML( Xml::element( 'h2', null, $this->msg( 'history' )->text() ) . "\n" ); if( $haveRevisions ) { # The page's stored (deleted) history: @@ -1188,7 +1137,7 @@ class SpecialUndelete extends SpecialPage { } if( $haveFiles ) { - $out->addHTML( Xml::element( 'h2', null, wfMsg( 'filehist' ) ) . "\n" ); + $out->addHTML( Xml::element( 'h2', null, $this->msg( 'filehist' )->text() ) . "\n" ); $out->addHTML( '
          ' ); foreach ( $files as $row ) { $out->addHTML( $this->formatFileRow( $row ) ); @@ -1200,7 +1149,7 @@ class SpecialUndelete extends SpecialPage { if ( $this->mAllowed ) { # Slip in the hidden controls here $misc = Html::hidden( 'target', $this->mTarget ); - $misc .= Html::hidden( 'wpEditToken', $this->getUser()->editToken() ); + $misc .= Html::hidden( 'wpEditToken', $this->getUser()->getEditToken() ); $misc .= Xml::closeElement( 'form' ); $out->addHTML( $misc ); } @@ -1227,18 +1176,19 @@ class SpecialUndelete extends SpecialPage { } else { $checkBox = ''; } + $user = $this->getUser(); // Build page & diff links... if( $this->mCanView ) { $titleObj = $this->getTitle(); # Last link - if( !$rev->userCan( Revision::DELETED_TEXT ) ) { - $pageLink = htmlspecialchars( $this->getLang()->timeanddate( $ts, true ) ); - $last = wfMsgHtml( 'diff' ); + if( !$rev->userCan( Revision::DELETED_TEXT, $this->getUser() ) ) { + $pageLink = htmlspecialchars( $this->getLanguage()->userTimeAndDate( $ts, $user ) ); + $last = $this->msg( 'diff' )->escaped(); } elseif( $remaining > 0 || ( $earliestLiveTime && $ts > $earliestLiveTime ) ) { $pageLink = $this->getPageLink( $rev, $titleObj, $ts ); $last = Linker::linkKnown( $titleObj, - wfMsgHtml( 'diff' ), + $this->msg( 'diff' )->escaped(), array(), array( 'target' => $this->mTargetObj->getPrefixedText(), @@ -1248,11 +1198,11 @@ class SpecialUndelete extends SpecialPage { ); } else { $pageLink = $this->getPageLink( $rev, $titleObj, $ts ); - $last = wfMsgHtml( 'diff' ); + $last = $this->msg( 'diff' )->escaped(); } } else { - $pageLink = htmlspecialchars( $this->getLang()->timeanddate( $ts, true ) ); - $last = wfMsgHtml( 'diff' ); + $pageLink = htmlspecialchars( $this->getLanguage()->userTimeAndDate( $ts, $user ) ); + $last = $this->msg( 'diff' )->escaped(); } // User links $userLink = Linker::revUserTools( $rev ); @@ -1264,7 +1214,7 @@ class SpecialUndelete extends SpecialPage { // Edit summary $comment = Linker::revComment( $rev ); // Revision delete links - $revdlink = $this->revDeleteLink( $rev ); + $revdlink = Linker::getRevDeleteLink( $user, $rev, $this->mTargetObj ); return "
        • $checkBox $revdlink ($last) $pageLink . . $userLink $stxt $comment
        • "; } @@ -1272,28 +1222,25 @@ class SpecialUndelete extends SpecialPage { $file = ArchivedFile::newFromRow( $row ); $ts = wfTimestamp( TS_MW, $row->fa_timestamp ); + $user = $this->getUser(); if( $this->mAllowed && $row->fa_storage_key ) { $checkBox = Xml::check( 'fileid' . $row->fa_id ); $key = urlencode( $row->fa_storage_key ); $pageLink = $this->getFileLink( $file, $this->getTitle(), $ts, $key ); } else { $checkBox = ''; - $pageLink = $this->getLang()->timeanddate( $ts, true ); + $pageLink = $this->getLanguage()->userTimeAndDate( $ts, $user ); } $userLink = $this->getFileUser( $file ); - $data = - wfMsg( 'widthheight', - $this->getLang()->formatNum( $row->fa_width ), - $this->getLang()->formatNum( $row->fa_height ) ) . - ' (' . - wfMsg( 'nbytes', $this->getLang()->formatNum( $row->fa_size ) ) . - ')'; + $data = $this->msg( 'widthheight' )->numParams( $row->fa_width, $row->fa_height )->text() . + ' (' . $this->msg( 'nbytes' )->numParams( $row->fa_size )->text() . ')'; $data = htmlspecialchars( $data ); $comment = $this->getFileComment( $file ); + // Add show/hide deletion links if available - $canHide = $this->getUser()->isAllowed( 'deleterevision' ); - if( $canHide || ( $file->getVisibility() && $this->getUser()->isAllowed( 'deletedhistory' ) ) ) { - if( !$file->userCan( File::DELETED_RESTRICTED ) ) { + $canHide = $user->isAllowed( 'deleterevision' ); + if( $canHide || ( $file->getVisibility() && $user->isAllowed( 'deletedhistory' ) ) ) { + if( !$file->userCan( File::DELETED_RESTRICTED, $user ) ) { $revdlink = Linker::revDeleteLinkDisabled( $canHide ); // revision was hidden from sysops } else { $query = array( @@ -1307,6 +1254,7 @@ class SpecialUndelete extends SpecialPage { } else { $revdlink = ''; } + return "
        • $checkBox $revdlink $pageLink . . $userLink $data $comment
        • \n"; } @@ -1314,17 +1262,20 @@ class SpecialUndelete extends SpecialPage { * Fetch revision text link if it's available to all users * * @param $rev Revision + * @param $titleObj Title + * @param $ts Timestamp * @return string */ function getPageLink( $rev, $titleObj, $ts ) { - $time = htmlspecialchars( $this->getLang()->timeanddate( $ts, true ) ); + $user = $this->getUser(); + $time = $this->getLanguage()->userTimeAndDate( $ts, $user ); - if( !$rev->userCan( Revision::DELETED_TEXT ) ) { + if( !$rev->userCan( Revision::DELETED_TEXT, $user ) ) { return '' . $time . ''; } else { $link = Linker::linkKnown( $titleObj, - $time, + htmlspecialchars( $time ), array(), array( 'target' => $this->mTargetObj->getPrefixedText(), @@ -1342,20 +1293,27 @@ class SpecialUndelete extends SpecialPage { * Fetch image view link if it's available to all users * * @param $file File + * @param $titleObj Title + * @param $ts A timestamp + * @param $key String: a storage key + * * @return String: HTML fragment */ function getFileLink( $file, $titleObj, $ts, $key ) { - if( !$file->userCan( File::DELETED_FILE ) ) { - return '' . $this->getLang()->timeanddate( $ts, true ) . ''; + $user = $this->getUser(); + $time = $this->getLanguage()->userTimeAndDate( $ts, $user ); + + if( !$file->userCan( File::DELETED_FILE, $user ) ) { + return '' . $time . ''; } else { $link = Linker::linkKnown( $titleObj, - $this->getLang()->timeanddate( $ts, true ), + htmlspecialchars( $time ), array(), array( 'target' => $this->mTargetObj->getPrefixedText(), 'file' => $key, - 'token' => $this->getUser()->editToken( $key ) + 'token' => $user->getEditToken( $key ) ) ); if( $file->isDeleted( File::DELETED_FILE ) ) { @@ -1372,8 +1330,8 @@ class SpecialUndelete extends SpecialPage { * @return String: HTML fragment */ function getFileUser( $file ) { - if( !$file->userCan( File::DELETED_USER ) ) { - return '' . wfMsgHtml( 'rev-deleted-user' ) . ''; + if( !$file->userCan( File::DELETED_USER, $this->getUser() ) ) { + return '' . $this->msg( 'rev-deleted-user' )->escaped() . ''; } else { $link = Linker::userLink( $file->getRawUser(), $file->getRawUserText() ) . Linker::userToolLinks( $file->getRawUser(), $file->getRawUserText() ); @@ -1391,9 +1349,9 @@ class SpecialUndelete extends SpecialPage { * @return String: HTML fragment */ function getFileComment( $file ) { - if( !$file->userCan( File::DELETED_COMMENT ) ) { + if( !$file->userCan( File::DELETED_COMMENT, $this->getUser() ) ) { return '' . - wfMsgHtml( 'rev-deleted-comment' ) . ''; + $this->msg( 'rev-deleted-comment' )->escaped() . ''; } else { $link = Linker::commentBlock( $file->getRawDescription() ); if( $file->isDeleted( File::DELETED_COMMENT ) ) { @@ -1404,41 +1362,44 @@ class SpecialUndelete extends SpecialPage { } function undelete() { + global $wgUploadMaintenance; + + if ( $wgUploadMaintenance && $this->mTargetObj->getNamespace() == NS_FILE ) { + throw new ErrorPageError( 'undelete-error', 'filedelete-maintenance' ); + } + if ( wfReadOnly() ) { throw new ReadOnlyError; } - if( !is_null( $this->mTargetObj ) ) { - $archive = new PageArchive( $this->mTargetObj ); - wfRunHooks( 'UndeleteForm::undelete', array( &$archive, $this->mTargetObj ) ); - $ok = $archive->undelete( - $this->mTargetTimestamp, - $this->mComment, - $this->mFileVersions, - $this->mUnsuppress ); - - if( is_array( $ok ) ) { - if ( $ok[1] ) { // Undeleted file count - wfRunHooks( 'FileUndeleteComplete', array( - $this->mTargetObj, $this->mFileVersions, - $this->getUser(), $this->mComment ) ); - } - - $link = Linker::linkKnown( $this->mTargetObj ); - $this->getOutput()->addHTML( wfMessage( 'undeletedpage' )->rawParams( $link )->parse() ); - } else { - $this->getOutput()->showFatalError( wfMsg( 'cannotundelete' ) ); - $this->getOutput()->addWikiMsg( 'undeleterevdel' ); + $out = $this->getOutput(); + $archive = new PageArchive( $this->mTargetObj ); + wfRunHooks( 'UndeleteForm::undelete', array( &$archive, $this->mTargetObj ) ); + $ok = $archive->undelete( + $this->mTargetTimestamp, + $this->mComment, + $this->mFileVersions, + $this->mUnsuppress ); + + if( is_array( $ok ) ) { + if ( $ok[1] ) { // Undeleted file count + wfRunHooks( 'FileUndeleteComplete', array( + $this->mTargetObj, $this->mFileVersions, + $this->getUser(), $this->mComment ) ); } - // Show file deletion warnings and errors - $status = $archive->getFileStatus(); - if( $status && !$status->isGood() ) { - $this->getOutput()->addWikiText( $status->getWikiText( 'undelete-error-short', 'undelete-error-long' ) ); - } + $link = Linker::linkKnown( $this->mTargetObj ); + $out->addHTML( $this->msg( 'undeletedpage' )->rawParams( $link )->parse() ); } else { - $this->getOutput()->showFatalError( wfMsg( 'cannotundelete' ) ); + $out->setPageTitle( $this->msg( 'undelete-error' ) ); + $out->addWikiMsg( 'cannotundelete' ); + $out->addWikiMsg( 'undeleterevdel' ); + } + + // Show file deletion warnings and errors + $status = $archive->getFileStatus(); + if( $status && !$status->isGood() ) { + $out->addWikiText( $status->getWikiText( 'undelete-error-short', 'undelete-error-long' ) ); } - return false; } } diff --git a/includes/specials/SpecialUnlockdb.php b/includes/specials/SpecialUnlockdb.php index 95ad0bf5..2e772540 100644 --- a/includes/specials/SpecialUnlockdb.php +++ b/includes/specials/SpecialUnlockdb.php @@ -26,102 +26,62 @@ * * @ingroup SpecialPage */ -class SpecialUnlockdb extends SpecialPage { +class SpecialUnlockdb extends FormSpecialPage { public function __construct() { parent::__construct( 'Unlockdb', 'siteadmin' ); } - public function execute( $par ) { - global $wgUser, $wgRequest; - - $this->setHeaders(); - - # Permission check - if( !$this->userCanExecute( $wgUser ) ) { - $this->displayRestrictionError(); - return; - } - - $this->outputHeader(); - - $action = $wgRequest->getVal( 'action' ); - - if ( $action == 'success' ) { - $this->showSuccess(); - } elseif ( $action == 'submit' && $wgRequest->wasPosted() && - $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) { - $this->doSubmit(); - } else { - $this->showForm(); - } + public function requiresWrite() { + return false; } - private function showForm( $err = '' ) { - global $wgOut, $wgUser; - + public function checkExecutePermissions( User $user ) { global $wgReadOnlyFile; - if( !file_exists( $wgReadOnlyFile ) ) { - $wgOut->addWikiMsg( 'databasenotlocked' ); - return; - } - - $wgOut->addWikiMsg( 'unlockdbtext' ); - if ( $err != '' ) { - $wgOut->setSubtitle( wfMsg( 'formerror' ) ); - $wgOut->addHTML( '

          ' . htmlspecialchars( $err ) . "

          \n" ); + parent::checkExecutePermissions( $user ); + # If the lock file isn't writable, we can do sweet bugger all + if ( !file_exists( $wgReadOnlyFile ) ) { + throw new ErrorPageError( 'lockdb', 'databasenotlocked' ); } + } - $wgOut->addHTML( - Html::openElement( 'form', array( 'id' => 'unlockdb', 'method' => 'POST', - 'action' => $this->getTitle()->getLocalURL( 'action=submit' ) ) ) . " - - - " . Html::openElement( 'td', array( 'style' => 'text-align:right' ) ) . " - " . Html::input( 'wpLockConfirm', null, 'checkbox' ) . " - - " . Html::openElement( 'td', array( 'style' => 'text-align:left' ) ) . - wfMsgHtml( 'unlockconfirm' ) . " - - - - " . Html::openElement( 'td', array( 'style' => 'text-align:left' ) ) . " - " . Html::input( 'wpLock', wfMsg( 'unlockbtn' ), 'submit' ) . " - - -
           
          \n" . - Html::hidden( 'wpEditToken', $wgUser->editToken() ) . "\n" . - Html::closeElement( 'form' ) + protected function getFormFields() { + return array( + 'Confirm' => array( + 'type' => 'toggle', + 'label-message' => 'unlockconfirm', + ), ); + } + protected function alterForm( HTMLForm $form ) { + $form->setWrapperLegend( false ); + $form->setHeaderText( $this->msg( 'unlockdbtext' )->parseAsBlock() ); + $form->setSubmitTextMsg( 'unlockbtn' ); } - private function doSubmit() { - global $wgOut, $wgRequest, $wgReadOnlyFile; + public function onSubmit( array $data ) { + global $wgReadOnlyFile; - $wpLockConfirm = $wgRequest->getCheck( 'wpLockConfirm' ); - if ( !$wpLockConfirm ) { - $this->showForm( wfMsg( 'locknoconfirm' ) ); - return; + if ( !$data['Confirm'] ) { + return Status::newFatal( 'locknoconfirm' ); } wfSuppressWarnings(); $res = unlink( $wgReadOnlyFile ); wfRestoreWarnings(); - if ( !$res ) { - $wgOut->showFileDeleteError( $wgReadOnlyFile ); - return; + if ( $res ) { + return Status::newGood(); + } else { + return Status::newFatal( 'filedeleteerror', $wgReadOnlyFile ); } - - $wgOut->redirect( $this->getTitle()->getFullURL( 'action=success' ) ); } - private function showSuccess() { - global $wgOut; - - $wgOut->setSubtitle( wfMsg( 'unlockdbsuccesssub' ) ); - $wgOut->addWikiMsg( 'unlockdbsuccesstext' ); + public function onSuccess() { + $out = $this->getOutput(); + $out->addSubtitle( $this->msg( 'unlockdbsuccesssub' ) ); + $out->addWikiMsg( 'unlockdbsuccesstext' ); } } diff --git a/includes/specials/SpecialUnusedcategories.php b/includes/specials/SpecialUnusedcategories.php index e4b8e544..48a93e8d 100644 --- a/includes/specials/SpecialUnusedcategories.php +++ b/includes/specials/SpecialUnusedcategories.php @@ -33,7 +33,7 @@ class UnusedCategoriesPage extends QueryPage { } function getPageHeader() { - return wfMsgExt( 'unusedcategoriestext', array( 'parse' ) ); + return $this->msg( 'unusedcategoriestext' )->parseAsBlock(); } function getQueryInfo() { @@ -59,6 +59,6 @@ class UnusedCategoriesPage extends QueryPage { function formatResult( $skin, $result ) { $title = Title::makeTitle( NS_CATEGORY, $result->title ); - return $skin->link( $title, $title->getText() ); + return Linker::link( $title, htmlspecialchars( $title->getText() ) ); } } diff --git a/includes/specials/SpecialUnusedtemplates.php b/includes/specials/SpecialUnusedtemplates.php index da501605..e5c55b83 100644 --- a/includes/specials/SpecialUnusedtemplates.php +++ b/includes/specials/SpecialUnusedtemplates.php @@ -61,19 +61,19 @@ class UnusedtemplatesPage extends QueryPage { */ function formatResult( $skin, $result ) { $title = Title::makeTitle( NS_TEMPLATE, $result->title ); - $pageLink = $skin->linkKnown( + $pageLink = Linker::linkKnown( $title, null, array(), array( 'redirect' => 'no' ) ); - $wlhLink = $skin->linkKnown( + $wlhLink = Linker::linkKnown( SpecialPage::getTitleFor( 'Whatlinkshere' ), wfMsgHtml( 'unusedtemplateswlh' ), array(), array( 'target' => $title->getPrefixedText() ) ); - return wfSpecialList( $pageLink, $wlhLink ); + return $this->getLanguage()->specialList( $pageLink, $wlhLink ); } function getPageHeader() { diff --git a/includes/specials/SpecialUnwatchedpages.php b/includes/specials/SpecialUnwatchedpages.php index 0f11140b..22c64858 100644 --- a/includes/specials/SpecialUnwatchedpages.php +++ b/includes/specials/SpecialUnwatchedpages.php @@ -83,6 +83,6 @@ class UnwatchedpagesPage extends QueryPage { array( 'action' => 'watch', 'token' => $token ) ); - return wfSpecialList( $plink, $wlink ); + return $this->getLanguage()->specialList( $plink, $wlink ); } } diff --git a/includes/specials/SpecialUpload.php b/includes/specials/SpecialUpload.php index 33013e08..d6a76d02 100644 --- a/includes/specials/SpecialUpload.php +++ b/includes/specials/SpecialUpload.php @@ -35,11 +35,7 @@ class SpecialUpload extends SpecialPage { * @param $request WebRequest : data posted. */ public function __construct( $request = null ) { - global $wgRequest; - parent::__construct( 'Upload', 'upload' ); - - $this->loadRequest( is_null( $request ) ? $wgRequest : $request ); } /** Misc variables **/ @@ -83,13 +79,9 @@ class SpecialUpload extends SpecialPage { /** * Initialize instance variables from request and create an Upload handler - * - * @param $request WebRequest: the request to extract variables from */ - protected function loadRequest( $request ) { - global $wgUser; - - $this->mRequest = $request; + protected function loadRequest() { + $this->mRequest = $request = $this->getRequest(); $this->mSourceType = $request->getVal( 'wpSourceType', 'file' ); $this->mUpload = UploadBase::createFromRequest( $request ); $this->mUploadClicked = $request->wasPosted() @@ -108,7 +100,7 @@ class SpecialUpload extends SpecialPage { $this->mDestWarningAck = $request->getText( 'wpDestFileWarningAck' ); $this->mIgnoreWarning = $request->getCheck( 'wpIgnoreWarning' ) || $request->getCheck( 'wpUploadIgnoreWarning' ); - $this->mWatchthis = $request->getBool( 'wpWatchthis' ) && $wgUser->isLoggedIn(); + $this->mWatchthis = $request->getBool( 'wpWatchthis' ) && $this->getUser()->isLoggedIn(); $this->mCopyrightStatus = $request->getText( 'wpUploadCopyStatus' ); $this->mCopyrightSource = $request->getText( 'wpUploadSource' ); @@ -119,7 +111,7 @@ class SpecialUpload extends SpecialPage { // If it was posted check for the token (no remote POST'ing with user credentials) $token = $request->getVal( 'wpEditToken' ); - $this->mTokenOk = $wgUser->matchEditToken( $token ); + $this->mTokenOk = $this->getUser()->matchEditToken( $token ); $this->uploadFormTextTop = ''; $this->uploadFormTextAfterSummary = ''; @@ -141,42 +133,30 @@ class SpecialUpload extends SpecialPage { * Special page entry point */ public function execute( $par ) { - global $wgUser, $wgOut; - $this->setHeaders(); $this->outputHeader(); # Check uploading enabled if( !UploadBase::isEnabled() ) { - $wgOut->showErrorPage( 'uploaddisabled', 'uploaddisabledtext' ); - return; + throw new ErrorPageError( 'uploaddisabled', 'uploaddisabledtext' ); } # Check permissions - global $wgGroupPermissions; - $permissionRequired = UploadBase::isAllowed( $wgUser ); + $user = $this->getUser(); + $permissionRequired = UploadBase::isAllowed( $user ); if( $permissionRequired !== true ) { - if( !$wgUser->isLoggedIn() && ( $wgGroupPermissions['user']['upload'] - || $wgGroupPermissions['autoconfirmed']['upload'] ) ) { - // Custom message if logged-in users without any special rights can upload - $wgOut->showErrorPage( 'uploadnologin', 'uploadnologintext' ); - } else { - $wgOut->permissionRequired( $permissionRequired ); - } - return; + throw new PermissionsError( $permissionRequired ); } # Check blocks - if( $wgUser->isBlocked() ) { - $wgOut->blockedPage(); - return; + if( $user->isBlocked() ) { + throw new UserBlockedError( $user->mBlock ); } # Check whether we actually want to allow changing stuff - if( wfReadOnly() ) { - $wgOut->readOnlyPage(); - return; - } + $this->checkReadOnly(); + + $this->loadRequest(); # Unsave the temporary file in case this was a cancelled upload if ( $this->mCancelUpload ) { @@ -190,8 +170,7 @@ class SpecialUpload extends SpecialPage { if ( $this->mTokenOk && !$this->mCancelUpload && ( $this->mUpload && $this->mUploadClicked ) - ) - { + ) { $this->processUpload(); } else { # Backwards compatibility hook @@ -199,8 +178,6 @@ class SpecialUpload extends SpecialPage { wfDebug( "Hook 'UploadForm:initial' broke output of the upload form" ); return; } - - $this->showUploadForm( $this->getUploadForm() ); } @@ -224,8 +201,7 @@ class SpecialUpload extends SpecialPage { if ( $form instanceof HTMLForm ) { $form->show(); } else { - global $wgOut; - $wgOut->addHTML( $form ); + $this->getOutput()->addHTML( $form ); } } @@ -239,8 +215,6 @@ class SpecialUpload extends SpecialPage { * @return UploadForm */ protected function getUploadForm( $message = '', $sessionKey = '', $hideIgnoreWarning = false ) { - global $wgOut; - # Initialize form $form = new UploadForm( array( 'watch' => $this->getWatchCheck(), @@ -253,15 +227,14 @@ class SpecialUpload extends SpecialPage { 'texttop' => $this->uploadFormTextTop, 'textaftersummary' => $this->uploadFormTextAfterSummary, 'destfile' => $this->mDesiredDestName, - ) ); + ), $this->getContext() ); $form->setTitle( $this->getTitle() ); # Check the token, but only if necessary if( !$this->mTokenOk && !$this->mCancelUpload && ( $this->mUpload && $this->mUploadClicked ) - ) - { + ) { $form->addPreText( wfMsgExt( 'session_fail_preview', 'parseinline' ) ); } @@ -271,7 +244,7 @@ class SpecialUpload extends SpecialPage { $delNotice = ''; // empty by default if ( $desiredTitleObj instanceof Title && !$desiredTitleObj->exists() ) { LogEventsList::showLogExtract( $delNotice, array( 'delete', 'move' ), - $desiredTitleObj->getPrefixedText(), + $desiredTitleObj, '', array( 'lim' => 10, 'conds' => array( "log_action != 'revision'" ), 'showIfEmpty' => false, @@ -291,33 +264,31 @@ class SpecialUpload extends SpecialPage { $uploadFooter = wfMessage( 'uploadfooter' ); if ( !$uploadFooter->isDisabled() ) { $form->addPostText( '\n" ); + . $this->getOutput()->parse( $uploadFooter->plain() ) . "
        \n" ); } return $form; - } /** * Shows the "view X deleted revivions link"" */ protected function showViewDeletedLinks() { - global $wgOut, $wgUser; - $title = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName ); + $user = $this->getUser(); // Show a subtitle link to deleted revisions (to sysops et al only) if( $title instanceof Title ) { $count = $title->isDeleted(); - if ( $count > 0 && $wgUser->isAllowed( 'deletedhistory' ) ) { + if ( $count > 0 && $user->isAllowed( 'deletedhistory' ) ) { $link = wfMsgExt( - $wgUser->isAllowed( 'delete' ) ? 'thisisdeleted' : 'viewdeleted', + $user->isAllowed( 'delete' ) ? 'thisisdeleted' : 'viewdeleted', array( 'parse', 'replaceafter' ), - $this->getSkin()->linkKnown( + Linker::linkKnown( SpecialPage::getTitleFor( 'Undelete', $title->getPrefixedText() ), wfMsgExt( 'restorelink', array( 'parsemag', 'escape' ), $count ) ) ); - $wgOut->addHTML( "
        {$link}
        " ); + $this->getOutput()->addHTML( "
        {$link}
        " ); } } } @@ -402,7 +373,7 @@ class SpecialUpload extends SpecialPage { /** * Show the upload form with error message, but do not stash the file. * - * @param $message HTML string + * @param $message string HTML string */ protected function showUploadError( $message ) { $message = '

        ' . wfMsgHtml( 'uploadwarning' ) . "

        \n" . @@ -415,12 +386,10 @@ class SpecialUpload extends SpecialPage { * Checks are made in SpecialUpload::execute() */ protected function processUpload() { - global $wgUser, $wgOut; - // Fetch the file if required $status = $this->mUpload->fetchFile(); if( !$status->isOK() ) { - $this->showUploadError( $wgOut->parse( $status->getWikiText() ) ); + $this->showUploadError( $this->getOutput()->parse( $status->getWikiText() ) ); return; } @@ -442,7 +411,7 @@ class SpecialUpload extends SpecialPage { } // Verify permissions for this title - $permErrors = $this->mUpload->verifyTitlePermissions( $wgUser ); + $permErrors = $this->mUpload->verifyTitlePermissions( $this->getUser() ); if( $permErrors !== true ) { $code = array_shift( $permErrors[0] ); $this->showRecoverableUploadError( wfMsgExt( $code, @@ -467,25 +436,31 @@ class SpecialUpload extends SpecialPage { } else { $pageText = false; } - $status = $this->mUpload->performUpload( $this->mComment, $pageText, $this->mWatchthis, $wgUser ); + $status = $this->mUpload->performUpload( $this->mComment, $pageText, $this->mWatchthis, $this->getUser() ); if ( !$status->isGood() ) { - $this->showUploadError( $wgOut->parse( $status->getWikiText() ) ); + $this->showUploadError( $this->getOutput()->parse( $status->getWikiText() ) ); return; } // Success, redirect to description page $this->mUploadSuccessful = true; wfRunHooks( 'SpecialUploadComplete', array( &$this ) ); - $wgOut->redirect( $this->mLocalFile->getTitle()->getFullURL() ); + $this->getOutput()->redirect( $this->mLocalFile->getTitle()->getFullURL() ); } /** * Get the initial image page text based on a comment and optional file status information + * @param $comment string + * @param $license string + * @param $copyStatus string + * @param $source string + * @return string */ public static function getInitialPageText( $comment = '', $license = '', $copyStatus = '', $source = '' ) { global $wgUseCopyrightUpload, $wgForceUIMsgAsContentMsg; $wgForceUIMsgAsContentMsg = (array) $wgForceUIMsgAsContentMsg; + $msg = array(); /* These messages are transcluded into the actual text of the description page. * Thus, forcing them as content messages makes the upload to produce an int: template * instead of hardcoding it there in the uploader language. @@ -529,10 +504,10 @@ class SpecialUpload extends SpecialPage { * * Note that the page target can be changed *on the form*, so our check * state can get out of sync. + * @return Bool|String */ protected function getWatchCheck() { - global $wgUser; - if( $wgUser->getOption( 'watchdefault' ) ) { + if( $this->getUser()->getOption( 'watchdefault' ) ) { // Watch all edits! return true; } @@ -544,7 +519,7 @@ class SpecialUpload extends SpecialPage { return $local->getTitle()->userIsWatching(); } else { // New page should get watched if that's our option. - return $wgUser->getOption( 'watchcreations' ); + return $this->getUser()->getOption( 'watchcreations' ); } } @@ -555,7 +530,7 @@ class SpecialUpload extends SpecialPage { * @param $details Array: result of UploadBase::verifyUpload */ protected function processVerificationError( $details ) { - global $wgFileExtensions, $wgLang; + global $wgFileExtensions; switch( $details['status'] ) { @@ -567,6 +542,9 @@ class SpecialUpload extends SpecialPage { $this->showRecoverableUploadError( wfMsgExt( 'illegalfilename', 'parseinline', $details['filtered'] ) ); break; + case UploadBase::FILENAME_TOO_LONG: + $this->showRecoverableUploadError( wfMsgHtml( 'filename-toolong' ) ); + break; case UploadBase::FILETYPE_MISSING: $this->showRecoverableUploadError( wfMsgExt( 'filetype-missing', 'parseinline' ) ); @@ -586,11 +564,11 @@ class SpecialUpload extends SpecialPage { case UploadBase::FILETYPE_BADTYPE: $msg = wfMessage( 'filetype-banned-type' ); if ( isset( $details['blacklistedExt'] ) ) { - $msg->params( $wgLang->commaList( $details['blacklistedExt'] ) ); + $msg->params( $this->getLanguage()->commaList( $details['blacklistedExt'] ) ); } else { $msg->params( $details['finalExt'] ); } - $msg->params( $wgLang->commaList( $wgFileExtensions ), + $msg->params( $this->getLanguage()->commaList( $wgFileExtensions ), count( $wgFileExtensions ) ); // Add PLURAL support for the first parameter. This results @@ -631,13 +609,12 @@ class SpecialUpload extends SpecialPage { * @return Boolean: success */ protected function unsaveUploadedFile() { - global $wgOut; if ( !( $this->mUpload instanceof UploadFromStash ) ) { return true; } $success = $this->mUpload->unsaveUploadedFile(); if ( !$success ) { - $wgOut->showFileDeleteError( $this->mUpload->getTempPath() ); + $this->getOutput()->showFileDeleteError( $this->mUpload->getTempPath() ); return false; } else { return true; @@ -654,8 +631,6 @@ class SpecialUpload extends SpecialPage { * @return String: empty string if there is no warning or an HTML fragment */ public static function getExistsWarning( $exists ) { - global $wgUser; - if ( !$exists ) { return ''; } @@ -664,8 +639,6 @@ class SpecialUpload extends SpecialPage { $filename = $file->getTitle()->getPrefixedText(); $warning = ''; - $sk = $wgUser->getSkin(); - if( $exists['warning'] == 'exists' ) { // Exact match $warning = wfMsgExt( 'fileexists', 'parseinline', $filename ); @@ -689,7 +662,7 @@ class SpecialUpload extends SpecialPage { } elseif ( $exists['warning'] == 'was-deleted' ) { # If the file existed before and was deleted, warn the user of this $ltitle = SpecialPage::getTitleFor( 'Log' ); - $llink = $sk->linkKnown( + $llink = Linker::linkKnown( $ltitle, wfMsgHtml( 'deletionlog' ), array(), @@ -730,10 +703,12 @@ class SpecialUpload extends SpecialPage { /** * Construct a warning and a gallery from an array of duplicate files. + * @param $dupes array + * @return string */ public static function getDupeWarning( $dupes ) { + global $wgOut; if( $dupes ) { - global $wgOut; $msg = ''; foreach( $dupes as $file ) { $title = $file->getTitle(); @@ -771,7 +746,9 @@ class UploadForm extends HTMLForm { protected $mMaxFileSize = array(); - public function __construct( $options = array() ) { + protected $mMaxUploadSize = array(); + + public function __construct( array $options = array(), IContextSource $context = null ) { $this->mWatch = !empty( $options['watch'] ); $this->mForReUpload = !empty( $options['forreupload'] ); $this->mSessionKey = isset( $options['sessionkey'] ) @@ -795,7 +772,7 @@ class UploadForm extends HTMLForm { + $this->getOptionsSection(); wfRunHooks( 'UploadFormInitDescriptor', array( &$descriptor ) ); - parent::__construct( $descriptor, 'upload' ); + parent::__construct( $descriptor, $context, 'upload' ); # Set some form properties $this->setSubmitText( wfMsg( 'uploadbtn' ) ); @@ -821,8 +798,6 @@ class UploadForm extends HTMLForm { * @return Array: descriptor array */ protected function getSourceSection() { - global $wgLang, $wgUser, $wgRequest; - if ( $this->mSessionKey ) { return array( 'SessionKey' => array( @@ -836,9 +811,9 @@ class UploadForm extends HTMLForm { ); } - $canUploadByUrl = UploadFromUrl::isEnabled() && $wgUser->isAllowed( 'upload_by_url' ); + $canUploadByUrl = UploadFromUrl::isEnabled() && UploadFromUrl::isAllowed( $this->getUser() ); $radio = $canUploadByUrl; - $selectedSourceType = strtolower( $wgRequest->getText( 'wpSourceType', 'File' ) ); + $selectedSourceType = strtolower( $this->getRequest()->getText( 'wpSourceType', 'File' ) ); $descriptor = array(); if ( $this->mTextTop ) { @@ -868,7 +843,7 @@ class UploadForm extends HTMLForm { 'radio' => &$radio, 'help' => wfMsgExt( 'upload-maxfilesize', array( 'parseinline', 'escapenoentities' ), - $wgLang->formatSize( $this->mMaxUploadSize['file'] ) + $this->getContext()->getLanguage()->formatSize( $this->mMaxUploadSize['file'] ) ) . ' ' . wfMsgHtml( 'upload_source_file' ), 'checked' => $selectedSourceType == 'file', ); @@ -883,7 +858,7 @@ class UploadForm extends HTMLForm { 'radio' => &$radio, 'help' => wfMsgExt( 'upload-maxfilesize', array( 'parseinline', 'escapenoentities' ), - $wgLang->formatSize( $this->mMaxUploadSize['url'] ) + $this->getContext()->getLanguage()->formatSize( $this->mMaxUploadSize['url'] ) ) . ' ' . wfMsgHtml( 'upload_source_url' ), 'checked' => $selectedSourceType == 'url', ); @@ -907,7 +882,7 @@ class UploadForm extends HTMLForm { protected function getExtensionsMessage() { # Print a list of allowed file extensions, if so configured. We ignore # MIME type here, it's incomprehensible to most people and too long. - global $wgLang, $wgCheckFileExtensions, $wgStrictFileExtensions, + global $wgCheckFileExtensions, $wgStrictFileExtensions, $wgFileExtensions, $wgFileBlacklist; if( $wgCheckFileExtensions ) { @@ -915,16 +890,16 @@ class UploadForm extends HTMLForm { # Everything not permitted is banned $extensionsList = '
        ' . - wfMsgExt( 'upload-permitted', 'parse', $wgLang->commaList( $wgFileExtensions ) ) . + wfMsgExt( 'upload-permitted', 'parse', $this->getContext()->getLanguage()->commaList( $wgFileExtensions ) ) . "
        \n"; } else { # We have to list both preferred and prohibited $extensionsList = '
        ' . - wfMsgExt( 'upload-preferred', 'parse', $wgLang->commaList( $wgFileExtensions ) ) . + wfMsgExt( 'upload-preferred', 'parse', $this->getContext()->getLanguage()->commaList( $wgFileExtensions ) ) . "
        \n" . '
        ' . - wfMsgExt( 'upload-prohibited', 'parse', $wgLang->commaList( $wgFileBlacklist ) ) . + wfMsgExt( 'upload-prohibited', 'parse', $this->getContext()->getLanguage()->commaList( $wgFileBlacklist ) ) . "
        \n"; } } else { @@ -941,8 +916,6 @@ class UploadForm extends HTMLForm { * @return Array: descriptor array */ protected function getDescriptionSection() { - global $wgUser; - if ( $this->mSessionKey ) { $stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash(); try { @@ -982,7 +955,7 @@ class UploadForm extends HTMLForm { ? 'filereuploadsummary' : 'fileuploadsummary', 'default' => $this->mComment, - 'cols' => intval( $wgUser->getOption( 'cols' ) ), + 'cols' => intval( $this->getUser()->getOption( 'cols' ) ), 'rows' => 8, ) ); @@ -1041,16 +1014,15 @@ class UploadForm extends HTMLForm { * @return Array: descriptor array */ protected function getOptionsSection() { - global $wgUser; - - if ( $wgUser->isLoggedIn() ) { + $user = $this->getUser(); + if ( $user->isLoggedIn() ) { $descriptor = array( 'Watchthis' => array( 'type' => 'check', 'id' => 'wpWatchthis', 'label-message' => 'watchthisupload', 'section' => 'options', - 'default' => $wgUser->getOption( 'watchcreations' ), + 'default' => $user->getOption( 'watchcreations' ), ) ); } @@ -1089,11 +1061,10 @@ class UploadForm extends HTMLForm { } /** - * Add upload JS to $wgOut + * Add upload JS to the OutputPage */ protected function addUploadJS() { global $wgUseAjax, $wgAjaxUploadDestCheck, $wgAjaxLicensePreview, $wgEnableAPI, $wgStrictFileExtensions; - global $wgOut; $useAjaxDestCheck = $wgUseAjax && $wgAjaxUploadDestCheck; $useAjaxLicensePreview = $wgUseAjax && $wgAjaxLicensePreview && $wgEnableAPI; @@ -1112,10 +1083,11 @@ class UploadForm extends HTMLForm { 'wgMaxUploadSize' => $this->mMaxUploadSize, ); - $wgOut->addScript( Skin::makeVariablesScript( $scriptVars ) ); + $out = $this->getOutput(); + $out->addJsConfigVars( $scriptVars ); - $wgOut->addModules( array( + $out->addModules( array( 'mediawiki.action.edit', // For support 'mediawiki.legacy.upload', // Old form stuff... 'mediawiki.special.upload', // Newer extras for thumbnail preview. @@ -1137,6 +1109,11 @@ class UploadForm extends HTMLForm { * A form field that contains a radio box in the label */ class UploadSourceField extends HTMLTextField { + + /** + * @param $cellAttributes array + * @return string + */ function getLabelHtml( $cellAttributes = array() ) { $id = "wpSourceType{$this->mParams['upload-type']}"; $label = Html::rawElement( 'label', array( 'for' => $id ), $this->mLabel ); @@ -1157,6 +1134,9 @@ class UploadSourceField extends HTMLTextField { return Html::rawElement( 'td', array( 'class' => 'mw-label' ) + $cellAttributes, $label ); } + /** + * @return int + */ function getSize() { return isset( $this->mParams['size'] ) ? $this->mParams['size'] diff --git a/includes/specials/SpecialUploadStash.php b/includes/specials/SpecialUploadStash.php index 20a37f0b..121b6a44 100644 --- a/includes/specials/SpecialUploadStash.php +++ b/includes/specials/SpecialUploadStash.php @@ -35,7 +35,6 @@ class SpecialUploadStash extends UnlistedSpecialPage { try { $this->stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash(); } catch ( UploadStashNotAvailableException $e ) { - return null; } } @@ -46,21 +45,14 @@ class SpecialUploadStash extends UnlistedSpecialPage { * @return Boolean: success */ public function execute( $subPage ) { - global $wgUser; + $this->checkPermissions(); - if ( !$this->userCanExecute( $wgUser ) ) { - $this->displayRestrictionError(); - return; - } - - if ( !isset( $subPage ) || $subPage === '' ) { + if ( $subPage === null || $subPage === '' ) { return $this->showUploads(); } - return $this->showUpload( $subPage ); } - /** * If file available in stash, cats it out to the client as a simple HTTP response. * n.b. Most sanity checking done in UploadStashLocalFile, so this is straightforward. @@ -68,10 +60,8 @@ class SpecialUploadStash extends UnlistedSpecialPage { * @param $key String: the key of a particular requested file */ public function showUpload( $key ) { - global $wgOut; - // prevent callers from doing standard HTML output -- we'll take it from here - $wgOut->disable(); + $this->getOutput()->disable(); try { $params = $this->parseKey( $key ); @@ -97,8 +87,7 @@ class SpecialUploadStash extends UnlistedSpecialPage { $message = $e->getMessage(); } - wfHttpError( $code, HttpStatus::getMessage( $code ), $message ); - return false; + throw new HttpError( $code, $message ); } /** @@ -177,14 +166,15 @@ class SpecialUploadStash extends UnlistedSpecialPage { } // we should have just generated it locally - if ( ! $thumbnailImage->getPath() ) { + if ( !$thumbnailImage->getStoragePath() ) { throw new UploadStashFileNotFoundException( "no local path for scaled item" ); } // now we should construct a File, so we can get mime and other such info in a standard way // n.b. mimetype may be different from original (ogx original -> jpeg thumb) - $thumbFile = new UnregisteredLocalFile( false, $this->stash->repo, $thumbnailImage->getPath(), false ); - if ( ! $thumbFile ) { + $thumbFile = new UnregisteredLocalFile( false, + $this->stash->repo, $thumbnailImage->getStoragePath(), false ); + if ( !$thumbFile ) { throw new UploadStashFileNotFoundException( "couldn't create local file object for thumbnail" ); } @@ -210,12 +200,20 @@ class SpecialUploadStash extends UnlistedSpecialPage { // this global probably looks something like 'http://upload.wikimedia.org/wikipedia/test/thumb/temp' // do not use trailing slash global $wgUploadStashScalerBaseUrl; + $scalerBaseUrl = $wgUploadStashScalerBaseUrl; + + if( preg_match( '/^\/\//', $scalerBaseUrl ) ) { + // this is apparently a protocol-relative URL, which makes no sense in this context, + // since this is used for communication that's internal to the application. + // default to http. + $scalerBaseUrl = wfExpandUrl( $scalerBaseUrl, PROTO_CANONICAL ); + } // We need to use generateThumbName() instead of thumbName(), because // the suffix needs to match the file name for the remote thumbnailer // to work $scalerThumbName = $file->generateThumbName( $file->getName(), $params ); - $scalerThumbUrl = $wgUploadStashScalerBaseUrl . '/' . $file->getUrlRel() . + $scalerThumbUrl = $scalerBaseUrl . '/' . $file->getUrlRel() . '/' . rawurlencode( $scalerThumbName ); // make a curl call to the scaler to create a thumbnail @@ -241,18 +239,17 @@ class SpecialUploadStash extends UnlistedSpecialPage { /** * Output HTTP response for file * Side effect: writes HTTP response to STDOUT. - * XXX could use wfStreamfile (in includes/Streamfile.php), but for consistency with outputContents() doing it this way. - * XXX is mimeType really enough, or do we need encoding for full Content-Type header? * * @param $file File object with a local path (e.g. UnregisteredLocalFile, LocalFile. Oddly these don't share an ancestor!) */ - private function outputLocalFile( $file ) { + private function outputLocalFile( File $file ) { if ( $file->getSize() > self::MAX_SERVE_BYTES ) { throw new SpecialUploadStashTooLargeException(); } - self::outputFileHeaders( $file->getMimeType(), $file->getSize() ); - readfile( $file->getPath() ); - return true; + return $file->getRepo()->streamFile( $file->getPath(), + array( 'Content-Transfer-Encoding: binary', + 'Expires: Sun, 17-Jan-2038 19:14:07 GMT' ) + ); } /** @@ -309,7 +306,6 @@ class SpecialUploadStash extends UnlistedSpecialPage { * @param Status : $status - the result of processRequest */ private function showUploads( $status = null ) { - global $wgOut; if ( $status === null ) { $status = Status::newGood(); } @@ -327,7 +323,7 @@ class SpecialUploadStash extends UnlistedSpecialPage { 'default' => true, 'name' => 'clear', ) - ), 'clearStashedUploads' ); + ), $this->getContext(), 'clearStashedUploads' ); $form->setSubmitCallback( array( __CLASS__ , 'tryClearStashedUploads' ) ); $form->setTitle( $this->getTitle() ); $form->setSubmitText( wfMsg( 'uploadstash-clear' ) ); @@ -340,7 +336,7 @@ class SpecialUploadStash extends UnlistedSpecialPage { array( 'href' => $this->getTitle()->getLocalURL() ), wfMsg( 'uploadstash-refresh' ) ); $files = $this->stash->listFiles(); - if ( count( $files ) ) { + if ( $files && count( $files ) ) { sort( $files ); $fileListItemsHtml = ''; foreach ( $files as $file ) { @@ -350,11 +346,11 @@ class SpecialUploadStash extends UnlistedSpecialPage { $this->getTitle( "file/$file" )->getLocalURL() ), $file ) ); } - $wgOut->addHtml( Html::rawElement( 'ul', array(), $fileListItemsHtml ) ); + $this->getOutput()->addHtml( Html::rawElement( 'ul', array(), $fileListItemsHtml ) ); $form->displayForm( $formResult ); - $wgOut->addHtml( Html::rawElement( 'p', array(), $refreshHtml ) ); + $this->getOutput()->addHtml( Html::rawElement( 'p', array(), $refreshHtml ) ); } else { - $wgOut->addHtml( Html::rawElement( 'p', array(), + $this->getOutput()->addHtml( Html::rawElement( 'p', array(), Html::element( 'span', array(), wfMsg( 'uploadstash-nofiles' ) ) . ' ' . $refreshHtml diff --git a/includes/specials/SpecialUserlogin.php b/includes/specials/SpecialUserlogin.php index 0e5baa2d..13ea5def 100644 --- a/includes/specials/SpecialUserlogin.php +++ b/includes/specials/SpecialUserlogin.php @@ -49,34 +49,44 @@ class LoginForm extends SpecialPage { var $mSkipCookieCheck, $mReturnToQuery, $mToken, $mStickHTTPS; var $mType, $mReason, $mRealName; var $mAbortLoginErrorMsg = 'login-abort-generic'; + private $mLoaded = false; /** * @var ExternalUser */ private $mExtUser = null; + /** + * @ var WebRequest + */ + private $mOverrideRequest = null; + /** * @param WebRequest $request */ public function __construct( $request = null ) { parent::__construct( 'Userlogin' ); - if ( $request === null ) { - global $wgRequest; - $this->load( $wgRequest ); - } else { - $this->load( $request ); - } + $this->mOverrideRequest = $request; } /** * Loader - * - * @param $request WebRequest object */ - function load( $request ) { + function load() { global $wgAuth, $wgHiddenPrefs, $wgEnableEmail, $wgRedirectOnLogin; + if ( $this->mLoaded ) { + return; + } + $this->mLoaded = true; + + if ( $this->mOverrideRequest === null ) { + $request = $this->getRequest(); + } else { + $request = $this->mOverrideRequest; + } + $this->mType = $request->getText( 'type' ); $this->mUsername = $request->getText( 'wpName' ); $this->mPassword = $request->getText( 'wpPassword' ); @@ -115,7 +125,11 @@ class LoginForm extends SpecialPage { } if( !$wgAuth->validDomain( $this->mDomain ) ) { - $this->mDomain = 'invaliddomain'; + if ( isset( $_SESSION['wsDomain'] ) ) { + $this->mDomain = $_SESSION['wsDomain']; + } else { + $this->mDomain = 'invaliddomain'; + } } $wgAuth->setDomain( $this->mDomain ); @@ -127,11 +141,19 @@ class LoginForm extends SpecialPage { } } + function getDescription() { + return $this->msg( $this->getUser()->isAllowed( 'createaccount' ) ? + 'userlogin' : 'userloginnocreate' )->text(); + } + public function execute( $par ) { if ( session_id() == '' ) { wfSetupSession(); } + $this->load(); + $this->setHeaders(); + if ( $par == 'signup' ) { # Check for [[Special:Userlogin/signup]] $this->mType = 'signup'; } @@ -155,10 +177,8 @@ class LoginForm extends SpecialPage { * @private */ function addNewAccountMailPassword() { - global $wgOut; - if ( $this->mEmail == '' ) { - $this->mainLoginForm( wfMsgExt( 'noemailcreate', array( 'parsemag', 'escape' ) ) ); + $this->mainLoginForm( $this->msg( 'noemailcreate' )->escaped() ); return; } @@ -176,13 +196,14 @@ class LoginForm extends SpecialPage { wfRunHooks( 'AddNewAccount', array( $u, true ) ); $u->addNewUserLogEntry( true, $this->mReason ); - $wgOut->setPageTitle( wfMsg( 'accmailtitle' ) ); + $out = $this->getOutput(); + $out->setPageTitle( $this->msg( 'accmailtitle' ) ); if( !$result->isGood() ) { - $this->mainLoginForm( wfMsg( 'mailerror', $result->getWikiText() ) ); + $this->mainLoginForm( $this->msg( 'mailerror', $result->getWikiText() )->text() ); } else { - $wgOut->addWikiMsg( 'accmailtext', $u->getName(), $u->getEmail() ); - $wgOut->returnToMain( false ); + $out->addWikiMsg( 'accmailtext', $u->getName(), $u->getEmail() ); + $out->returnToMain( false ); } } @@ -190,7 +211,7 @@ class LoginForm extends SpecialPage { * @private */ function addNewAccount() { - global $wgUser, $wgEmailAuthentication, $wgOut; + global $wgUser, $wgEmailAuthentication, $wgLoginLanguageSelector; # Create the account and abort if there's a problem doing so $u = $this->addNewAccountInternal(); @@ -200,18 +221,19 @@ class LoginForm extends SpecialPage { # If we showed up language selection links, and one was in use, be # smart (and sensible) and save that language as the user's preference - global $wgLoginLanguageSelector; if( $wgLoginLanguageSelector && $this->mLanguage ) { $u->setOption( 'language', $this->mLanguage ); } + $out = $this->getOutput(); + # Send out an email authentication message if needed if( $wgEmailAuthentication && Sanitizer::validateEmail( $u->getEmail() ) ) { $status = $u->sendConfirmationMail(); if( $status->isGood() ) { - $wgOut->addWikiMsg( 'confirmemail_oncreate' ); + $out->addWikiMsg( 'confirmemail_oncreate' ); } else { - $wgOut->addWikiText( $status->getWikiText( 'confirmemail_sendfailed' ) ); + $out->addWikiText( $status->getWikiText( 'confirmemail_sendfailed' ) ); } } @@ -221,15 +243,15 @@ class LoginForm extends SpecialPage { # If not logged in, assume the new account as the current one and set # session cookies then show a "welcome" message or a "need cookies" # message as needed - if( $wgUser->isAnon() ) { + if( $this->getUser()->isAnon() ) { + $u->setCookies(); $wgUser = $u; - $wgUser->setCookies(); // This should set it for OutputPage and the Skin // which is needed or the personal links will be // wrong. - RequestContext::getMain()->setUser( $u ); - wfRunHooks( 'AddNewAccount', array( $wgUser, false ) ); - $wgUser->addNewUserLogEntry(); + $this->getContext()->setUser( $u ); + wfRunHooks( 'AddNewAccount', array( $u, false ) ); + $u->addNewUserLogEntry(); if( $this->hasSessionCookie() ) { return $this->successfulCreation(); } else { @@ -237,10 +259,9 @@ class LoginForm extends SpecialPage { } } else { # Confirm that the account was created - $self = SpecialPage::getTitleFor( 'Userlogin' ); - $wgOut->setPageTitle( wfMsgHtml( 'accountcreated' ) ); - $wgOut->addWikiMsg( 'accountcreatedtext', $u->getName() ); - $wgOut->returnToMain( false, $self ); + $out->setPageTitle( $this->msg( 'accountcreated' ) ); + $out->addWikiMsg( 'accountcreatedtext', $u->getName() ); + $out->returnToMain( false, $this->getTitle() ); wfRunHooks( 'AddNewAccount', array( $u, false ) ); $u->addNewUserLogEntry( false, $this->mReason ); return true; @@ -251,14 +272,12 @@ class LoginForm extends SpecialPage { * @private */ function addNewAccountInternal() { - global $wgUser, $wgOut; - global $wgMemc, $wgAccountCreationThrottle; - global $wgAuth, $wgMinimalPasswordLength; - global $wgEmailConfirmToEdit; + global $wgAuth, $wgMemc, $wgAccountCreationThrottle, + $wgMinimalPasswordLength, $wgEmailConfirmToEdit; // If the user passes an invalid domain, something is fishy if( !$wgAuth->validDomain( $this->mDomain ) ) { - $this->mainLoginForm( wfMsg( 'wrongpassword' ) ); + $this->mainLoginForm( $this->msg( 'wrongpassword' )->text() ); return false; } @@ -270,47 +289,46 @@ class LoginForm extends SpecialPage { if( 'local' != $this->mDomain && $this->mDomain != '' ) { if( !$wgAuth->canCreateAccounts() && ( !$wgAuth->userExists( $this->mUsername ) || !$wgAuth->authenticate( $this->mUsername, $this->mPassword ) ) ) { - $this->mainLoginForm( wfMsg( 'wrongpassword' ) ); + $this->mainLoginForm( $this->msg( 'wrongpassword' )->text() ); return false; } } if ( wfReadOnly() ) { - $wgOut->readOnlyPage(); - return false; + throw new ReadOnlyError; } # Request forgery checks. if ( !self::getCreateaccountToken() ) { self::setCreateaccountToken(); - $this->mainLoginForm( wfMsgExt( 'nocookiesfornew', array( 'parseinline' ) ) ); + $this->mainLoginForm( $this->msg( 'nocookiesfornew' )->parse() ); return false; } # The user didn't pass a createaccount token if ( !$this->mToken ) { - $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); + $this->mainLoginForm( $this->msg( 'sessionfailure' )->text() ); return false; } # Validate the createaccount token if ( $this->mToken !== self::getCreateaccountToken() ) { - $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); + $this->mainLoginForm( $this->msg( 'sessionfailure' )->text() ); return false; } # Check permissions - if ( !$wgUser->isAllowed( 'createaccount' ) ) { - $wgOut->permissionRequired( 'createaccount' ); - return false; - } elseif ( $wgUser->isBlockedFromCreateAccount() ) { - $this->userBlockedMessage( $wgUser->isBlockedFromCreateAccount() ); + $currentUser = $this->getUser(); + if ( !$currentUser->isAllowed( 'createaccount' ) ) { + throw new PermissionsError( 'createaccount' ); + } elseif ( $currentUser->isBlockedFromCreateAccount() ) { + $this->userBlockedMessage( $currentUser->isBlockedFromCreateAccount() ); return false; } - $ip = wfGetIP(); - if ( $wgUser->isDnsBlacklisted( $ip, true /* check $wgProxyWhitelist */ ) ) { - $this->mainLoginForm( wfMsg( 'sorbs_create_account_reason' ) . ' (' . htmlspecialchars( $ip ) . ')' ); + $ip = $this->getRequest()->getIP(); + if ( $currentUser->isDnsBlacklisted( $ip, true /* check $wgProxyWhitelist */ ) ) { + $this->mainLoginForm( $this->msg( 'sorbs_create_account_reason' )->text() . ' (' . htmlspecialchars( $ip ) . ')' ); return false; } @@ -318,17 +336,17 @@ class LoginForm extends SpecialPage { $name = trim( $this->mUsername ); $u = User::newFromName( $name, 'creatable' ); if ( !is_object( $u ) ) { - $this->mainLoginForm( wfMsg( 'noname' ) ); + $this->mainLoginForm( $this->msg( 'noname' )->text() ); return false; } if ( 0 != $u->idForName() ) { - $this->mainLoginForm( wfMsg( 'userexists' ) ); + $this->mainLoginForm( $this->msg( 'userexists' )->text() ); return false; } if ( 0 != strcmp( $this->mPassword, $this->mRetype ) ) { - $this->mainLoginForm( wfMsg( 'badretype' ) ); + $this->mainLoginForm( $this->msg( 'badretype' )->text() ); return false; } @@ -343,7 +361,7 @@ class LoginForm extends SpecialPage { $message = $valid; $params = array( $wgMinimalPasswordLength ); } - $this->mainLoginForm( wfMsgExt( $message, array( 'parsemag' ), $params ) ); + $this->mainLoginForm( $this->msg( $message, $params )->text() ); return false; } else { # do not force a password for account creation by email @@ -355,12 +373,12 @@ class LoginForm extends SpecialPage { # if you need a confirmed email address to edit, then obviously you # need an email address. if ( $wgEmailConfirmToEdit && empty( $this->mEmail ) ) { - $this->mainLoginForm( wfMsg( 'noemailtitle' ) ); + $this->mainLoginForm( $this->msg( 'noemailtitle' )->text() ); return false; } if( !empty( $this->mEmail ) && !Sanitizer::validateEmail( $this->mEmail ) ) { - $this->mainLoginForm( wfMsg( 'invalidemailaddress' ) ); + $this->mainLoginForm( $this->msg( 'invalidemailaddress' )->text() ); return false; } @@ -377,21 +395,26 @@ class LoginForm extends SpecialPage { return false; } - if ( $wgAccountCreationThrottle && $wgUser->isPingLimitable() ) { - $key = wfMemcKey( 'acctcreate', 'ip', $ip ); - $value = $wgMemc->get( $key ); - if ( !$value ) { - $wgMemc->set( $key, 0, 86400 ); - } - if ( $value >= $wgAccountCreationThrottle ) { - $this->throttleHit( $wgAccountCreationThrottle ); - return false; + // Hook point to check for exempt from account creation throttle + if ( !wfRunHooks( 'ExemptFromAccountCreationThrottle', array( $ip ) ) ) { + wfDebug( "LoginForm::exemptFromAccountCreationThrottle: a hook allowed account creation w/o throttle\n" ); + } else { + if ( ( $wgAccountCreationThrottle && $currentUser->isPingLimitable() ) ) { + $key = wfMemcKey( 'acctcreate', 'ip', $ip ); + $value = $wgMemc->get( $key ); + if ( !$value ) { + $wgMemc->set( $key, 0, 86400 ); + } + if ( $value >= $wgAccountCreationThrottle ) { + $this->throttleHit( $wgAccountCreationThrottle ); + return false; + } + $wgMemc->incr( $key ); } - $wgMemc->incr( $key ); } if( !$wgAuth->addUser( $u, $this->mPassword, $this->mEmail, $this->mRealName ) ) { - $this->mainLoginForm( wfMsg( 'externaldberror' ) ); + $this->mainLoginForm( $this->msg( 'externaldberror' )->text() ); return false; } @@ -451,6 +474,8 @@ class LoginForm extends SpecialPage { public function authenticateUserData() { global $wgUser, $wgAuth; + $this->load(); + if ( $this->mUsername == '' ) { return self::NO_NAME; } @@ -480,13 +505,13 @@ class LoginForm extends SpecialPage { return self::WRONG_TOKEN; } - // Load $wgUser now, and check to see if we're logging in as the same - // name. This is necessary because loading $wgUser (say by calling - // getName()) calls the UserLoadFromSession hook, which potentially - // creates the user in the database. Until we load $wgUser, checking - // for user existence using User::newFromName($name)->getId() below + // Load the current user now, and check to see if we're logging in as + // the same name. This is necessary because loading the current user + // (say by calling getName()) calls the UserLoadFromSession hook, which + // potentially creates the user in the database. Until we load $wgUser, + // checking for user existence using User::newFromName($name)->getId() below // will effectively be using stale data. - if ( $wgUser->getName() === $this->mUsername ) { + if ( $this->getUser()->getName() === $this->mUsername ) { wfDebug( __METHOD__ . ": already logged in as {$this->mUsername}\n" ); return self::SUCCESS; } @@ -567,7 +592,7 @@ class LoginForm extends SpecialPage { // This should set it for OutputPage and the Skin // which is needed or the personal links will be // wrong. - RequestContext::getMain()->setUser( $u ); + $this->getContext()->setUser( $u ); // Please reset throttle for successful logins, thanks! if ( $throttleCount ) { @@ -576,7 +601,7 @@ class LoginForm extends SpecialPage { if ( $isAutoCreated ) { // Must be run after $wgUser is set, for correct new user log - wfRunHooks( 'AuthPluginAutoCreate', array( $wgUser ) ); + wfRunHooks( 'AuthPluginAutoCreate', array( $u ) ); } $retval = self::SUCCESS; @@ -585,18 +610,19 @@ class LoginForm extends SpecialPage { return $retval; } - /* + /** * Increment the login attempt throttle hit count for the (username,current IP) * tuple unless the throttle was already reached. * @param $username string The user name * @return Bool|Integer The integer hit count or True if it is already at the limit */ public static function incLoginThrottle( $username ) { - global $wgPasswordAttemptThrottle, $wgMemc; + global $wgPasswordAttemptThrottle, $wgMemc, $wgRequest; + $username = trim( $username ); // sanity $throttleCount = 0; if ( is_array( $wgPasswordAttemptThrottle ) ) { - $throttleKey = wfMemcKey( 'password-throttle', wfGetIP(), md5( $username ) ); + $throttleKey = wfMemcKey( 'password-throttle', $wgRequest->getIP(), md5( $username ) ); $count = $wgPasswordAttemptThrottle['count']; $period = $wgPasswordAttemptThrottle['seconds']; @@ -613,15 +639,16 @@ class LoginForm extends SpecialPage { return $throttleCount; } - /* + /** * Clear the login attempt throttle hit count for the (username,current IP) tuple. * @param $username string The user name * @return void */ public static function clearLoginThrottle( $username ) { - global $wgMemc; + global $wgMemc, $wgRequest; + $username = trim( $username ); // sanity - $throttleKey = wfMemcKey( 'password-throttle', wfGetIP(), md5( $username ) ); + $throttleKey = wfMemcKey( 'password-throttle', $wgRequest->getIP(), md5( $username ) ); $wgMemc->delete( $throttleKey ); } @@ -634,9 +661,9 @@ class LoginForm extends SpecialPage { * @return integer Status code */ function attemptAutoCreate( $user ) { - global $wgAuth, $wgUser, $wgAutocreatePolicy; + global $wgAuth, $wgAutocreatePolicy; - if ( $wgUser->isBlockedFromCreateAccount() ) { + if ( $this->getUser()->isBlockedFromCreateAccount() ) { wfDebug( __METHOD__ . ": user is blocked from account creation\n" ); return self::CREATE_BLOCKED; } @@ -684,32 +711,34 @@ class LoginForm extends SpecialPage { } function processLogin() { - global $wgUser; + global $wgMemc, $wgLang; switch ( $this->authenticateUserData() ) { case self::SUCCESS: # We've verified now, update the real record - if( (bool)$this->mRemember != (bool)$wgUser->getOption( 'rememberpassword' ) ) { - $wgUser->setOption( 'rememberpassword', $this->mRemember ? 1 : 0 ); - $wgUser->saveSettings(); + $user = $this->getUser(); + if( (bool)$this->mRemember != (bool)$user->getOption( 'rememberpassword' ) ) { + $user->setOption( 'rememberpassword', $this->mRemember ? 1 : 0 ); + $user->saveSettings(); } else { - $wgUser->invalidateCache(); + $user->invalidateCache(); } - $wgUser->setCookies(); + $user->setCookies(); self::clearLoginToken(); // Reset the throttle - $key = wfMemcKey( 'password-throttle', wfGetIP(), md5( $this->mUsername ) ); - global $wgMemc; + $request = $this->getRequest(); + $key = wfMemcKey( 'password-throttle', $request->getIP(), md5( $this->mUsername ) ); $wgMemc->delete( $key ); if( $this->hasSessionCookie() || $this->mSkipCookieCheck ) { /* Replace the language object to provide user interface in * correct language immediately on this first page load. */ - global $wgLang, $wgRequest; - $code = $wgRequest->getVal( 'uselang', $wgUser->getOption( 'language' ) ); - $wgLang = Language::factory( $code ); + $code = $request->getVal( 'uselang', $user->getOption( 'language' ) ); + $userLang = Language::factory( $code ); + $wgLang = $userLang; + $this->getContext()->setLanguage( $userLang ); return $this->successfulLogin(); } else { return $this->cookieRedirectCheck( 'login' ); @@ -717,48 +746,48 @@ class LoginForm extends SpecialPage { break; case self::NEED_TOKEN: - $this->mainLoginForm( wfMsgExt( 'nocookiesforlogin', array( 'parseinline' ) ) ); + $this->mainLoginForm( $this->msg( 'nocookiesforlogin' )->parse() ); break; case self::WRONG_TOKEN: - $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); + $this->mainLoginForm( $this->msg( 'sessionfailure' )->text() ); break; case self::NO_NAME: case self::ILLEGAL: - $this->mainLoginForm( wfMsg( 'noname' ) ); + $this->mainLoginForm( $this->msg( 'noname' )->text() ); break; case self::WRONG_PLUGIN_PASS: - $this->mainLoginForm( wfMsg( 'wrongpassword' ) ); + $this->mainLoginForm( $this->msg( 'wrongpassword' )->text() ); break; case self::NOT_EXISTS: - if( $wgUser->isAllowed( 'createaccount' ) ) { - $this->mainLoginForm( wfMsgExt( 'nosuchuser', 'parseinline', - wfEscapeWikiText( $this->mUsername ) ) ); + if( $this->getUser()->isAllowed( 'createaccount' ) ) { + $this->mainLoginForm( $this->msg( 'nosuchuser', + wfEscapeWikiText( $this->mUsername ) )->parse() ); } else { - $this->mainLoginForm( wfMsg( 'nosuchusershort', - wfEscapeWikiText( $this->mUsername ) ) ); + $this->mainLoginForm( $this->msg( 'nosuchusershort', + wfEscapeWikiText( $this->mUsername ) )->text() ); } break; case self::WRONG_PASS: - $this->mainLoginForm( wfMsg( 'wrongpassword' ) ); + $this->mainLoginForm( $this->msg( 'wrongpassword' )->text() ); break; case self::EMPTY_PASS: - $this->mainLoginForm( wfMsg( 'wrongpasswordempty' ) ); + $this->mainLoginForm( $this->msg( 'wrongpasswordempty' )->text() ); break; case self::RESET_PASS: - $this->resetLoginForm( wfMsg( 'resetpass_announce' ) ); + $this->resetLoginForm( $this->msg( 'resetpass_announce' )->text() ); break; case self::CREATE_BLOCKED: - $this->userBlockedMessage( $wgUser->mBlock ); + $this->userBlockedMessage( $this->getUser()->mBlock ); break; case self::THROTTLED: - $this->mainLoginForm( wfMsg( 'login-throttled' ) ); + $this->mainLoginForm( $this->msg( 'login-throttled' )->text() ); break; case self::USER_BLOCKED: - $this->mainLoginForm( wfMsgExt( 'login-userblocked', - array( 'parsemag', 'escape' ), $this->mUsername ) ); + $this->mainLoginForm( $this->msg( 'login-userblocked', + $this->mUsername )->escaped() ); break; case self::ABORTED: - $this->mainLoginForm( wfMsg( $this->mAbortLoginErrorMsg ) ); + $this->mainLoginForm( $this->msg( $this->mAbortLoginErrorMsg )->text() ); break; default: throw new MWException( 'Unhandled case value' ); @@ -766,9 +795,9 @@ class LoginForm extends SpecialPage { } function resetLoginForm( $error ) { - global $wgOut; - $wgOut->addHTML( Xml::element('p', array( 'class' => 'error' ), $error ) ); + $this->getOutput()->addHTML( Xml::element('p', array( 'class' => 'error' ), $error ) ); $reset = new SpecialChangePassword(); + $reset->setContext( $this->getContext() ); $reset->execute( null ); } @@ -778,28 +807,28 @@ class LoginForm extends SpecialPage { * @param $emailTitle String: message name of email title * @param $emailText String: message name of email text * @return Status object - * @private */ function mailPasswordInternal( $u, $throttle = true, $emailTitle = 'passwordremindertitle', $emailText = 'passwordremindertext' ) { - global $wgServer, $wgScript, $wgUser, $wgNewPasswordExpiry; + global $wgServer, $wgScript, $wgNewPasswordExpiry; if ( $u->getEmail() == '' ) { return Status::newFatal( 'noemail', $u->getName() ); } - $ip = wfGetIP(); + $ip = $this->getRequest()->getIP(); if( !$ip ) { return Status::newFatal( 'badipaddress' ); } - wfRunHooks( 'User::mailPasswordInternal', array( &$wgUser, &$ip, &$u ) ); + $currentUser = $this->getUser(); + wfRunHooks( 'User::mailPasswordInternal', array( &$currentUser, &$ip, &$u ) ); $np = $u->randomPassword(); $u->setNewpassword( $np, $throttle ); $u->saveSettings(); $userLanguage = $u->getOption( 'language' ); - $m = wfMsgExt( $emailText, array( 'parsemag', 'language' => $userLanguage ), $ip, $u->getName(), $np, - $wgServer . $wgScript, round( $wgNewPasswordExpiry / 86400 ) ); - $result = $u->sendMail( wfMsgExt( $emailTitle, array( 'parsemag', 'language' => $userLanguage ) ), $m ); + $m = $this->msg( $emailText, $ip, $u->getName(), $np, $wgServer . $wgScript, + round( $wgNewPasswordExpiry / 86400 ) )->inLanguage( $userLanguage )->text(); + $result = $u->sendMail( $this->msg( $emailTitle )->inLanguage( $userLanguage )->text(), $m ); return $result; } @@ -816,11 +845,10 @@ class LoginForm extends SpecialPage { * @private */ function successfulLogin() { - global $wgUser, $wgOut; - # Run any hooks; display injected HTML if any, else redirect + $currentUser = $this->getUser(); $injected_html = ''; - wfRunHooks( 'UserLoginComplete', array( &$wgUser, &$injected_html ) ); + wfRunHooks( 'UserLoginComplete', array( &$currentUser, &$injected_html ) ); if( $injected_html !== '' ) { $this->displaySuccessfulLogin( 'loginsuccess', $injected_html ); @@ -834,7 +862,7 @@ class LoginForm extends SpecialPage { if( $wgSecureLogin && !$this->mStickHTTPS ) { $redirectUrl = preg_replace( '/^https:/', 'http:', $redirectUrl ); } - $wgOut->redirect( $redirectUrl ); + $this->getOutput()->redirect( $redirectUrl ); } } @@ -845,14 +873,18 @@ class LoginForm extends SpecialPage { * @private */ function successfulCreation() { - global $wgUser; # Run any hooks; display injected HTML + $currentUser = $this->getUser(); $injected_html = ''; $welcome_creation_msg = 'welcomecreation'; - wfRunHooks( 'UserLoginComplete', array( &$wgUser, &$injected_html ) ); + wfRunHooks( 'UserLoginComplete', array( &$currentUser, &$injected_html ) ); - //let any extensions change what message is shown + /** + * Let any extensions change what message is shown. + * @see https://www.mediawiki.org/wiki/Manual:Hooks/BeforeWelcomeCreation + * @since 1.18 + */ wfRunHooks( 'BeforeWelcomeCreation', array( &$welcome_creation_msg, &$injected_html ) ); $this->displaySuccessfulLogin( $welcome_creation_msg, $injected_html ); @@ -862,19 +894,18 @@ class LoginForm extends SpecialPage { * Display a "login successful" page. */ private function displaySuccessfulLogin( $msgname, $injected_html ) { - global $wgOut, $wgUser; - - $wgOut->setPageTitle( wfMsg( 'loginsuccesstitle' ) ); + $out = $this->getOutput(); + $out->setPageTitle( $this->msg( 'loginsuccesstitle' ) ); if( $msgname ){ - $wgOut->addWikiMsg( $msgname, wfEscapeWikiText( $wgUser->getName() ) ); + $out->addWikiMsg( $msgname, wfEscapeWikiText( $this->getUser()->getName() ) ); } - $wgOut->addHTML( $injected_html ); + $out->addHTML( $injected_html ); if ( !empty( $this->mReturnTo ) ) { - $wgOut->returnToMain( null, $this->mReturnTo, $this->mReturnToQuery ); + $out->returnToMain( null, $this->mReturnTo, $this->mReturnToQuery ); } else { - $wgOut->returnToMain( null ); + $out->returnToMain( null ); } } @@ -886,8 +917,6 @@ class LoginForm extends SpecialPage { * @param $block Block the block causing this error */ function userBlockedMessage( Block $block ) { - global $wgOut; - # Let's be nice about this, it's likely that this feature will be used # for blocking large numbers of innocent people, e.g. range blocks on # schools. Don't blame it on the user. There's a small chance that it @@ -896,56 +925,56 @@ class LoginForm extends SpecialPage { # evade it, but we'll leave that to their guilty conscience to figure # out. - $wgOut->setPageTitle( wfMsg( 'cantcreateaccounttitle' ) ); + $out = $this->getOutput(); + $out->setPageTitle( $this->msg( 'cantcreateaccounttitle' ) ); $block_reason = $block->mReason; if ( strval( $block_reason ) === '' ) { - $block_reason = wfMsg( 'blockednoreason' ); + $block_reason = $this->msg( 'blockednoreason' )->text(); } - $wgOut->addWikiMsg( + $out->addWikiMsg( 'cantcreateaccount-text', $block->getTarget(), $block_reason, - $block->getBlocker()->getName() + $block->getByName() ); - $wgOut->returnToMain( false ); + $out->returnToMain( false ); } /** * @private */ function mainLoginForm( $msg, $msgtype = 'error' ) { - global $wgUser, $wgOut, $wgHiddenPrefs; global $wgEnableEmail, $wgEnableUserEmail; - global $wgRequest, $wgLoginLanguageSelector; + global $wgHiddenPrefs, $wgLoginLanguageSelector; global $wgAuth, $wgEmailConfirmToEdit, $wgCookieExpiration; global $wgSecureLogin, $wgPasswordResetRoutes; - $titleObj = SpecialPage::getTitleFor( 'Userlogin' ); + $titleObj = $this->getTitle(); + $user = $this->getUser(); if ( $this->mType == 'signup' ) { // Block signup here if in readonly. Keeps user from // going through the process (filling out data, etc) // and being informed later. - if ( wfReadOnly() ) { - $wgOut->readOnlyPage(); - return; - } elseif ( $wgUser->isBlockedFromCreateAccount() ) { - $this->userBlockedMessage( $wgUser->isBlockedFromCreateAccount() ); - return; - } elseif ( count( $permErrors = $titleObj->getUserPermissionsErrors( 'createaccount', $wgUser, true ) )>0 ) { - $wgOut->showPermissionsErrorPage( $permErrors, 'createaccount' ); + $permErrors = $titleObj->getUserPermissionsErrors( 'createaccount', $user, true ); + if ( count( $permErrors ) ) { + throw new PermissionsError( 'createaccount', $permErrors ); + } elseif ( $user->isBlockedFromCreateAccount() ) { + $this->userBlockedMessage( $user->isBlockedFromCreateAccount() ); return; + } elseif ( wfReadOnly() ) { + throw new ReadOnlyError; } } if ( $this->mUsername == '' ) { - if ( $wgUser->isLoggedIn() ) { - $this->mUsername = $wgUser->getName(); + if ( $user->isLoggedIn() ) { + $this->mUsername = $user->getName(); } else { - $this->mUsername = $wgRequest->getCookie( 'UserName' ); + $this->mUsername = $this->getRequest()->getCookie( 'UserName' ); } } @@ -971,18 +1000,16 @@ class LoginForm extends SpecialPage { $linkq .= $returnto; } - # Pass any language selection on to the mode switch link - if( $wgLoginLanguageSelector && $this->mLanguage ) { - $linkq .= '&uselang=' . $this->mLanguage; - } - - $link = ''; - $link .= wfMsgHtml( $linkmsg . 'link' ); # Calling either 'gotaccountlink' or 'nologinlink' - $link .= ''; - # Don't show a "create account" link if the user can't - if( $this->showCreateOrLoginLink( $wgUser ) ) { - $template->set( 'link', wfMsgExt( $linkmsg, array( 'parseinline', 'replaceafter' ), $link ) ); + if( $this->showCreateOrLoginLink( $user ) ) { + # Pass any language selection on to the mode switch link + if( $wgLoginLanguageSelector && $this->mLanguage ) { + $linkq .= '&uselang=' . $this->mLanguage; + } + $link = Html::element( 'a', array( 'href' => $titleObj->getLocalURL( $linkq ) ), + $this->msg( $linkmsg . 'link' )->text() ); # Calling either 'gotaccountlink' or 'nologinlink' + + $template->set( 'link', $this->msg( $linkmsg )->rawParams( $link )->parse() ); } else { $template->set( 'link', '' ); } @@ -1003,7 +1030,7 @@ class LoginForm extends SpecialPage { $template->set( 'action', $titleObj->getLocalURL( $q ) ); $template->set( 'message', $msg ); $template->set( 'messagetype', $msgtype ); - $template->set( 'createemail', $wgEnableEmail && $wgUser->isLoggedIn() ); + $template->set( 'createemail', $wgEnableEmail && $user->isLoggedIn() ); $template->set( 'userealname', !in_array( 'realname', $wgHiddenPrefs ) ); $template->set( 'useemail', $wgEnableEmail ); $template->set( 'emailrequired', $wgEmailConfirmToEdit ); @@ -1011,8 +1038,8 @@ class LoginForm extends SpecialPage { $template->set( 'canreset', $wgAuth->allowPasswordChange() ); $template->set( 'resetlink', $resetLink ); $template->set( 'canremember', ( $wgCookieExpiration > 0 ) ); - $template->set( 'usereason', $wgUser->isLoggedIn() ); - $template->set( 'remember', $wgUser->getOption( 'rememberpassword' ) || $this->mRemember ); + $template->set( 'usereason', $user->isLoggedIn() ); + $template->set( 'remember', $user->getOption( 'rememberpassword' ) || $this->mRemember ); $template->set( 'cansecurelogin', ( $wgSecureLogin === true ) ); $template->set( 'stickHTTPS', $this->mStickHTTPS ); @@ -1031,24 +1058,25 @@ class LoginForm extends SpecialPage { # Prepare language selection links as needed if( $wgLoginLanguageSelector ) { $template->set( 'languages', $this->makeLanguageSelector() ); - if( $this->mLanguage ) + if( $this->mLanguage ) { $template->set( 'uselang', $this->mLanguage ); + } } - + // Use loginend-https for HTTPS requests if it's not blank, loginend otherwise // Ditto for signupend $usingHTTPS = WebRequest::detectProtocol() == 'https'; - $loginendHTTPS = wfMessage( 'loginend-https' ); - $signupendHTTPS = wfMessage( 'signupend-https' ); + $loginendHTTPS = $this->msg( 'loginend-https' ); + $signupendHTTPS = $this->msg( 'signupend-https' ); if ( $usingHTTPS && !$loginendHTTPS->isBlank() ) { $template->set( 'loginend', $loginendHTTPS->parse() ); } else { - $template->set( 'loginend', wfMessage( 'loginend' )->parse() ); + $template->set( 'loginend', $this->msg( 'loginend' )->parse() ); } if ( $usingHTTPS && !$signupendHTTPS->isBlank() ) { $template->set( 'signupend', $signupendHTTPS->parse() ); } else { - $template->set( 'signupend', wfMessage( 'signupend' )->parse() ); + $template->set( 'signupend', $this->msg( 'signupend' )->parse() ); } // Give authentication and captcha plugins a chance to modify the form @@ -1059,15 +1087,9 @@ class LoginForm extends SpecialPage { wfRunHooks( 'UserLoginForm', array( &$template ) ); } - // Changes the title depending on permissions for creating account - if ( $wgUser->isAllowed( 'createaccount' ) ) { - $wgOut->setPageTitle( wfMsg( 'userlogin' ) ); - } else { - $wgOut->setPageTitle( wfMsg( 'userloginnocreate' ) ); - } - - $wgOut->disallowUserJs(); // just in case... - $wgOut->addTemplate( $template ); + $out = $this->getOutput(); + $out->disallowUserJs(); // just in case... + $out->addTemplate( $template ); } /** @@ -1097,8 +1119,8 @@ class LoginForm extends SpecialPage { * @private */ function hasSessionCookie() { - global $wgDisableCookieCheck, $wgRequest; - return $wgDisableCookieCheck ? true : $wgRequest->checkSessionCookie(); + global $wgDisableCookieCheck; + return $wgDisableCookieCheck ? true : $this->getRequest()->checkSessionCookie(); } /** @@ -1155,8 +1177,6 @@ class LoginForm extends SpecialPage { * @private */ function cookieRedirectCheck( $type ) { - global $wgOut; - $titleObj = SpecialPage::getTitleFor( 'Userlogin' ); $query = array( 'wpCookieCheck' => $type ); if ( $this->mReturnTo ) { @@ -1164,7 +1184,7 @@ class LoginForm extends SpecialPage { } $check = $titleObj->getFullURL( $query ); - return $wgOut->redirect( $check ); + return $this->getOutput()->redirect( $check ); } /** @@ -1173,12 +1193,12 @@ class LoginForm extends SpecialPage { function onCookieRedirectCheck( $type ) { if ( !$this->hasSessionCookie() ) { if ( $type == 'new' ) { - return $this->mainLoginForm( wfMsgExt( 'nocookiesnew', array( 'parseinline' ) ) ); + return $this->mainLoginForm( $this->msg( 'nocookiesnew' )->parse() ); } elseif ( $type == 'login' ) { - return $this->mainLoginForm( wfMsgExt( 'nocookieslogin', array( 'parseinline' ) ) ); + return $this->mainLoginForm( $this->msg( 'nocookieslogin' )->parse() ); } else { # shouldn't happen - return $this->mainLoginForm( wfMsg( 'error' ) ); + return $this->mainLoginForm( $this->msg( 'error' )->text() ); } } else { return $this->successfulLogin(); @@ -1189,7 +1209,7 @@ class LoginForm extends SpecialPage { * @private */ function throttleHit( $limit ) { - $this->mainLoginForm( wfMsgExt( 'acct_creation_throttle_hit', array( 'parseinline' ), $limit ) ); + $this->mainLoginForm( $this->msg( 'acct_creation_throttle_hit' )->numParams( $limit )->parse() ); } /** @@ -1199,9 +1219,7 @@ class LoginForm extends SpecialPage { * @return string */ function makeLanguageSelector() { - global $wgLang; - - $msg = wfMessage( 'loginlanguagelinks' )->inContentLanguage(); + $msg = $this->msg( 'loginlanguagelinks' )->inContentLanguage(); if( !$msg->isBlank() ) { $langs = explode( "\n", $msg->text() ); $links = array(); @@ -1212,7 +1230,8 @@ class LoginForm extends SpecialPage { $links[] = $this->makeLanguageSelectorLink( $parts[0], trim( $parts[1] ) ); } } - return count( $links ) > 0 ? wfMsgHtml( 'loginlanguagelabel', $wgLang->pipeList( $links ) ) : ''; + return count( $links ) > 0 ? $this->msg( 'loginlanguagelabel' )->rawParams( + $this->getLanguage()->pipeList( $links ) )->escaped() : ''; } else { return ''; } @@ -1226,7 +1245,6 @@ class LoginForm extends SpecialPage { * @param $lang Language code */ function makeLanguageSelectorLink( $text, $lang ) { - $self = SpecialPage::getTitleFor( 'Userlogin' ); $attr = array( 'uselang' => $lang ); if( $this->mType == 'signup' ) { $attr['type'] = 'signup'; @@ -1235,7 +1253,7 @@ class LoginForm extends SpecialPage { $attr['returnto'] = $this->mReturnTo; } return Linker::linkKnown( - $self, + $this->getTitle(), htmlspecialchars( $text ), array(), $attr diff --git a/includes/specials/SpecialUserlogout.php b/includes/specials/SpecialUserlogout.php index 39b5b284..d747448f 100644 --- a/includes/specials/SpecialUserlogout.php +++ b/includes/specials/SpecialUserlogout.php @@ -1,6 +1,6 @@ setHeaders(); $this->outputHeader(); - $oldName = $wgUser->getName(); - $wgUser->logout(); + $user = $this->getUser(); + $oldName = $user->getName(); + $user->logout(); - $wgOut->addWikiMsg( 'logouttext' ); + $out = $this->getOutput(); + $out->addWikiMsg( 'logouttext' ); // Hook. $injected_html = ''; - wfRunHooks( 'UserLogoutComplete', array( &$wgUser, &$injected_html, $oldName ) ); - $wgOut->addHTML( $injected_html ); + wfRunHooks( 'UserLogoutComplete', array( &$user, &$injected_html, $oldName ) ); + $out->addHTML( $injected_html ); - $wgOut->returnToMain(); + $out->returnToMain(); } } diff --git a/includes/specials/SpecialUserrights.php b/includes/specials/SpecialUserrights.php index 4de048c0..e2e0f38b 100644 --- a/includes/specials/SpecialUserrights.php +++ b/includes/specials/SpecialUserrights.php @@ -63,22 +63,24 @@ class UserrightsPage extends SpecialPage { public function execute( $par ) { // If the visitor doesn't have permissions to assign or remove // any groups, it's a bit silly to give them the user search prompt. - global $wgUser, $wgRequest, $wgOut; - if( $par !== null ) { - $this->mTarget = $par; - } else { - $this->mTarget = $wgRequest->getVal( 'user' ); - } + $user = $this->getUser(); /* * If the user is blocked and they only have "partial" access * (e.g. they don't have the userrights permission), then don't * allow them to use Special:UserRights. */ - if( $wgUser->isBlocked() && !$wgUser->isAllowed( 'userrights' ) ) { - $wgOut->blockedPage(); - return; + if( $user->isBlocked() && !$user->isAllowed( 'userrights' ) ) { + throw new UserBlockedError( $user->mBlock ); + } + + $request = $this->getRequest(); + + if( $par !== null ) { + $this->mTarget = $par; + } else { + $this->mTarget = $request->getVal( 'user' ); } $available = $this->changeableGroups(); @@ -90,49 +92,44 @@ class UserrightsPage extends SpecialPage { * target. */ if ( !count( $available['add'] ) && !count( $available['remove'] ) ) - $this->mTarget = $wgUser->getName(); + $this->mTarget = $user->getName(); } - if ( User::getCanonicalName( $this->mTarget ) == $wgUser->getName() ) { + if ( User::getCanonicalName( $this->mTarget ) == $user->getName() ) { $this->isself = true; } - if( !$this->userCanChangeRights( $wgUser, true ) ) { + if( !$this->userCanChangeRights( $user, true ) ) { // @todo FIXME: There may be intermediate groups we can mention. - $wgOut->showPermissionsErrorPage( array( array( - $wgUser->isAnon() - ? 'userrights-nologin' - : 'userrights-notallowed' ) ) ); - return; + $msg = $user->isAnon() ? 'userrights-nologin' : 'userrights-notallowed'; + throw new PermissionsError( null, array( array( $msg ) ) ); } - if ( wfReadOnly() ) { - $wgOut->readOnlyPage(); - return; - } + $this->checkReadOnly(); - $this->outputHeader(); - $wgOut->addModuleStyles( 'mediawiki.special' ); $this->setHeaders(); + $this->outputHeader(); + + $out = $this->getOutput(); + $out->addModuleStyles( 'mediawiki.special' ); // show the general form if ( count( $available['add'] ) || count( $available['remove'] ) ) { $this->switchForm(); } - if( $wgRequest->wasPosted() ) { + if( $request->wasPosted() ) { // save settings - if( $wgRequest->getCheck( 'saveusergroups' ) ) { - $reason = $wgRequest->getVal( 'user-reason' ); - $tok = $wgRequest->getVal( 'wpEditToken' ); - if( $wgUser->matchEditToken( $tok, $this->mTarget ) ) { + if( $request->getCheck( 'saveusergroups' ) ) { + $reason = $request->getVal( 'user-reason' ); + $tok = $request->getVal( 'wpEditToken' ); + if( $user->matchEditToken( $tok, $this->mTarget ) ) { $this->saveUserGroups( $this->mTarget, $reason ); - $url = $this->getSuccessURL(); - $wgOut->redirect( $url ); + $out->redirect( $this->getSuccessURL() ); return; } } @@ -157,11 +154,9 @@ class UserrightsPage extends SpecialPage { * @return null */ function saveUserGroups( $username, $reason = '' ) { - global $wgRequest, $wgOut; - $status = $this->fetchUser( $username ); if( !$status->isOK() ) { - $wgOut->addWikiText( $status->getWikiText() ); + $this->getOutput()->addWikiText( $status->getWikiText() ); return; } else { $user = $status->value; @@ -176,7 +171,7 @@ class UserrightsPage extends SpecialPage { foreach ( $allgroups as $group ) { // We'll tell it to remove all unchecked groups, and add all checked groups. // Later on, this gets filtered for what can actually be removed - if ( $wgRequest->getCheck( "wpGroup-$group" ) ) { + if ( $this->getRequest()->getCheck( "wpGroup-$group" ) ) { $addgroup[] = $group; } else { $removegroup[] = $group; @@ -196,10 +191,8 @@ class UserrightsPage extends SpecialPage { * @return Array: Tuple of added, then removed groups */ function doSaveUserGroups( $user, $add, $remove, $reason = '' ) { - global $wgUser; - // Validate input set... - $isself = ( $user->getName() == $wgUser->getName() ); + $isself = ( $user->getName() == $this->getUser()->getName() ); $groups = $user->getGroups(); $changeable = $this->changeableGroups(); $addable = array_merge( $changeable['add'], $isself ? $changeable['add-self'] : array() ); @@ -265,11 +258,9 @@ class UserrightsPage extends SpecialPage { * @param $username String: name of the user. */ function editUserGroupsForm( $username ) { - global $wgOut; - $status = $this->fetchUser( $username ); if( !$status->isOK() ) { - $wgOut->addWikiText( $status->getWikiText() ); + $this->getOutput()->addWikiText( $status->getWikiText() ); return; } else { $user = $status->value; @@ -281,7 +272,7 @@ class UserrightsPage extends SpecialPage { // This isn't really ideal logging behavior, but let's not hide the // interwiki logs if we're using them as is. - $this->showLogFragment( $user, $wgOut ); + $this->showLogFragment( $user, $this->getOutput() ); } /** @@ -292,7 +283,7 @@ class UserrightsPage extends SpecialPage { * @return Status object */ public function fetchUser( $username ) { - global $wgUser, $wgUserrightsInterwikiDelimiter; + global $wgUserrightsInterwikiDelimiter; $parts = explode( $wgUserrightsInterwikiDelimiter, $username ); if( count( $parts ) < 2 ) { @@ -304,7 +295,7 @@ class UserrightsPage extends SpecialPage { if( $database == wfWikiID() ) { $database = ''; } else { - if( !$wgUser->isAllowed( 'userrights-interwiki' ) ) { + if( !$this->getUser()->isAllowed( 'userrights-interwiki' ) ) { return Status::newFatal( 'userrights-no-interwiki' ); } if( !UserRightsProxy::validDatabase( $database ) ) { @@ -372,8 +363,8 @@ class UserrightsPage extends SpecialPage { * Output a form to allow searching for a user */ function switchForm() { - global $wgOut, $wgScript; - $wgOut->addHTML( + global $wgScript; + $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' ) ) . @@ -414,8 +405,6 @@ class UserrightsPage extends SpecialPage { * @param $groups Array: Array of groups the user is in */ protected function showEditUserGroupsForm( $user, $groups ) { - global $wgOut, $wgUser, $wgLang, $wgRequest; - $list = array(); foreach( $groups as $group ) { $list[] = self::buildGroupLink( $group ); @@ -432,30 +421,38 @@ class UserrightsPage extends SpecialPage { $count = count( $list ); if( $count > 0 ) { $grouplist = wfMessage( 'userrights-groupsmember', $count)->parse(); - $grouplist = '

        ' . $grouplist . ' ' . $wgLang->listToText( $list ) . "

        \n"; + $grouplist = '

        ' . $grouplist . ' ' . $this->getLanguage()->listToText( $list ) . "

        \n"; } $count = count( $autolist ); if( $count > 0 ) { $autogrouplistintro = wfMessage( 'userrights-groupsmember-auto', $count)->parse(); - $grouplist .= '

        ' . $autogrouplistintro . ' ' . $wgLang->listToText( $autolist ) . "

        \n"; + $grouplist .= '

        ' . $autogrouplistintro . ' ' . $this->getLanguage()->listToText( $autolist ) . "

        \n"; } - $wgOut->addHTML( + + $userToolLinks = Linker::userToolLinks( + $user->getId(), + $user->getName(), + false, /* default for redContribsWhenNoEdits */ + Linker::TOOL_LINKS_EMAIL /* Add "send e-mail" link */ + ); + + $this->getOutput()->addHTML( Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalURL(), 'name' => 'editGroup', 'id' => 'mw-userrights-form2' ) ) . Html::hidden( 'user', $this->mTarget ) . - Html::hidden( 'wpEditToken', $wgUser->editToken( $this->mTarget ) ) . + Html::hidden( 'wpEditToken', $this->getUser()->getEditToken( $this->mTarget ) ) . Xml::openElement( 'fieldset' ) . - Xml::element( 'legend', array(), wfMsg( 'userrights-editusergroup' ) ) . - wfMsgExt( 'editinguser', array( 'parse' ), wfEscapeWikiText( $user->getName() ) ) . - wfMsgExt( 'userrights-groups-help', array( 'parse' ) ) . + 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() . $grouplist . - Xml::tags( 'p', null, $this->groupCheckboxes( $groups ) ) . + Xml::tags( 'p', null, $this->groupCheckboxes( $groups, $user ) ) . Xml::openElement( 'table', array( 'border' => '0', 'id' => 'mw-userrights-table-outer' ) ) . " " . Xml::label( wfMsg( 'userrights-reason' ), 'wpReason' ) . " " . - Xml::input( 'user-reason', 60, $wgRequest->getVal( 'user-reason', false ), + Xml::input( 'user-reason', 60, $this->getRequest()->getVal( 'user-reason', false ), array( 'id' => 'wpReason', 'maxlength' => 255 ) ) . " @@ -496,10 +493,12 @@ class UserrightsPage extends SpecialPage { /** * Adds a table with checkboxes where you can select what groups to add/remove * + * @todo Just pass the username string? * @param $usergroups Array: groups the user belongs to + * @param $user User a user object * @return string XHTML table element with checkboxes */ - private function groupCheckboxes( $usergroups ) { + private function groupCheckboxes( $usergroups, $user ) { $allgroups = $this->getAllGroups(); $ret = ''; @@ -547,11 +546,11 @@ class UserrightsPage extends SpecialPage { foreach( $column as $group => $checkbox ) { $attr = $checkbox['disabled'] ? array( 'disabled' => 'disabled' ) : array(); + $member = User::getGroupMember( $group, $user->getName() ); if ( $checkbox['irreversible'] ) { - $text = htmlspecialchars( wfMsg( 'userrights-irreversible-marker', - User::getGroupMember( $group ) ) ); + $text = wfMessage( 'userrights-irreversible-marker', $member )->escaped(); } else { - $text = htmlspecialchars( User::getGroupMember( $group ) ); + $text = htmlspecialchars( $member ); } $checkboxHtml = Xml::checkLabel( $text, "wpGroup-" . $group, "wpGroup-" . $group, $checkbox['set'], $attr ); @@ -588,13 +587,12 @@ class UserrightsPage extends SpecialPage { } /** - * Returns $wgUser->changeableGroups() + * Returns $this->getUser()->changeableGroups() * * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) , 'add-self' => array( addablegroups to self), 'remove-self' => array( removable groups from self) ) */ function changeableGroups() { - global $wgUser; - return $wgUser->changeableGroups(); + return $this->getUser()->changeableGroups(); } /** @@ -605,6 +603,6 @@ class UserrightsPage extends SpecialPage { */ protected function showLogFragment( $user, $output ) { $output->addHTML( Xml::element( 'h2', null, LogPage::logName( 'rights' ) . "\n" ) ); - LogEventsList::showLogExtract( $output, 'rights', $user->getUserPage()->getPrefixedText() ); + LogEventsList::showLogExtract( $output, 'rights', $user->getUserPage() ); } } diff --git a/includes/specials/SpecialVersion.php b/includes/specials/SpecialVersion.php index 0331f056..8185fe88 100644 --- a/includes/specials/SpecialVersion.php +++ b/includes/specials/SpecialVersion.php @@ -37,8 +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', - # Doesn't work at the time of writing but maybe some day: - 'https://svn.wikimedia.org/viewvc/mediawiki' => 'http://svn.wikimedia.org/viewvc/mediawiki', + 'https://svn.wikimedia.org/viewvc/mediawiki' => 'https://svn.wikimedia.org/viewvc/mediawiki', ); public function __construct(){ @@ -49,11 +48,12 @@ class SpecialVersion extends SpecialPage { * main() */ public function execute( $par ) { - global $wgOut, $wgSpecialVersionShowHooks, $wgRequest; + global $wgSpecialVersionShowHooks; $this->setHeaders(); $this->outputHeader(); - $wgOut->allowClickjacking(); + $out = $this->getOutput(); + $out->allowClickjacking(); $text = $this->getMediaWikiCredits() . @@ -63,10 +63,10 @@ class SpecialVersion extends SpecialPage { $text .= $this->getWgHooks(); } - $wgOut->addWikiText( $text ); - $wgOut->addHTML( $this->IPInfo() ); + $out->addWikiText( $text ); + $out->addHTML( $this->IPInfo() ); - if ( $wgRequest->getVal( 'easteregg' ) ) { + if ( $this->getRequest()->getVal( 'easteregg' ) ) { if ( $this->showEasterEgg() ) { // TODO: put something interesting here } @@ -106,7 +106,7 @@ class SpecialVersion extends SpecialPage { 'Aryeh Gregor', 'Aaron Schulz', 'Andrew Garrett', 'Raimond Spekking', 'Alexandre Emsenhuber', 'Siebrand Mazeland', 'Chad Horohoe', 'Roan Kattouw', 'Trevor Parscal', 'Bryan Tong Minh', 'Sam Reed', - 'Victor Vasiliev', 'Rotem Liss', 'Platonides', 'Ashar Voultoiz', + 'Victor Vasiliev', 'Rotem Liss', 'Platonides', 'Antoine Musso', wfMsg( 'version-poweredby-others' ) ); @@ -126,7 +126,7 @@ class SpecialVersion extends SpecialPage { // be loaded here, so feel free to use wfMsg*() in the 'name'. Raw HTML or wikimarkup // can be used. $software = array(); - $software['[http://www.mediawiki.org/ MediaWiki]'] = self::getVersionLinked(); + $software['[https://www.mediawiki.org/ MediaWiki]'] = self::getVersionLinked(); $software['[http://www.php.net/ PHP]'] = phpversion() . " (" . php_sapi_name() . ")"; $software[$dbr->getSoftwareLink()] = $dbr->getServerInfo(); @@ -143,7 +143,7 @@ class SpecialVersion extends SpecialPage { foreach( $software as $name => $version ) { $out .= " " . $name . " - " . $version . " + " . $version . " \n"; } @@ -153,6 +153,7 @@ class SpecialVersion extends SpecialPage { /** * Return a string of the MediaWiki version with SVN revision if available. * + * @param $flags String * @return mixed */ public static function getVersion( $flags = '' ) { @@ -357,18 +358,17 @@ class SpecialVersion extends SpecialPage { * Callback to sort extensions by type. */ function compare( $a, $b ) { - global $wgLang; if( $a['name'] === $b['name'] ) { return 0; } else { - return $wgLang->lc( $a['name'] ) > $wgLang->lc( $b['name'] ) + return $this->getLanguage()->lc( $a['name'] ) > $this->getLanguage()->lc( $b['name'] ) ? 1 : -1; } } /** - * Creates and formats the creidts for a single extension and returns this. + * Creates and formats the credits for a single extension and returns this. * * @param $extension Array * @@ -502,7 +502,7 @@ class SpecialVersion extends SpecialPage { * @return String: HTML fragment */ private function IPInfo() { - $ip = str_replace( '--', ' - ', htmlspecialchars( wfGetIP() ) ); + $ip = str_replace( '--', ' - ', htmlspecialchars( $this->getRequest()->getIP() ) ); return "\n" . "visited from $ip"; } @@ -542,11 +542,10 @@ class SpecialVersion extends SpecialPage { } elseif ( $cnt == 0 ) { return ''; } else { - global $wgLang; if ( $sort ) { sort( $list ); } - return $wgLang->listToText( array_map( array( __CLASS__, 'arrayToString' ), $list ) ); + return $this->getLanguage()->listToText( array_map( array( __CLASS__, 'arrayToString' ), $list ) ); } } diff --git a/includes/specials/SpecialWantedcategories.php b/includes/specials/SpecialWantedcategories.php index 800e940a..f497e4e2 100644 --- a/includes/specials/SpecialWantedcategories.php +++ b/includes/specials/SpecialWantedcategories.php @@ -54,14 +54,14 @@ class WantedCategoriesPage extends WantedQueryPage { * @return string */ function formatResult( $skin, $result ) { - global $wgLang, $wgContLang; + global $wgContLang; $nt = Title::makeTitle( $result->namespace, $result->title ); $text = htmlspecialchars( $wgContLang->convert( $nt->getText() ) ); $plink = $this->isCached() ? - $skin->link( $nt, $text ) : - $skin->link( + Linker::link( $nt, $text ) : + Linker::link( $nt, $text, array(), @@ -69,8 +69,7 @@ class WantedCategoriesPage extends WantedQueryPage { array( 'broken' ) ); - $nlinks = wfMsgExt( 'nmembers', array( 'parsemag', 'escape'), - $wgLang->formatNum( $result->value ) ); - return wfSpecialList($plink, $nlinks); + $nlinks = $this->msg( 'nmembers' )->numParams( $result->value )->escaped(); + return $this->getLanguage()->specialList( $plink, $nlinks ); } } diff --git a/includes/specials/SpecialWantedfiles.php b/includes/specials/SpecialWantedfiles.php index 8a4fe56f..ec0912df 100644 --- a/includes/specials/SpecialWantedfiles.php +++ b/includes/specials/SpecialWantedfiles.php @@ -35,6 +35,32 @@ class WantedFilesPage extends WantedQueryPage { parent::__construct( $name ); } + function getPageHeader() { + # 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' ) + ->title( Title::newFromText( "Wanted Files", NS_MAIN ) ) + ->inContentLanguage(); + + if ( !$catMessage->isDisabled() ) { + $category = Title::makeTitleSafe( NS_CATEGORY, $catMessage->text() ); + } else { + $category = false; + } + + if ( $category ) { + return $this + ->msg( 'wantedfiletext-cat' ) + ->params( $category->getFullText() ) + ->parseAsBlock(); + } else { + return $this + ->msg( 'wantedfiletext-nocat' ) + ->parseAsBlock(); + } + } + /** * KLUGE: The results may contain false positives for files * that exist e.g. in a shared repo. Setting this at least diff --git a/includes/specials/SpecialWantedpages.php b/includes/specials/SpecialWantedpages.php index a4233155..4624b355 100644 --- a/includes/specials/SpecialWantedpages.php +++ b/includes/specials/SpecialWantedpages.php @@ -27,9 +27,10 @@ * @ingroup SpecialPage */ class WantedPagesPage extends WantedQueryPage { + function __construct( $name = 'Wantedpages' ) { parent::__construct( $name ); - $this->includable( true ); + $this->mIncludable = true; } function execute( $par ) { @@ -39,12 +40,12 @@ class WantedPagesPage extends WantedQueryPage { $parts = explode( '/', $par, 2 ); $this->limit = (int)$parts[0]; // @todo FIXME: nlinks is ignored - $nlinks = isset( $parts[1] ) && $parts[1] === 'nlinks'; + //$nlinks = isset( $parts[1] ) && $parts[1] === 'nlinks'; $this->offset = 0; } else { - $nlinks = true; + //$nlinks = true; } - $this->setListOutput( $inc ); + $this->setListoutput( $inc ); $this->shownavigation = !$inc; parent::execute( $par ); } diff --git a/includes/specials/SpecialWatchlist.php b/includes/specials/SpecialWatchlist.php index fd562be4..fef54911 100644 --- a/includes/specials/SpecialWatchlist.php +++ b/includes/specials/SpecialWatchlist.php @@ -40,6 +40,20 @@ class SpecialWatchlist extends SpecialPage { $user = $this->getUser(); $output = $this->getOutput(); + # Anons don't get a watchlist + if( $user->isAnon() ) { + $output->setPageTitle( $this->msg( 'watchnologin' ) ); + $output->setRobotPolicy( 'noindex,nofollow' ); + $llink = Linker::linkKnown( + SpecialPage::getTitleFor( 'Userlogin' ), + $this->msg( 'loginreqlink' )->escaped(), + array(), + array( 'returnto' => $this->getTitle()->getPrefixedText() ) + ); + $output->addHTML( $this->msg( 'watchlistanontext' )->rawParams( $llink )->parse() ); + return; + } + // Add feed links $wlToken = $user->getOption( 'watchlisttoken' ); if ( !$wlToken ) { @@ -51,31 +65,11 @@ class SpecialWatchlist extends SpecialPage { $this->addFeedLinks( array( 'action' => 'feedwatchlist', 'allrev' => 'allrev', 'wlowner' => $user->getName(), 'wltoken' => $wlToken ) ); - $output->setRobotPolicy( 'noindex,nofollow' ); - - # Anons don't get a watchlist - if( $user->isAnon() ) { - $output->setPageTitle( wfMsg( 'watchnologin' ) ); - $llink = Linker::linkKnown( - SpecialPage::getTitleFor( 'Userlogin' ), - wfMsgHtml( 'loginreqlink' ), - array(), - array( 'returnto' => $this->getTitle()->getPrefixedText() ) - ); - $output->addHTML( wfMessage( 'watchlistanontext' )->rawParams( $llink )->parse() ); - return; - } - $this->setHeaders(); $this->outputHeader(); - $sub = wfMsgExt( - 'watchlistfor2', - array( 'parseinline', 'replaceafter' ), - $user->getName(), - SpecialEditWatchlist::buildTools( $this->getSkin() ) - ); - $output->setSubtitle( $sub ); + $output->addSubtitle( $this->msg( 'watchlistfor2', $user->getName() + )->rawParams( SpecialEditWatchlist::buildTools( null ) ) ); $request = $this->getRequest(); @@ -245,23 +239,21 @@ class SpecialWatchlist extends SpecialPage { $output->showLagWarning( $lag ); } - $lang = $this->getLang(); - # Create output form - $form = Xml::fieldset( wfMsg( 'watchlist-options' ), false, array( 'id' => 'mw-watchlist-options' ) ); + $form = Xml::fieldset( $this->msg( 'watchlist-options' )->text(), false, array( 'id' => 'mw-watchlist-options' ) ); # Show watchlist header - $form .= wfMsgExt( 'watchlist-details', array( 'parseinline' ), $lang->formatNum( $nitems ) ); + $form .= $this->msg( 'watchlist-details' )->numParams( $nitems )->parse(); if( $user->getOption( 'enotifwatchlistpages' ) && $wgEnotifWatchlist) { - $form .= wfMsgExt( 'wlheader-enotif', 'parse' ) . "\n"; + $form .= $this->msg( 'wlheader-enotif' )->parseAsBlock() . "\n"; } if( $wgShowUpdatedMarker ) { $form .= Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalUrl(), 'id' => 'mw-watchlist-resetbutton' ) ) . - wfMsgExt( 'wlheader-showupdated', array( 'parseinline' ) ) . ' ' . - Xml::submitButton( wfMsg( 'enotif_reset' ), array( 'name' => 'dummy' ) ) . + $this->msg( 'wlheader-showupdated' )->parse() . ' ' . + Xml::submitButton( $this->msg( 'enotif_reset' )->text(), array( 'name' => 'dummy' ) ) . Html::hidden( 'reset', 'all' ) . Xml::closeElement( 'form' ); } @@ -297,21 +289,12 @@ class SpecialWatchlist extends SpecialPage { /* Start bottom header */ + $lang = $this->getLanguage(); $wlInfo = ''; - if( $values['days'] >= 1 ) { + if( $values['days'] > 0 ) { $timestamp = wfTimestampNow(); - $wlInfo = wfMsgExt( 'rcnote', 'parseinline', - $lang->formatNum( $numRows ), - $lang->formatNum( $values['days'] ), - $lang->timeAndDate( $timestamp, true ), - $lang->date( $timestamp, true ), - $lang->time( $timestamp, true ) - ) . '
        '; - } elseif( $values['days'] > 0 ) { - $wlInfo = wfMsgExt( 'wlnote', 'parseinline', - $lang->formatNum( $numRows ), - $lang->formatNum( round( $values['days'] * 24 ) ) - ) . '
        '; + $wlInfo = $this->msg( 'wlnote' )->numParams( $numRows, round( $values['days'] * 24 ) )->params( + $lang->userDate( $timestamp, $user ), $lang->userTime( $timestamp, $user ) )->parse() . '
        '; } $cutofflinks = "\n" . $this->cutoffLinks( $values['days'], $nondefaults ) . "
        \n"; @@ -344,10 +327,10 @@ 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 .= '

        '; - $form .= Xml::label( wfMsg( 'namespace' ), 'namespace' ) . ' '; + $form .= Xml::label( $this->msg( 'namespace' )->text(), 'namespace' ) . ' '; $form .= Xml::namespaceSelector( $nameSpace, '' ) . ' '; - $form .= Xml::checkLabel( wfMsg('invert'), 'invert', 'nsinvert', $invert ) . ' '; - $form .= Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . '

        '; + $form .= Xml::checkLabel( $this->msg( 'invert' )->text(), 'invert', 'nsinvert', $invert ) . ' '; + $form .= Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . '

        '; $form .= Html::hidden( 'days', $values['days'] ); foreach ( $filters as $key => $msg ) { if ( $values[$key] ) { @@ -416,13 +399,10 @@ class SpecialWatchlist extends SpecialPage { } protected function showHideLink( $options, $message, $name, $value ) { - $showLinktext = wfMsgHtml( 'show' ); - $hideLinktext = wfMsgHtml( 'hide' ); - - $label = $value ? $showLinktext : $hideLinktext; + $label = $this->msg( $value ? 'show' : 'hide' )->escaped(); $options[$name] = 1 - (int) $value; - return wfMsgHtml( $message, Linker::linkKnown( $this->getTitle(), $label, array(), $options ) ); + return $this->msg( $message )->rawParams( Linker::linkKnown( $this->getTitle(), $label, array(), $options ) )->escaped(); } protected function hoursLink( $h, $options = array() ) { @@ -430,7 +410,7 @@ class SpecialWatchlist extends SpecialPage { return Linker::linkKnown( $this->getTitle(), - $this->getLang()->formatNum( $h ), + $this->getLanguage()->formatNum( $h ), array(), $options ); @@ -438,7 +418,7 @@ class SpecialWatchlist extends SpecialPage { protected function daysLink( $d, $options = array() ) { $options['days'] = $d; - $message = ( $d ? $this->getLang()->formatNum( $d ) : wfMsgHtml( 'watchlistall2' ) ); + $message = ( $d ? $this->getLanguage()->formatNum( $d ) : $this->msg( 'watchlistall2' )->escaped() ); return Linker::linkKnown( $this->getTitle(), @@ -464,11 +444,10 @@ class SpecialWatchlist extends SpecialPage { foreach( $days as $d ) { $days[$i++] = $this->daysLink( $d, $options ); } - return wfMsgExt('wlshowlast', - array('parseinline', 'replaceafter'), - $this->getLang()->pipeList( $hours ), - $this->getLang()->pipeList( $days ), - $this->daysLink( 0, $options ) ); + return $this->msg( 'wlshowlast' )->rawParams( + $this->getLanguage()->pipeList( $hours ), + $this->getLanguage()->pipeList( $days ), + $this->daysLink( 0, $options ) )->parse(); } /** diff --git a/includes/specials/SpecialWhatlinkshere.php b/includes/specials/SpecialWhatlinkshere.php index f7d7bfef..d5129bf6 100644 --- a/includes/specials/SpecialWhatlinkshere.php +++ b/includes/specials/SpecialWhatlinkshere.php @@ -47,8 +47,9 @@ class SpecialWhatLinksHere extends SpecialPage { } function execute( $par ) { + global $wgQueryPageDefaultLimit; $out = $this->getOutput(); - + $this->setHeaders(); $this->outputHeader(); @@ -56,7 +57,7 @@ class SpecialWhatLinksHere extends SpecialPage { $opts->add( 'target', '' ); $opts->add( 'namespace', '', FormOptions::INTNULL ); - $opts->add( 'limit', 50 ); + $opts->add( 'limit', $wgQueryPageDefaultLimit ); $opts->add( 'from', 0 ); $opts->add( 'back', 0 ); $opts->add( 'hideredirs', false ); @@ -83,11 +84,10 @@ class SpecialWhatLinksHere extends SpecialPage { $this->getSkin()->setRelevantTitle( $this->target ); - $this->selfTitle = $this->getTitle( $this->target->getPrefixedDBkey() ); - $out->setPageTitle( wfMsg( 'whatlinkshere-title', $this->target->getPrefixedText() ) ); - $out->setSubtitle( wfMsg( 'whatlinkshere-backlink', Linker::link( $this->target, $this->target->getPrefixedText(), array(), array( 'redirect' => 'no' ) ) ) ); + $out->setPageTitle( $this->msg( 'whatlinkshere-title', $this->target->getPrefixedText() ) ); + $out->addBacklinkSubtitle( $this->target ); $this->showIndirectLinks( 0, $this->target, $opts->getValue( 'limit' ), $opts->getValue( 'from' ), $opts->getValue( 'back' ) ); @@ -120,9 +120,9 @@ class SpecialWhatLinksHere extends SpecialPage { 'pl_title' => $target->getDBkey(), ); if( $hideredirs ) { - $plConds['page_is_redirect'] = 0; + $plConds['rd_from'] = null; } elseif( $hidelinks ) { - $plConds['page_is_redirect'] = 1; + $plConds[] = 'rd_from is NOT NULL'; } $tlConds = array( @@ -157,24 +157,34 @@ class SpecialWhatLinksHere extends SpecialPage { $options[] = 'STRAIGHT_JOIN'; $options['LIMIT'] = $queryLimit; - $fields = array( 'page_id', 'page_namespace', 'page_title', 'page_is_redirect' ); + $fields = array( 'page_id', 'page_namespace', 'page_title', 'rd_from' ); + + $joinConds = array( 'redirect' => array( 'LEFT JOIN', array( + 'rd_from = page_id', + 'rd_namespace' => $target->getNamespace(), + 'rd_title' => $target->getDBkey(), + '(rd_interwiki is NULL) or (rd_interwiki = \'\')' + ))); if( $fetchlinks ) { $options['ORDER BY'] = 'pl_from'; - $plRes = $dbr->select( array( 'pagelinks', 'page' ), $fields, - $plConds, __METHOD__, $options ); + $plRes = $dbr->select( array( 'pagelinks', 'page', 'redirect' ), $fields, + $plConds, __METHOD__, $options, + $joinConds); } if( !$hidetrans ) { $options['ORDER BY'] = 'tl_from'; - $tlRes = $dbr->select( array( 'templatelinks', 'page' ), $fields, - $tlConds, __METHOD__, $options ); + $tlRes = $dbr->select( array( 'templatelinks', 'page', 'redirect' ), $fields, + $tlConds, __METHOD__, $options, + $joinConds); } if( !$hideimages ) { $options['ORDER BY'] = 'il_from'; - $ilRes = $dbr->select( array( 'imagelinks', 'page' ), $fields, - $ilConds, __METHOD__, $options ); + $ilRes = $dbr->select( array( 'imagelinks', 'page', 'redirect' ), $fields, + $ilConds, __METHOD__, $options, + $joinConds); } if( ( !$fetchlinks || !$dbr->numRows($plRes) ) && ( $hidetrans || !$dbr->numRows($tlRes) ) && ( $hideimages || !$dbr->numRows($ilRes) ) ) { @@ -248,7 +258,7 @@ class SpecialWhatLinksHere extends SpecialPage { foreach ( $rows as $row ) { $nt = Title::makeTitle( $row->page_namespace, $row->page_title ); - if ( $row->page_is_redirect && $level < 2 ) { + if ( $row->rd_from && $level < 2 ) { $out->addHTML( $this->listItem( $row, $nt, true ) ); $this->showIndirectLinks( $level + 1, $nt, $wgMaxRedirectLinksRetrieved ); $out->addHTML( Xml::closeElement( 'li' ) ); @@ -269,8 +279,7 @@ class SpecialWhatLinksHere extends SpecialPage { } protected function listItem( $row, $nt, $notClose = false ) { - global $wgLang; - $dirmark = $wgLang->getDirMark(); + $dirmark = $this->getLanguage()->getDirMark(); # local message cache static $msgcache = null; @@ -283,7 +292,7 @@ class SpecialWhatLinksHere extends SpecialPage { } } - if( $row->page_is_redirect ) { + if( $row->rd_from ) { $query = array( 'redirect' => 'no' ); } else { $query = array(); @@ -299,7 +308,7 @@ class SpecialWhatLinksHere extends SpecialPage { // Display properties (redirect or template) $propsText = ''; $props = array(); - if ( $row->page_is_redirect ) + if ( $row->rd_from ) $props[] = $msgcache['isredirect']; if ( $row->is_template ) $props[] = $msgcache['istemplate']; @@ -346,11 +355,9 @@ class SpecialWhatLinksHere extends SpecialPage { } function getPrevNext( $prevId, $nextId ) { - global $wgLang; $currentLimit = $this->opts->getValue( 'limit' ); - $fmtLimit = $wgLang->formatNum( $currentLimit ); - $prev = wfMsgExt( 'whatlinkshere-prev', array( 'parsemag', 'escape' ), $fmtLimit ); - $next = wfMsgExt( 'whatlinkshere-next', array( 'parsemag', 'escape' ), $fmtLimit ); + $prev = wfMessage( 'whatlinkshere-prev' )->numParams( $currentLimit )->escaped(); + $next = wfMessage( 'whatlinkshere-next' )->numParams( $currentLimit )->escaped(); $changed = $this->opts->getChangedValues(); unset($changed['target']); // Already in the request title @@ -365,13 +372,14 @@ class SpecialWhatLinksHere extends SpecialPage { } $limitLinks = array(); + $lang = $this->getLanguage(); foreach ( $this->limits as $limit ) { - $prettyLimit = $wgLang->formatNum( $limit ); + $prettyLimit = htmlspecialchars( $lang->formatNum( $limit ) ); $overrides = array( 'limit' => $limit ); $limitLinks[] = $this->makeSelfLink( $prettyLimit, array_merge( $changed, $overrides ) ); } - $nums = $wgLang->pipeList( $limitLinks ); + $nums = $lang->pipeList( $limitLinks ); return wfMsgHtml( 'viewprevnext', $prev, $next, $nums ); } @@ -425,7 +433,6 @@ class SpecialWhatLinksHere extends SpecialPage { * @return string HTML fieldset and filter panel with the show/hide links */ function getFilterPanel() { - global $wgLang; $show = wfMsgHtml( 'show' ); $hide = wfMsgHtml( 'hide' ); @@ -445,6 +452,6 @@ class SpecialWhatLinksHere extends SpecialPage { $overrides = array( $type => !$chosen ); $links[] = wfMsgHtml( "whatlinkshere-{$type}", $this->makeSelfLink( $msg, array_merge( $changed, $overrides ) ) ); } - return Xml::fieldset( wfMsg( 'whatlinkshere-filters' ), $wgLang->pipeList( $links ) ); + return Xml::fieldset( wfMsg( 'whatlinkshere-filters' ), $this->getLanguage()->pipeList( $links ) ); } } diff --git a/includes/specials/SpecialWithoutinterwiki.php b/includes/specials/SpecialWithoutinterwiki.php index 9d91b833..89dae203 100644 --- a/includes/specials/SpecialWithoutinterwiki.php +++ b/includes/specials/SpecialWithoutinterwiki.php @@ -35,8 +35,8 @@ class WithoutInterwikiPage extends PageQueryPage { } function execute( $par ) { - global $wgRequest; - $this->prefix = Title::capitalize( $wgRequest->getVal( 'prefix', $par ), NS_MAIN ); + $this->prefix = Title::capitalize( + $this->getRequest()->getVal( 'prefix', $par ), NS_MAIN ); parent::execute( $par ); } @@ -84,7 +84,7 @@ class WithoutInterwikiPage extends PageQueryPage { 'page_title AS title', 'page_title AS value' ), 'conds' => array ( 'll_title IS NULL', - 'page_namespace' => NS_MAIN, + 'page_namespace' => MWNamespace::getContentNamespaces(), 'page_is_redirect' => 0 ), 'join_conds' => array ( 'langlinks' => array ( 'LEFT JOIN', 'll_from = page_id' ) ) -- cgit v1.2.3-54-g00ecf