summaryrefslogtreecommitdiff
path: root/includes/specials
diff options
context:
space:
mode:
Diffstat (limited to 'includes/specials')
-rw-r--r--includes/specials/SpecialActiveusers.php90
-rw-r--r--includes/specials/SpecialAllmessages.php84
-rw-r--r--includes/specials/SpecialAllpages.php66
-rw-r--r--includes/specials/SpecialAncientpages.php38
-rw-r--r--includes/specials/SpecialBlankpage.php22
-rw-r--r--includes/specials/SpecialBlockip.php195
-rw-r--r--includes/specials/SpecialBlockme.php66
-rw-r--r--includes/specials/SpecialBooksources.php31
-rw-r--r--includes/specials/SpecialBrokenRedirects.php22
-rw-r--r--includes/specials/SpecialCategories.php68
-rw-r--r--includes/specials/SpecialComparePages.php170
-rw-r--r--includes/specials/SpecialConfirmemail.php46
-rw-r--r--includes/specials/SpecialContributions.php231
-rw-r--r--includes/specials/SpecialDeadendpages.php19
-rw-r--r--includes/specials/SpecialDeletedContributions.php32
-rw-r--r--includes/specials/SpecialDisambiguations.php33
-rw-r--r--includes/specials/SpecialDoubleRedirects.php21
-rw-r--r--includes/specials/SpecialEmailuser.php514
-rw-r--r--includes/specials/SpecialExport.php267
-rw-r--r--includes/specials/SpecialFewestrevisions.php17
-rw-r--r--includes/specials/SpecialFileDuplicateSearch.php28
-rw-r--r--includes/specials/SpecialFilepath.php94
-rw-r--r--includes/specials/SpecialImport.php89
-rw-r--r--includes/specials/SpecialIpblocklist.php275
-rw-r--r--includes/specials/SpecialLinkSearch.php41
-rw-r--r--includes/specials/SpecialListfiles.php123
-rw-r--r--includes/specials/SpecialListgrouprights.php62
-rw-r--r--includes/specials/SpecialListredirects.php26
-rw-r--r--includes/specials/SpecialListusers.php69
-rw-r--r--includes/specials/SpecialLockdb.php140
-rw-r--r--includes/specials/SpecialLog.php185
-rw-r--r--includes/specials/SpecialLonelypages.php18
-rw-r--r--includes/specials/SpecialLongpages.php17
-rw-r--r--includes/specials/SpecialMIMEsearch.php24
-rw-r--r--includes/specials/SpecialMergeHistory.php90
-rw-r--r--includes/specials/SpecialMostcategories.php25
-rw-r--r--includes/specials/SpecialMostimages.php27
-rw-r--r--includes/specials/SpecialMostlinked.php31
-rw-r--r--includes/specials/SpecialMostlinkedcategories.php27
-rw-r--r--includes/specials/SpecialMostlinkedtemplates.php25
-rw-r--r--includes/specials/SpecialMostrevisions.php25
-rw-r--r--includes/specials/SpecialMovepage.php181
-rw-r--r--includes/specials/SpecialNewimages.php42
-rw-r--r--includes/specials/SpecialNewpages.php100
-rw-r--r--includes/specials/SpecialPopularpages.php20
-rw-r--r--includes/specials/SpecialPreferences.php37
-rw-r--r--includes/specials/SpecialPrefixindex.php54
-rw-r--r--includes/specials/SpecialProtectedpages.php94
-rw-r--r--includes/specials/SpecialProtectedtitles.php71
-rw-r--r--includes/specials/SpecialRandompage.php30
-rw-r--r--includes/specials/SpecialRandomredirect.php24
-rw-r--r--includes/specials/SpecialRecentchanges.php113
-rw-r--r--includes/specials/SpecialRecentchangeslinked.php43
-rw-r--r--includes/specials/SpecialRemoveRestrictions.php60
-rw-r--r--includes/specials/SpecialResetpass.php39
-rw-r--r--includes/specials/SpecialRevisiondelete.php1283
-rw-r--r--includes/specials/SpecialSearch.php185
-rw-r--r--includes/specials/SpecialShortpages.php28
-rw-r--r--includes/specials/SpecialSpecialpages.php166
-rw-r--r--includes/specials/SpecialStatistics.php92
-rw-r--r--includes/specials/SpecialTags.php38
-rw-r--r--includes/specials/SpecialUncategorizedcategories.php22
-rw-r--r--includes/specials/SpecialUncategorizedimages.php19
-rw-r--r--includes/specials/SpecialUncategorizedpages.php18
-rw-r--r--includes/specials/SpecialUncategorizedtemplates.php19
-rw-r--r--includes/specials/SpecialUndelete.php253
-rw-r--r--includes/specials/SpecialUnlockdb.php127
-rw-r--r--includes/specials/SpecialUnusedcategories.php17
-rw-r--r--includes/specials/SpecialUnusedimages.php37
-rw-r--r--includes/specials/SpecialUnusedtemplates.php26
-rw-r--r--includes/specials/SpecialUnwatchedpages.php24
-rw-r--r--includes/specials/SpecialUpload.php422
-rw-r--r--includes/specials/SpecialUploadStash.php394
-rw-r--r--includes/specials/SpecialUserlogin.php256
-rw-r--r--includes/specials/SpecialUserlogout.php72
-rw-r--r--includes/specials/SpecialUserrights.php107
-rw-r--r--includes/specials/SpecialVersion.php353
-rw-r--r--includes/specials/SpecialWantedcategories.php23
-rw-r--r--includes/specials/SpecialWantedfiles.php44
-rw-r--r--includes/specials/SpecialWantedpages.php22
-rw-r--r--includes/specials/SpecialWantedtemplates.php30
-rw-r--r--includes/specials/SpecialWatchlist.php108
-rw-r--r--includes/specials/SpecialWhatlinkshere.php48
-rw-r--r--includes/specials/SpecialWithoutinterwiki.php23
84 files changed, 4874 insertions, 3763 deletions
diff --git a/includes/specials/SpecialActiveusers.php b/includes/specials/SpecialActiveusers.php
index 7d907fb5..f016ab92 100644
--- a/includes/specials/SpecialActiveusers.php
+++ b/includes/specials/SpecialActiveusers.php
@@ -1,37 +1,40 @@
<?php
-# Copyright (C) 2008 Aaron Schulz
-#
-# http://www.mediawiki.org/
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-# http://www.gnu.org/copyleft/gpl.html
+/**
+ * Implements Special:Activeusers
+ *
+ * Copyright © 2008 Aaron Schulz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
/**
* This class is used to get a list of active users. The ones with specials
* rights (sysop, bureaucrat, developer) will have them displayed
* next to their names.
*
- * @file
* @ingroup SpecialPage
*/
class ActiveUsersPager extends UsersPager {
function __construct( $group = null ) {
- global $wgRequest, $wgRCMaxAge;
- $this->RCMaxAge = ceil( $wgRCMaxAge / ( 3600 * 24 ) ); // Constant
-
+ global $wgRequest, $wgActiveUserDays;
+ $this->RCMaxAge = $wgActiveUserDays;
$un = $wgRequest->getText( 'username' );
$this->requestedUser = '';
if ( $un != '' ) {
@@ -40,15 +43,15 @@ class ActiveUsersPager extends UsersPager {
$this->requestedUser = $username->getText();
}
}
-
+
$this->setupOptions();
-
+
parent::__construct();
}
public function setupOptions() {
global $wgRequest;
-
+
$this->opts = new FormOptions();
$this->opts->add( 'hidebots', false, FormOptions::BOOL );
@@ -57,10 +60,12 @@ class ActiveUsersPager extends UsersPager {
$this->opts->fetchValuesFromRequest( $wgRequest );
$this->groups = array();
- if ($this->opts->getValue('hidebots') == 1)
+ if ( $this->opts->getValue( 'hidebots' ) == 1 ) {
$this->groups['bot'] = true;
- if ($this->opts->getValue('hidesysops') == 1)
+ }
+ if ( $this->opts->getValue( 'hidesysops' ) == 1 ) {
$this->groups['sysop'] = true;
+ }
}
function getIndexField() {
@@ -72,7 +77,8 @@ class ActiveUsersPager extends UsersPager {
$conds = array( 'rc_user > 0' ); // Users - no anons
$conds[] = 'ipb_deleted IS NULL'; // don't show hidden names
$conds[] = "rc_log_type IS NULL OR rc_log_type != 'newusers'";
-
+ $conds[] = "rc_timestamp >= '{$dbr->timestamp( wfTimestamp( TS_UNIX ) - $this->RCMaxAge*24*3600 )}'";
+
if( $this->requestedUser != '' ) {
$conds[] = 'rc_user_text >= ' . $dbr->addQuotes( $this->requestedUser );
}
@@ -101,14 +107,15 @@ 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 );
$list = array();
foreach( self::getGroups( $row->user_id ) as $group ) {
- if (isset($this->groups[$group]))
+ if ( isset( $this->groups[$group] ) ) {
return;
+ }
$list[] = self::buildGroupLink( $group );
}
$groups = $wgLang->commaList( $list );
@@ -126,14 +133,14 @@ class ActiveUsersPager extends UsersPager {
}
function getPageHeader() {
- global $wgScript, $wgRequest;
+ global $wgScript;
$self = $this->getTitle();
- $limit = $this->mLimit ? Xml::hidden( 'limit', $this->mLimit ) : '';
+ $limit = $this->mLimit ? Html::hidden( 'limit', $this->mLimit ) : '';
- $out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ); # Form tag
+ $out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ); # Form tag
$out .= Xml::fieldset( wfMsg( 'activeusers' ) ) . "\n";
- $out .= Xml::hidden( 'title', $self->getPrefixedDBkey() ) . $limit . "\n";
+ $out .= Html::hidden( 'title', $self->getPrefixedDBkey() ) . $limit . "\n";
$out .= Xml::inputLabel( wfMsg( 'activeusers-from' ), 'username', 'offset', 20, $this->requestedUser ) . '<br />';# Username field
@@ -141,10 +148,10 @@ class ActiveUsersPager extends UsersPager {
$out .= Xml::checkLabel( wfMsg('activeusers-hidesysops'), 'hidesysops', 'hidesysops', $this->opts->getValue( 'hidesysops' ) ) . '<br />';
- $out .= Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n";# Submit button and form bottom
+ $out .= Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n";# Submit button and form bottom
$out .= Xml::closeElement( 'fieldset' );
$out .= Xml::closeElement( 'form' );
-
+
return $out;
}
}
@@ -157,7 +164,7 @@ class SpecialActiveUsers extends SpecialPage {
/**
* Constructor
*/
- public function __construct() {
+ public function __construct() {
parent::__construct( 'Activeusers' );
}
@@ -167,18 +174,19 @@ class SpecialActiveUsers extends SpecialPage {
* @param $par Mixed: parameter passed to the page or null
*/
public function execute( $par ) {
- global $wgOut, $wgLang, $wgRCMaxAge;
+ global $wgOut, $wgLang, $wgActiveUserDays;
$this->setHeaders();
+ $this->outputHeader();
$up = new ActiveUsersPager();
# 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( ceil( $wgRCMaxAge / 86400 ) ) )
- );
+ $s = Html::rawElement( 'div', array( 'class' => 'mw-activeusers-intro' ),
+ wfMsgExt( 'activeusers-intro', array( 'parsemag', 'escape' ), $wgLang->formatNum( $wgActiveUserDays ) )
+ );
$s .= $up->getPageHeader();
if( $usersbody ) {
diff --git a/includes/specials/SpecialAllmessages.php b/includes/specials/SpecialAllmessages.php
index 1745bf6c..296c6f50 100644
--- a/includes/specials/SpecialAllmessages.php
+++ b/includes/specials/SpecialAllmessages.php
@@ -1,6 +1,29 @@
<?php
/**
+ * Implements Special:Allmessages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+/**
* Use this special page to get a list of the MediaWiki system messages.
+ *
* @file
* @ingroup SpecialPage
*/
@@ -58,7 +81,7 @@ class SpecialAllmessages extends SpecialPage {
$out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'mw-allmessages-form' ) ) .
Xml::fieldset( wfMsg( 'allmessages-filter-legend' ) ) .
- Xml::hidden( 'title', $this->getTitle() ) .
+ Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) .
Xml::openElement( 'table', array( 'class' => 'mw-allmessages-table' ) ) . "\n" .
'<tr>
<td class="mw-label">' .
@@ -77,19 +100,19 @@ class SpecialAllmessages extends SpecialPage {
'filter',
'unmodified',
'mw-allmessages-form-filter-unmodified',
- ( $this->filter == 'unmodified' ? true : false )
+ ( $this->filter == 'unmodified' )
) .
Xml::radioLabel( wfMsg( 'allmessages-filter-all' ),
'filter',
'all',
'mw-allmessages-form-filter-all',
- ( $this->filter == 'all' ? true : false )
+ ( $this->filter == 'all' )
) .
Xml::radioLabel( wfMsg( 'allmessages-filter-modified' ),
'filter',
'modified',
'mw-allmessages-form-filter-modified',
- ( $this->filter == 'modified' ? true : false )
+ ( $this->filter == 'modified' )
) .
"</td>\n
</tr>
@@ -101,7 +124,7 @@ class SpecialAllmessages extends SpecialPage {
Xml::openElement( 'select', array( 'id' => 'mw-allmessages-form-lang', 'name' => 'lang' ) );
foreach( $languages as $lang => $name ) {
- $selected = $lang == $this->langCode ? true : false;
+ $selected = $lang == $this->langCode;
$out .= Xml::option( $lang . ' - ' . $name, $lang, $selected ) . "\n";
}
$out .= Xml::closeElement( 'select' ) .
@@ -134,10 +157,7 @@ class AllmessagesTablePager extends TablePager {
$this->mPage = $page;
$this->mConds = $conds;
$this->mDefaultDirection = true; // always sort ascending
- // We want to have an option for people to view *all* the messages,
- // so they can use Ctrl+F to search them. 5000 is the maximum that
- // will get through WebRequest::getLimitOffset().
- $this->mLimitsShown = array( 20, 50, 100, 250, 500, 5000 => wfMsg('limitall') );
+ $this->mLimitsShown = array( 20, 50, 100, 250, 500, 5000 );
global $wgLang, $wgContLang, $wgRequest;
@@ -182,8 +202,8 @@ class AllmessagesTablePager extends TablePager {
// Normalise message names so they look like page titles
$messageNames = array_map( array( $this->lang, 'ucfirst' ), $messageNames );
- wfProfileIn( __METHOD__ );
+ wfProfileOut( __METHOD__ );
return $messageNames;
}
@@ -207,7 +227,7 @@ class AllmessagesTablePager extends TablePager {
$pageFlags = $talkFlags = array();
- while( $s = $dbr->fetchObject( $res ) ) {
+ foreach ( $res as $s ) {
if( $s->page_namespace == NS_MEDIAWIKI ) {
if( $this->foreign ) {
$title = explode( '/', $s->page_title );
@@ -223,7 +243,6 @@ class AllmessagesTablePager extends TablePager {
$talkFlags[$s->page_title] = true;
}
}
- $dbr->freeResult( $res );
wfProfileOut( __METHOD__ . '-db' );
@@ -327,7 +346,7 @@ class AllmessagesTablePager extends TablePager {
$s .= Xml::openElement( 'tr', $this->getRowAttrs( $row, true ) );
$formatted = strval( $this->formatValue( 'am_actual', $row->am_actual ) );
if ( $formatted == '' ) {
- $formatted = '&nbsp;';
+ $formatted = '&#160;';
}
$s .= Xml::tags( 'td', $this->getCellAttrs( 'am_actual', $row->am_actual ), $formatted )
. "</tr>\n";
@@ -375,43 +394,4 @@ class AllmessagesTablePager extends TablePager {
return '';
}
}
-/* Overloads the relevant methods of the real ResultsWrapper so it
- * doesn't go anywhere near an actual database.
- */
-class FakeResultWrapper extends ResultWrapper {
-
- var $result = array();
- var $db = null; // And it's going to stay that way :D
- var $pos = 0;
- var $currentRow = null;
- function __construct( $array ){
- $this->result = $array;
- }
-
- function numRows() {
- return count( $this->result );
- }
-
- function fetchRow() {
- $this->currentRow = $this->result[$this->pos++];
- return $this->currentRow;
- }
-
- function seek( $row ) {
- $this->pos = $row;
- }
-
- function free() {}
-
- // Callers want to be able to access fields with $this->fieldName
- function fetchObject(){
- $this->currentRow = $this->result[$this->pos++];
- return (object)$this->currentRow;
- }
-
- function rewind() {
- $this->pos = 0;
- $this->currentRow = null;
- }
-}
diff --git a/includes/specials/SpecialAllpages.php b/includes/specials/SpecialAllpages.php
index 19816dcd..5fa1aa47 100644
--- a/includes/specials/SpecialAllpages.php
+++ b/includes/specials/SpecialAllpages.php
@@ -1,7 +1,29 @@
<?php
-
/**
* Implements Special:Allpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+/**
+ * Implements Special:Allpages
+ *
* @ingroup SpecialPage
*/
class SpecialAllpages extends IncludableSpecialPage {
@@ -32,8 +54,8 @@ class SpecialAllpages extends IncludableSpecialPage {
/**
* Entry point : initialise variables and call subfunctions.
+ *
* @param $par String: becomes "FOO" when called like Special:Allpages/FOO (default NULL)
- * @param $specialPage See the SpecialPage object.
*/
function execute( $par ) {
global $wgRequest, $wgOut, $wgContLang;
@@ -66,9 +88,10 @@ class SpecialAllpages extends IncludableSpecialPage {
/**
* HTML for the top form
- * @param integer $namespace A namespace constant (default NS_MAIN).
- * @param string $from dbKey we are starting listing at.
- * @param string $to dbKey we are ending listing at.
+ *
+ * @param $namespace Integer: a namespace constant (default NS_MAIN).
+ * @param $from String: dbKey we are starting listing at.
+ * @param $to String: dbKey we are ending listing at.
*/
function namespaceForm( $namespace = NS_MAIN, $from = '', $to = '' ) {
global $wgScript;
@@ -76,7 +99,7 @@ class SpecialAllpages extends IncludableSpecialPage {
$out = Xml::openElement( 'div', array( 'class' => 'namespaceoptions' ) );
$out .= Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) );
- $out .= Xml::hidden( 'title', $t->getPrefixedText() );
+ $out .= Html::hidden( 'title', $t->getPrefixedText() );
$out .= Xml::openElement( 'fieldset' );
$out .= Xml::element( 'legend', null, wfMsg( 'allpages' ) );
$out .= Xml::openElement( 'table', array( 'id' => 'nsselect', 'class' => 'allpages' ) );
@@ -113,7 +136,9 @@ class SpecialAllpages extends IncludableSpecialPage {
}
/**
- * @param integer $namespace (default NS_MAIN)
+ * @param $namespace Integer (default NS_MAIN)
+ * @param $from String: list all pages from this name
+ * @param $to String: list all pages to this name
*/
function showToplevel( $namespace = NS_MAIN, $from = '', $to = '' ) {
global $wgOut;
@@ -164,7 +189,8 @@ class SpecialAllpages extends IncludableSpecialPage {
array ('LIMIT' => 2, 'OFFSET' => $maxPerSubpage - 1, 'ORDER BY' => 'page_title ASC')
);
- if( $s = $dbr->fetchObject( $res ) ) {
+ $s = $dbr->fetchObject( $res );
+ if( $s ) {
array_push( $lines, $s->page_title );
} else {
// Final chunk, but ended prematurely. Go back and find the end.
@@ -174,7 +200,8 @@ class SpecialAllpages extends IncludableSpecialPage {
array_push( $lines, $endTitle );
$done = true;
}
- if( $s = $res->fetchObject() ) {
+ $s = $res->fetchObject();
+ if( $s ) {
array_push( $lines, $s->page_title );
$lastTitle = $s->page_title;
} else {
@@ -234,9 +261,10 @@ class SpecialAllpages extends IncludableSpecialPage {
/**
* Show a line of "ABC to DEF" ranges of articles
- * @param string $inpoint Lower limit of pagenames
- * @param string $outpout Upper limit of pagenames
- * @param integer $namespace (Default NS_MAIN)
+ *
+ * @param $inpoint String: lower limit of pagenames
+ * @param $outpoint String: upper limit of pagenames
+ * @param $namespace Integer (Default NS_MAIN)
*/
function showline( $inpoint, $outpoint, $namespace = NS_MAIN ) {
global $wgContLang;
@@ -258,9 +286,9 @@ class SpecialAllpages extends IncludableSpecialPage {
}
/**
- * @param integer $namespace (Default NS_MAIN)
- * @param string $from list all pages from this name (default FALSE)
- * @param string $to list all pages to this name (default FALSE)
+ * @param $namespace Integer (Default NS_MAIN)
+ * @param $from String: list all pages from this name (default FALSE)
+ * @param $to String: list all pages to this name (default FALSE)
*/
function showChunk( $namespace = NS_MAIN, $from = false, $to = false ) {
global $wgOut, $wgUser, $wgContLang, $wgLang;
@@ -280,7 +308,7 @@ class SpecialAllpages extends IncludableSpecialPage {
$namespace = NS_MAIN;
} else {
list( $namespace, $fromKey, $from ) = $fromList;
- list( $namespace2, $toKey, $to ) = $toList;
+ list( , $toKey, $to ) = $toList;
$dbr = wfGetDB( DB_SLAVE );
$conds = array(
@@ -316,7 +344,7 @@ class SpecialAllpages extends IncludableSpecialPage {
if( $n % 3 == 0 ) {
$out .= '<tr>';
}
- $out .= "<td width=\"33%\">$link</td>";
+ $out .= "<td style=\"width:33%\">$link</td>";
$n++;
if( $n % 3 == 0 ) {
$out .= "</tr>\n";
@@ -437,8 +465,8 @@ class SpecialAllpages extends IncludableSpecialPage {
}
/**
- * @param int $ns the namespace of the article
- * @param string $text the name of the article
+ * @param $ns Integer: the namespace of the article
+ * @param $text String: the name of the article
* @return array( int namespace, string dbkey, string pagename ) or NULL on error
* @static (sort of)
* @access private
diff --git a/includes/specials/SpecialAncientpages.php b/includes/specials/SpecialAncientpages.php
index 92192435..2d5047d2 100644
--- a/includes/specials/SpecialAncientpages.php
+++ b/includes/specials/SpecialAncientpages.php
@@ -1,11 +1,29 @@
<?php
/**
+ * Implements Special:Ancientpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
* Implements Special:Ancientpages
+ *
* @ingroup SpecialPage
*/
class AncientPagesPage extends QueryPage {
@@ -21,28 +39,10 @@ class AncientPagesPage extends QueryPage {
function isSyndicated() { return false; }
function getSQL() {
- global $wgDBtype;
$db = wfGetDB( DB_SLAVE );
$page = $db->tableName( 'page' );
$revision = $db->tableName( 'revision' );
-
- switch ($wgDBtype) {
- case 'mysql':
- $epoch = 'UNIX_TIMESTAMP(rev_timestamp)';
- break;
- case 'ibm_db2':
- // TODO implement proper conversion to a Unix epoch
- $epoch = 'rev_timestamp';
- break;
- case 'oracle':
- $epoch = '((trunc(rev_timestamp) - to_date(\'19700101\',\'YYYYMMDD\')) * 86400)';
- break;
- case 'sqlite':
- $epoch = 'rev_timestamp';
- break;
- default:
- $epoch = 'EXTRACT(epoch FROM rev_timestamp)';
- }
+ $epoch = $db->unixTimestamp( 'rev_timestamp' );
return
"SELECT 'Ancientpages' as type,
diff --git a/includes/specials/SpecialBlankpage.php b/includes/specials/SpecialBlankpage.php
index e1fadd02..aaa45a80 100644
--- a/includes/specials/SpecialBlankpage.php
+++ b/includes/specials/SpecialBlankpage.php
@@ -1,5 +1,27 @@
<?php
/**
+ * Implements Special:Blankpage
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+/**
* Special page designed for basic benchmarking of
* MediaWiki since it doesn't really do much.
*
diff --git a/includes/specials/SpecialBlockip.php b/includes/specials/SpecialBlockip.php
index 16720dd1..28a0f3f1 100644
--- a/includes/specials/SpecialBlockip.php
+++ b/includes/specials/SpecialBlockip.php
@@ -1,52 +1,78 @@
<?php
/**
- * Constructor for Special:Blockip page
+ * Implements Special:Blockip
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup SpecialPage
*/
/**
- * Constructor
+ * A special page that allows users with 'block' right to block users from
+ * editing pages and other actions
+ *
+ * @ingroup SpecialPage
*/
-function wfSpecialBlockip( $par ) {
- global $wgUser, $wgOut, $wgRequest;
+class IPBlockForm extends SpecialPage {
+ var $BlockAddress, $BlockExpiry, $BlockReason, $BlockReasonList, $BlockOther, $BlockAnonOnly, $BlockCreateAccount,
+ $BlockEnableAutoblock, $BlockEmail, $BlockHideName, $BlockAllowUsertalk, $BlockReblock;
+ // The maximum number of edits a user can have and still be hidden
+ const HIDEUSER_CONTRIBLIMIT = 1000;
- # Can't block when the database is locked
- if( wfReadOnly() ) {
- $wgOut->readOnlyPage();
- return;
- }
- # Permission check
- if( !$wgUser->isAllowed( 'block' ) ) {
- $wgOut->permissionRequired( 'block' );
- return;
+ public function __construct() {
+ parent::__construct( 'Blockip', 'block' );
}
- $ipb = new IPBlockForm( $par );
+ public function execute( $par ) {
+ global $wgUser, $wgOut, $wgRequest;
- $action = $wgRequest->getVal( 'action' );
- if( 'success' == $action ) {
- $ipb->showSuccess();
- } elseif( $wgRequest->wasPosted() && 'submit' == $action &&
- $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
- $ipb->doSubmit();
- } else {
- $ipb->showForm( '' );
- }
-}
+ # Can't block when the database is locked
+ if( wfReadOnly() ) {
+ $wgOut->readOnlyPage();
+ return;
+ }
+ # Permission check
+ if( !$this->userCanExecute( $wgUser ) ) {
+ $wgOut->permissionRequired( 'block' );
+ return;
+ }
-/**
- * Form object for the Special:Blockip page.
- *
- * @ingroup SpecialPage
- */
-class IPBlockForm {
- var $BlockAddress, $BlockExpiry, $BlockReason;
- // The maximum number of edits a user can have and still be hidden
- const HIDEUSER_CONTRIBLIMIT = 1000;
+ $this->setup( $par );
+
+ # bug 15810: blocked admins should have limited access here
+ if ( $wgUser->isBlocked() ) {
+ $status = IPBlockForm::checkUnblockSelf( $this->BlockAddress );
+ if ( $status !== true ) {
+ throw new ErrorPageError( 'badaccess', $status );
+ }
+ }
- public function __construct( $par ) {
+ $action = $wgRequest->getVal( 'action' );
+ if( 'success' == $action ) {
+ $this->showSuccess();
+ } elseif( $wgRequest->wasPosted() && 'submit' == $action &&
+ $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
+ $this->doSubmit();
+ } else {
+ $this->showForm( '' );
+ }
+ }
+
+ private function setup( $par ) {
global $wgRequest, $wgUser, $wgBlockAllowsUTEdit;
$this->BlockAddress = $wgRequest->getVal( 'wpBlockAddress', $wgRequest->getVal( 'ip', $par ) );
@@ -105,7 +131,7 @@ class IPBlockForm {
$msg = wfMsgReal( $key, $err );
$wgOut->setSubtitle( wfMsgHtml( 'formerror' ) );
$wgOut->addHTML( Xml::tags( 'p', array( 'class' => 'error' ), $msg ) );
- } elseif( $this->BlockAddress ) {
+ } elseif( $this->BlockAddress !== null ) {
# Get other blocks, i.e. from GlobalBlocking or TorBlock extension
wfRunHooks( 'OtherBlockLogLink', array( &$otherBlockedMsgs, $this->BlockAddress ) );
@@ -149,7 +175,7 @@ class IPBlockForm {
# Username/IP is blocked already locally
if( $alreadyBlocked ) {
- $wgOut->addWikiMsg( 'ipb-needreblock', $this->BlockAddress );
+ $wgOut->wrapWikiMsg( "<div class='mw-ipb-needreblock'>\n$1\n</div>", array( 'ipb-needreblock', $this->BlockAddress ) );
}
$scBlockExpiryOptions = wfMsgForContent( 'ipboptions' );
@@ -163,16 +189,15 @@ class IPBlockForm {
list( $show, $value ) = explode( ':', $option );
$show = htmlspecialchars( $show );
$value = htmlspecialchars( $value );
- $blockExpiryFormOptions .= Xml::option( $show, $value, $this->BlockExpiry === $value ? true : false ) . "\n";
+ $blockExpiryFormOptions .= Xml::option( $show, $value, $this->BlockExpiry === $value ) . "\n";
}
$reasonDropDown = Xml::listDropDown( 'wpBlockReasonList',
wfMsgForContent( 'ipbreason-dropdown' ),
wfMsgForContent( 'ipbreasonotherlist' ), $this->BlockReasonList, 'wpBlockDropDown', 4 );
- global $wgStylePath, $wgStyleVersion;
+ $wgOut->addModules( 'mediawiki.legacy.block' );
$wgOut->addHTML(
- Xml::tags( 'script', array( 'type' => 'text/javascript', 'src' => "$wgStylePath/common/block.js?$wgStyleVersion" ), '' ) .
Xml::openElement( 'form', array( 'method' => 'post', 'action' => $titleObj->getLocalURL( 'action=submit' ), 'id' => 'blockip' ) ) .
Xml::openElement( 'fieldset' ) .
Xml::element( 'legend', null, wfMsg( 'blockip-legend' ) ) .
@@ -242,7 +267,7 @@ class IPBlockForm {
</td>
</tr>
<tr id='wpAnonOnlyRow'>
- <td>&nbsp;</td>
+ <td>&#160;</td>
<td class='mw-input'>" .
Xml::checkLabel( wfMsg( 'ipbanononly' ),
'wpAnonOnly', 'wpAnonOnly', $this->BlockAnonOnly,
@@ -250,7 +275,7 @@ class IPBlockForm {
</td>
</tr>
<tr id='wpCreateAccountRow'>
- <td>&nbsp;</td>
+ <td>&#160;</td>
<td class='mw-input'>" .
Xml::checkLabel( wfMsg( 'ipbcreateaccount' ),
'wpCreateAccount', 'wpCreateAccount', $this->BlockCreateAccount,
@@ -258,7 +283,7 @@ class IPBlockForm {
</td>
</tr>
<tr id='wpEnableAutoblockRow'>
- <td>&nbsp;</td>
+ <td>&#160;</td>
<td class='mw-input'>" .
Xml::checkLabel( wfMsg( 'ipbenableautoblock' ),
'wpEnableAutoblock', 'wpEnableAutoblock', $this->BlockEnableAutoblock,
@@ -270,7 +295,7 @@ class IPBlockForm {
if( self::canBlockEmail( $wgUser ) ) {
$wgOut->addHTML("
<tr id='wpEnableEmailBan'>
- <td>&nbsp;</td>
+ <td>&#160;</td>
<td class='mw-input'>" .
Xml::checkLabel( wfMsg( 'ipbemailban' ),
'wpEmailBan', 'wpEmailBan', $this->BlockEmail,
@@ -284,7 +309,7 @@ class IPBlockForm {
if( $wgUser->isAllowed( 'hideuser' ) ) {
$wgOut->addHTML("
<tr id='wpEnableHideUser'>
- <td>&nbsp;</td>
+ <td>&#160;</td>
<td class='mw-input'><strong>" .
Xml::checkLabel( wfMsg( 'ipbhidename' ),
'wpHideName', 'wpHideName', $this->BlockHideName,
@@ -299,7 +324,7 @@ class IPBlockForm {
if( $wgUser->isLoggedIn() ) {
$wgOut->addHTML("
<tr id='wpEnableWatchUser'>
- <td>&nbsp;</td>
+ <td>&#160;</td>
<td class='mw-input'>" .
Xml::checkLabel( wfMsg( 'ipbwatchuser' ),
'wpWatchUser', 'wpWatchUser', $this->BlockWatchUser,
@@ -314,7 +339,7 @@ class IPBlockForm {
if( $wgBlockAllowsUTEdit ){
$wgOut->addHTML("
<tr id='wpAllowUsertalkRow'>
- <td>&nbsp;</td>
+ <td>&#160;</td>
<td class='mw-input'>" .
Xml::checkLabel( wfMsg( 'ipballowusertalk' ),
'wpAllowUsertalk', 'wpAllowUsertalk', $this->BlockAllowUsertalk,
@@ -326,18 +351,18 @@ class IPBlockForm {
$wgOut->addHTML("
<tr>
- <td style='padding-top: 1em'>&nbsp;</td>
+ <td style='padding-top: 1em'>&#160;</td>
<td class='mw-submit' style='padding-top: 1em'>" .
Xml::submitButton( wfMsg( $alreadyBlocked ? 'ipb-change-block' : 'ipbsubmit' ),
- array( 'name' => 'wpBlock', 'tabindex' => '13', 'accesskey' => 's' ) ) . "
+ array( 'name' => 'wpBlock', 'tabindex' => '13' )
+ + $wgUser->getSkin()->tooltipAndAccessKeyAttribs( 'blockip-block' ) ). "
</td>
</tr>" .
Xml::closeElement( 'table' ) .
- Xml::hidden( 'wpEditToken', $wgUser->editToken() ) .
- ( $alreadyBlocked ? Xml::hidden( 'wpChangeBlock', 1 ) : "" ) .
+ Html::hidden( 'wpEditToken', $wgUser->editToken() ) .
+ ( $alreadyBlocked ? Html::hidden( 'wpChangeBlock', 1 ) : "" ) .
Xml::closeElement( 'fieldset' ) .
- Xml::closeElement( 'form' ) .
- Xml::tags( 'script', array( 'type' => 'text/javascript' ), 'updateBlockOptions()' ) . "\n"
+ Xml::closeElement( 'form' )
);
$wgOut->addHTML( $this->getConvenienceLinks() );
@@ -353,13 +378,39 @@ class IPBlockForm {
/**
* Can we do an email block?
- * @param User $user The sysop wanting to make a block
- * @return boolean
+ * @param $user User: the sysop wanting to make a block
+ * @return Boolean
*/
public static function canBlockEmail( $user ) {
global $wgEnableUserEmail, $wgSysopEmailBans;
return ( $wgEnableUserEmail && $wgSysopEmailBans && $user->isAllowed( 'blockemail' ) );
}
+
+ /**
+ * bug 15810: blocked admins should not be able to block/unblock
+ * others, and probably shouldn't be able to unblock themselves
+ * either.
+ * @param $user User, Int or String
+ */
+ public static function checkUnblockSelf( $user ) {
+ global $wgUser;
+ if ( is_int( $user ) ) {
+ $user = User::newFromId( $user );
+ } elseif ( is_string( $user ) ) {
+ $user = User::newFromName( $user );
+ }
+ if( $user instanceof User && $user->getId() == $wgUser->getId() ) {
+ # User is trying to unblock themselves
+ if ( $wgUser->isAllowed( 'unblockself' ) ) {
+ return true;
+ } else {
+ return 'ipbnounblockself';
+ }
+ } else {
+ # User is trying to block/unblock someone else
+ return 'ipbblocked';
+ }
+ }
/**
* Backend block code.
@@ -382,7 +433,7 @@ class IPBlockForm {
$matches = array();
if( preg_match( "/^($rxIP4)\\/(\\d{1,2})$/", $this->BlockAddress, $matches ) ) {
# IPv4
- if( $wgSysopRangeBans ) {
+ if( $wgSysopRangeBans && $wgBlockCIDRLimit['IPv4'] != 32 ) {
if( !IP::isIPv4( $this->BlockAddress ) || $matches[2] > 32 ) {
return array( 'ip_range_invalid' );
} elseif ( $matches[2] < $wgBlockCIDRLimit['IPv4'] ) {
@@ -395,7 +446,7 @@ class IPBlockForm {
}
} elseif( preg_match( "/^($rxIP6)\\/(\\d{1,3})$/", $this->BlockAddress, $matches ) ) {
# IPv6
- if( $wgSysopRangeBans ) {
+ if( $wgSysopRangeBans && $wgBlockCIDRLimit['IPv6'] != 128 ) {
if( !IP::isIPv6( $this->BlockAddress ) || $matches[2] > 128 ) {
return array( 'ip_range_invalid' );
} elseif( $matches[2] < $wgBlockCIDRLimit['IPv6'] ) {
@@ -410,7 +461,7 @@ class IPBlockForm {
# Username block
if( $wgSysopUserBans ) {
$user = User::newFromName( $this->BlockAddress );
- if( !is_null( $user ) && $user->getId() ) {
+ if( $user instanceof User && $user->getId() ) {
# Use canonical name
$userId = $user->getId();
$this->BlockAddress = $user->getName();
@@ -642,7 +693,7 @@ class IPBlockForm {
);
// Add suppression block entries if allowed
- if( $wgUser->isAllowed( 'hideuser' ) ) {
+ if( $wgUser->isAllowed( 'suppressionlog' ) ) {
LogEventsList::showLogExtract( $out, 'suppress', $title->getPrefixedText(), '',
array(
'lim' => 10,
@@ -759,32 +810,20 @@ class IPBlockForm {
* @return string
*/
private function getBlockListLink( $skin ) {
- $list = SpecialPage::getTitleFor( 'Ipblocklist' );
- $query = array();
-
- if( $this->BlockAddress ) {
- $addr = strtr( $this->BlockAddress, '_', ' ' );
- $message = wfMsg( 'ipb-blocklist-addr', $addr );
- $query['ip'] = $this->BlockAddress;
- } else {
- $message = wfMsg( 'ipb-blocklist' );
- }
-
return $skin->linkKnown(
- $list,
- htmlspecialchars( $message ),
- array(),
- $query
+ SpecialPage::getTitleFor( 'Ipblocklist' ),
+ wfMsg( 'ipb-blocklist' )
);
}
/**
* Block a list of selected users
- * @param array $users
- * @param string $reason
- * @param string $tag replaces user pages
- * @param string $talkTag replaces user talk pages
- * @returns array, list of html-safe usernames
+ *
+ * @param $users Array
+ * @param $reason String
+ * @param $tag String: replaces user pages
+ * @param $talkTag String: replaces user talk pages
+ * @return Array: list of html-safe usernames
*/
public static function doMassUserBlock( $users, $reason = '', $tag = '', $talkTag = '' ) {
global $wgUser;
diff --git a/includes/specials/SpecialBlockme.php b/includes/specials/SpecialBlockme.php
index f222e3c6..f5131f5f 100644
--- a/includes/specials/SpecialBlockme.php
+++ b/includes/specials/SpecialBlockme.php
@@ -1,37 +1,59 @@
<?php
/**
+ * Implements Special:Blockme
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
+ * A special page called by proxy_check.php to block open proxies
*
+ * @ingroup SpecialPage
*/
-function wfSpecialBlockme() {
- global $wgRequest, $wgBlockOpenProxies, $wgOut, $wgProxyKey;
-
- $ip = wfGetIP();
+class SpecialBlockme extends UnlistedSpecialPage {
- if( !$wgBlockOpenProxies || $wgRequest->getText( 'ip' ) != md5( $ip . $wgProxyKey ) ) {
- $wgOut->addWikiMsg( 'proxyblocker-disabled' );
- return;
+ function __construct() {
+ parent::__construct( 'Blockme' );
}
- $blockerName = wfMsg( "proxyblocker" );
- $reason = wfMsg( "proxyblockreason" );
-
- $u = User::newFromName( $blockerName );
- $id = $u->idForName();
- if ( !$id ) {
- $u = User::newFromName( $blockerName );
- $u->addToDatabase();
- $u->setPassword( bin2hex( mt_rand(0, 0x7fffffff ) ) );
- $u->saveSettings();
- $id = $u->getID();
- }
+ function execute( $par ) {
+ global $wgRequest, $wgOut, $wgBlockOpenProxies, $wgProxyKey;
+
+ $this->setHeaders();
+ $this->outputHeader();
+
+ $ip = wfGetIP();
+ if( !$wgBlockOpenProxies || $wgRequest->getText( 'ip' ) != md5( $ip . $wgProxyKey ) ) {
+ $wgOut->addWikiMsg( 'proxyblocker-disabled' );
+ return;
+ }
- $block = new Block( $ip, 0, $id, $reason, wfTimestampNow() );
- $block->insert();
+ $user = User::newFromName( wfMsgForContent( 'proxyblocker' ) );
+ if ( !$user->isLoggedIn() ) {
+ $user->addToDatabase();
+ }
+ $id = $user->getId();
+ $reason = wfMsg( 'proxyblockreason' );
- $wgOut->addWikiMsg( "proxyblocksuccess" );
+ $block = new Block( $ip, 0, $id, $reason, wfTimestampNow() );
+ $block->insert();
+
+ $wgOut->addWikiMsg( 'proxyblocksuccess' );
+ }
}
diff --git a/includes/specials/SpecialBooksources.php b/includes/specials/SpecialBooksources.php
index 8ee5467a..67fb5404 100644
--- a/includes/specials/SpecialBooksources.php
+++ b/includes/specials/SpecialBooksources.php
@@ -1,4 +1,25 @@
<?php
+/**
+ * Implements Special:Booksources
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
/**
* Special page outputs information on sourcing a book with a particular ISBN
@@ -35,7 +56,7 @@ class SpecialBookSources extends SpecialPage {
$wgOut->addHTML( $this->makeForm() );
if( strlen( $this->isbn ) > 0 ) {
if( !self::isValidISBN( $this->isbn ) ) {
- $wgOut->wrapWikiMsg( "<div class=\"error\">\n$1</div>", 'booksources-invalid-isbn' );
+ $wgOut->wrapWikiMsg( "<div class=\"error\">\n$1\n</div>", 'booksources-invalid-isbn' );
}
$this->showList();
}
@@ -48,7 +69,6 @@ class SpecialBookSources extends SpecialPage {
public static function isValidISBN( $isbn ) {
$isbn = self::cleanIsbn( $isbn );
$sum = 0;
- $check = -1;
if( strlen( $isbn ) == 13 ) {
for( $i = 0; $i < 12; $i++ ) {
if($i % 2 == 0) {
@@ -78,7 +98,6 @@ class SpecialBookSources extends SpecialPage {
return false;
}
-
/**
* Trim ISBN and remove characters which aren't required
*
@@ -99,9 +118,9 @@ class SpecialBookSources extends SpecialPage {
$title = self::getTitleFor( 'Booksources' );
$form = '<fieldset><legend>' . wfMsgHtml( 'booksources-search-legend' ) . '</legend>';
$form .= Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) );
- $form .= Xml::hidden( 'title', $title->getPrefixedText() );
+ $form .= Html::hidden( 'title', $title->getPrefixedText() );
$form .= '<p>' . Xml::inputLabel( wfMsg( 'booksources-isbn' ), 'isbn', 'isbn', 20, $this->isbn );
- $form .= '&nbsp;' . Xml::submitButton( wfMsg( 'booksources-go' ) ) . '</p>';
+ $form .= '&#160;' . Xml::submitButton( wfMsg( 'booksources-go' ) ) . '</p>';
$form .= Xml::closeElement( 'form' );
$form .= '</fieldset>';
return $form;
@@ -147,6 +166,6 @@ class SpecialBookSources extends SpecialPage {
*/
private function makeListItem( $label, $url ) {
$url = str_replace( '$1', $this->isbn, $url );
- return '<li><a href="' . htmlspecialchars( $url ) . '">' . htmlspecialchars( $label ) . '</a></li>';
+ return '<li><a href="' . htmlspecialchars( $url ) . '" class="external">' . htmlspecialchars( $label ) . '</a></li>';
}
}
diff --git a/includes/specials/SpecialBrokenRedirects.php b/includes/specials/SpecialBrokenRedirects.php
index b6ae2ada..98b02126 100644
--- a/includes/specials/SpecialBrokenRedirects.php
+++ b/includes/specials/SpecialBrokenRedirects.php
@@ -1,12 +1,30 @@
<?php
/**
+ * Implements Special:Brokenredirects
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
- * A special page listing redirects to non existent page. Those should be
+ * A special page listing redirects tonon existent page. Those should be
* fixed to point to an existing page.
+ *
* @ingroup SpecialPage
*/
class BrokenRedirectsPage extends PageQueryPage {
@@ -61,7 +79,7 @@ class BrokenRedirectsPage extends PageQueryPage {
// $toObj may very easily be false if the $result list is cached
if ( !is_object( $toObj ) ) {
- return '<s>' . $skin->link( $fromObj ) . '</s>';
+ return '<del>' . $skin->link( $fromObj ) . '</del>';
}
$from = $skin->linkKnown(
diff --git a/includes/specials/SpecialCategories.php b/includes/specials/SpecialCategories.php
index eb49fdbc..c2dd40cd 100644
--- a/includes/specials/SpecialCategories.php
+++ b/includes/specials/SpecialCategories.php
@@ -1,29 +1,57 @@
<?php
/**
+ * Implements Special:Categories
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
-function wfSpecialCategories( $par=null ) {
- global $wgOut, $wgRequest;
+/**
+ * @ingroup SpecialPage
+ */
+class SpecialCategories extends SpecialPage {
+
+ function __construct() {
+ parent::__construct( 'Categories' );
+ }
+
+ function execute( $par ) {
+ global $wgOut, $wgRequest;
+
+ $this->setHeaders();
+ $this->outputHeader();
+ $wgOut->allowClickjacking();
- if( $par == '' ) {
- $from = $wgRequest->getText( 'from' );
- } else {
- $from = $par;
+ $from = $wgRequest->getText( 'from', $par );
+
+ $cap = new CategoryPager( $from );
+ $cap->doQuery();
+
+ $wgOut->addHTML(
+ Html::openElement( 'div', array( 'class' => 'mw-spcontent' ) ) .
+ wfMsgExt( 'categoriespagetext', array( 'parse' ), $cap->getNumRows() ) .
+ $cap->getStartForm( $from ) .
+ $cap->getNavigationBar() .
+ '<ul>' . $cap->getBody() . '</ul>' .
+ $cap->getNavigationBar() .
+ Html::closeElement( 'div' )
+ );
}
- $wgOut->allowClickjacking();
- $cap = new CategoryPager( $from );
- $cap->doQuery();
- $wgOut->addHTML(
- XML::openElement( 'div', array('class' => 'mw-spcontent') ) .
- wfMsgExt( 'categoriespagetext', array( 'parse' ), $cap->getNumRows() ) .
- $cap->getStartForm( $from ) .
- $cap->getNavigationBar() .
- '<ul>' . $cap->getBody() . '</ul>' .
- $cap->getNavigationBar() .
- XML::closeElement( 'div' )
- );
}
/**
@@ -77,7 +105,7 @@ class CategoryPager extends AlphabeticPager {
$this->mResult->rewind();
- while ( $row = $this->mResult->fetchObject() ) {
+ foreach ( $this->mResult as $row ) {
$batch->addObj( Title::makeTitleSafe( NS_CATEGORY, $row->cat_title ) );
}
$batch->execute();
@@ -100,7 +128,7 @@ class CategoryPager extends AlphabeticPager {
return
Xml::tags( 'form', array( 'method' => 'get', 'action' => $wgScript ),
- Xml::hidden( 'title', $t->getPrefixedText() ) .
+ Html::hidden( 'title', $t->getPrefixedText() ) .
Xml::fieldset( wfMsg( 'categories' ),
Xml::inputLabel( wfMsg( 'categoriesfrom' ),
'from', 'from', 20, $from ) .
diff --git a/includes/specials/SpecialComparePages.php b/includes/specials/SpecialComparePages.php
new file mode 100644
index 00000000..4650fc94
--- /dev/null
+++ b/includes/specials/SpecialComparePages.php
@@ -0,0 +1,170 @@
+<?php
+/**
+ * Implements Special:ComparePages
+ *
+ * Copyright © 2010 Derk-Jan Hartman <hartman@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+/**
+ * Implements Special:ComparePages
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialComparePages extends SpecialPage {
+
+ // Stored objects
+ protected $opts, $skin;
+
+ // Some internal settings
+ protected $showNavigation = false;
+
+ public function __construct() {
+ parent::__construct( 'ComparePages' );
+ }
+
+ protected function setup( $par ) {
+ global $wgRequest, $wgUser;
+
+ // Options
+ $opts = new FormOptions();
+ $this->opts = $opts; // bind
+ $opts->add( 'page1', '' );
+ $opts->add( 'page2', '' );
+ $opts->add( 'rev1', '' );
+ $opts->add( 'rev2', '' );
+ $opts->add( 'action', '' );
+
+ // Set values
+ $opts->fetchValuesFromRequest( $wgRequest );
+
+ $title1 = Title::newFromText( $opts->getValue( 'page1' ) );
+ $title2 = Title::newFromText( $opts->getValue( 'page2' ) );
+
+ if( $title1 && $title1->exists() && $opts->getValue( 'rev1' ) == '' ) {
+ $pda = new Article( $title1 );
+ $pdi = $pda->getID();
+ $pdLastRevision = Revision::loadFromPageId( wfGetDB( DB_SLAVE ), $pdi );
+ $opts->setValue( 'rev1', $pdLastRevision->getId() );
+ } elseif ( $opts->getValue( 'rev1' ) != '' ) {
+ $pdrev = Revision::newFromId( $opts->getValue( 'rev1' ) );
+ if( $pdrev ) $opts->setValue( 'page1', $pdrev->getTitle()->getPrefixedText() );
+ }
+ if( $title2 && $title2->exists() && $opts->getValue( 'rev2' ) == '' ) {
+ $pda = new Article( $title2 );
+ $pdi = $pda->getID();
+ $pdLastRevision = Revision::loadFromPageId( wfGetDB( DB_SLAVE ), $pdi );
+ $opts->setValue('rev2', $pdLastRevision->getId() );
+ } elseif ( $opts->getValue( 'rev2' ) != '' ) {
+ $pdrev = Revision::newFromId( $opts->getValue( 'rev2' ) );
+ if( $pdrev ) $opts->setValue( 'page2', $pdrev->getTitle()->getPrefixedText() );
+ }
+
+ // Store some objects
+ $this->skin = $wgUser->getSkin();
+ }
+
+ /**
+ * Show a form for filtering namespace and username
+ *
+ * @param $par String
+ * @return String
+ */
+ public function execute( $par ) {
+ $this->setHeaders();
+ $this->outputHeader();
+
+ $this->setup( $par );
+
+ // Settings
+ $this->form();
+
+ if( $this->opts->getValue( 'rev1' ) && $this->opts->getValue( 'rev2' ) ) {
+ $de = new DifferenceEngine( null,
+ $this->opts->getValue( 'rev1' ),
+ $this->opts->getValue( 'rev2' ),
+ null, // rcid
+ ( $this->opts->getValue( 'action' ) == 'purge' ),
+ false );
+ $de->showDiffPage( true );
+ }
+ }
+
+ protected function form() {
+ global $wgOut, $wgScript;
+
+ // Consume values
+ $page1 = $this->opts->consumeValue( 'page1' );
+ $page2 = $this->opts->consumeValue( 'page2' );
+ $rev1 = $this->opts->consumeValue( 'rev1' );
+ $rev2 = $this->opts->consumeValue( 'rev2' );
+
+ // Store query values in hidden fields so that form submission doesn't lose them
+ $hidden = array();
+ foreach ( $this->opts->getUnconsumedValues() as $key => $value ) {
+ $hidden[] = Html::hidden( $key, $value );
+ }
+ $hidden = implode( "\n", $hidden );
+
+ $form = Html::openElement( 'form', array( 'action' => $wgScript ) ) .
+ Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) .
+ Xml::fieldset( wfMsg( 'compare-selector' ) ) .
+ Html::openElement( 'table', array( 'id' => 'mw-diff-table', 'style' => 'width:100%' ) ) .
+ "<tr>
+ <td class='mw-label' style='width:10%'>" .
+ Html::element( 'label', array( 'for' => 'page1' ), wfMsg( 'compare-page1' ) ) .
+ "</td>
+ <td class='mw-input' style='width:40%'>" .
+ Html::input( 'page1', $page1, 'text', array( 'size' => 40, 'id' => 'page1' ) ) .
+ "</td>
+ <td class='mw-label' style='width:10%'>" .
+ Html::element( 'label', array( 'for' => 'page2' ), wfMsg( 'compare-page2' ) ) .
+ "</td>
+ <td class='mw-input' style='width:40%'>" .
+ Html::input( 'page2', $page2, 'text', array( 'size' => 40, 'id' => 'page2' ) ) .
+ "</td>
+ </tr>" .
+ "<tr>
+ <td class='mw-label'>" .
+ Html::element( 'label', array( 'for' => 'rev1' ), wfMsg( 'compare-rev1' ) ) .
+ "</td>
+ <td class='mw-input'>" .
+ Html::input( 'rev1', $rev1, 'text', array( 'size' => 8, 'id' => 'rev1' ) ) .
+ "</td>
+ <td class='mw-label'>" .
+ Html::element( 'label', array( 'for' => 'rev2' ), wfMsg( 'compare-rev2' ) ) .
+ "</td>
+ <td class='mw-input'>" .
+ Html::input( 'rev2', $rev2, 'text', array( 'size' => 8, 'id' => 'rev2' ) ) .
+ "</td>
+ </tr>" .
+ "<tr> <td></td>
+ <td class='mw-submit' colspan='3'>" .
+ Xml::submitButton( wfMsg( 'compare-submit' ) ) .
+ "</td>
+ </tr>" .
+ Html::closeElement( 'table' ) .
+ Html::closeElement( 'fieldset' ) .
+ $hidden .
+ Html::closeElement( 'form' );
+
+ $wgOut->addHTML( $form );
+ }
+}
diff --git a/includes/specials/SpecialConfirmemail.php b/includes/specials/SpecialConfirmemail.php
index 372a574c..e556a60b 100644
--- a/includes/specials/SpecialConfirmemail.php
+++ b/includes/specials/SpecialConfirmemail.php
@@ -1,4 +1,25 @@
<?php
+/**
+ * Implements Special:Confirmemail and Special:Invalidateemail
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
/**
* Special page allows users to request email confirmation message, and handles
@@ -25,6 +46,12 @@ class EmailConfirmation extends UnlistedSpecialPage {
function execute( $code ) {
global $wgUser, $wgOut;
$this->setHeaders();
+
+ if ( wfReadOnly() ) {
+ $wgOut->readOnlyPage();
+ return;
+ }
+
if( empty( $code ) ) {
if( $wgUser->isLoggedIn() ) {
if( User::isValidEmailAddr( $wgUser->getEmail() ) ) {
@@ -54,11 +81,11 @@ class EmailConfirmation extends UnlistedSpecialPage {
function showRequestForm() {
global $wgOut, $wgUser, $wgLang, $wgRequest;
if( $wgRequest->wasPosted() && $wgUser->matchEditToken( $wgRequest->getText( 'token' ) ) ) {
- $ok = $wgUser->sendConfirmationMail();
- if ( WikiError::isError( $ok ) ) {
- $wgOut->addWikiMsg( 'confirmemail_sendfailed', $ok->toString() );
- } else {
+ $status = $wgUser->sendConfirmationMail();
+ if ( $status->isGood() ) {
$wgOut->addWikiMsg( 'confirmemail_sent' );
+ } else {
+ $wgOut->addWikiText( $status->getWikiText( 'confirmemail_sendfailed' ) );
}
} else {
if( $wgUser->isEmailConfirmed() ) {
@@ -71,11 +98,11 @@ class EmailConfirmation extends UnlistedSpecialPage {
$wgOut->addWikiMsg( 'emailauthenticated', $time, $d, $t );
}
if( $wgUser->isEmailConfirmationPending() ) {
- $wgOut->wrapWikiMsg( "<div class=\"error mw-confirmemail-pending\">\n$1</div>", 'confirmemail_pending' );
+ $wgOut->wrapWikiMsg( "<div class=\"error mw-confirmemail-pending\">\n$1\n</div>", 'confirmemail_pending' );
}
$wgOut->addWikiMsg( 'confirmemail_text' );
$form = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalUrl() ) );
- $form .= Xml::hidden( 'token', $wgUser->editToken() );
+ $form .= Html::hidden( 'token', $wgUser->editToken() );
$form .= Xml::submitButton( wfMsg( 'confirmemail_send' ) );
$form .= Xml::closeElement( 'form' );
$wgOut->addHTML( $form );
@@ -121,6 +148,13 @@ class EmailInvalidation extends UnlistedSpecialPage {
function execute( $code ) {
$this->setHeaders();
+
+ if ( wfReadOnly() ) {
+ global $wgOut;
+ $wgOut->readOnlyPage();
+ return;
+ }
+
$this->attemptInvalidate( $code );
}
diff --git a/includes/specials/SpecialContributions.php b/includes/specials/SpecialContributions.php
index b5d6107a..cee01a7f 100644
--- a/includes/specials/SpecialContributions.php
+++ b/includes/specials/SpecialContributions.php
@@ -1,10 +1,32 @@
<?php
/**
- * Special:Contributions, show user contributions in a paged list
+ * Implements Special:Contributions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
-
+
+/**
+ * Special:Contributions, show user contributions in a paged list
+ *
+ * @ingroup SpecialPage
+ */
+
class SpecialContributions extends SpecialPage {
public function __construct() {
@@ -12,7 +34,7 @@ class SpecialContributions extends SpecialPage {
}
public function execute( $par ) {
- global $wgUser, $wgOut, $wgLang, $wgRequest;
+ global $wgUser, $wgOut, $wgRequest;
$this->setHeaders();
$this->outputHeader();
@@ -34,6 +56,8 @@ class SpecialContributions extends SpecialPage {
$this->opts['contribs'] = 'newbie';
}
+ $this->opts['deletedOnly'] = $wgRequest->getBool( 'deletedOnly' );
+
if( !strlen( $target ) ) {
$wgOut->addHTML( $this->getForm() );
return;
@@ -41,6 +65,7 @@ class SpecialContributions extends SpecialPage {
$this->opts['limit'] = $wgRequest->getInt( 'limit', $wgUser->getOption('rclimit') );
$this->opts['target'] = $target;
+ $this->opts['topOnly'] = $wgRequest->getBool( 'topOnly' );
$nt = Title::makeTitleSafe( NS_USER, $target );
if( !$nt ) {
@@ -64,10 +89,10 @@ class SpecialContributions extends SpecialPage {
$this->opts['namespace'] = '';
}
- $this->opts['tagfilter'] = (string) $wgRequest->getVal( 'tagfilter' );
-
+ $this->opts['tagFilter'] = (string) $wgRequest->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
+ // be passed in the form at the top of the page
if( $wgUser->isAllowed( 'markbotedits' ) && $wgRequest->getBool( 'bot' ) ) {
$this->opts['bot'] = '1';
}
@@ -81,7 +106,7 @@ class SpecialContributions extends SpecialPage {
$this->opts['year'] = $wgRequest->getIntOrNull( 'year' );
$this->opts['month'] = $wgRequest->getIntOrNull( 'month' );
}
-
+
// Add RSS/atom links
$this->setSyndicated();
$feedType = $wgRequest->getVal( 'feed' );
@@ -93,7 +118,14 @@ class SpecialContributions extends SpecialPage {
$wgOut->addHTML( $this->getForm() );
- $pager = new ContribsPager( $target, $this->opts['namespace'], $this->opts['year'], $this->opts['month'] );
+ $pager = new ContribsPager( array(
+ 'target' => $target,
+ 'namespace' => $this->opts['namespace'],
+ 'year' => $this->opts['year'],
+ 'month' => $this->opts['month'],
+ 'deletedOnly' => $this->opts['deletedOnly'],
+ 'topOnly' => $this->opts['topOnly'],
+ ) );
if( !$pager->getNumRows() ) {
$wgOut->addWikiMsg( 'nocontribs', $target );
} else {
@@ -132,7 +164,7 @@ class SpecialContributions extends SpecialPage {
}
}
}
-
+
protected function setSyndicated() {
global $wgOut;
$wgOut->setSyndicated( true );
@@ -141,8 +173,8 @@ class SpecialContributions extends SpecialPage {
/**
* Generates the subheading with links
- * @param Title $nt @see Title object for the target
- * @param integer $id User ID for the target
+ * @param $nt Title object for the target
+ * @param $id Integer: User ID 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.
*/
@@ -169,12 +201,12 @@ class SpecialContributions extends SpecialPage {
wfMsgHtml( 'change-blocklink' )
);
$tools[] = $sk->linkKnown( # Unblock link
- SpecialPage::getTitleFor( 'BlockList' ),
+ SpecialPage::getTitleFor( 'Ipblocklist' ),
wfMsgHtml( 'unblocklink' ),
array(),
array(
'action' => 'unblock',
- 'ip' => $nt->getDBkey()
+ 'ip' => $nt->getDBkey()
)
);
}
@@ -196,6 +228,14 @@ class SpecialContributions extends SpecialPage {
)
);
}
+ # Uploads
+ $tools[] = $sk->linkKnown(
+ SpecialPage::getTitleFor( 'Listfiles' ),
+ wfMsgHtml( 'sp-contributions-uploads' ),
+ array(),
+ array( 'user' => $nt->getText() )
+ );
+
# Other logs link
$tools[] = $sk->linkKnown(
SpecialPage::getTitleFor( 'Log' ),
@@ -236,7 +276,9 @@ class SpecialContributions extends SpecialPage {
'lim' => 1,
'showIfEmpty' => false,
'msgKey' => array(
- 'sp-contributions-blocked-notice',
+ $userObj->isAnon() ?
+ 'sp-contributions-blocked-notice-anon' :
+ 'sp-contributions-blocked-notice',
$nt->getText() # Support GENDER in 'sp-contributions-blocked-notice'
),
'offset' => '' # don't use $wgRequest parameter offset
@@ -258,99 +300,103 @@ class SpecialContributions extends SpecialPage {
/**
* Generates the namespace selector form with hidden attributes.
- * @param $this->opts Array: the options to be included.
+ * @return String: HTML fragment
*/
protected function getForm() {
global $wgScript;
-
+
$this->opts['title'] = $this->getTitle()->getPrefixedText();
if( !isset( $this->opts['target'] ) ) {
$this->opts['target'] = '';
} else {
$this->opts['target'] = str_replace( '_' , ' ' , $this->opts['target'] );
}
-
+
if( !isset( $this->opts['namespace'] ) ) {
$this->opts['namespace'] = '';
}
-
+
if( !isset( $this->opts['contribs'] ) ) {
$this->opts['contribs'] = 'user';
}
-
+
if( !isset( $this->opts['year'] ) ) {
$this->opts['year'] = '';
}
-
+
if( !isset( $this->opts['month'] ) ) {
$this->opts['month'] = '';
}
-
+
if( $this->opts['contribs'] == 'newbie' ) {
$this->opts['target'] = '';
}
- if( !isset( $this->opts['tagfilter'] ) ) {
- $this->opts['tagfilter'] = '';
+ if( !isset( $this->opts['tagFilter'] ) ) {
+ $this->opts['tagFilter'] = '';
}
-
- $f = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) );
- # Add hidden params for tracking
+
+ if( !isset( $this->opts['topOnly'] ) ) {
+ $this->opts['topOnly'] = false;
+ }
+
+ $f = 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' );
foreach ( $this->opts as $name => $value ) {
- if( in_array( $name, array( 'namespace', 'target', 'contribs', 'year', 'month' ) ) ) {
+ if( in_array( $name, $skipParameters ) ) {
continue;
}
- $f .= "\t" . Xml::hidden( $name, $value ) . "\n";
+ $f .= "\t" . Html::hidden( $name, $value ) . "\n";
}
- $tagFilter = ChangeTags::buildTagFilterSelector( $this->opts['tagfilter'] );
-
- $f .= '<fieldset>' .
- Xml::element( 'legend', array(), wfMsg( 'sp-contributions-search' ) ) .
- Xml::radioLabel( wfMsgExt( 'sp-contributions-newbies', array( 'parsemag' ) ),
- 'contribs', 'newbie' , 'newbie', $this->opts['contribs'] == 'newbie' ? true : false ) . '<br />' .
- Xml::radioLabel( wfMsgExt( 'sp-contributions-username', array( 'parsemag' ) ),
- 'contribs' , 'user', 'user', $this->opts['contribs'] == 'user' ? true : false ) . ' ' .
+ $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' ) . '<br />' .
+ 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' ) ) ) . ' '.
- '<span style="white-space: nowrap">' .
- Xml::label( wfMsg( 'namespace' ), 'namespace' ) . ' ' .
- Xml::namespaceSelector( $this->opts['namespace'], '' ) .
- '</span>' .
- ( $tagFilter ? Xml::tags( 'p', null, implode( '&nbsp;', $tagFilter ) ) : '' ) .
- Xml::openElement( 'p' ) .
- '<span style="white-space: nowrap">' .
- Xml::dateMenu( $this->opts['year'], $this->opts['month'] ) .
- '</span>' . ' ' .
- Xml::submitButton( wfMsg( 'sp-contributions-submit' ) ) .
- Xml::closeElement( 'p' );
-
+ Html::rawElement( 'span', array( 'style' => 'white-space: nowrap' ),
+ Xml::label( wfMsg( 'namespace' ), 'namespace' ) . ' ' .
+ Xml::namespaceSelector( $this->opts['namespace'], '' )
+ ) .
+ Xml::checkLabel( wfMsg( 'history-show-deleted' ),
+ 'deletedOnly', 'mw-show-deleted-only', $this->opts['deletedOnly'] ) . '<br />' .
+ Xml::tags( 'p', null, Xml::checkLabel( wfMsg( 'sp-contributions-toponly' ),
+ 'topOnly', 'mw-show-top-only', $this->opts['topOnly'] ) ) .
+ ( $tagFilter ? Xml::tags( 'p', null, implode( '&#160;', $tagFilter ) ) : '' ) .
+ Html::rawElement( 'p', array( 'style' => 'white-space: nowrap' ),
+ Xml::dateMenu( $this->opts['year'], $this->opts['month'] ) . ' ' .
+ Xml::submitButton( wfMsg( 'sp-contributions-submit' ) )
+ ) . ' ';
$explain = wfMsgExt( 'sp-contributions-explain', 'parseinline' );
- if( !wfEmptyMsg( 'sp-contributions-explain', $explain ) )
+ if( !wfEmptyMsg( 'sp-contributions-explain', $explain ) ) {
$f .= "<p id='mw-sp-contributions-explain'>{$explain}</p>";
-
- $f .= '</fieldset>' .
+ }
+ $f .= Xml::closeElement('fieldset' ) .
Xml::closeElement( 'form' );
return $f;
}
-
+
/**
* Output a subscription feed listing recent edits to this page.
- * @param string $type
+ * @param $type String
*/
protected function feed( $type ) {
- global $wgRequest, $wgFeed, $wgFeedClasses, $wgFeedLimit;
+ global $wgFeed, $wgFeedClasses, $wgFeedLimit, $wgOut;
if( !$wgFeed ) {
- global $wgOut;
$wgOut->addWikiMsg( 'feed-unavailable' );
return;
}
if( !isset( $wgFeedClasses[$type] ) ) {
- global $wgOut;
$wgOut->addWikiMsg( 'feed-invalid' );
return;
}
@@ -360,19 +406,26 @@ class SpecialContributions extends SpecialPage {
wfMsgExt( 'tagline', 'parsemag' ),
$this->getTitle()->getFullUrl() . "/" . urlencode($this->opts['target'])
);
-
+
// Already valid title
$nt = Title::makeTitleSafe( NS_USER, $this->opts['target'] );
$target = $this->opts['target'] == 'newbies' ? 'newbies' : $nt->getText();
-
- $pager = new ContribsPager( $target, $this->opts['namespace'],
- $this->opts['year'], $this->opts['month'], $this->opts['tagfilter'] );
+
+ $pager = new ContribsPager( array(
+ 'target' => $target,
+ 'namespace' => $this->opts['namespace'],
+ 'year' => $this->opts['year'],
+ 'month' => $this->opts['month'],
+ 'tagFilter' => $this->opts['tagFilter'],
+ 'deletedOnly' => $this->opts['deletedOnly'],
+ 'topOnly' => $this->opts['topOnly'],
+ ) );
$pager->mLimit = min( $this->opts['limit'], $wgFeedLimit );
$feed->outHeader();
if( $pager->getNumRows() > 0 ) {
- while( $row = $pager->mResult->fetchObject() ) {
+ foreach ( $pager->mResult as $row ) {
$feed->outItem( $this->feedItem( $row ) );
}
}
@@ -380,10 +433,10 @@ class SpecialContributions extends SpecialPage {
}
protected function feedTitle() {
- global $wgContLanguageCode, $wgSitename;
+ global $wgLanguageCode, $wgSitename;
$page = SpecialPage::getPage( 'Contributions' );
$desc = $page->getDescription();
- return "$wgSitename - $desc [$wgContLanguageCode]";
+ return "$wgSitename - $desc [$wgLanguageCode]";
}
protected function feedItem( $row ) {
@@ -413,7 +466,7 @@ class SpecialContributions extends SpecialPage {
protected function feedItemDesc( $revision ) {
if( $revision ) {
return '<p>' . htmlspecialchars( $revision->getUserText() ) . wfMsgForContent( 'colon-separator' ) .
- htmlspecialchars( FeedItem::stripComment( $revision->getComment() ) ) .
+ htmlspecialchars( FeedItem::stripComment( $revision->getComment() ) ) .
"</p>\n<hr />\n<div>" .
nl2br( htmlspecialchars( $revision->getText() ) ) . "</div>";
}
@@ -431,7 +484,7 @@ class ContribsPager extends ReverseChronologicalPager {
var $namespace = '', $mDb;
var $preventClickjacking = false;
- function __construct( $target, $namespace = false, $year = false, $month = false, $tagFilter = false ) {
+ function __construct( $options ) {
parent::__construct();
$msgs = array( 'uctop', 'diff', 'newarticle', 'rollbacklink', 'diff', 'hist', 'rev-delundel', 'pipe-separator' );
@@ -440,10 +493,15 @@ class ContribsPager extends ReverseChronologicalPager {
$this->messages[$msg] = wfMsgExt( $msg, array( 'escapenoentities' ) );
}
- $this->target = $target;
- $this->namespace = $namespace;
- $this->tagFilter = $tagFilter;
+ $this->target = isset( $options['target'] ) ? $options['target'] : '';
+ $this->namespace = isset( $options['namespace'] ) ? $options['namespace'] : '';
+ $this->tagFilter = isset( $options['tagFilter'] ) ? $options['tagFilter'] : false;
+
+ $this->deletedOnly = !empty( $options['deletedOnly'] );
+ $this->topOnly = !empty( $options['topOnly'] );
+ $year = isset( $options['year'] ) ? $options['year'] : false;
+ $month = isset( $options['month'] ) ? $options['month'] : false;
$this->getDateCond( $year, $month );
$this->mDb = wfGetDB( DB_SLAVE, 'contributions' );
@@ -458,7 +516,7 @@ class ContribsPager extends ReverseChronologicalPager {
function getQueryInfo() {
global $wgUser;
list( $tables, $index, $userCond, $join_cond ) = $this->getUserCond();
-
+
$conds = array_merge( $userCond, $this->getNamespaceCond() );
// Paranoia: avoid brute force searches (bug 17342)
if( !$wgUser->isAllowed( 'deletedhistory' ) ) {
@@ -468,12 +526,12 @@ class ContribsPager extends ReverseChronologicalPager {
' != ' . Revision::SUPPRESSED_USER;
}
$join_cond['page'] = array( 'INNER JOIN', 'page_id=rev_page' );
-
+
$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',
+ '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'
),
'conds' => $conds,
@@ -510,6 +568,12 @@ class ContribsPager extends ReverseChronologicalPager {
$condition['rev_user_text'] = $this->target;
$index = 'usertext_timestamp';
}
+ if( $this->deletedOnly ) {
+ $condition[] = "rev_deleted != '0'";
+ }
+ if( $this->topOnly ) {
+ $condition[] = "rev_id = page_latest";
+ }
return array( $tables, $index, $condition, $join_conds );
}
@@ -552,7 +616,6 @@ class ContribsPager extends ReverseChronologicalPager {
$classes = array();
$page = Title::newFromRow( $row );
- $page->resetArticleId( $row->rev_page ); // use process cache
$link = $sk->link(
$page,
htmlspecialchars( $page->getPrefixedText() ),
@@ -560,7 +623,7 @@ class ContribsPager extends ReverseChronologicalPager {
$page->isRedirect() ? array( 'redirect' => 'no' ) : array()
);
# Mark current revisions
- $difftext = $topmarktext = '';
+ $topmarktext = '';
if( $row->rev_id == $row->page_latest ) {
$topmarktext .= '<span class="mw-uctop">' . $this->messages['uctop'] . '</span>';
# Add rollback link
@@ -594,15 +657,18 @@ class ContribsPager extends ReverseChronologicalPager {
$comment = $wgContLang->getDirMark() . $sk->revComment( $rev, false, true );
$date = $wgLang->timeanddate( wfTimestamp( TS_MW, $row->rev_timestamp ), true );
- if( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
- $d = '<span class="history-deleted">' . $date . '</span>';
- } else {
+ if( $rev->userCan( Revision::DELETED_TEXT ) ) {
$d = $sk->linkKnown(
$page,
htmlspecialchars($date),
array(),
array( 'oldid' => intval( $row->rev_id ) )
);
+ } else {
+ $d = htmlspecialchars( $date );
+ }
+ if( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
+ $d = '<span class="history-deleted">' . $d . '</span>';
}
if( $this->target == 'newbies' ) {
@@ -645,7 +711,7 @@ class ContribsPager extends ReverseChronologicalPager {
$diffHistLinks = '(' . $difftext . $this->messages['pipe-separator'] . $histlink . ')';
$ret = "{$del}{$d} {$diffHistLinks} {$nflag}{$mflag} {$link}{$userlink} {$comment} {$topmarktext}";
-
+
# Denote if username is redacted for this edit
if( $rev->isDeleted( Revision::DELETED_USER ) ) {
$ret .= " <strong>" . wfMsgHtml('rev-deleted-user-contribs') . "</strong>";
@@ -674,6 +740,17 @@ class ContribsPager extends ReverseChronologicalPager {
return $this->mDb;
}
+ /**
+ * Overwrite Pager function and return a helpful comment
+ */
+ function getSqlComment() {
+ if ( $this->namespace || $this->deletedOnly ) {
+ return 'contributions page filtered for namespace or RevisionDeleted edits'; // potentially slow, see CR r58153
+ } else {
+ return 'contributions page unfiltered';
+ }
+ }
+
protected function preventClickjacking() {
$this->preventClickjacking = true;
}
diff --git a/includes/specials/SpecialDeadendpages.php b/includes/specials/SpecialDeadendpages.php
index a8416c97..dfa053aa 100644
--- a/includes/specials/SpecialDeadendpages.php
+++ b/includes/specials/SpecialDeadendpages.php
@@ -1,10 +1,29 @@
<?php
/**
+ * Implements Special:Deadenpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
+ * A special page that list pages that contain no link to other pages
+ *
* @ingroup SpecialPage
*/
class DeadendPagesPage extends PageQueryPage {
diff --git a/includes/specials/SpecialDeletedContributions.php b/includes/specials/SpecialDeletedContributions.php
index 8884bb22..92e22586 100644
--- a/includes/specials/SpecialDeletedContributions.php
+++ b/includes/specials/SpecialDeletedContributions.php
@@ -1,5 +1,27 @@
<?php
/**
+ * Implements Special:DeletedContributions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+/**
* Implements Special:DeletedContributions to display archived revisions
* @ingroup SpecialPage
*/
@@ -258,7 +280,7 @@ class DeletedContributionsPage extends SpecialPage {
return;
}
- global $wgOut, $wgLang, $wgRequest;
+ global $wgOut, $wgRequest;
$wgOut->setPageTitle( wfMsgExt( 'deletedcontributions-title', array( 'parsemag' ) ) );
@@ -328,8 +350,8 @@ class DeletedContributionsPage extends SpecialPage {
/**
* Generates the subheading with links
- * @param Title $nt @see Title object for the target
- * @param integer $id User ID for the target
+ * @param $nt Title object for the target
+ * @param $id Integer: User ID 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.
*/
@@ -445,7 +467,7 @@ class DeletedContributionsPage extends SpecialPage {
* @param $options Array: the options to be included.
*/
function getForm( $options ) {
- global $wgScript, $wgRequest;
+ global $wgScript;
$options['title'] = SpecialPage::getTitleFor( 'DeletedContributions' )->getPrefixedText();
if ( !isset( $options['target'] ) ) {
@@ -472,7 +494,7 @@ class DeletedContributionsPage extends SpecialPage {
if ( in_array( $name, array( 'namespace', 'target', 'contribs' ) ) ) {
continue;
}
- $f .= "\t" . Xml::hidden( $name, $value ) . "\n";
+ $f .= "\t" . Html::hidden( $name, $value ) . "\n";
}
$f .= Xml::openElement( 'fieldset' ) .
diff --git a/includes/specials/SpecialDisambiguations.php b/includes/specials/SpecialDisambiguations.php
index 1941112a..3e706189 100644
--- a/includes/specials/SpecialDisambiguations.php
+++ b/includes/specials/SpecialDisambiguations.php
@@ -1,10 +1,29 @@
<?php
/**
+ * Implements Special:Disambiguations
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
+ * A special page that lists pages containing links to disambiguations pages
+ *
* @ingroup SpecialPage
*/
class DisambiguationsPage extends PageQueryPage {
@@ -22,6 +41,8 @@ class DisambiguationsPage extends PageQueryPage {
}
function getSQL() {
+ global $wgContentNamespaces;
+
$dbr = wfGetDB( DB_SLAVE );
$dMsgText = wfMsgForContent('disambiguationspage');
@@ -48,11 +69,9 @@ class DisambiguationsPage extends PageQueryPage {
'page_namespace' => $disPageObj->getNamespace(), 'page_title' => $disPageObj->getDBkey()),
__METHOD__ );
- while ( $row = $dbr->fetchObject( $res ) ) {
+ foreach ( $res as $row ) {
$linkBatch->addObj( Title::makeTitle( NS_TEMPLATE, $row->pl_title ));
}
-
- $dbr->freeResult( $res );
}
$set = $linkBatch->constructSet( 'lb.tl', $dbr );
@@ -64,12 +83,18 @@ class DisambiguationsPage extends PageQueryPage {
list( $page, $pagelinks, $templatelinks) = $dbr->tableNamesN( 'page', 'pagelinks', 'templatelinks' );
+ if ( $wgContentNamespaces ) {
+ $nsclause = 'IN (' . $dbr->makeList( $wgContentNamespaces ) . ')';
+ } else {
+ $nsclause = '= ' . NS_MAIN;
+ }
+
$sql = "SELECT 'Disambiguations' AS \"type\", pb.page_namespace AS namespace,"
." pb.page_title AS title, la.pl_from AS value"
." FROM {$templatelinks} AS lb, {$page} AS pb, {$pagelinks} AS la, {$page} AS pa"
." WHERE $set" # disambiguation template(s)
.' AND pa.page_id = la.pl_from'
- .' AND pa.page_namespace = ' . NS_MAIN # Limit to just articles in the main namespace
+ .' AND pa.page_namespace ' . $nsclause
.' AND pb.page_id = lb.tl_from'
.' AND pb.page_namespace = la.pl_namespace'
.' AND pb.page_title = la.pl_title'
diff --git a/includes/specials/SpecialDoubleRedirects.php b/includes/specials/SpecialDoubleRedirects.php
index 893fee9e..c7f63210 100644
--- a/includes/specials/SpecialDoubleRedirects.php
+++ b/includes/specials/SpecialDoubleRedirects.php
@@ -1,5 +1,22 @@
<?php
/**
+ * Implements Special:DoubleRedirects
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
@@ -7,6 +24,7 @@
/**
* A special page listing redirects to redirecting page.
* The software will automatically not follow double redirects, to prevent loops.
+ *
* @ingroup SpecialPage
*/
class DoubleRedirectsPage extends PageQueryPage {
@@ -70,11 +88,10 @@ class DoubleRedirectsPage extends PageQueryPage {
$res = $dbr->query( $sql, $fname );
if ( $res ) {
$result = $dbr->fetchObject( $res );
- $dbr->freeResult( $res );
}
}
if ( !$result ) {
- return '<s>' . $skin->link( $titleA, null, array(), array( 'redirect' => 'no' ) ) . '</s>';
+ return '<del>' . $skin->link( $titleA, null, array(), array( 'redirect' => 'no' ) ) . '</del>';
}
$titleB = Title::makeTitle( $result->nsb, $result->tb );
diff --git a/includes/specials/SpecialEmailuser.php b/includes/specials/SpecialEmailuser.php
index 48088ded..61271227 100644
--- a/includes/specials/SpecialEmailuser.php
+++ b/includes/specials/SpecialEmailuser.php
@@ -1,329 +1,303 @@
<?php
/**
+ * Implements Special:Emailuser
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
- * Constructor for Special:Emailuser.
+ * A special page that allows users to send e-mails to other users
+ *
+ * @ingroup SpecialPage
*/
-function wfSpecialEmailuser( $par ) {
- global $wgRequest, $wgUser, $wgOut;
-
- if ( !EmailUserForm::userEmailEnabled() ) {
- $wgOut->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' );
- return;
- }
-
- $action = $wgRequest->getVal( 'action' );
- $target = isset($par) ? $par : $wgRequest->getVal( 'target' );
- $targetUser = EmailUserForm::validateEmailTarget( $target );
+class SpecialEmailUser extends UnlistedSpecialPage {
+ protected $mTarget;
- if ( !( $targetUser instanceof User ) ) {
- $wgOut->showErrorPage( $targetUser.'title', $targetUser.'text' );
- return;
+ public function __construct(){
+ parent::__construct( 'Emailuser' );
}
- $form = new EmailUserForm( $targetUser,
- $wgRequest->getText( 'wpText' ),
- $wgRequest->getText( 'wpSubject' ),
- $wgRequest->getBool( 'wpCCMe' ) );
- if ( $action == 'success' ) {
- $form->showSuccess();
- return;
+ protected function getFormFields(){
+ global $wgUser;
+ return array(
+ 'From' => array(
+ 'type' => 'info',
+ 'raw' => 1,
+ 'default' => $wgUser->getSkin()->link(
+ $wgUser->getUserPage(),
+ htmlspecialchars( $wgUser->getName() )
+ ),
+ 'label-message' => 'emailfrom',
+ 'id' => 'mw-emailuser-sender',
+ ),
+ 'To' => array(
+ 'type' => 'info',
+ 'raw' => 1,
+ 'default' => $wgUser->getSkin()->link(
+ $this->mTargetObj->getUserPage(),
+ htmlspecialchars( $this->mTargetObj->getName() )
+ ),
+ 'label-message' => 'emailto',
+ 'id' => 'mw-emailuser-recipient',
+ ),
+ 'Target' => array(
+ 'type' => 'hidden',
+ 'default' => $this->mTargetObj->getName(),
+ ),
+ 'Subject' => array(
+ 'type' => 'text',
+ 'default' => wfMsgExt( 'defemailsubject', array( 'content', 'parsemag' ) ),
+ 'label-message' => 'emailsubject',
+ 'maxlength' => 200,
+ 'size' => 60,
+ 'required' => 1,
+ ),
+ 'Text' => array(
+ 'type' => 'textarea',
+ 'rows' => 20,
+ 'cols' => 80,
+ 'label-message' => 'emailmessage',
+ 'required' => 1,
+ ),
+ 'CCMe' => array(
+ 'type' => 'check',
+ 'label-message' => 'emailccme',
+ 'default' => $wgUser->getBoolOption( 'ccmeonemails' ),
+ ),
+ );
}
-
- $error = EmailUserForm::getPermissionsError( $wgUser, $wgRequest->getVal( 'wpEditToken' ) );
- if ( $error ) {
+
+ public function execute( $par ) {
+ global $wgRequest, $wgOut, $wgUser;
+
+ $this->setHeaders();
+ $this->outputHeader();
+
+ $this->mTarget = is_null( $par )
+ ? $wgRequest->getVal( 'wpTarget', $wgRequest->getVal( 'target', '' ) )
+ : $par;
+
+ $ret = self::getTarget( $this->mTarget );
+ if( $ret instanceof User ){
+ $this->mTargetObj = $ret;
+ } else {
+ $wgOut->showErrorPage( "{$ret}title", "{$ret}text" );
+ return false;
+ }
+
+ $error = self::getPermissionsError( $wgUser, $wgRequest->getVal( 'wpEditToken' ) );
switch ( $error ) {
+ case null:
+ # Wahey!
+ break;
+ case 'badaccess':
+ $wgOut->permissionRequired( 'sendemail' );
+ return;
case 'blockedemailuser':
$wgOut->blockedPage();
return;
case 'actionthrottledtext':
$wgOut->rateLimited();
return;
- case 'sessionfailure':
- $form->showForm();
- return;
case 'mailnologin':
- $wgOut->showErrorPage( 'mailnologin', 'mailnologintext' );
+ case 'usermaildisabled':
+ $wgOut->showErrorPage( $error, "{$error}text" );
return;
default:
- // It's a hook error
+ # It's a hook error
list( $title, $msg, $params ) = $error;
$wgOut->showErrorPage( $title, $msg, $params );
return;
-
}
- }
-
- if ( "submit" == $action && $wgRequest->wasPosted() ) {
- $result = $form->doSubmit();
- if ( !is_null( $result ) ) {
- $wgOut->addHTML( wfMsg( "usermailererror" ) .
- ' ' . htmlspecialchars( $result->getMessage() ) );
- } else {
- $titleObj = SpecialPage::getTitleFor( "Emailuser" );
- $encTarget = wfUrlencode( $form->getTarget()->getName() );
- $wgOut->redirect( $titleObj->getFullURL( "target={$encTarget}&action=success" ) );
- }
- } else {
- $form->showForm();
- }
-}
-
-/**
- * Implements the Special:Emailuser web interface, and invokes userMailer for sending the email message.
- * @ingroup SpecialPage
- */
-class EmailUserForm {
-
- var $target;
- var $text, $subject;
- var $cc_me; // Whether user requested to be sent a separate copy of their email.
-
- /**
- * @param User $target
- */
- function EmailUserForm( $target, $text, $subject, $cc_me ) {
- $this->target = $target;
- $this->text = $text;
- $this->subject = $subject;
- $this->cc_me = $cc_me;
- }
-
- function showForm() {
- global $wgOut, $wgUser;
- $skin = $wgUser->getSkin();
-
- $wgOut->setPagetitle( wfMsg( "emailpage" ) );
- $wgOut->addWikiMsg( "emailpagetext" );
-
- if ( $this->subject === "" ) {
- $this->subject = wfMsgExt( 'defemailsubject', array( 'content', 'parsemag' ) );
- }
-
- $titleObj = SpecialPage::getTitleFor( "Emailuser" );
- $action = $titleObj->getLocalURL( "target=" .
- urlencode( $this->target->getName() ) . "&action=submit" );
-
- $wgOut->addHTML(
- Xml::openElement( 'form', array( 'method' => 'post', 'action' => $action, 'id' => 'emailuser' ) ) .
- Xml::openElement( 'fieldset' ) .
- Xml::element( 'legend', null, wfMsgExt( 'email-legend', 'parsemag' ) ) .
- Xml::openElement( 'table', array( 'class' => 'mw-emailuser-table' ) ) .
- "<tr>
- <td class='mw-label'>" .
- Xml::label( wfMsg( 'emailfrom' ), 'emailfrom' ) .
- "</td>
- <td class='mw-input' id='mw-emailuser-sender'>" .
- $skin->link( $wgUser->getUserPage(), htmlspecialchars( $wgUser->getName() ) ) .
- "</td>
- </tr>
- <tr>
- <td class='mw-label'>" .
- Xml::label( wfMsg( 'emailto' ), 'emailto' ) .
- "</td>
- <td class='mw-input' id='mw-emailuser-recipient'>" .
- $skin->link( $this->target->getUserPage(), htmlspecialchars( $this->target->getName() ) ) .
- "</td>
- </tr>
- <tr>
- <td class='mw-label'>" .
- Xml::label( wfMsg( 'emailsubject' ), 'wpSubject' ) .
- "</td>
- <td class='mw-input'>" .
- Xml::input( 'wpSubject', 60, $this->subject, array( 'type' => 'text', 'maxlength' => 200 ) ) .
- "</td>
- </tr>
- <tr>
- <td class='mw-label'>" .
- Xml::label( wfMsg( 'emailmessage' ), 'wpText' ) .
- "</td>
- <td class='mw-input'>" .
- Xml::textarea( 'wpText', $this->text, 80, 20, array( 'id' => 'wpText' ) ) .
- "</td>
- </tr>
- <tr>
- <td></td>
- <td class='mw-input'>" .
- Xml::checkLabel( wfMsg( 'emailccme' ), 'wpCCMe', 'wpCCMe', $wgUser->getBoolOption( 'ccmeonemails' ) ) .
- "</td>
- </tr>
- <tr>
- <td></td>
- <td class='mw-submit'>" .
- Xml::submitButton( wfMsg( 'emailsend' ), array( 'name' => 'wpSend', 'accesskey' => 's' ) ) .
- "</td>
- </tr>" .
- Xml::hidden( 'wpEditToken', $wgUser->editToken() ) .
- Xml::closeElement( 'table' ) .
- Xml::closeElement( 'fieldset' ) .
- Xml::closeElement( 'form' )
- );
- }
-
- /*
- * Really send a mail. Permissions should have been checked using
- * EmailUserForm::getPermissionsError. It is probably also a good idea to
- * check the edit token and ping limiter in advance.
- */
- function doSubmit() {
- global $wgUser, $wgUserEmailUseReplyTo, $wgSiteName;
-
- $to = new MailAddress( $this->target );
- $from = new MailAddress( $wgUser );
- $subject = $this->subject;
-
- // Add a standard footer and trim up trailing newlines
- $this->text = rtrim($this->text) . "\n\n-- \n" . wfMsgExt( 'emailuserfooter',
- array( 'content', 'parsemag' ), array( $from->name, $to->name ) );
+ $form = new HTMLForm( $this->getFormFields() );
+ $form->addPreText( wfMsgExt( 'emailpagetext', 'parseinline' ) );
+ $form->setSubmitText( wfMsg( 'emailsend' ) );
+ $form->setTitle( $this->getTitle() );
+ $form->setSubmitCallback( array( __CLASS__, 'submit' ) );
+ $form->setWrapperLegend( wfMsgExt( 'email-legend', 'parsemag' ) );
+ $form->loadData();
- if( wfRunHooks( 'EmailUser', array( &$to, &$from, &$subject, &$this->text ) ) ) {
-
- if( $wgUserEmailUseReplyTo ) {
- // Put the generic wiki autogenerated address in the From:
- // header and reserve the user for Reply-To.
- //
- // This is a bit ugly, but will serve to differentiate
- // wiki-borne mails from direct mails and protects against
- // SPF and bounce problems with some mailers (see below).
- global $wgPasswordSender;
- $mailFrom = new MailAddress( $wgPasswordSender );
- $replyTo = $from;
- } else {
- // Put the sending user's e-mail address in the From: header.
- //
- // This is clean-looking and convenient, but has issues.
- // One is that it doesn't as clearly differentiate the wiki mail
- // from "directly" sent mails.
- //
- // Another is that some mailers (like sSMTP) will use the From
- // address as the envelope sender as well. For open sites this
- // can cause mails to be flunked for SPF violations (since the
- // wiki server isn't an authorized sender for various users'
- // domains) as well as creating a privacy issue as bounces
- // containing the recipient's e-mail address may get sent to
- // the sending user.
- $mailFrom = $from;
- $replyTo = null;
- }
-
- $mailResult = UserMailer::send( $to, $mailFrom, $subject, $this->text, $replyTo );
-
- if( WikiError::isError( $mailResult ) ) {
- return $mailResult;
-
- } else {
-
- // if the user requested a copy of this mail, do this now,
- // unless they are emailing themselves, in which case one copy of the message is sufficient.
- if ($this->cc_me && $to != $from) {
- $cc_subject = wfMsg('emailccsubject', $this->target->getName(), $subject);
- if( wfRunHooks( 'EmailUser', array( &$from, &$from, &$cc_subject, &$this->text ) ) ) {
- $ccResult = UserMailer::send( $from, $from, $cc_subject, $this->text );
- if( WikiError::isError( $ccResult ) ) {
- // At this stage, the user's CC mail has failed, but their
- // original mail has succeeded. It's unlikely, but still, what to do?
- // We can either show them an error, or we can say everything was fine,
- // or we can say we sort of failed AND sort of succeeded. Of these options,
- // simply saying there was an error is probably best.
- return $ccResult;
- }
- }
- }
-
- wfRunHooks( 'EmailUserComplete', array( $to, $from, $subject, $this->text ) );
- return;
- }
+ if( !wfRunHooks( 'EmailUserForm', array( &$form ) ) ){
+ return false;
}
- }
-
- function showSuccess( &$user = null ) {
- global $wgOut;
- if ( is_null($user) )
- $user = $this->target;
-
- $wgOut->setPagetitle( wfMsg( "emailsent" ) );
- $wgOut->addWikiMsg( 'emailsenttext' );
-
- $wgOut->returnToMain( false, $user->getUserPage() );
- }
-
- function getTarget() {
- return $this->target;
- }
-
- static function userEmailEnabled() {
- global $wgEnableEmail, $wgEnableUserEmail;
- return $wgEnableEmail && $wgEnableUserEmail;
+ $wgOut->setPagetitle( wfMsg( '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() );
+ }
}
- static function validateEmailTarget ( $target ) {
- if ( $target == "" ) {
+
+ /**
+ * Validate target User
+ *
+ * @param $target String: target user name
+ * @return User object on success or a string on error
+ */
+ public static function getTarget( $target ) {
+ if ( $target == '' ) {
wfDebug( "Target is empty.\n" );
- return "notarget";
- }
-
- $nt = Title::newFromURL( $target );
- if ( is_null( $nt ) ) {
- wfDebug( "Target is invalid title.\n" );
- return "notarget";
+ return 'notarget';
}
-
- $nu = User::newFromName( $nt->getText() );
+
+ $nu = User::newFromName( $target );
if( !$nu instanceof User || !$nu->getId() ) {
wfDebug( "Target is invalid user.\n" );
- return "notarget";
+ return 'notarget';
} else if ( !$nu->isEmailConfirmed() ) {
wfDebug( "User has no valid email.\n" );
- return "noemail";
+ return 'noemail';
} else if ( !$nu->canReceiveEmail() ) {
wfDebug( "User does not allow user emails.\n" );
- return "nowikiemail";
+ return 'nowikiemail';
}
-
+
return $nu;
}
- static function getPermissionsError ( $user, $editToken ) {
- if( !$user->canSendEmail() ) {
- wfDebug( "User can't send.\n" );
- // FIXME: this is also the error if user is in a group
- // that is not allowed to send e-mail (no right
- // 'sendemail'). Error messages should probably
- // be more fine grained.
- return "mailnologin";
+
+ /**
+ * Check whether a user is allowed to send email
+ *
+ * @param $user User object
+ * @param $editToken String: edit token
+ * @return null on success or string on error
+ */
+ public static function getPermissionsError( $user, $editToken ) {
+ global $wgEnableEmail, $wgEnableUserEmail;
+ if( !$wgEnableEmail || !$wgEnableUserEmail ){
+ return 'usermaildisabled';
+ }
+
+ if( !$user->isAllowed( 'sendemail' ) ) {
+ return 'badaccess';
}
+ if( !$user->isEmailConfirmed() ){
+ return 'mailnologin';
+ }
+
if( $user->isBlockedFromEmailuser() ) {
wfDebug( "User is blocked from sending e-mail.\n" );
return "blockedemailuser";
}
-
+
if( $user->pingLimiter( 'emailuser' ) ) {
- wfDebug( "Ping limiter triggered.\n" );
+ wfDebug( "Ping limiter triggered.\n" );
return 'actionthrottledtext';
}
-
- $hookErr = null;
+
+ $hookErr = false;
+ wfRunHooks( 'UserCanSendEmail', array( &$user, &$hookErr ) );
wfRunHooks( 'EmailUserPermissionsErrors', array( $user, $editToken, &$hookErr ) );
-
- if ($hookErr) {
+ if ( $hookErr ) {
return $hookErr;
}
+
+ return null;
+ }
+
+ /**
+ * Really send a mail. Permissions should have been checked using
+ * getPermissionsError(). It is probably also a good
+ * idea to check the edit token and ping limiter in advance.
+ *
+ * @return Mixed: Status object, or potentially a String on error
+ * or maybe even true on success if anything uses the EmailUser hook.
+ */
+ public static function submit( $data ) {
+ global $wgUser, $wgUserEmailUseReplyTo;
+
+ $target = self::getTarget( $data['Target'] );
+ if( !$target instanceof User ){
+ return wfMsgExt( $target . 'text', 'parse' );
+ }
+ $to = new MailAddress( $target );
+ $from = new MailAddress( $wgUser );
+ $subject = $data['Subject'];
+ $text = $data['Text'];
+
+ // Add a standard footer and trim up trailing newlines
+ $text = rtrim( $text ) . "\n\n-- \n";
+ $text .= wfMsgExt(
+ 'emailuserfooter',
+ array( 'content', 'parsemag' ),
+ array( $from->name, $to->name )
+ );
+
+ $error = '';
+ if( !wfRunHooks( 'EmailUser', array( &$to, &$from, &$subject, &$text, &$error ) ) ) {
+ return $error;
+ }
- if( !$user->matchEditToken( $editToken ) ) {
- wfDebug( "Matching edit token failed.\n" );
- return 'sessionfailure';
+ if( $wgUserEmailUseReplyTo ) {
+ // Put the generic wiki autogenerated address in the From:
+ // header and reserve the user for Reply-To.
+ //
+ // This is a bit ugly, but will serve to differentiate
+ // wiki-borne mails from direct mails and protects against
+ // SPF and bounce problems with some mailers (see below).
+ global $wgPasswordSender, $wgPasswordSenderName;
+ $mailFrom = new MailAddress( $wgPasswordSender, $wgPasswordSenderName );
+ $replyTo = $from;
+ } else {
+ // Put the sending user's e-mail address in the From: header.
+ //
+ // This is clean-looking and convenient, but has issues.
+ // One is that it doesn't as clearly differentiate the wiki mail
+ // from "directly" sent mails.
+ //
+ // Another is that some mailers (like sSMTP) will use the From
+ // address as the envelope sender as well. For open sites this
+ // can cause mails to be flunked for SPF violations (since the
+ // wiki server isn't an authorized sender for various users'
+ // domains) as well as creating a privacy issue as bounces
+ // containing the recipient's e-mail address may get sent to
+ // the sending user.
+ $mailFrom = $from;
+ $replyTo = null;
+ }
+
+ $status = UserMailer::send( $to, $mailFrom, $subject, $text, $replyTo );
+
+ if( !$status->isGood() ) {
+ return $status;
+ } else {
+ // if the user requested a copy of this mail, do this now,
+ // unless they are emailing themselves, in which case one
+ // copy of the message is sufficient.
+ if ( $data['CCMe'] && $to != $from ) {
+ $cc_subject = wfMsg(
+ 'emailccsubject',
+ $target->getName(),
+ $subject
+ );
+ wfRunHooks( 'EmailUserCC', array( &$from, &$from, &$cc_subject, &$text ) );
+ $ccStatus = UserMailer::send( $from, $from, $cc_subject, $text );
+ $status->merge( $ccStatus );
+ }
+
+ wfRunHooks( 'EmailUserComplete', array( $to, $from, $subject, $text ) );
+ return $status;
}
- }
-
- static function newFromURL( $target, $text, $subject, $cc_me )
- {
- $nt = Title::newFromURL( $target );
- $nu = User::newFromName( $nt->getText() );
- return new EmailUserForm( $nu, $text, $subject, $cc_me );
}
}
diff --git a/includes/specials/SpecialExport.php b/includes/specials/SpecialExport.php
index b9a44d48..eaed2393 100644
--- a/includes/specials/SpecialExport.php
+++ b/includes/specials/SpecialExport.php
@@ -1,56 +1,64 @@
<?php
-# Copyright (C) 2003-2008 Brion Vibber <brion@pobox.com>
-# http://www.mediawiki.org/
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-# http://www.gnu.org/copyleft/gpl.html
/**
+ * Implements Special:Export
+ *
+ * Copyright © 2003-2008 Brion Vibber <brion@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
+/**
+ * A special page that allows users to export pages in a XML file
+ *
+ * @ingroup SpecialPage
+ */
class SpecialExport extends SpecialPage {
-
+
private $curonly, $doExport, $pageLinkDepth, $templates;
private $images;
-
+
public function __construct() {
parent::__construct( 'Export' );
}
-
+
public function execute( $par ) {
global $wgOut, $wgRequest, $wgSitename, $wgExportAllowListContributors;
global $wgExportAllowHistory, $wgExportMaxHistory, $wgExportMaxLinkDepth;
- global $wgExportFromNamespaces;
-
+ global $wgExportFromNamespaces, $wgUser;
+
$this->setHeaders();
$this->outputHeader();
-
+
// Set some variables
$this->curonly = true;
$this->doExport = false;
$this->templates = $wgRequest->getCheck( 'templates' );
$this->images = $wgRequest->getCheck( 'images' ); // Doesn't do anything yet
$this->pageLinkDepth = $this->validateLinkDepth(
- $wgRequest->getIntOrNull( 'pagelink-depth' ) );
+ $wgRequest->getIntOrNull( 'pagelink-depth' )
+ );
$nsindex = '';
-
+
if ( $wgRequest->getCheck( 'addcat' ) ) {
$page = $wgRequest->getText( 'pages' );
$catname = $wgRequest->getText( 'catname' );
-
+
if ( $catname !== '' && $catname !== null && $catname !== false ) {
$t = Title::makeTitleSafe( NS_MAIN, $catname );
if ( $t ) {
@@ -67,7 +75,7 @@ class SpecialExport extends SpecialPage {
else if( $wgRequest->getCheck( 'addns' ) && $wgExportFromNamespaces ) {
$page = $wgRequest->getText( 'pages' );
$nsindex = $wgRequest->getText( 'nsindex', '' );
-
+
if ( strval( $nsindex ) !== '' ) {
/**
* Same implementation as above, so same @todo
@@ -80,11 +88,13 @@ class SpecialExport extends SpecialPage {
$page = $wgRequest->getText( 'pages' );
$this->curonly = $wgRequest->getCheck( 'curonly' );
$rawOffset = $wgRequest->getVal( 'offset' );
+
if( $rawOffset ) {
$offset = wfTimestamp( TS_MW, $rawOffset );
} else {
$offset = null;
}
+
$limit = $wgRequest->getInt( 'limit' );
$dir = $wgRequest->getVal( 'dir' );
$history = array(
@@ -93,6 +103,7 @@ class SpecialExport extends SpecialPage {
'limit' => $wgExportMaxHistory,
);
$historyCheck = $wgRequest->getCheck( 'history' );
+
if ( $this->curonly ) {
$history = WikiExporter::CURRENT;
} elseif ( !$historyCheck ) {
@@ -106,93 +117,101 @@ class SpecialExport extends SpecialPage {
$history['dir'] = 'desc';
}
}
-
+
if( $page != '' ) $this->doExport = true;
} else {
- // Default to current-only for GET requests
+ // Default to current-only for GET requests.
$page = $wgRequest->getText( 'pages', $par );
$historyCheck = $wgRequest->getCheck( 'history' );
+
if( $historyCheck ) {
$history = WikiExporter::FULL;
} else {
$history = WikiExporter::CURRENT;
}
-
+
if( $page != '' ) $this->doExport = true;
}
-
+
if( !$wgExportAllowHistory ) {
// Override
$history = WikiExporter::CURRENT;
}
-
+
$list_authors = $wgRequest->getCheck( 'listauthors' );
if ( !$this->curonly || !$wgExportAllowListContributors ) $list_authors = false ;
-
+
if ( $this->doExport ) {
$wgOut->disable();
+
// Cancel output buffering and gzipping if set
// This should provide safer streaming for pages with history
wfResetOutputBuffers();
- header( "Content-type: application/xml; charset=utf-8" );
+ $wgRequest->response()->header( "Content-type: application/xml; charset=utf-8" );
+
if( $wgRequest->getCheck( 'wpDownload' ) ) {
// Provide a sane filename suggestion
$filename = urlencode( $wgSitename . '-' . wfTimestampNow() . '.xml' );
$wgRequest->response()->header( "Content-disposition: attachment;filename={$filename}" );
}
+
$this->doExport( $page, $history, $list_authors );
+
return;
}
-
+
$wgOut->addWikiMsg( 'exporttext' );
-
+
$form = Xml::openElement( 'form', array( 'method' => 'post',
'action' => $this->getTitle()->getLocalUrl( 'action=submit' ) ) );
- $form .= Xml::inputLabel( wfMsg( 'export-addcattext' ) , 'catname', 'catname', 40 ) . '&nbsp;';
+ $form .= Xml::inputLabel( wfMsg( 'export-addcattext' ) , 'catname', 'catname', 40 ) . '&#160;';
$form .= Xml::submitButton( wfMsg( 'export-addcat' ), array( 'name' => 'addcat' ) ) . '<br />';
-
+
if ( $wgExportFromNamespaces ) {
- $form .= Xml::namespaceSelector( $nsindex, null, 'nsindex', wfMsg( 'export-addnstext' ) ) . '&nbsp;';
+ $form .= Xml::namespaceSelector( $nsindex, null, 'nsindex', wfMsg( 'export-addnstext' ) ) . '&#160;';
$form .= Xml::submitButton( wfMsg( 'export-addns' ), array( 'name' => 'addns' ) ) . '<br />';
}
-
+
$form .= Xml::element( 'textarea', array( 'name' => 'pages', 'cols' => 40, 'rows' => 10 ), $page, false );
$form .= '<br />';
-
+
if( $wgExportAllowHistory ) {
$form .= Xml::checkLabel( wfMsg( 'exportcuronly' ), 'curonly', 'curonly', true ) . '<br />';
} else {
$wgOut->addHTML( wfMsgExt( 'exportnohistory', 'parse' ) );
}
+
$form .= Xml::checkLabel( wfMsg( 'export-templates' ), 'templates', 'wpExportTemplates', false ) . '<br />';
+
if( $wgExportMaxLinkDepth || $this->userCanOverrideExportDepth() ) {
$form .= Xml::inputLabel( wfMsg( 'export-pagelinks' ), 'pagelink-depth', 'pagelink-depth', 20, 0 ) . '<br />';
}
// Enable this when we can do something useful exporting/importing image information. :)
//$form .= Xml::checkLabel( wfMsg( 'export-images' ), 'images', 'wpExportImages', false ) . '<br />';
$form .= Xml::checkLabel( wfMsg( 'export-download' ), 'wpDownload', 'wpDownload', true ) . '<br />';
-
- $form .= Xml::submitButton( wfMsg( 'export-submit' ), array( 'accesskey' => 's' ) );
+
+ $form .= Xml::submitButton( wfMsg( 'export-submit' ), $wgUser->getSkin()->tooltipAndAccessKeyAttribs( 'export' ) );
$form .= Xml::closeElement( 'form' );
+
$wgOut->addHTML( $form );
}
-
- private function userCanOverrideExportDepth() {
- global $wgUser;
+ private function userCanOverrideExportDepth() {
+ global $wgUser;
return $wgUser->isAllowed( 'override-export-depth' );
}
-
+
/**
* Do the actual page exporting
- * @param string $page User input on what page(s) to export
- * @param mixed $history one of the WikiExporter history export constants
+ *
+ * @param $page String: user input on what page(s) to export
+ * @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)
*/
private function doExport( $page, $history, $list_authors ) {
- global $wgExportMaxHistory;
-
$pageSet = array(); // Inverted index of all pages to look up
-
+
// Split up and normalize input
foreach( explode( "\n", $page ) as $pageName ) {
$pageName = trim( $pageName );
@@ -202,32 +221,33 @@ class SpecialExport extends SpecialPage {
$pageSet[$title->getPrefixedText()] = true;
}
}
-
+
// 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 );
}
-
- if( $linkDepth = $this->pageLinkDepth ) {
+ $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 );
}
*/
-
+
$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 );
}
+
$pages = array_unique( $pages );
/* Ok, let's get to it... */
@@ -240,15 +260,17 @@ class SpecialExport extends SpecialPage {
$lb = wfGetLBFactory()->newMainLB();
$db = $lb->getConnection( DB_SLAVE );
$buffer = WikiExporter::STREAM;
-
+
// This might take a while... :D
wfSuppressWarnings();
set_time_limit(0);
wfRestoreWarnings();
}
+
$exporter = new WikiExporter( $db, $history, $buffer );
$exporter->list_authors = $list_authors;
$exporter->openStream();
+
foreach( $pages as $page ) {
/*
if( $wgExportMaxHistory && !$this->curonly ) {
@@ -266,11 +288,12 @@ class SpecialExport extends SpecialPage {
$title = Title::newFromText( $page );
if( is_null( $title ) ) continue; #TODO: perhaps output an <error> tag or something.
if( !$title->userCanRead() ) continue; #TODO: perhaps output an <error> tag or something.
-
+
$exporter->pageByTitle( $title );
}
-
+
$exporter->closeStream();
+
if( $lb ) {
$lb->closeAll();
}
@@ -278,52 +301,59 @@ class SpecialExport extends SpecialPage {
private function getPagesFromCategory( $title ) {
global $wgContLang;
-
+
$name = $title->getDBkey();
-
+
$dbr = wfGetDB( DB_SLAVE );
- $res = $dbr->select( array('page', 'categorylinks' ),
- array( 'page_namespace', 'page_title' ),
- array('cl_from=page_id', 'cl_to' => $name ),
- __METHOD__, array('LIMIT' => '5000'));
-
+ $res = $dbr->select(
+ array( 'page', 'categorylinks' ),
+ array( 'page_namespace', 'page_title' ),
+ array( 'cl_from=page_id', 'cl_to' => $name ),
+ __METHOD__,
+ array( 'LIMIT' => '5000' )
+ );
+
$pages = array();
- while ( $row = $dbr->fetchObject( $res ) ) {
+
+ foreach ( $res as $row ) {
$n = $row->page_title;
if ($row->page_namespace) {
$ns = $wgContLang->getNsText( $row->page_namespace );
$n = $ns . ':' . $n;
}
-
+
$pages[] = $n;
}
- $dbr->freeResult($res);
-
return $pages;
}
-
+
private function getPagesFromNamespace( $nsindex ) {
global $wgContLang;
-
+
$dbr = wfGetDB( DB_SLAVE );
- $res = $dbr->select( 'page', array('page_namespace', 'page_title'),
- array('page_namespace' => $nsindex),
- __METHOD__, array('LIMIT' => '5000') );
-
+ $res = $dbr->select(
+ 'page',
+ array( 'page_namespace', 'page_title' ),
+ array( 'page_namespace' => $nsindex ),
+ __METHOD__,
+ array( 'LIMIT' => '5000' )
+ );
+
$pages = array();
- while ( $row = $dbr->fetchObject( $res ) ) {
+
+ foreach ( $res as $row ) {
$n = $row->page_title;
- if ($row->page_namespace) {
+
+ if ( $row->page_namespace ) {
$ns = $wgContLang->getNsText( $row->page_namespace );
$n = $ns . ':' . $n;
}
-
+
$pages[] = $n;
}
- $dbr->freeResult($res);
-
return $pages;
}
+
/**
* Expand a list of pages to include templates used in those pages.
* @param $inputPages array, list of titles to look up
@@ -332,24 +362,28 @@ class SpecialExport extends SpecialPage {
*/
private function getTemplates( $inputPages, $pageSet ) {
return $this->getLinks( $inputPages, $pageSet,
- 'templatelinks',
- array( 'tl_namespace AS namespace', 'tl_title AS title' ),
- array( 'page_id=tl_from' ) );
+ 'templatelinks',
+ array( 'tl_namespace AS namespace', 'tl_title AS title' ),
+ array( 'page_id=tl_from' )
+ );
}
-
+
/**
* Validate link depth setting, if available.
*/
private function validateLinkDepth( $depth ) {
- global $wgExportMaxLinkDepth, $wgExportMaxLinkDepthLimit;
+ global $wgExportMaxLinkDepth;
+
if( $depth < 0 ) {
return 0;
}
+
if ( !$this->userCanOverrideExportDepth() ) {
if( $depth > $wgExportMaxLinkDepth ) {
return $wgExportMaxLinkDepth;
}
}
+
/*
* There's a HARD CODED limit of 5 levels of recursion here to prevent a
* crazy-big export from being done by someone setting the depth
@@ -357,58 +391,73 @@ class SpecialExport extends SpecialPage {
*/
return intval( min( $depth, 5 ) );
}
-
+
/** Expand a list of pages to include pages linked to from that page. */
private function getPageLinks( $inputPages, $pageSet, $depth ) {
- for( $depth=$depth; $depth>0; --$depth ) {
- $pageSet = $this->getLinks( $inputPages, $pageSet, 'pagelinks',
- array( 'pl_namespace AS namespace', 'pl_title AS title' ),
- array( 'page_id=pl_from' ) );
+ for(; $depth > 0; --$depth ) {
+ $pageSet = $this->getLinks(
+ $inputPages, $pageSet, 'pagelinks',
+ array( 'pl_namespace AS namespace', 'pl_title AS title' ),
+ array( 'page_id=pl_from' )
+ );
$inputPages = array_keys( $pageSet );
}
+
return $pageSet;
}
-
+
/**
* Expand a list of pages to include images used in those pages.
+ *
* @param $inputPages array, list of titles to look up
* @param $pageSet array, associative array indexed by titles for output
+ *
* @return array associative array index by titles
*/
private function getImages( $inputPages, $pageSet ) {
- return $this->getLinks( $inputPages, $pageSet,
- 'imagelinks',
- array( NS_FILE . ' AS namespace', 'il_to AS title' ),
- array( 'page_id=il_from' ) );
+ return $this->getLinks(
+ $inputPages,
+ $pageSet,
+ 'imagelinks',
+ array( NS_FILE . ' AS namespace', 'il_to AS title' ),
+ array( 'page_id=il_from' )
+ );
}
-
+
/**
* Expand a list of pages to include items used in those pages.
- * @private
*/
private function getLinks( $inputPages, $pageSet, $table, $fields, $join ) {
$dbr = wfGetDB( DB_SLAVE );
+
foreach( $inputPages as $page ) {
$title = Title::newFromText( $page );
+
if( $title ) {
$pageSet[$title->getPrefixedText()] = true;
/// @todo Fixme: May or may not be more efficient to batch these
/// by namespace when given multiple input pages.
$result = $dbr->select(
- array( 'page', $table ),
- $fields,
- array_merge( $join,
- array(
- 'page_namespace' => $title->getNamespace(),
- 'page_title' => $title->getDBkey() ) ),
- __METHOD__ );
+ array( 'page', $table ),
+ $fields,
+ array_merge(
+ $join,
+ array(
+ 'page_namespace' => $title->getNamespace(),
+ 'page_title' => $title->getDBkey()
+ )
+ ),
+ __METHOD__
+ );
+
foreach( $result as $row ) {
$template = Title::makeTitle( $row->namespace, $row->title );
$pageSet[$template->getPrefixedText()] = true;
}
}
}
+
return $pageSet;
}
-}
-
+
+} \ No newline at end of file
diff --git a/includes/specials/SpecialFewestrevisions.php b/includes/specials/SpecialFewestrevisions.php
index 65d76a65..c265ed38 100644
--- a/includes/specials/SpecialFewestrevisions.php
+++ b/includes/specials/SpecialFewestrevisions.php
@@ -1,5 +1,22 @@
<?php
/**
+ * Implements Special:Fewestrevisions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
diff --git a/includes/specials/SpecialFileDuplicateSearch.php b/includes/specials/SpecialFileDuplicateSearch.php
index 0ed7020a..172e92ad 100644
--- a/includes/specials/SpecialFileDuplicateSearch.php
+++ b/includes/specials/SpecialFileDuplicateSearch.php
@@ -1,24 +1,37 @@
<?php
/**
- * A special page to search for files by hash value as defined in the
- * img_sha1 field in the image table
+ * Implements Special:FileDuplicateSearch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup SpecialPage
- *
* @author Raimond Spekking, based on Special:MIMESearch by Ævar Arnfjörð Bjarmason
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
/**
* Searches the database for files of the requested hash, comparing this with the
* 'img_sha1' field in the image table.
+ *
* @ingroup SpecialPage
*/
class FileDuplicateSearchPage extends QueryPage {
var $hash, $filename;
- function FileDuplicateSearchPage( $hash, $filename ) {
+ function __construct( $hash, $filename ) {
$this->hash = $hash;
$this->filename = $filename;
}
@@ -72,7 +85,7 @@ function wfSpecialFileDuplicateSearch( $par = null ) {
$hash = '';
$filename = isset( $par ) ? $par : $wgRequest->getText( 'filename' );
- $title = Title::newFromText( $filename );
+ $title = Title::makeTitleSafe( NS_FILE, $filename );
if( $title && $title->getText() != '' ) {
$dbr = wfGetDB( DB_SLAVE );
$image = $dbr->tableName( 'image' );
@@ -83,13 +96,12 @@ function wfSpecialFileDuplicateSearch( $par = null ) {
if( $row !== false ) {
$hash = $row[0];
}
- $dbr->freeResult( $res );
}
# Create the input form
$wgOut->addHTML(
Xml::openElement( 'form', array( 'id' => 'fileduplicatesearch', 'method' => 'get', 'action' => $wgScript ) ) .
- Xml::hidden( 'title', SpecialPage::getTitleFor( 'FileDuplicateSearch' )->getPrefixedDbKey() ) .
+ Html::hidden( 'title', SpecialPage::getTitleFor( 'FileDuplicateSearch' )->getPrefixedDbKey() ) .
Xml::openElement( 'fieldset' ) .
Xml::element( 'legend', null, wfMsg( 'fileduplicatesearch-legend' ) ) .
Xml::inputLabel( wfMsg( 'fileduplicatesearch-filename' ), 'filename', 'filename', 50, $filename ) . ' ' .
diff --git a/includes/specials/SpecialFilepath.php b/includes/specials/SpecialFilepath.php
index 8bc1c68b..8bb0890c 100644
--- a/includes/specials/SpecialFilepath.php
+++ b/includes/specials/SpecialFilepath.php
@@ -1,53 +1,81 @@
<?php
/**
+ * Implements Special:Filepath
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
-function wfSpecialFilepath( $par ) {
- global $wgRequest, $wgOut;
+/**
+ * A special page that redirects to the URL of a given file
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialFilepath extends SpecialPage {
- $file = isset( $par ) ? $par : $wgRequest->getText( 'file' );
+ function __construct() {
+ parent::__construct( 'Filepath' );
+ }
- $title = Title::makeTitleSafe( NS_FILE, $file );
+ function execute( $par ) {
+ global $wgRequest, $wgOut;
- if ( ! $title instanceof Title || $title->getNamespace() != NS_FILE ) {
- $cform = new FilepathForm( $title );
- $cform->execute();
- } else {
- $file = wfFindFile( $title );
- if ( $file && $file->exists() ) {
- $wgOut->redirect( $file->getURL() );
- } else {
- $wgOut->setStatusCode( 404 );
- $cform = new FilepathForm( $title );
- $cform->execute();
- }
- }
-}
+ $this->setHeaders();
+ $this->outputHeader();
-/**
- * @ingroup SpecialPage
- */
-class FilepathForm {
- var $mTitle;
+ $file = !is_null( $par ) ? $par : $wgRequest->getText( 'file' );
- function FilepathForm( &$title ) {
- $this->mTitle =& $title;
+ $title = Title::makeTitleSafe( NS_FILE, $file );
+
+ if ( ! $title instanceof Title || $title->getNamespace() != NS_FILE ) {
+ $this->showForm( $title );
+ } else {
+ $file = wfFindFile( $title );
+ if ( $file && $file->exists() ) {
+ $url = $file->getURL();
+ $width = $wgRequest->getInt( 'width', -1 );
+ $height = $wgRequest->getInt( 'height', -1 );
+ if ( $width != -1 ) {
+ $mto = $file->transform( array( 'width' => $width, 'height' => $height ) );
+ if ( $mto && !$mto->isError() ) {
+ $url = $mto->getURL();
+ }
+ }
+ $wgOut->redirect( $url );
+ } else {
+ $wgOut->setStatusCode( 404 );
+ $this->showForm( $title );
+ }
+ }
}
- function execute() {
+ function showForm( $title ) {
global $wgOut, $wgScript;
$wgOut->addHTML(
- Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'specialfilepath' ) ) .
- Xml::openElement( 'fieldset' ) .
- Xml::element( 'legend', null, wfMsg( 'filepath' ) ) .
- Xml::hidden( 'title', SpecialPage::getTitleFor( 'Filepath' )->getPrefixedText() ) .
- Xml::inputLabel( wfMsg( 'filepath-page' ), 'file', 'file', 25, is_object( $this->mTitle ) ? $this->mTitle->getText() : '' ) . ' ' .
+ Html::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'specialfilepath' ) ) .
+ Html::openElement( 'fieldset' ) .
+ Html::element( 'legend', null, wfMsg( 'filepath' ) ) .
+ Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) .
+ Xml::inputLabel( wfMsg( 'filepath-page' ), 'file', 'file', 25, is_object( $title ) ? $title->getText() : '' ) . ' ' .
Xml::submitButton( wfMsg( 'filepath-submit' ) ) . "\n" .
- Xml::closeElement( 'fieldset' ) .
- Xml::closeElement( 'form' )
+ Html::closeElement( 'fieldset' ) .
+ Html::closeElement( 'form' )
);
}
}
diff --git a/includes/specials/SpecialImport.php b/includes/specials/SpecialImport.php
index 248709a8..7d1cf0dd 100644
--- a/includes/specials/SpecialImport.php
+++ b/includes/specials/SpecialImport.php
@@ -1,7 +1,8 @@
<?php
/**
- * MediaWiki page data importer
- * Copyright (C) 2003,2005 Brion Vibber <brion@pobox.com>
+ * Implements Special:Import
+ *
+ * Copyright © 2003,2005 Brion Vibber <brion@pobox.com>
* http://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
@@ -23,6 +24,11 @@
* @ingroup SpecialPage
*/
+/**
+ * MediaWiki page data importer
+ *
+ * @ingroup SpecialPage
+ */
class SpecialImport extends SpecialPage {
private $interwiki = false;
@@ -51,7 +57,6 @@ class SpecialImport extends SpecialPage {
$this->outputHeader();
if ( wfReadOnly() ) {
- global $wgOut;
$wgOut->readOnlyPage();
return;
}
@@ -97,7 +102,7 @@ class SpecialImport extends SpecialPage {
$this->pageLinkDepth = $wgExportMaxLinkDepth == 0 ? 0 : $wgRequest->getIntOrNull( 'pagelink-depth' );
if ( !$wgUser->matchEditToken( $wgRequest->getVal( 'editToken' ) ) ) {
- $source = new WikiErrorMsg( 'import-token-mismatch' );
+ $source = Status::newFatal( 'import-token-mismatch' );
} elseif ( $sourceName == 'upload' ) {
$isUpload = true;
if( $wgUser->isAllowed( 'importupload' ) ) {
@@ -111,7 +116,7 @@ class SpecialImport extends SpecialPage {
}
$this->interwiki = $wgRequest->getVal( 'interwiki' );
if ( !in_array( $this->interwiki, $wgImportSources ) ) {
- $source = new WikiErrorMsg( "import-invalid-interwiki" );
+ $source = Status::newFatal( "import-invalid-interwiki" );
} else {
$this->history = $wgRequest->getCheck( 'interwikiHistory' );
$this->frompage = $wgRequest->getText( "frompage" );
@@ -124,30 +129,35 @@ class SpecialImport extends SpecialPage {
$this->pageLinkDepth );
}
} else {
- $source = new WikiErrorMsg( "importunknownsource" );
+ $source = Status::newFatal( "importunknownsource" );
}
- if( WikiError::isError( $source ) ) {
- $wgOut->wrapWikiMsg( '<p class="error">$1</p>', array( 'importfailed', $source->getMessage() ) );
+ if( !$source->isGood() ) {
+ $wgOut->wrapWikiMsg( "<p class=\"error\">\n$1\n</p>", array( 'importfailed', $source->getWikiText() ) );
} else {
$wgOut->addWikiMsg( "importstart" );
- $importer = new WikiImporter( $source );
+ $importer = new WikiImporter( $source->value );
if( !is_null( $this->namespace ) ) {
$importer->setTargetNamespace( $this->namespace );
}
$reporter = new ImportReporter( $importer, $isUpload, $this->interwiki , $this->logcomment);
+ $exception = false;
$reporter->open();
- $result = $importer->doImport();
- $resultCount = $reporter->close();
+ try {
+ $importer->doImport();
+ } catch ( MWException $e ) {
+ $exception = $e;
+ }
+ $result = $reporter->close();
- if( WikiError::isError( $result ) ) {
+ if ( $exception ) {
# No source or XML parse error
- $wgOut->wrapWikiMsg( '<p class="error">$1</p>', array( 'importfailed', $result->getMessage() ) );
- } elseif( WikiError::isError( $resultCount ) ) {
+ $wgOut->wrapWikiMsg( "<p class=\"error\">\n$1\n</p>", array( 'importfailed', $exception->getMessage() ) );
+ } elseif( !$result->isGood() ) {
# Zero revisions
- $wgOut->wrapWikiMsg( '<p class="error">$1</p>', array( 'importfailed', $resultCount->getMessage() ) );
+ $wgOut->wrapWikiMsg( "<p class=\"error\">\n$1\n</p>", array( 'importfailed', $result->getWikiText() ) );
} else {
# Success!
$wgOut->addWikiMsg( 'importsuccess' );
@@ -157,7 +167,7 @@ class SpecialImport extends SpecialPage {
}
private function showForm() {
- global $wgUser, $wgOut, $wgRequest, $wgImportSources, $wgExportMaxLinkDepth;
+ global $wgUser, $wgOut, $wgImportSources, $wgExportMaxLinkDepth;
$action = $this->getTitle()->getLocalUrl( array( 'action' => 'submit' ) );
@@ -167,8 +177,8 @@ class SpecialImport extends SpecialPage {
Xml::fieldset( wfMsg( 'import-upload' ) ).
Xml::openElement( 'form', array( 'enctype' => 'multipart/form-data', 'method' => 'post',
'action' => $action, 'id' => 'mw-import-upload-form' ) ) .
- Xml::hidden( 'action', 'submit' ) .
- Xml::hidden( 'source', 'upload' ) .
+ Html::hidden( 'action', 'submit' ) .
+ Html::hidden( 'source', 'upload' ) .
Xml::openElement( 'table', array( 'id' => 'mw-import-table' ) ) .
"<tr>
@@ -195,7 +205,7 @@ class SpecialImport extends SpecialPage {
"</td>
</tr>" .
Xml::closeElement( 'table' ).
- Xml::hidden( 'editToken', $wgUser->editToken() ) .
+ Html::hidden( 'editToken', $wgUser->editToken() ) .
Xml::closeElement( 'form' ) .
Xml::closeElement( 'fieldset' )
);
@@ -223,9 +233,9 @@ class SpecialImport extends SpecialPage {
Xml::fieldset( wfMsg( 'importinterwiki' ) ) .
Xml::openElement( 'form', array( 'method' => 'post', 'action' => $action, 'id' => 'mw-import-interwiki-form' ) ) .
wfMsgExt( 'import-interwiki-text', array( 'parse' ) ) .
- Xml::hidden( 'action', 'submit' ) .
- Xml::hidden( 'source', 'interwiki' ) .
- Xml::hidden( 'editToken', $wgUser->editToken() ) .
+ Html::hidden( 'action', 'submit' ) .
+ Html::hidden( 'source', 'interwiki' ) .
+ Html::hidden( 'editToken', $wgUser->editToken() ) .
Xml::openElement( 'table', array( 'id' => 'mw-import-table' ) ) .
"<tr>
<td class='mw-label'>" .
@@ -280,7 +290,7 @@ class SpecialImport extends SpecialPage {
<td>
</td>
<td class='mw-submit'>" .
- Xml::submitButton( wfMsg( 'import-interwiki-submit' ), array( 'accesskey' => 's' ) ) .
+ Xml::submitButton( wfMsg( 'import-interwiki-submit' ), $wgUser->getSkin()->tooltipAndAccessKeyAttribs( 'import' ) ) .
"</td>
</tr>" .
Xml::closeElement( 'table' ).
@@ -297,9 +307,15 @@ class SpecialImport extends SpecialPage {
*/
class ImportReporter {
private $reason=false;
+ private $mOriginalLogCallback = null;
+ private $mOriginalPageOutCallback = null;
+ private $mLogItemCount = 0;
function __construct( $importer, $upload, $interwiki , $reason=false ) {
- $importer->setPageOutCallback( array( $this, 'reportPage' ) );
+ $this->mOriginalPageOutCallback =
+ $importer->setPageOutCallback( array( $this, 'reportPage' ) );
+ $this->mOriginalLogCallback =
+ $importer->setLogItemCallback( array( $this, 'reportLogItem' ) );
$this->mPageCount = 0;
$this->mIsUpload = $upload;
$this->mInterwiki = $interwiki;
@@ -310,9 +326,19 @@ class ImportReporter {
global $wgOut;
$wgOut->addHTML( "<ul>\n" );
}
+
+ function reportLogItem( /* ... */ ) {
+ $this->mLogItemCount++;
+ if ( is_callable( $this->mOriginalLogCallback ) ) {
+ call_user_func_array( $this->mOriginalLogCallback, func_get_args() );
+ }
+ }
- function reportPage( $title, $origTitle, $revisionCount, $successCount ) {
+ function reportPage( $title, $origTitle, $revisionCount, $successCount, $pageInfo ) {
global $wgOut, $wgUser, $wgLang, $wgContLang;
+
+ $args = func_get_args();
+ call_user_func_array( $this->mOriginalPageOutCallback, $args );
$skin = $wgUser->getSkin();
@@ -362,13 +388,18 @@ class ImportReporter {
}
function close() {
- global $wgOut;
- if( $this->mPageCount == 0 ) {
+ global $wgOut, $wgLang;
+
+ if ( $this->mLogItemCount > 0 ) {
+ $msg = wfMsgExt( 'imported-log-entries', 'parseinline',
+ $wgLang->formatNum( $this->mLogItemCount ) );
+ $wgOut->addHTML( Xml::tags( 'li', null, $msg ) );
+ } elseif( $this->mPageCount == 0 && $this->mLogItemCount == 0 ) {
$wgOut->addHTML( "</ul>\n" );
- return new WikiErrorMsg( "importnopages" );
+ return Status::newFatal( 'importnopages' );
}
$wgOut->addHTML( "</ul>\n" );
- return $this->mPageCount;
+ return Status::newGood( $this->mPageCount );
}
}
diff --git a/includes/specials/SpecialIpblocklist.php b/includes/specials/SpecialIpblocklist.php
index dfdcf1a7..24d7f008 100644
--- a/includes/specials/SpecialIpblocklist.php
+++ b/includes/specials/SpecialIpblocklist.php
@@ -1,103 +1,134 @@
<?php
/**
+ * Implements Special:ipblocklist
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
- * @param $ip part of title: Special:Ipblocklist/<ip>.
- * @todo document
+ * A special page that lists existing blocks and allows users with the 'block'
+ * permission to remove blocks
+ *
+ * @ingroup SpecialPage
*/
-function wfSpecialIpblocklist( $ip = '' ) {
- global $wgUser, $wgOut, $wgRequest;
- $ip = $wgRequest->getVal( 'ip', $ip );
- $ip = trim( $wgRequest->getVal( 'wpUnblockAddress', $ip ) );
- $id = $wgRequest->getVal( 'id' );
- $reason = $wgRequest->getText( 'wpUnblockReason' );
- $action = $wgRequest->getText( 'action' );
- $successip = $wgRequest->getVal( 'successip' );
-
- $ipu = new IPUnblockForm( $ip, $id, $reason );
-
- if( $action == 'unblock' ) {
- # Check permissions
- if( !$wgUser->isAllowed( 'block' ) ) {
- $wgOut->permissionRequired( 'block' );
- return;
- }
- # Check for database lock
- if( wfReadOnly() ) {
- $wgOut->readOnlyPage();
- return;
- }
- # Show unblock form
- $ipu->showForm( '' );
- } elseif( $action == 'submit' && $wgRequest->wasPosted()
- && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
- # Check permissions
- if( !$wgUser->isAllowed( 'block' ) ) {
- $wgOut->permissionRequired( 'block' );
- return;
- }
- # Check for database lock
- if( wfReadOnly() ) {
- $wgOut->readOnlyPage();
- return;
- }
- # Remove blocks and redirect user to success page
- $ipu->doSubmit();
- } elseif( $action == 'success' ) {
- # Inform the user of a successful unblock
- # (No need to check permissions or locks here,
- # if something was done, then it's too late!)
- if ( substr( $successip, 0, 1) == '#' ) {
- // A block ID was unblocked
- $ipu->showList( $wgOut->parse( wfMsg( 'unblocked-id', $successip ) ) );
- } else {
- // A username/IP was unblocked
- $ipu->showList( $wgOut->parse( wfMsg( 'unblocked', $successip ) ) );
- }
- } else {
- # Just show the block list
- $ipu->showList( '' );
+class IPUnblockForm extends SpecialPage {
+ var $ip, $reason, $id;
+ var $hideuserblocks, $hidetempblocks, $hideaddressblocks;
+
+ function __construct() {
+ parent::__construct( 'Ipblocklist' );
}
-}
+ /**
+ * Main execution point
+ *
+ * @param $ip part of title: Special:Ipblocklist/<ip>.
+ */
+ function execute( $ip ) {
+ global $wgUser, $wgOut, $wgRequest;
-/**
- * implements Special:ipblocklist GUI
- * @ingroup SpecialPage
- */
-class IPUnblockForm {
- var $ip, $reason, $id;
+ $this->setHeaders();
+ $this->outputHeader();
- function IPUnblockForm( $ip, $id, $reason ) {
- global $wgRequest;
- $this->ip = strtr( $ip, '_', ' ' );
- $this->id = $id;
- $this->reason = $reason;
+ $ip = $wgRequest->getVal( 'ip', $ip );
+ $this->ip = trim( $wgRequest->getVal( 'wpUnblockAddress', $ip ) );
+ $this->id = $wgRequest->getVal( 'id' );
+ $this->reason = $wgRequest->getText( 'wpUnblockReason' );
$this->hideuserblocks = $wgRequest->getBool( 'hideuserblocks' );
$this->hidetempblocks = $wgRequest->getBool( 'hidetempblocks' );
$this->hideaddressblocks = $wgRequest->getBool( 'hideaddressblocks' );
+
+ $action = $wgRequest->getText( 'action' );
+ $successip = $wgRequest->getVal( 'successip' );
+
+ if( $action == 'unblock' || $action == 'submit' && $wgRequest->wasPosted() ) {
+ # Check permissions
+ if( !$wgUser->isAllowed( 'block' ) ) {
+ $wgOut->permissionRequired( 'block' );
+ return;
+ }
+ # Check for database lock
+ if( wfReadOnly() ) {
+ $wgOut->readOnlyPage();
+ return;
+ }
+
+ # bug 15810: blocked admins should have limited access here
+ if ( $wgUser->isBlocked() ) {
+ if ( $this->id ) {
+ # This doesn't pick up on autoblocks, but admins
+ # should have the ipblock-exempt permission anyway
+ $block = Block::newFromID( $this->id );
+ $user = User::newFromName( $block->mAddress );
+ } else {
+ $user = User::newFromName( $this->ip );
+ }
+ $status = IPBlockForm::checkUnblockSelf( $user );
+ if ( $status !== true ) {
+ throw new ErrorPageError( 'badaccess', $status );
+ }
+ }
+
+ if( $action == 'unblock' ){
+ # Show unblock form
+ $this->showForm( '' );
+ } elseif( $action == 'submit'
+ && $wgRequest->wasPosted()
+ && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) )
+ {
+ # Remove blocks and redirect user to success page
+ $this->doSubmit();
+ }
+
+ } elseif( $action == 'success' ) {
+ # Inform the user of a successful unblock
+ # (No need to check permissions or locks here,
+ # if something was done, then it's too late!)
+ if ( substr( $successip, 0, 1) == '#' ) {
+ // A block ID was unblocked
+ $this->showList( $wgOut->parse( wfMsg( 'unblocked-id', $successip ) ) );
+ } else {
+ // A username/IP was unblocked
+ $this->showList( $wgOut->parse( wfMsg( 'unblocked', $successip ) ) );
+ }
+ } else {
+ # Just show the block list
+ $this->showList( '' );
+ }
}
/**
* Generates the unblock form
+ *
* @param $err string: error message
* @return $out string: HTML form
*/
function showForm( $err ) {
global $wgOut, $wgUser, $wgSysopUserBans;
- $wgOut->setPagetitle( wfMsg( 'unblockip' ) );
$wgOut->addWikiMsg( 'unblockiptext' );
- $titleObj = SpecialPage::getTitleFor( "Ipblocklist" );
- $action = $titleObj->getLocalURL( "action=submit" );
+ $action = $this->getTitle()->getLocalURL( 'action=submit' );
- if ( $err != "" ) {
- $wgOut->setSubtitle( wfMsg( "formerror" ) );
- $wgOut->addWikiText( Xml::tags( 'span', array( 'class' => 'error' ), $err ) . "\n" );
+ if ( $err != '' ) {
+ $wgOut->setSubtitle( wfMsg( 'formerror' ) );
+ $wgOut->addWikiText( Html::rawElement( 'span', array( 'class' => 'error' ), $err ) . "\n" );
}
$addressPart = false;
@@ -106,7 +137,7 @@ class IPUnblockForm {
if ( $block ) {
$encName = htmlspecialchars( $block->getRedactedName() );
$encId = $this->id;
- $addressPart = $encName . Xml::hidden( 'id', $encId );
+ $addressPart = $encName . Html::hidden( 'id', $encId );
$ipa = wfMsgHtml( $wgSysopUserBans ? 'ipadressorusername' : 'ipaddress' );
}
}
@@ -116,10 +147,10 @@ class IPUnblockForm {
}
$wgOut->addHTML(
- Xml::openElement( 'form', array( 'method' => 'post', 'action' => $action, 'id' => 'unblockip' ) ) .
- Xml::openElement( 'fieldset' ) .
- Xml::element( 'legend', null, wfMsg( 'ipb-unblock' ) ) .
- Xml::openElement( 'table', array( 'id' => 'mw-unblock-table' ) ).
+ Html::openElement( 'form', array( 'method' => 'post', 'action' => $action, 'id' => 'unblockip' ) ) .
+ Html::openElement( 'fieldset' ) .
+ Html::element( 'legend', null, wfMsg( 'ipb-unblock' ) ) .
+ Html::openElement( 'table', array( 'id' => 'mw-unblock-table' ) ).
"<tr>
<td class='mw-label'>
{$ipa}
@@ -137,15 +168,15 @@ class IPUnblockForm {
"</td>
</tr>
<tr>
- <td>&nbsp;</td>
+ <td>&#160;</td>
<td class='mw-submit'>" .
Xml::submitButton( wfMsg( 'ipusubmit' ), array( 'name' => 'wpBlock', 'tabindex' => '3' ) ) .
"</td>
</tr>" .
- Xml::closeElement( 'table' ) .
- Xml::closeElement( 'fieldset' ) .
- Xml::hidden( 'wpEditToken', $wgUser->editToken() ) .
- Xml::closeElement( 'form' ) . "\n"
+ Html::closeElement( 'table' ) .
+ Html::closeElement( 'fieldset' ) .
+ Html::hidden( 'wpEditToken', $wgUser->editToken() ) .
+ Html::closeElement( 'form' ) . "\n"
);
}
@@ -162,34 +193,35 @@ class IPUnblockForm {
* case it contains the range $ip is part of.
* @return array array(message key, parameters) on failure, empty array on success
*/
-
- static function doUnblock(&$id, &$ip, &$reason, &$range = null, $blocker=null) {
+ public static function doUnblock( &$id, &$ip, &$reason, &$range = null, $blocker = null ) {
if ( $id ) {
$block = Block::newFromID( $id );
if ( !$block ) {
- return array('ipb_cant_unblock', htmlspecialchars($id));
+ return array( 'ipb_cant_unblock', htmlspecialchars( $id ) );
}
$ip = $block->getRedactedName();
} else {
- $block = new Block();
$ip = trim( $ip );
if ( substr( $ip, 0, 1 ) == "#" ) {
$id = substr( $ip, 1 );
$block = Block::newFromID( $id );
if( !$block ) {
- return array('ipb_cant_unblock', htmlspecialchars($id));
+ return array( 'ipb_cant_unblock', htmlspecialchars( $id ) );
}
$ip = $block->getRedactedName();
} else {
+ # FIXME: do proper sanitisation/cleanup here
+ $ip = str_replace( '_', ' ', $ip );
+
$block = Block::newFromDB( $ip );
if ( !$block ) {
- return array('ipb_cant_unblock', htmlspecialchars($id));
+ return array( 'ipb_cant_unblock', htmlspecialchars( $id ) );
}
if( $block->mRangeStart != $block->mRangeEnd && !strstr( $ip, "/" ) ) {
/* If the specified IP is a single address, and the block is
* a range block, don't unblock the range. */
$range = $block->mAddress;
- return array('ipb_blocked_as_range', $ip, $range);
+ return array( 'ipb_blocked_as_range', $ip, $range );
}
}
}
@@ -198,13 +230,13 @@ class IPUnblockForm {
# If the name was hidden and the blocking user cannot hide
# names, then don't allow any block removals...
- if( $blocker && $block->mHideName && !$blocker->isAllowed('hideuser') ) {
- return array('ipb_cant_unblock', htmlspecialchars($id));
+ if( $blocker && $block->mHideName && !$blocker->isAllowed( 'hideuser' ) ) {
+ return array( 'ipb_cant_unblock', htmlspecialchars( $id ) );
}
# Delete block
if ( !$block->delete() ) {
- return array('ipb_cant_unblock', htmlspecialchars($id));
+ return array( 'ipb_cant_unblock', htmlspecialchars( $id ) );
}
# Unset _deleted fields as needed
@@ -220,23 +252,23 @@ class IPUnblockForm {
function doSubmit() {
global $wgOut, $wgUser;
- $retval = self::doUnblock($this->id, $this->ip, $this->reason, $range, $wgUser);
- if( !empty($retval) ) {
- $key = array_shift($retval);
- $this->showForm(wfMsgReal($key, $retval));
+
+ $retval = self::doUnblock( $this->id, $this->ip, $this->reason, $range, $wgUser );
+ if( !empty( $retval ) ) {
+ $key = array_shift( $retval );
+ $this->showForm( wfMsgReal( $key, $retval ) );
return;
}
+
# Report to the user
- $titleObj = SpecialPage::getTitleFor( "Ipblocklist" );
- $success = $titleObj->getFullURL( "action=success&successip=" . urlencode( $this->ip ) );
+ $success = $this->getTitle()->getFullURL( 'action=success&successip=' . urlencode( $this->ip ) );
$wgOut->redirect( $success );
}
function showList( $msg ) {
global $wgOut, $wgUser;
- $wgOut->setPagetitle( wfMsg( "ipblocklist" ) );
- if ( $msg != "" ) {
+ if ( $msg != '' ) {
$wgOut->setSubtitle( $msg );
}
@@ -246,7 +278,6 @@ class IPUnblockForm {
}
$conds = array();
- $matches = array();
// Is user allowed to see all the blocks?
if ( !$wgUser->isAllowed( 'hideuser' ) )
$conds['ipb_deleted'] = 0;
@@ -255,25 +286,26 @@ class IPUnblockForm {
} elseif ( substr( $this->ip, 0, 1 ) == '#' ) {
$conds['ipb_id'] = substr( $this->ip, 1 );
// Single IPs
- } elseif ( IP::isIPAddress($this->ip) && strpos($this->ip,'/') === false ) {
- if( $iaddr = IP::toHex($this->ip) ) {
+ } elseif ( IP::isIPAddress( $this->ip ) && strpos( $this->ip, '/' ) === false ) {
+ $iaddr = IP::toHex( $this->ip );
+ if( $iaddr ) {
# Only scan ranges which start in this /16, this improves search speed
# Blocks should not cross a /16 boundary.
$range = substr( $iaddr, 0, 4 );
// Fixme -- encapsulate this sort of query-building.
$dbr = wfGetDB( DB_SLAVE );
- $encIp = $dbr->addQuotes( IP::sanitizeIP($this->ip) );
+ $encIp = $dbr->addQuotes( IP::sanitizeIP( $this->ip ) );
$encAddr = $dbr->addQuotes( $iaddr );
$conds[] = "(ipb_address = $encIp) OR
(ipb_range_start" . $dbr->buildLike( $range, $dbr->anyString() ) . " AND
ipb_range_start <= $encAddr
AND ipb_range_end >= $encAddr)";
} else {
- $conds['ipb_address'] = IP::sanitizeIP($this->ip);
+ $conds['ipb_address'] = IP::sanitizeIP( $this->ip );
}
$conds['ipb_auto'] = 0;
// IP range
- } elseif ( IP::isIPAddress($this->ip) ) {
+ } elseif ( IP::isIPAddress( $this->ip ) ) {
$conds['ipb_address'] = Block::normaliseRange( $this->ip );
$conds['ipb_auto'] = 0;
} else {
@@ -315,7 +347,7 @@ class IPUnblockForm {
if ( $pager->getNumRows() ) {
$wgOut->addHTML(
$pager->getNavigationBar() .
- Xml::tags( 'ul', null, $pager->getBody() ) .
+ Html::rawElement( 'ul', null, $pager->getBody() ) .
$pager->getNavigationBar()
);
} elseif ( $this->ip != '') {
@@ -338,7 +370,7 @@ class IPUnblockForm {
}
function searchForm() {
- global $wgScript, $wgRequest, $wgLang;
+ global $wgScript, $wgLang;
$showhide = array( wfMsg( 'show' ), wfMsg( 'hide' ) );
$nondefaults = array();
@@ -365,30 +397,32 @@ class IPUnblockForm {
$hl = $wgLang->pipeList( $links );
return
- Xml::tags( 'form', array( 'action' => $wgScript ),
- Xml::hidden( 'title', SpecialPage::getTitleFor( 'Ipblocklist' )->getPrefixedDbKey() ) .
- Xml::openElement( 'fieldset' ) .
- Xml::element( 'legend', null, wfMsg( 'ipblocklist-legend' ) ) .
+ Html::rawElement( 'form', array( 'action' => $wgScript ),
+ Html::hidden( 'title', $this->getTitle()->getPrefixedDbKey() ) .
+ Html::openElement( 'fieldset' ) .
+ Html::element( 'legend', null, wfMsg( 'ipblocklist-legend' ) ) .
Xml::inputLabel( wfMsg( 'ipblocklist-username' ), 'ip', 'ip', /* size */ false, $this->ip ) .
- '&nbsp;' .
+ '&#160;' .
Xml::submitButton( wfMsg( 'ipblocklist-submit' ) ) . '<br />' .
$hl .
- Xml::closeElement( 'fieldset' )
+ Html::closeElement( 'fieldset' )
);
}
/**
* Makes change an option link which carries all the other options
+ *
* @param $title see Title
- * @param $override
- * @param $options
+ * @param $override Array: special query string options, will override the
+ * ones in $options
+ * @param $options Array: query string options
+ * @param $active Boolean: whether to display the link in bold
*/
function makeOptionsLink( $title, $override, $options, $active = false ) {
global $wgUser;
$sk = $wgUser->getSkin();
$params = $override + $options;
- $ipblocklist = SpecialPage::getTitleFor( 'Ipblocklist' );
- return $sk->link( $ipblocklist, htmlspecialchars( $title ),
+ return $sk->link( $this->getTitle(), htmlspecialchars( $title ),
( $active ? array( 'style'=>'font-weight: bold;' ) : array() ), $params, array( 'known' ) );
}
@@ -453,11 +487,10 @@ class IPUnblockForm {
$line = wfMsgReplaceArgs( $msg['blocklistline'], array( $formattedTime, $blocker, $target, $properties ) );
- $unblocklink = '';
$changeblocklink = '';
$toolLinks = '';
if ( $wgUser->isAllowed( 'block' ) ) {
- $unblocklink = $sk->link( SpecialPage::getTitleFor( 'Ipblocklist' ),
+ $unblocklink = $sk->link( $this->getTitle(),
$msg['unblocklink'],
array(),
array( 'action' => 'unblock', 'id' => $block->mId ),
@@ -513,7 +546,7 @@ class IPBlocklistPager extends ReverseChronologicalPager {
# Faster way
# Usernames and titles are in fact related by a simple substitution of space -> underscore
# The last few lines of Title::secureAndSplit() tell the story.
- while ( $row = $this->mResult->fetchObject() ) {
+ foreach ( $this->mResult as $row ) {
$name = str_replace( ' ', '_', $row->ipb_by_text );
$lb->add( NS_USER, $name );
$lb->add( NS_USER_TALK, $name );
diff --git a/includes/specials/SpecialLinkSearch.php b/includes/specials/SpecialLinkSearch.php
index 70b2257a..9dee9d5a 100644
--- a/includes/specials/SpecialLinkSearch.php
+++ b/includes/specials/SpecialLinkSearch.php
@@ -1,11 +1,27 @@
<?php
/**
+ * Implements Special:LinkSearch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
- *
* @author Brion Vibber
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
+
/**
* Special:LinkSearch to search the external-links table.
@@ -13,7 +29,7 @@
function wfSpecialLinkSearch( $par ) {
list( $limit, $offset ) = wfCheckLimits();
- global $wgOut, $wgRequest, $wgUrlProtocols, $wgMiserMode, $wgLang;
+ global $wgOut, $wgUrlProtocols, $wgMiserMode, $wgLang;
$target = $GLOBALS['wgRequest']->getVal( 'target', $par );
$namespace = $GLOBALS['wgRequest']->getIntorNull( 'namespace', null );
@@ -44,19 +60,18 @@ function wfSpecialLinkSearch( $par ) {
$protocol = '';
}
- $wgOut->allowClickjacking();
-
$self = Title::makeTitle( NS_SPECIAL, 'Linksearch' );
-
+
+ $wgOut->allowClickjacking();
$wgOut->addWikiMsg( 'linksearch-text', '<nowiki>' . $wgLang->commaList( $wgUrlProtocols ) . '</nowiki>' );
- $s = Xml::openElement( 'form', array( 'id' => 'mw-linksearch-form', 'method' => 'get', 'action' => $GLOBALS['wgScript'] ) ) .
- Xml::hidden( 'title', $self->getPrefixedDbKey() ) .
+ $s = Xml::openElement( 'form', array( 'id' => 'mw-linksearch-form', 'method' => 'get', 'action' => $GLOBALS['wgScript'] ) ) .
+ Html::hidden( 'title', $self->getPrefixedDbKey() ) .
'<fieldset>' .
Xml::element( 'legend', array(), wfMsg( 'linksearch' ) ) .
Xml::inputLabel( wfMsg( 'linksearch-pat' ), 'target', 'target', 50, $target ) . ' ';
if ( !$wgMiserMode ) {
$s .= Xml::label( wfMsg( 'linksearch-ns' ), 'namespace' ) . ' ' .
- XML::namespaceSelector( $namespace, '' );
+ Xml::namespaceSelector( $namespace, '' );
}
$s .= Xml::submitButton( wfMsg( 'linksearch-ok' ) ) .
'</fieldset>' .
@@ -73,6 +88,9 @@ function wfSpecialLinkSearch( $par ) {
}
}
+/**
+ * @ingroup SpecialPage
+ */
class LinkSearchPage extends QueryPage {
function setParams( $params ) {
$this->mQuery = $params['query'];
@@ -98,8 +116,9 @@ class LinkSearchPage extends QueryPage {
$field = 'el_index';
$rv = LinkFilter::makeLikeArray( $query , $prot );
if ($rv === false) {
- //makeLike doesn't handle wildcard in IP, so we'll have to munge here.
+ // LinkFilter doesn't handle wildcard in IP, so we'll have to munge here.
if (preg_match('/^(:?[0-9]{1,3}\.)+\*\s*$|^(:?[0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]*\*\s*$/', $query)) {
+ $dbr = wfGetDB( DB_SLAVE );
$rv = array( $prot . rtrim($query, " \t*"), $dbr->anyString() );
$field = 'el_to';
}
@@ -162,7 +181,7 @@ class LinkSearchPage extends QueryPage {
*/
function doQuery( $offset, $limit, $shownavigation=true ) {
global $wgOut;
- list( $this->mMungedQuery, $clause ) = LinkSearchPage::mungeQuery( $this->mQuery, $this->mProt );
+ list( $this->mMungedQuery, ) = LinkSearchPage::mungeQuery( $this->mQuery, $this->mProt );
if( $this->mMungedQuery === false ) {
$wgOut->addWikiMsg( 'linksearch-error' );
} else {
diff --git a/includes/specials/SpecialListfiles.php b/includes/specials/SpecialListfiles.php
index b9332422..350e833b 100644
--- a/includes/specials/SpecialListfiles.php
+++ b/includes/specials/SpecialListfiles.php
@@ -1,16 +1,30 @@
<?php
/**
+ * Implements Special:Listfiles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
-
-/**
- *
- */
-function wfSpecialListfiles() {
+
+function wfSpecialListfiles( $par = null ) {
global $wgOut;
- $pager = new ImageListPager;
+ $pager = new ImageListPager( $par );
$limit = $pager->getForm();
$body = $pager->getBody();
@@ -24,21 +38,32 @@ function wfSpecialListfiles() {
class ImageListPager extends TablePager {
var $mFieldNames = null;
var $mQueryConds = array();
-
- function __construct() {
+ var $mUserName = null;
+
+ function __construct( $par = null ) {
global $wgRequest, $wgMiserMode;
if ( $wgRequest->getText( 'sort', 'img_date' ) == 'img_date' ) {
$this->mDefaultDirection = true;
} else {
$this->mDefaultDirection = false;
}
+
+ $userName = $wgRequest->getText( 'user', $par );
+ if ( $userName ) {
+ $nt = Title::newFromText( $userName, NS_USER );
+ if ( !is_null( $nt ) ) {
+ $this->mUserName = $nt->getText();
+ $this->mQueryConds['img_user_text'] = $this->mUserName;
+ }
+ }
+
$search = $wgRequest->getText( 'ilsearch' );
if ( $search != '' && !$wgMiserMode ) {
$nt = Title::newFromURL( $search );
- if( $nt ) {
+ if ( $nt ) {
$dbr = wfGetDB( DB_SLAVE );
- $this->mQueryConds = array( 'LOWER(img_name)' . $dbr->buildLike( $dbr->anyString(),
- strtolower( $nt->getDBkey() ), $dbr->anyString() ) );
+ $this->mQueryConds[] = 'LOWER(img_name)' . $dbr->buildLike( $dbr->anyString(),
+ strtolower( $nt->getDBkey() ), $dbr->anyString() );
}
}
@@ -49,6 +74,7 @@ class ImageListPager extends TablePager {
if ( !$this->mFieldNames ) {
global $wgMiserMode;
$this->mFieldNames = array(
+ 'thumb' => wfMsg( 'listfiles_thumb' ),
'img_timestamp' => wfMsg( 'listfiles_date' ),
'img_name' => wfMsg( 'listfiles_name' ),
'img_user_text' => wfMsg( 'listfiles_user' ),
@@ -63,7 +89,11 @@ class ImageListPager extends TablePager {
}
function isFieldSortable( $field ) {
- static $sortable = array( 'img_timestamp', 'img_name', 'img_size' );
+ static $sortable = array( 'img_timestamp', 'img_name' );
+ if ( $field == 'img_size' ) {
+ # No index for both img_size and img_user_text
+ return !isset( $this->mQueryConds['img_user_text'] );
+ }
return in_array( $field, $sortable );
}
@@ -71,6 +101,7 @@ class ImageListPager extends TablePager {
$tables = array( 'image' );
$fields = array_keys( $this->getFieldNames() );
$fields[] = 'img_user';
+ $fields[array_search('thumb', $fields)] = 'img_name as thumb';
$options = $join_conds = array();
# Depends on $wgMiserMode
@@ -78,9 +109,11 @@ class ImageListPager extends TablePager {
$tables[] = 'oldimage';
# Need to rewrite this one
- foreach ( $fields as &$field )
- if ( $field == 'count' )
+ foreach ( $fields as &$field ) {
+ if ( $field == 'count' ) {
$field = 'COUNT(oi_archive_name) as count';
+ }
+ }
unset( $field );
$dbr = wfGetDB( DB_SLAVE );
@@ -110,7 +143,7 @@ class ImageListPager extends TablePager {
if ( $this->mResult->numRows() ) {
$lb = new LinkBatch;
$this->mResult->seek( 0 );
- while ( $row = $this->mResult->fetchObject() ) {
+ foreach ( $this->mResult as $row ) {
if ( $row->img_user ) {
$lb->add( NS_USER, str_replace( ' ', '_', $row->img_user_text ) );
}
@@ -124,14 +157,18 @@ class ImageListPager extends TablePager {
function formatValue( $field, $value ) {
global $wgLang;
switch ( $field ) {
+ case 'thumb':
+ $file = wfLocalFile( $value );
+ $thumb = $file->transform( array( 'width' => 180 ) );
+ return $thumb->toHtml( array( 'desc-link' => true ) );
case 'img_timestamp':
return htmlspecialchars( $wgLang->timeanddate( $value, true ) );
case 'img_name':
static $imgfile = null;
if ( $imgfile === null ) $imgfile = wfMsg( 'imgfile' );
- $name = $this->mCurrentRow->img_name;
- $link = $this->getSkin()->linkKnown( Title::makeTitle( NS_FILE, $name ), $value );
+ $filePage = Title::makeTitle( NS_FILE, $value );
+ $link = $this->getSkin()->linkKnown( $filePage, htmlspecialchars( $filePage->getText() ) );
$image = wfLocalFile( $value );
$url = $image->getURL();
$download = Xml::element('a', array( 'href' => $url ), $imgfile );
@@ -158,21 +195,26 @@ class ImageListPager extends TablePager {
function getForm() {
global $wgRequest, $wgScript, $wgMiserMode;
$search = $wgRequest->getText( 'ilsearch' );
-
- $s = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'mw-listfiles-form' ) ) .
- Xml::openElement( 'fieldset' ) .
- Xml::element( 'legend', null, wfMsg( 'listfiles' ) ) .
- Xml::tags( 'label', null, wfMsgHtml( 'table_pager_limit', $this->getLimitSelect() ) );
-
+ $inputForm = array();
+ $inputForm['table_pager_limit_label'] = $this->getLimitSelect();
if ( !$wgMiserMode ) {
- $s .= "<br />\n" .
- Xml::inputLabel( wfMsg( 'listfiles_search_for' ), 'ilsearch', 'mw-ilsearch', 20, $search );
+ $inputForm['listfiles_search_for'] = Html::input( 'ilsearch', $search, 'text', array(
+ 'size' => '40',
+ 'maxlength' => '255',
+ 'id' => 'mw-ilsearch',
+ ) );
}
- $s .= ' ' .
- Xml::submitButton( wfMsg( 'table_pager_limit_submit' ) ) ."\n" .
- $this->getHiddenFields( array( 'limit', 'ilsearch' ) ) .
- Xml::closeElement( 'fieldset' ) .
- Xml::closeElement( 'form' ) . "\n";
+ $inputForm['username'] = Html::input( 'user', $this->mUserName, 'text', array(
+ 'size' => '40',
+ 'maxlength' => '255',
+ 'id' => 'mw-listfiles-user',
+ ) );
+ $s = Html::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'mw-listfiles-form' ) ) .
+ Xml::fieldset( wfMsg( 'listfiles' ) ) .
+ Xml::buildForm( $inputForm, 'table_pager_limit_submit' ) .
+ $this->getHiddenFields( array( 'limit', 'ilsearch', 'user' ) ) .
+ Html::closeElement( 'fieldset' ) .
+ Html::closeElement( 'form' ) . "\n";
return $s;
}
@@ -187,4 +229,25 @@ class ImageListPager extends TablePager {
function getSortHeaderClass() {
return 'listfiles_sort ' . parent::getSortHeaderClass();
}
+
+ function getPagingQueries() {
+ $queries = parent::getPagingQueries();
+ if ( !is_null( $this->mUserName ) ) {
+ # Append the username to the query string
+ foreach ( $queries as &$query ) {
+ $query['user'] = $this->mUserName;
+ }
+ }
+ return $queries;
+ }
+
+ function getDefaultQuery() {
+ $queries = parent::getDefaultQuery();
+ if ( !isset( $queries['user'] )
+ && !is_null( $this->mUserName ) )
+ {
+ $queries['user'] = $this->mUserName;
+ }
+ return $queries;
+ }
}
diff --git a/includes/specials/SpecialListgrouprights.php b/includes/specials/SpecialListgrouprights.php
index 83724a4f..910ffd08 100644
--- a/includes/specials/SpecialListgrouprights.php
+++ b/includes/specials/SpecialListgrouprights.php
@@ -1,4 +1,25 @@
<?php
+/**
+ * Implements Special:Listgrouprights
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
/**
* This special page lists all defined user groups and the associated rights.
@@ -24,10 +45,9 @@ class SpecialListGroupRights extends SpecialPage {
* Show the special page
*/
public function execute( $par ) {
- global $wgOut, $wgImplicitGroups, $wgMessageCache;
+ global $wgOut, $wgImplicitGroups;
global $wgGroupPermissions, $wgRevokePermissions, $wgAddGroups, $wgRemoveGroups;
global $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
- $wgMessageCache->loadAllMessages();
$this->setHeaders();
$this->outputHeader();
@@ -40,8 +60,23 @@ class SpecialListGroupRights extends SpecialPage {
'</tr>'
);
- foreach( $wgGroupPermissions as $group => $permissions ) {
- $groupname = ( $group == '*' ) ? 'all' : $group; // Replace * with a more descriptive groupname
+ $allGroups = array_unique( array_merge(
+ array_keys( $wgGroupPermissions ),
+ array_keys( $wgRevokePermissions ),
+ array_keys( $wgAddGroups ),
+ array_keys( $wgRemoveGroups ),
+ array_keys( $wgGroupsAddToSelf ),
+ array_keys( $wgGroupsRemoveFromSelf )
+ ) );
+ asort( $allGroups );
+
+ foreach ( $allGroups as $group ) {
+ $permissions = isset( $wgGroupPermissions[$group] )
+ ? $wgGroupPermissions[$group]
+ : array();
+ $groupname = ( $group == '*' ) // Replace * with a more descriptive groupname
+ ? 'all'
+ : $group;
$msg = wfMsg( 'group-' . $groupname );
if ( wfEmptyMsg( 'group-' . $groupname, $msg ) || $msg == '' ) {
@@ -59,11 +94,11 @@ class SpecialListGroupRights extends SpecialPage {
if( $group == '*' ) {
// Do not make a link for the generic * group
- $grouppage = htmlspecialchars($groupnameLocalized);
+ $grouppage = htmlspecialchars( $groupnameLocalized );
} else {
$grouppage = $this->skin->link(
Title::newFromText( $grouppageLocalized ),
- htmlspecialchars($groupnameLocalized)
+ htmlspecialchars( $groupnameLocalized )
);
}
@@ -95,16 +130,15 @@ class SpecialListGroupRights extends SpecialPage {
$addgroupsSelf = isset( $wgGroupsAddToSelf[$group] ) ? $wgGroupsAddToSelf[$group] : array();
$removegroupsSelf = isset( $wgGroupsRemoveFromSelf[$group] ) ? $wgGroupsRemoveFromSelf[$group] : array();
- $wgOut->addHTML(
- '<tr>
- <td>' .
- $grouppage . $grouplink .
- '</td>
- <td>' .
+ $id = $group == '*' ? false : Sanitizer::escapeId( $group );
+ $wgOut->addHTML( Html::rawElement( 'tr', array( 'id' => $id ),
+ "
+ <td>$grouppage$grouplink</td>
+ <td>" .
self::formatPermissions( $permissions, $revoke, $addgroups, $removegroups, $addgroupsSelf, $removegroupsSelf ) .
'</td>
- </tr>'
- );
+ '
+ ) );
}
$wgOut->addHTML(
Xml::closeElement( 'table' ) . "\n<br /><hr />\n"
diff --git a/includes/specials/SpecialListredirects.php b/includes/specials/SpecialListredirects.php
index bf594070..315047da 100644
--- a/includes/specials/SpecialListredirects.php
+++ b/includes/specials/SpecialListredirects.php
@@ -1,11 +1,27 @@
<?php
/**
+ * Implements Special:Listredirects
+ *
+ * Copyright © 2006 Rob Church
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
- *
* @author Rob Church <robchur@gmail.com>
- * @copyright © 2006 Rob Church
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
/**
@@ -49,10 +65,10 @@ class ListredirectsPage extends QueryPage {
$targetLink = $skin->link( $target );
return "$rd_link $arr $targetLink";
} else {
- return "<s>$rd_link</s>";
+ return "<del>$rd_link</del>";
}
} else {
- return "<s>$rd_link</s>";
+ return "<del>$rd_link</del>";
}
}
}
diff --git a/includes/specials/SpecialListusers.php b/includes/specials/SpecialListusers.php
index bdb59980..abc0363a 100644
--- a/includes/specials/SpecialListusers.php
+++ b/includes/specials/SpecialListusers.php
@@ -1,27 +1,26 @@
<?php
-
-# Copyright (C) 2004 Brion Vibber, lcrocker, Tim Starling,
-# Domas Mituzas, Ashar Voultoiz, Jens Frank, Zhengzhu.
-#
-# © 2006 Rob Church <robchur@gmail.com>
-#
-# http://www.mediawiki.org/
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-# http://www.gnu.org/copyleft/gpl.html
/**
+ * Implements Special:Listusers
+ *
+ * Copyright © 2004 Brion Vibber, lcrocker, Tim Starling,
+ * Domas Mituzas, Ashar Voultoiz, Jens Frank, Zhengzhu,
+ * 2006 Rob Church <robchur@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
@@ -120,16 +119,18 @@ 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 = $this->getSkin()->link( $userPage, htmlspecialchars( $userPage->getText() ) );
- if( $row->numgroups > 1 || ( $this->requestedGroup && $row->numgroups == 1 ) ) {
+ $groups_list = self::getGroups( $row->user_id );
+ if( count( $groups_list ) > 0 ) {
$list = array();
- foreach( self::getGroups( $row->user_id ) as $group )
+ foreach( $groups_list as $group )
$list[] = self::buildGroupLink( $group );
$groups = $wgLang->commaList( $list );
- } elseif( $row->numgroups == 1 ) {
- $groups = self::buildGroupLink( $row->singlegroup );
} else {
$groups = '';
}
@@ -166,7 +167,7 @@ class UsersPager extends AlphabeticPager {
}
$this->mResult->rewind();
$batch = new LinkBatch;
- while ( $row = $this->mResult->fetchObject() ) {
+ foreach ( $this->mResult as $row ) {
$batch->addObj( Title::makeTitleSafe( NS_USER, $row->user_name ) );
}
$batch->execute();
@@ -175,13 +176,13 @@ class UsersPager extends AlphabeticPager {
}
function getPageHeader( ) {
- global $wgScript, $wgRequest;
+ global $wgScript;
$self = $this->getTitle();
# Form tag
$out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'id' => 'mw-listusers-form' ) ) .
Xml::fieldset( wfMsg( 'listusers' ) ) .
- Xml::hidden( 'title', $self->getPrefixedDbKey() );
+ Html::hidden( 'title', $self->getPrefixedDbKey() );
# Username field
$out .= Xml::label( wfMsg( 'listusersfrom' ), 'offset' ) . ' ' .
@@ -195,14 +196,14 @@ class UsersPager extends AlphabeticPager {
$out .= Xml::option( $groupText, $group, $group == $this->requestedGroup );
$out .= Xml::closeElement( 'select' ) . '<br />';
$out .= Xml::checkLabel( wfMsg('listusers-editsonly'), 'editsOnly', 'editsOnly', $this->editsOnly );
- $out .= '&nbsp;';
+ $out .= '&#160;';
$out .= Xml::checkLabel( wfMsg('listusers-creationsort'), 'creationSort', 'creationSort', $this->creationSort );
$out .= '<br />';
wfRunHooks( 'SpecialListusersHeaderForm', array( $this, &$out ) );
# Submit button and form bottom
- $out .= Xml::hidden( 'limit', $this->mLimit );
+ $out .= Html::hidden( 'limit', $this->mLimit );
$out .= Xml::submitButton( wfMsg( 'allpagessubmit' ) );
wfRunHooks( 'SpecialListusersHeader', array( $this, &$out ) );
$out .= Xml::closeElement( 'fieldset' ) .
@@ -269,13 +270,13 @@ class UsersPager extends AlphabeticPager {
* $par string (optional) A group to list users from
*/
function wfSpecialListusers( $par = null ) {
- global $wgRequest, $wgOut;
+ global $wgOut;
$up = new UsersPager($par);
# getBody() first to check, if empty
$usersbody = $up->getBody();
- $s = XML::openElement( 'div', array('class' => 'mw-spcontent') );
+ $s = Xml::openElement( 'div', array('class' => 'mw-spcontent') );
$s .= $up->getPageHeader();
if( $usersbody ) {
$s .= $up->getNavigationBar();
@@ -284,6 +285,6 @@ function wfSpecialListusers( $par = null ) {
} else {
$s .= '<p>' . wfMsgHTML('listusers-noresult') . '</p>';
};
- $s .= XML::closeElement( 'div' );
+ $s .= Xml::closeElement( 'div' );
$wgOut->addHTML( $s );
}
diff --git a/includes/specials/SpecialLockdb.php b/includes/specials/SpecialLockdb.php
index 8c701dd6..aad3cea4 100644
--- a/includes/specials/SpecialLockdb.php
+++ b/includes/specials/SpecialLockdb.php
@@ -1,97 +1,108 @@
<?php
/**
+ * Implements Special:Lockdb
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
- * Constructor
+ * A form to make the database readonly (eg for maintenance purposes).
+ *
+ * @ingroup SpecialPage
*/
-function wfSpecialLockdb() {
- global $wgUser, $wgOut, $wgRequest;
+class SpecialLockdb extends SpecialPage {
+ var $reason = '';
- if( !$wgUser->isAllowed( 'siteadmin' ) ) {
- $wgOut->permissionRequired( 'siteadmin' );
- return;
+ public function __construct() {
+ parent::__construct( 'Lockdb', 'siteadmin' );
}
- # If the lock file isn't writable, we can do sweet bugger all
- global $wgReadOnlyFile;
- if( !is_writable( dirname( $wgReadOnlyFile ) ) ) {
- DBLockForm::notWritable();
- return;
- }
+ public function execute( $par ) {
+ global $wgUser, $wgOut, $wgRequest;
- $action = $wgRequest->getVal( 'action' );
- $f = new DBLockForm();
+ $this->setHeaders();
- if ( 'success' == $action ) {
- $f->showSuccess();
- } else if ( 'submit' == $action && $wgRequest->wasPosted() &&
- $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
- $f->doSubmit();
- } else {
- $f->showForm( '' );
- }
-}
+ if( !$wgUser->isAllowed( 'siteadmin' ) ) {
+ $wgOut->permissionRequired( 'siteadmin' );
+ return;
+ }
-/**
- * A form to make the database readonly (eg for maintenance purposes).
- * @ingroup SpecialPage
- */
-class DBLockForm {
- var $reason = '';
+ $this->outputHeader();
- function DBLockForm() {
- global $wgRequest;
- $this->reason = $wgRequest->getText( 'wpLockReason' );
+ # If the lock file isn't writable, we can do sweet bugger all
+ global $wgReadOnlyFile;
+ if( !is_writable( dirname( $wgReadOnlyFile ) ) ) {
+ self::notWritable();
+ return;
+ }
+
+ $action = $wgRequest->getVal( 'action' );
+ $this->reason = $wgRequest->getVal( 'wpLockReason', '' );
+
+ if ( $action == 'success' ) {
+ $this->showSuccess();
+ } else if ( $action == 'submit' && $wgRequest->wasPosted() &&
+ $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
+ $this->doSubmit();
+ } else {
+ $this->showForm();
+ }
}
- function showForm( $err ) {
+ private function showForm( $err = '' ) {
global $wgOut, $wgUser;
- $wgOut->setPagetitle( wfMsg( 'lockdb' ) );
$wgOut->addWikiMsg( 'lockdbtext' );
- if ( $err != "" ) {
+ if ( $err != '' ) {
$wgOut->setSubtitle( wfMsg( 'formerror' ) );
$wgOut->addHTML( '<p class="error">' . htmlspecialchars( $err ) . "</p>\n" );
}
- $lc = htmlspecialchars( wfMsg( 'lockconfirm' ) );
- $lb = htmlspecialchars( wfMsg( 'lockbtn' ) );
- $elr = htmlspecialchars( wfMsg( 'enterlockreason' ) );
- $titleObj = SpecialPage::getTitleFor( 'Lockdb' );
- $action = $titleObj->escapeLocalURL( 'action=submit' );
- $reason = htmlspecialchars( $this->reason );
- $token = htmlspecialchars( $wgUser->editToken() );
-
- $wgOut->addHTML( <<<HTML
-<form id="lockdb" method="post" action="{$action}">
-{$elr}:
-<textarea name="wpLockReason" rows="10" cols="60" wrap="virtual">{$reason}</textarea>
-<table border="0">
+
+ $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 ) ). "
+<table>
<tr>
- <td align="right">
- <input type="checkbox" name="wpLockConfirm" />
+ " . Html::openElement( 'td', array( 'style' => 'text-align:right' ) ) . "
+ " . Html::input( 'wpLockConfirm', null, 'checkbox' ) . "
</td>
- <td align="left">{$lc}</td>
+ " . Html::openElement( 'td', array( 'style' => 'text-align:left' ) ) .
+ wfMsgHtml( 'lockconfirm' ) . "</td>
</tr>
<tr>
- <td>&nbsp;</td>
- <td align="left">
- <input type="submit" name="wpLock" value="{$lb}" />
+ <td>&#160;</td>
+ " . Html::openElement( 'td', array( 'style' => 'text-align:left' ) ) . "
+ " . Html::input( 'wpLock', wfMsg( 'lockbtn' ), 'submit' ) . "
</td>
</tr>
-</table>
-<input type="hidden" name="wpEditToken" value="{$token}" />
-</form>
-HTML
-);
+</table>\n" .
+ Html::hidden( 'wpEditToken', $wgUser->editToken() ) . "\n" .
+ Html::closeElement( 'form' )
+ );
}
- function doSubmit() {
- global $wgOut, $wgUser, $wgLang, $wgRequest;
+ private function doSubmit() {
+ global $wgOut, $wgUser, $wgContLang, $wgRequest;
global $wgReadOnlyFile;
if ( ! $wgRequest->getCheck( 'wpLockConfirm' ) ) {
@@ -109,14 +120,13 @@ HTML
}
fwrite( $fp, $this->reason );
fwrite( $fp, "\n<p>(by " . $wgUser->getName() . " at " .
- $wgLang->timeanddate( wfTimestampNow() ) . ")</p>\n" );
+ $wgContLang->timeanddate( wfTimestampNow() ) . ")</p>\n" );
fclose( $fp );
- $titleObj = SpecialPage::getTitleFor( 'Lockdb' );
- $wgOut->redirect( $titleObj->getFullURL( 'action=success' ) );
+ $wgOut->redirect( $this->getTitle()->getFullURL( 'action=success' ) );
}
- function showSuccess() {
+ private function showSuccess() {
global $wgOut;
$wgOut->setPagetitle( wfMsg( 'lockdb' ) );
diff --git a/includes/specials/SpecialLog.php b/includes/specials/SpecialLog.php
index d1ccc8c4..a2af8de5 100644
--- a/includes/specials/SpecialLog.php
+++ b/includes/specials/SpecialLog.php
@@ -1,86 +1,127 @@
<?php
-# Copyright (C) 2008 Aaron Schulz
-# http://www.mediawiki.org/
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-# http://www.gnu.org/copyleft/gpl.html
-
/**
+ * Implements Special:Log
+ *
+ * Copyright © 2008 Aaron Schulz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
- * constructor
+ * A special page that lists log entries
+ *
+ * @ingroup SpecialPage
*/
-function wfSpecialLog( $par = '' ) {
- global $wgRequest, $wgOut, $wgUser, $wgLogTypes;
-
- # Get parameters
- $parms = explode( '/', ($par = ( $par !== null ) ? $par : '' ) );
- $symsForAll = array( '*', 'all' );
- if ( $parms[0] != '' && ( in_array( $par, $wgLogTypes ) || in_array( $par, $symsForAll ) ) ) {
- $type = $par;
- $user = $wgRequest->getText( 'user' );
- } else if ( count( $parms ) == 2 ) {
- $type = $parms[0];
- $user = $parms[1];
- } else {
- $type = $wgRequest->getVal( 'type' );
- $user = ( $par != '' ) ? $par : $wgRequest->getText( 'user' );
+class SpecialLog extends SpecialPage {
+
+ public function __construct() {
+ parent::__construct( 'Log' );
}
- $title = $wgRequest->getText( 'page' );
- $pattern = $wgRequest->getBool( 'pattern' );
- $y = $wgRequest->getIntOrNull( 'year' );
- $m = $wgRequest->getIntOrNull( 'month' );
- $tagFilter = $wgRequest->getVal( 'tagfilter' );
- # Don't let the user get stuck with a certain date
- $skip = $wgRequest->getText( 'offset' ) || $wgRequest->getText( 'dir' ) == 'prev';
- if( $skip ) {
- $y = '';
- $m = '';
+
+ public function execute( $par ) {
+ global $wgRequest;
+
+ $this->setHeaders();
+ $this->outputHeader();
+
+ $opts = new FormOptions;
+ $opts->add( 'type', '' );
+ $opts->add( 'user', '' );
+ $opts->add( 'page', '' );
+ $opts->add( 'pattern', false );
+ $opts->add( 'year', null, FormOptions::INTNULL );
+ $opts->add( 'month', null, FormOptions::INTNULL );
+ $opts->add( 'tagfilter', '' );
+ $opts->add( 'offset', '' );
+ $opts->add( 'dir', '' );
+ $opts->add( 'offender', '' );
+
+ // Set values
+ $opts->fetchValuesFromRequest( $wgRequest );
+ if ( $par ) {
+ $this->parseParams( $opts, (string)$par );
+ }
+
+ # Don't let the user get stuck with a certain date
+ if ( $opts->getValue( 'offset' ) || $opts->getValue( 'dir' ) == 'prev' ) {
+ $opts->setValue( 'year', '' );
+ $opts->setValue( 'month', '' );
+ }
+
+ # Handle type-specific inputs
+ $qc = array();
+ if ( $opts->getValue( 'type' ) == 'suppress' ) {
+ $offender = User::newFromName( $opts->getValue( 'offender' ), false );
+ if ( $offender && $offender->getId() > 0 ) {
+ $qc = array( 'ls_field' => 'target_author_id', 'ls_value' => $offender->getId() );
+ } elseif ( $offender && IP::isIPAddress( $offender->getName() ) ) {
+ $qc = array( 'ls_field' => 'target_author_ip', 'ls_value' => $offender->getName() );
+ }
+ }
+
+ $this->show( $opts, $qc );
}
- # Handle type-specific inputs
- $qc = array();
- if( $type == 'suppress' ) {
- $offender = User::newFromName( $wgRequest->getVal('offender'), false );
- if( $offender && $offender->getId() > 0 ) {
- $qc = array( 'ls_field' => 'target_author_id', 'ls_value' => $offender->getId() );
- } else if( $offender && IP::isIPAddress( $offender->getName() ) ) {
- $qc = array( 'ls_field' => 'target_author_ip', 'ls_value' => $offender->getName() );
+
+ private function parseParams( FormOptions $opts, $par ) {
+ global $wgLogTypes;
+
+ # Get parameters
+ $parms = explode( '/', ($par = ( $par !== null ) ? $par : '' ) );
+ $symsForAll = array( '*', 'all' );
+ if ( $parms[0] != '' && ( in_array( $par, $wgLogTypes ) || in_array( $par, $symsForAll ) ) ) {
+ $opts->setValue( 'type', $par );
+ } elseif ( count( $parms ) == 2 ) {
+ $opts->setValue( 'type', $parms[0] );
+ $opts->setValue( 'user', $parms[1] );
+ } elseif ( $par != '' ) {
+ $opts->setValue( 'user', $par );
}
}
- # Create a LogPager item to get the results and a LogEventsList item to format them...
- $loglist = new LogEventsList( $wgUser->getSkin(), $wgOut, 0 );
- $pager = new LogPager( $loglist, $type, $user, $title, $pattern, $qc, $y, $m, $tagFilter );
- # Set title and add header
- $loglist->showHeader( $pager->getType() );
- # Show form options
- $loglist->showOptions( $pager->getType(), $pager->getUser(), $pager->getPage(), $pager->getPattern(),
- $pager->getYear(), $pager->getMonth(), $pager->getFilterParams(), $tagFilter );
- # Insert list
- $logBody = $pager->getBody();
- if( $logBody ) {
- $wgOut->addHTML(
- $pager->getNavigationBar() .
- $loglist->beginLogEventsList() .
- $logBody .
- $loglist->endLogEventsList() .
- $pager->getNavigationBar()
- );
- } else {
- $wgOut->addWikiMsg( 'logempty' );
+
+ private function show( FormOptions $opts, array $extraConds ) {
+ global $wgOut, $wgUser;
+
+ # Create a LogPager item to get the results and a LogEventsList item to format them...
+ $loglist = new LogEventsList( $wgUser->getSkin(), $wgOut, 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() );
+
+ # Show form options
+ $loglist->showOptions( $pager->getType(), $pager->getUser(), $pager->getPage(), $pager->getPattern(),
+ $pager->getYear(), $pager->getMonth(), $pager->getFilterParams(), $opts->getValue( 'tagfilter' ) );
+
+ # Insert list
+ $logBody = $pager->getBody();
+ if ( $logBody ) {
+ $wgOut->addHTML(
+ $pager->getNavigationBar() .
+ $loglist->beginLogEventsList() .
+ $logBody .
+ $loglist->endLogEventsList() .
+ $pager->getNavigationBar()
+ );
+ } else {
+ $wgOut->addWikiMsg( 'logempty' );
+ }
}
}
diff --git a/includes/specials/SpecialLonelypages.php b/includes/specials/SpecialLonelypages.php
index 90da25fd..0788037f 100644
--- a/includes/specials/SpecialLonelypages.php
+++ b/includes/specials/SpecialLonelypages.php
@@ -1,5 +1,22 @@
<?php
/**
+ * Implements Special:Lonelypaages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
@@ -7,6 +24,7 @@
/**
* A special page looking for articles with no article linking to them,
* thus being lonely.
+ *
* @ingroup SpecialPage
*/
class LonelyPagesPage extends PageQueryPage {
diff --git a/includes/specials/SpecialLongpages.php b/includes/specials/SpecialLongpages.php
index be16a029..cd0f3090 100644
--- a/includes/specials/SpecialLongpages.php
+++ b/includes/specials/SpecialLongpages.php
@@ -1,5 +1,22 @@
<?php
/**
+ * Implements Special:Longpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
diff --git a/includes/specials/SpecialMIMEsearch.php b/includes/specials/SpecialMIMEsearch.php
index dafe003e..79683a35 100644
--- a/includes/specials/SpecialMIMEsearch.php
+++ b/includes/specials/SpecialMIMEsearch.php
@@ -1,13 +1,25 @@
<?php
/**
- * A special page to search for files by MIME type as defined in the
- * img_major_mime and img_minor_mime fields in the image table
+ * Implements Special:MIMESearch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup SpecialPage
- *
* @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
/**
@@ -18,7 +30,7 @@
class MIMEsearchPage extends QueryPage {
var $major, $minor;
- function MIMEsearchPage( $major, $minor ) {
+ function __construct( $major, $minor ) {
$this->major = $major;
$this->minor = $minor;
}
@@ -95,7 +107,7 @@ function wfSpecialMIMEsearch( $par = null ) {
$wgOut->addHTML(
Xml::openElement( 'form', array( 'id' => 'specialmimesearch', 'method' => 'get', 'action' => SpecialPage::getTitleFor( 'MIMEsearch' )->getLocalUrl() ) ) .
Xml::openElement( 'fieldset' ) .
- Xml::hidden( 'title', SpecialPage::getTitleFor( 'MIMEsearch' )->getPrefixedText() ) .
+ Html::hidden( 'title', SpecialPage::getTitleFor( 'MIMEsearch' )->getPrefixedText() ) .
Xml::element( 'legend', null, wfMsg( 'mimesearch' ) ) .
Xml::inputLabel( wfMsg( 'mimetype' ), 'mime', 'mime', 20, $mime ) . ' ' .
Xml::submitButton( wfMsg( 'ilsubmit' ) ) .
diff --git a/includes/specials/SpecialMergeHistory.php b/includes/specials/SpecialMergeHistory.php
index 1b4ef30c..43b4ef6a 100644
--- a/includes/specials/SpecialMergeHistory.php
+++ b/includes/specials/SpecialMergeHistory.php
@@ -1,34 +1,42 @@
<?php
/**
- * Special page allowing users with the appropriate permissions to
- * merge article histories, with some restrictions
+ * Implements Special:MergeHistory
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup SpecialPage
*/
/**
- * Constructor
- */
-function wfSpecialMergehistory( $par ) {
- global $wgRequest;
-
- $form = new MergehistoryForm( $wgRequest, $par );
- $form->execute();
-}
-
-/**
- * The HTML form for Special:MergeHistory, which allows users with the appropriate
- * permissions to view and restore deleted content.
+ * Special page allowing users with the appropriate permissions to
+ * merge article histories, with some restrictions
+ *
* @ingroup SpecialPage
*/
-class MergehistoryForm {
+class SpecialMergeHistory extends SpecialPage {
var $mAction, $mTarget, $mDest, $mTimestamp, $mTargetID, $mDestID, $mComment;
var $mTargetObj, $mDestObj;
- function MergehistoryForm( $request, $par = "" ) {
- global $wgUser;
+ public function __construct() {
+ parent::__construct( 'MergeHistory', 'mergehistory' );
+ }
+ private function loadRequestParams( $request ) {
+ global $wgUser;
$this->mAction = $request->getVal( 'action' );
$this->mTarget = $request->getVal( 'target' );
$this->mDest = $request->getVal( 'dest' );
@@ -51,7 +59,6 @@ class MergehistoryForm {
$this->mTargetObj = null;
$this->mDestObj = null;
}
-
$this->preCacheMessages();
}
@@ -62,14 +69,27 @@ class MergehistoryForm {
function preCacheMessages() {
// Precache various messages
if( !isset( $this->message ) ) {
- $this->message['last'] = wfMsgExt( 'last', array( 'escape') );
+ $this->message['last'] = wfMsgExt( 'last', array( 'escape' ) );
}
}
- function execute() {
- global $wgOut;
+ function execute( $par ) {
+ global $wgOut, $wgRequest, $wgUser;
+
+ if ( wfReadOnly() ) {
+ $wgOut->readOnlyPage();
+ return;
+ }
+
+ if( !$this->userCanExecute( $wgUser ) ) {
+ $this->displayRestrictionError();
+ return;
+ }
+
+ $this->loadRequestParams( $wgRequest );
- $wgOut->setPagetitle( wfMsgHtml( "mergehistory" ) );
+ $this->setHeaders();
+ $this->outputHeader();
if( $this->mTargetID && $this->mDestID && $this->mAction=="submit" && $this->mMerge ) {
return $this->merge();
@@ -122,10 +142,9 @@ class MergehistoryForm {
'<fieldset>' .
Xml::element( 'legend', array(),
wfMsg( 'mergehistory-box' ) ) .
- Xml::hidden( 'title',
- SpecialPage::getTitleFor( 'Mergehistory' )->getPrefixedDbKey() ) .
- Xml::hidden( 'submitted', '1' ) .
- Xml::hidden( 'mergepoint', $this->mTimestamp ) .
+ Html::hidden( 'title', $this->getTitle()->getPrefixedDbKey() ) .
+ Html::hidden( 'submitted', '1' ) .
+ Html::hidden( 'mergepoint', $this->mTimestamp ) .
Xml::openElement( 'table' ) .
"<tr>
<td>".Xml::label( wfMsg( 'mergehistory-from' ), 'target' )."</td>
@@ -142,7 +161,7 @@ class MergehistoryForm {
}
private function showHistory() {
- global $wgLang, $wgUser, $wgOut;
+ global $wgUser, $wgOut;
$this->sk = $wgUser->getSkin();
@@ -154,7 +173,7 @@ class MergehistoryForm {
$revisions = new MergeHistoryPager( $this, array(), $this->mTargetObj, $this->mDestObj );
$haveRevisions = $revisions && $revisions->getNumRows() > 0;
- $titleObj = SpecialPage::getTitleFor( "Mergehistory" );
+ $titleObj = $this->getTitle();
$action = $titleObj->getLocalURL( array( 'action' => 'submit' ) );
# Start the form here
$top = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $action, 'id' => 'merge' ) );
@@ -177,7 +196,7 @@ class MergehistoryForm {
"</td>
</tr>
<tr>
- <td>&nbsp;</td>
+ <td>&#160;</td>
<td class='mw-submit'>" .
Xml::submitButton( wfMsg( 'mergehistory-submit' ), array( 'name' => 'merge', 'id' => 'mw-merge-submit' ) ) .
"</td>
@@ -206,11 +225,11 @@ class MergehistoryForm {
# 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
- $misc = Xml::hidden( 'targetID', $this->mTargetObj->getArticleID() );
- $misc .= Xml::hidden( 'destID', $this->mDestObj->getArticleID() );
- $misc .= Xml::hidden( 'target', $this->mTarget );
- $misc .= Xml::hidden( 'dest', $this->mDest );
- $misc .= Xml::hidden( 'wpEditToken', $wgUser->editToken() );
+ $misc = Html::hidden( 'targetID', $this->mTargetObj->getArticleID() );
+ $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 .= Xml::closeElement( 'form' );
$wgOut->addHTML( $misc );
@@ -419,7 +438,7 @@ class MergeHistoryPager extends ReverseChronologicalPager {
$batch = new LinkBatch();
# Give some pointers to make (last) links
$this->mForm->prevId = array();
- while( $row = $this->mResult->fetchObject() ) {
+ 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 ) );
@@ -440,7 +459,6 @@ class MergeHistoryPager extends ReverseChronologicalPager {
}
function formatRow( $row ) {
- $block = new Block;
return $this->mForm->formatRevisionRow( $row );
}
diff --git a/includes/specials/SpecialMostcategories.php b/includes/specials/SpecialMostcategories.php
index 1ba05626..124f0bd5 100644
--- a/includes/specials/SpecialMostcategories.php
+++ b/includes/specials/SpecialMostcategories.php
@@ -1,15 +1,32 @@
<?php
/**
+ * Implements Special:Mostcategories
+ *
+ * Copyright © 2005 Ævar Arnfjörð Bjarmason
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
- *
* @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
/**
- * implements Special:Mostcategories
+ * A special page that list pages that have highest category count
+ *
* @ingroup SpecialPage
*/
class MostcategoriesPage extends QueryPage {
diff --git a/includes/specials/SpecialMostimages.php b/includes/specials/SpecialMostimages.php
index 5cc100ba..411a281b 100644
--- a/includes/specials/SpecialMostimages.php
+++ b/includes/specials/SpecialMostimages.php
@@ -1,15 +1,32 @@
<?php
/**
+ * Implements Special:Mostimages
+ *
+ * Copyright © 2005 Ævar Arnfjörð Bjarmason
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
- *
* @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
/**
- * implements Special:Mostimages
+ * A special page page that list most used images
+ *
* @ingroup SpecialPage
*/
class MostimagesPage extends ImageQueryPage {
@@ -36,7 +53,7 @@ class MostimagesPage extends ImageQueryPage {
function getCellHtml( $row ) {
global $wgLang;
- return wfMsgExt( 'nlinks', array( 'parsemag', 'escape' ),
+ return wfMsgExt( 'nimagelinks', array( 'parsemag', 'escape' ),
$wgLang->formatNum( $row->value ) ) . '<br />';
}
diff --git a/includes/specials/SpecialMostlinked.php b/includes/specials/SpecialMostlinked.php
index f112ae17..c731588a 100644
--- a/includes/specials/SpecialMostlinked.php
+++ b/includes/specials/SpecialMostlinked.php
@@ -1,20 +1,34 @@
<?php
/**
+ * Implements Special:Mostlinked
+ *
+ * Copyright © 2005 Ævar Arnfjörð Bjarmason, 2006 Rob Church
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
+ * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ * @author Rob Church <robchur@gmail.com>
*/
/**
* A special page to show pages ordered by the number of pages linking to them.
- * Implements Special:Mostlinked
*
* @ingroup SpecialPage
- *
- * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * @author Rob Church <robchur@gmail.com>
- * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
- * @copyright © 2006 Rob Church
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
class MostlinkedPage extends QueryPage {
@@ -59,8 +73,9 @@ class MostlinkedPage extends QueryPage {
function preprocessResults( $db, $res ) {
if( $db->numRows( $res ) > 0 ) {
$linkBatch = new LinkBatch();
- while( $row = $db->fetchObject( $res ) )
+ foreach ( $res as $row ) {
$linkBatch->add( $row->namespace, $row->title );
+ }
$db->dataSeek( $res, 0 );
$linkBatch->execute();
}
diff --git a/includes/specials/SpecialMostlinkedcategories.php b/includes/specials/SpecialMostlinkedcategories.php
index 20a35c97..e1fc1d95 100644
--- a/includes/specials/SpecialMostlinkedcategories.php
+++ b/includes/specials/SpecialMostlinkedcategories.php
@@ -1,17 +1,33 @@
<?php
/**
+ * Implements Special:Mostlinkedcategories
+ *
+ * Copyright © 2005, Ævar Arnfjörð Bjarmason
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
+ * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
*/
/**
* A querypage to show categories ordered in descending order by the pages in them
*
* @ingroup SpecialPage
- *
- * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
class MostlinkedCategoriesPage extends QueryPage {
@@ -42,8 +58,9 @@ class MostlinkedCategoriesPage extends QueryPage {
*/
function preprocessResults( $db, $res ) {
$batch = new LinkBatch;
- while ( $row = $db->fetchObject( $res ) )
+ foreach ( $res as $row ) {
$batch->add( $row->namespace, $row->title );
+ }
$batch->execute();
// Back to start for display
diff --git a/includes/specials/SpecialMostlinkedtemplates.php b/includes/specials/SpecialMostlinkedtemplates.php
index 71a6b539..822d6bc9 100644
--- a/includes/specials/SpecialMostlinkedtemplates.php
+++ b/includes/specials/SpecialMostlinkedtemplates.php
@@ -1,7 +1,25 @@
<?php
/**
+ * Implements Special:Mostlinkedtemplates
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
+ * @author Rob Church <robchur@gmail.com>
*/
/**
@@ -9,7 +27,6 @@
* transclusion links, i.e. "most used" templates
*
* @ingroup SpecialPage
- * @author Rob Church <robchur@gmail.com>
*/
class SpecialMostlinkedtemplates extends QueryPage {
@@ -75,7 +92,7 @@ class SpecialMostlinkedtemplates extends QueryPage {
*/
public function preprocessResults( $db, $res ) {
$batch = new LinkBatch();
- while( $row = $db->fetchObject( $res ) ) {
+ foreach ( $res as $row ) {
$batch->add( $row->namespace, $row->title );
}
$batch->execute();
@@ -110,8 +127,8 @@ class SpecialMostlinkedtemplates extends QueryPage {
private function makeWlhLink( $title, $skin, $result ) {
global $wgLang;
$wlh = SpecialPage::getTitleFor( 'Whatlinkshere' );
- $label = wfMsgExt( 'nlinks', array( 'parsemag', 'escape' ),
- $wgLang->formatNum( $result->value ) );
+ $label = wfMsgExt( 'ntransclusions', array( 'parsemag', 'escape' ),
+ $wgLang->formatNum( $result->value ) );
return $skin->link( $wlh, $label, array(), array( 'target' => $title->getPrefixedText() ) );
}
}
diff --git a/includes/specials/SpecialMostrevisions.php b/includes/specials/SpecialMostrevisions.php
index 414e8d97..f9bafabc 100644
--- a/includes/specials/SpecialMostrevisions.php
+++ b/includes/specials/SpecialMostrevisions.php
@@ -1,15 +1,32 @@
<?php
/**
- * A special page to show pages in the
+ * Implements Special:Mostrevisions
*
- * @ingroup SpecialPage
+ * Copyright © 2005 Ævar Arnfjörð Bjarmason
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
* @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
/**
+ * A special page to show pages with highest revision count
+ *
* @ingroup SpecialPage
*/
class MostrevisionsPage extends QueryPage {
diff --git a/includes/specials/SpecialMovepage.php b/includes/specials/SpecialMovepage.php
index 02197b19..2f156c65 100644
--- a/includes/specials/SpecialMovepage.php
+++ b/includes/specials/SpecialMovepage.php
@@ -1,93 +1,104 @@
<?php
/**
+ * Implements Special:Movepage
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
- * Constructor
+ * A special page that allows users to change page titles
+ *
+ * @ingroup SpecialPage
*/
-function wfSpecialMovepage( $par = null ) {
- global $wgUser, $wgOut, $wgRequest, $action;
+class MovePageForm extends UnlistedSpecialPage {
+ var $oldTitle, $newTitle; # Objects
+ var $reason; # Text input
+ var $moveTalk, $deleteAndMove, $moveSubpages, $fixRedirects, $leaveRedirect, $moveOverShared; # Checks
- # Check for database lock
- if ( wfReadOnly() ) {
- $wgOut->readOnlyPage();
- return;
+ private $watch = false;
+
+ public function __construct() {
+ parent::__construct( 'Movepage' );
}
- $target = isset( $par ) ? $par : $wgRequest->getVal( 'target' );
+ public function execute( $par ) {
+ global $wgUser, $wgOut, $wgRequest;
- // Yes, the use of getVal() and getText() is wanted, see bug 20365
- $oldTitleText = $wgRequest->getVal( 'wpOldTitle', $target );
- $newTitleText = $wgRequest->getText( 'wpNewTitle' );
+ # Check for database lock
+ if ( wfReadOnly() ) {
+ $wgOut->readOnlyPage();
+ return;
+ }
- $oldTitle = Title::newFromText( $oldTitleText );
- $newTitle = Title::newFromText( $newTitleText );
+ $this->setHeaders();
+ $this->outputHeader();
- if( is_null( $oldTitle ) ) {
- $wgOut->showErrorPage( 'notargettitle', 'notargettext' );
- return;
- }
- if( !$oldTitle->exists() ) {
- $wgOut->showErrorPage( 'nopagetitle', 'nopagetext' );
- return;
- }
+ $target = !is_null( $par ) ? $par : $wgRequest->getVal( 'target' );
- # Check rights
- $permErrors = $oldTitle->getUserPermissionsErrors( 'move', $wgUser );
- if( !empty( $permErrors ) ) {
- $wgOut->showPermissionsErrorPage( $permErrors );
- return;
- }
+ // Yes, the use of getVal() and getText() is wanted, see bug 20365
+ $oldTitleText = $wgRequest->getVal( 'wpOldTitle', $target );
+ $newTitleText = $wgRequest->getText( 'wpNewTitle' );
- $form = new MovePageForm( $oldTitle, $newTitle );
+ $this->oldTitle = Title::newFromText( $oldTitleText );
+ $this->newTitle = Title::newFromText( $newTitleText );
- if ( 'submit' == $action && $wgRequest->wasPosted()
- && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
- $form->doSubmit();
- } else {
- $form->showForm( '' );
- }
-}
+ if( is_null( $this->oldTitle ) ) {
+ $wgOut->showErrorPage( 'notargettitle', 'notargettext' );
+ return;
+ }
+ if( !$this->oldTitle->exists() ) {
+ $wgOut->showErrorPage( 'nopagetitle', 'nopagetext' );
+ return;
+ }
-/**
- * HTML form for Special:Movepage
- * @ingroup SpecialPage
- */
-class MovePageForm {
- var $oldTitle, $newTitle; # Objects
- var $reason; # Text input
- var $moveTalk, $deleteAndMove, $moveSubpages, $fixRedirects, $leaveRedirect, $moveOverShared; # Checks
+ # Check rights
+ $permErrors = $this->oldTitle->getUserPermissionsErrors( 'move', $wgUser );
+ if( !empty( $permErrors ) ) {
+ $wgOut->showPermissionsErrorPage( $permErrors );
+ return;
+ }
- private $watch = false;
+ $def = !$wgRequest->wasPosted();
- function __construct( $oldTitle, $newTitle ) {
- global $wgRequest, $wgUser;
- $target = isset($par) ? $par : $wgRequest->getVal( 'target' );
- $this->oldTitle = $oldTitle;
- $this->newTitle = $newTitle;
$this->reason = $wgRequest->getText( 'wpReason' );
- if ( $wgRequest->wasPosted() ) {
- $this->moveTalk = $wgRequest->getBool( 'wpMovetalk', false );
- $this->fixRedirects = $wgRequest->getBool( 'wpFixRedirects', false );
- $this->leaveRedirect = $wgRequest->getBool( 'wpLeaveRedirect', false );
- } else {
- $this->moveTalk = $wgRequest->getBool( 'wpMovetalk', true );
- $this->fixRedirects = $wgRequest->getBool( 'wpFixRedirects', true );
- $this->leaveRedirect = $wgRequest->getBool( 'wpLeaveRedirect', true );
- }
+ $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();
+
+ if ( 'submit' == $wgRequest->getVal( 'action' ) && $wgRequest->wasPosted()
+ && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
+ $this->doSubmit();
+ } else {
+ $this->showForm( '' );
+ }
}
/**
* Show the form
- * @param mixed $err Error message. May either be a string message name or
- * array message name and parameters, like the second argument to
- * OutputPage::wrapWikiMsg().
+ *
+ * @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().
*/
function showForm( $err ) {
global $wgOut, $wgUser, $wgContLang, $wgFixDoubleRedirects;
@@ -134,7 +145,8 @@ class MovePageForm {
if ($this->oldTitle->getNamespace() == NS_USER && !$this->oldTitle->isSubpage() ) {
$wgOut->wrapWikiMsg( "<div class=\"error mw-moveuserpage-warning\">\n$1\n</div>", 'moveuserpage-warning' );
}
- $wgOut->addWikiMsg( 'movepagetext' );
+ $wgOut->addWikiMsg( $wgFixDoubleRedirects ? 'movepagetext' :
+ 'movepagetext-noredirectfixer' );
$movepagebtn = wfMsg( 'movepagebtn' );
$submitVar = 'wpMove';
$confirm = false;
@@ -145,14 +157,14 @@ class MovePageForm {
$submitVar = 'wpMoveOverSharedFile';
$err = '';
}
-
+
$oldTalk = $this->oldTitle->getTalkPage();
$considerTalk = ( !$this->oldTitle->isTalkPage() && $oldTalk->exists() );
$dbr = wfGetDB( DB_SLAVE );
if ( $wgFixDoubleRedirects ) {
- $hasRedirects = $dbr->selectField( 'redirect', '1',
- array(
+ $hasRedirects = $dbr->selectField( 'redirect', '1',
+ array(
'rd_namespace' => $this->oldTitle->getNamespace(),
'rd_title' => $this->oldTitle->getDBkey(),
) , __METHOD__ );
@@ -164,7 +176,6 @@ class MovePageForm {
$wgOut->addWikiMsg( 'movepagetalktext' );
}
- $titleObj = SpecialPage::getTitleFor( 'Movepage' );
$token = htmlspecialchars( $wgUser->editToken() );
if ( !empty($err) ) {
@@ -174,7 +185,7 @@ class MovePageForm {
$errMsg = "<p><strong class=\"error\">$hookErr</strong></p>\n";
$wgOut->addHTML( $errMsg );
} else {
- $wgOut->wrapWikiMsg( '<p><strong class="error">$1</strong></p>', $err );
+ $wgOut->wrapWikiMsg( "<p><strong class=\"error\">\n$1\n</strong></p>", $err );
}
}
@@ -195,7 +206,7 @@ class MovePageForm {
}
$wgOut->addHTML(
- Xml::openElement( 'form', array( 'method' => 'post', 'action' => $titleObj->getLocalURL( 'action=submit' ), 'id' => 'movepage' ) ) .
+ Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalURL( 'action=submit' ), 'id' => 'movepage' ) ) .
Xml::openElement( 'fieldset' ) .
Xml::element( 'legend', null, wfMsg( 'move-page-legend' ) ) .
Xml::openElement( 'table', array( 'border' => '0', 'id' => 'mw-movepage-table' ) ) .
@@ -213,7 +224,7 @@ class MovePageForm {
"</td>
<td class='mw-input'>" .
Xml::input( 'wpNewTitle', 40, $wgContLang->recodeForEdit( $newTitle->getPrefixedText() ), array( 'type' => 'text', 'id' => 'wpNewTitle' ) ) .
- Xml::hidden( 'wpOldTitle', $this->oldTitle->getPrefixedText() ) .
+ Html::hidden( 'wpOldTitle', $this->oldTitle->getPrefixedText() ) .
"</td>
</tr>
<tr>
@@ -243,7 +254,7 @@ class MovePageForm {
<tr>
<td></td>
<td class='mw-input' >" .
- Xml::checkLabel( wfMsg( 'move-leave-redirect' ), 'wpLeaveRedirect',
+ Xml::checkLabel( wfMsg( 'move-leave-redirect' ), 'wpLeaveRedirect',
'wpLeaveRedirect', $this->leaveRedirect ) .
"</td>
</tr>"
@@ -255,7 +266,7 @@ class MovePageForm {
<tr>
<td></td>
<td class='mw-input' >" .
- Xml::checkLabel( wfMsg( 'fix-double-redirects' ), 'wpFixRedirects',
+ Xml::checkLabel( wfMsg( 'fix-double-redirects' ), 'wpFixRedirects',
'wpFixRedirects', $this->fixRedirects ) .
"</td>
</tr>"
@@ -277,7 +288,7 @@ class MovePageForm {
# move and we aren't moving the talk page.
$this->moveSubpages && ($this->oldTitle->hasSubpages() || $this->moveTalk),
array( 'id' => 'wpMovesubpages' )
- ) . '&nbsp;' .
+ ) . '&#160;' .
Xml::tags( 'label', array( 'for' => 'wpMovesubpages' ),
wfMsgExt(
( $this->oldTitle->hasSubpages()
@@ -294,7 +305,7 @@ class MovePageForm {
);
}
- $watchChecked = $wgUser->isLoggedIn() && ($this->watch || $wgUser->getBoolOption( 'watchmoves' )
+ $watchChecked = $wgUser->isLoggedIn() && ($this->watch || $wgUser->getBoolOption( 'watchmoves' )
|| $this->oldTitle->userIsWatching());
# Don't allow watching if user is not logged in
if( $wgUser->isLoggedIn() ) {
@@ -307,16 +318,16 @@ class MovePageForm {
</tr>");
}
- $wgOut->addHTML( "
+ $wgOut->addHTML( "
{$confirm}
<tr>
- <td>&nbsp;</td>
+ <td>&#160;</td>
<td class='mw-submit'>" .
Xml::submitButton( $movepagebtn, array( 'name' => $submitVar ) ) .
"</td>
</tr>" .
Xml::closeElement( 'table' ) .
- Xml::hidden( 'wpEditToken', $token ) .
+ Html::hidden( 'wpEditToken', $token ) .
Xml::closeElement( 'fieldset' ) .
Xml::closeElement( 'form' ) .
"\n"
@@ -328,7 +339,7 @@ class MovePageForm {
}
function doSubmit() {
- global $wgOut, $wgUser, $wgRequest, $wgMaximumMovedPages, $wgLang;
+ global $wgOut, $wgUser, $wgMaximumMovedPages, $wgLang;
global $wgFixDoubleRedirects;
if ( $wgUser->pingLimiter( 'move' ) ) {
@@ -346,7 +357,7 @@ class MovePageForm {
# Disallow deletions of big articles
$bigHistory = $article->isBigDeletion();
if( $bigHistory && !$nt->userCan( 'bigdelete' ) ) {
- global $wgLang, $wgDeleteRevisionsLimit;
+ global $wgDeleteRevisionsLimit;
$this->showForm( array('delete-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) );
return;
}
@@ -368,16 +379,16 @@ class MovePageForm {
}
# Show a warning if the target file exists on a shared repo
- if ( $nt->getNamespace() == NS_FILE
+ if ( $nt->getNamespace() == NS_FILE
&& !( $this->moveOverShared && $wgUser->isAllowed( 'reupload-shared' ) )
- && !RepoGroup::singleton()->getLocalRepo()->findFile( $nt )
+ && !RepoGroup::singleton()->getLocalRepo()->findFile( $nt )
&& wfFindFile( $nt ) )
{
$this->showForm( array('file-exists-sharedrepo') );
return;
-
+
}
-
+
if ( $wgUser->isAllowed( 'suppressredirect' ) ) {
$createRedirect = $this->leaveRedirect;
} else {
@@ -433,7 +444,7 @@ class MovePageForm {
# would mean that you couldn't move them back in one operation, which
# is bad. FIXME: A specific error message should be given in this
# case.
-
+
// FIXME: Use Title::moveSubpages() here
$dbr = wfGetDB( DB_MASTER );
if( $this->moveSubpages && (
@@ -547,8 +558,8 @@ class MovePageForm {
$wgUser->removeWatch( $ot );
$wgUser->removeWatch( $nt );
}
-
- # Re-clear the file redirect cache, which may have been polluted by
+
+ # Re-clear the file redirect cache, which may have been polluted by
# parsing in messages above. See CR r56745.
# FIXME: needs a more robust solution inside FileRepo.
if( $ot->getNamespace() == NS_FILE ) {
diff --git a/includes/specials/SpecialNewimages.php b/includes/specials/SpecialNewimages.php
index a39b56ee..cecd7dfd 100644
--- a/includes/specials/SpecialNewimages.php
+++ b/includes/specials/SpecialNewimages.php
@@ -1,10 +1,29 @@
<?php
/**
+ * Implements Special:Newimages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
- * FIXME: this code is crap, should use Pager and Database::select().
*/
+/**
+ * @todo FIXME: this code is crap, should use Pager and Database::select().
+ */
function wfSpecialNewimages( $par, $specialPage ) {
global $wgUser, $wgOut, $wgLang, $wgRequest, $wgMiserMode;
@@ -49,16 +68,14 @@ function wfSpecialNewimages( $par, $specialPage ) {
} else {
$ts = false;
}
- $dbr->freeResult( $res );
- $sql = '';
# If we were clever, we'd use this to cache.
$latestTimestamp = wfTimestamp( TS_MW, $ts );
# Hardcode this for now.
$limit = 48;
-
- if ( $parval = intval( $par ) ) {
+ $parval = intval( $par );
+ if ( $parval ) {
if ( $parval <= $limit && $parval > 0 ) {
$limit = $parval;
}
@@ -75,14 +92,16 @@ function wfSpecialNewimages( $par, $specialPage ) {
}
$invertSort = false;
- if( $until = $wgRequest->getVal( 'until' ) ) {
+ $until = $wgRequest->getVal( 'until' );
+ if( $until ) {
$where[] = "img_timestamp < '" . $dbr->timestamp( $until ) . "'";
}
- if( $from = $wgRequest->getVal( 'from' ) ) {
+ $from = $wgRequest->getVal( 'from' );
+ if( $from ) {
$where[] = "img_timestamp >= '" . $dbr->timestamp( $from ) . "'";
$invertSort = true;
}
- $sql='SELECT img_size, img_name, img_user, img_user_text,'.
+ $sql = 'SELECT img_size, img_name, img_user, img_user_text,'.
"img_description,img_timestamp FROM $image";
if( $hidebotsql ) {
@@ -100,14 +119,13 @@ function wfSpecialNewimages( $par, $specialPage ) {
* We have to flip things around to get the last N after a certain date
*/
$images = array();
- while ( $s = $dbr->fetchObject( $res ) ) {
+ foreach ( $res as $s ) {
if( $invertSort ) {
array_unshift( $images, $s );
} else {
array_push( $images, $s );
}
}
- $dbr->freeResult( $res );
$gallery = new ImageGallery();
$firstTimestamp = null;
@@ -214,9 +232,9 @@ function wfSpecialNewimages( $par, $specialPage ) {
}
$nextLink = wfMsgExt( 'pager-older-n', $opts, $wgLang->formatNum( $limit ) );
- if( $shownImages > $limit && $lastTimestamp ) {
+ if( $invertSort || ( $shownImages > $limit && $lastTimestamp ) ) {
$query = array_merge(
- array( 'until' => $lastTimestamp ),
+ array( 'until' => ( $lastTimestamp ? $lastTimestamp : "" ) ),
$botpar,
$searchpar
);
diff --git a/includes/specials/SpecialNewpages.php b/includes/specials/SpecialNewpages.php
index 903ddab0..3235436a 100644
--- a/includes/specials/SpecialNewpages.php
+++ b/includes/specials/SpecialNewpages.php
@@ -1,10 +1,32 @@
<?php
+/**
+ * Implements Special:Newpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
/**
- * implements Special:Newpages
+ * A special page that list newly created pages
+ *
* @ingroup SpecialPage
*/
-class SpecialNewpages extends SpecialPage {
+class SpecialNewpages extends IncludableSpecialPage {
// Stored objects
protected $opts, $skin;
@@ -14,7 +36,6 @@ class SpecialNewpages extends SpecialPage {
public function __construct() {
parent::__construct( 'Newpages' );
- $this->includable( true );
}
protected function setup( $par ) {
@@ -85,11 +106,11 @@ class SpecialNewpages extends SpecialPage {
/**
* Show a form for filtering namespace and username
*
- * @param string $par
- * @return string
+ * @param $par String
+ * @return String
*/
public function execute( $par ) {
- global $wgLang, $wgOut;
+ global $wgOut;
$this->setHeaders();
$this->outputHeader();
@@ -136,6 +157,7 @@ class SpecialNewpages extends SpecialPage {
);
// Disable some if needed
+ # FIXME: throws E_NOTICEs if not set; and doesn't obey hooks etc
if ( $wgGroupPermissions['*']['createpage'] !== true )
unset($filters['hideliu']);
@@ -174,7 +196,7 @@ class SpecialNewpages extends SpecialPage {
// Store query values in hidden fields so that form submission doesn't lose them
$hidden = array();
foreach ( $this->opts->getUnconsumedValues() as $key => $value ) {
- $hidden[] = Xml::hidden( $key, $value );
+ $hidden[] = Html::hidden( $key, $value );
}
$hidden = implode( "\n", $hidden );
@@ -183,7 +205,7 @@ class SpecialNewpages extends SpecialPage {
list( $tagFilterLabel, $tagFilterSelector ) = $tagFilter;
$form = Xml::openElement( 'form', array( 'action' => $wgScript ) ) .
- Xml::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) .
+ Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) .
Xml::fieldset( wfMsg( 'newpages' ) ) .
Xml::openElement( 'table', array( 'id' => 'mw-newpages-table' ) ) .
"<tr>
@@ -239,9 +261,8 @@ class SpecialNewpages extends SpecialPage {
/**
* Format a row, providing the timestamp, links to the page/history, size, user links, and a comment
*
- * @param $skin Skin to use
* @param $result Result row
- * @return string
+ * @return String
*/
public function formatRow( $result ) {
global $wgLang, $wgContLang;
@@ -251,7 +272,9 @@ class SpecialNewpages extends SpecialPage {
$dm = $wgContLang->getDirMark();
$title = Title::makeTitleSafe( $result->rc_namespace, $result->rc_title );
- $time = htmlspecialchars( $wgLang->timeAndDate( $result->rc_timestamp, true ) );
+ $time = Html::element( 'span', array( 'class' => 'mw-newpages-time' ),
+ $wgLang->timeAndDate( $result->rc_timestamp, true )
+ );
$query = array( 'redirect' => 'no' );
@@ -261,38 +284,53 @@ class SpecialNewpages extends SpecialPage {
$plink = $this->skin->linkKnown(
$title,
null,
- array(),
- $query
+ array( 'class' => 'mw-newpages-pagename' ),
+ $query,
+ array( 'known' ) // Set explicitly to avoid the default of 'known','noclasses'. This breaks the colouration for stubs
);
- $hist = $this->skin->linkKnown(
+ $histLink = $this->skin->linkKnown(
$title,
wfMsgHtml( 'hist' ),
array(),
array( 'action' => 'history' )
);
- $length = wfMsgExt( 'nbytes', array( 'parsemag', 'escape' ),
- $wgLang->formatNum( $result->length ) );
+ $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 ) ) .
+ ']'
+ );
$ulink = $this->skin->userLink( $result->rc_user, $result->rc_user_text ) . ' ' .
$this->skin->userToolLinks( $result->rc_user, $result->rc_user_text );
$comment = $this->skin->commentBlock( $result->rc_comment );
- if ( $this->patrollable( $result ) )
+ if ( $this->patrollable( $result ) ) {
$classes[] = 'not-patrolled';
+ }
- # Tags, if any.
- list( $tagDisplay, $newClasses ) = ChangeTags::formatSummaryRow( $result->ts_tags, 'newpages' );
- $classes = array_merge( $classes, $newClasses );
+ # Add a class for zero byte pages
+ if ( $result->length == 0 ) {
+ $classes[] = 'mw-newpages-zero-byte-page';
+ }
+
+ # Tags, if any. check for including due to bug 23293
+ if ( !$this->including() ) {
+ list( $tagDisplay, $newClasses ) = ChangeTags::formatSummaryRow( $result->ts_tags, 'newpages' );
+ $classes = array_merge( $classes, $newClasses );
+ } else {
+ $tagDisplay = '';
+ }
$css = count($classes) ? ' class="'.implode( " ", $classes).'"' : '';
- return "<li{$css}>{$time} {$dm}{$plink} ({$hist}) {$dm}[{$length}] {$dm}{$ulink} {$comment} {$tagDisplay}</li>\n";
+ return "<li{$css}>{$time} {$dm}{$plink} {$hist} {$dm}{$length} {$dm}{$ulink} {$comment} {$tagDisplay}</li>\n";
}
/**
* Should a specific result row provide "patrollable" links?
*
* @param $result Result row
- * @return bool
+ * @return Boolean
*/
protected function patrollable( $result ) {
global $wgUser;
@@ -301,19 +339,18 @@ class SpecialNewpages extends SpecialPage {
/**
* Output a subscription feed listing recent edits to this page.
- * @param string $type
+ *
+ * @param $type String
*/
protected function feed( $type ) {
- global $wgFeed, $wgFeedClasses, $wgFeedLimit;
+ global $wgFeed, $wgFeedClasses, $wgFeedLimit, $wgOut;
if ( !$wgFeed ) {
- global $wgOut;
$wgOut->addWikiMsg( 'feed-unavailable' );
return;
}
if( !isset( $wgFeedClasses[$type] ) ) {
- global $wgOut;
$wgOut->addWikiMsg( 'feed-invalid' );
return;
}
@@ -329,7 +366,7 @@ class SpecialNewpages extends SpecialPage {
$feed->outHeader();
if( $pager->getNumRows() > 0 ) {
- while( $row = $pager->mResult->fetchObject() ) {
+ foreach ( $pager->mResult as $row ) {
$feed->outItem( $this->feedItem( $row ) );
}
}
@@ -337,10 +374,10 @@ class SpecialNewpages extends SpecialPage {
}
protected function feedTitle() {
- global $wgContLanguageCode, $wgSitename;
+ global $wgLanguageCode, $wgSitename;
$page = SpecialPage::getPage( 'Newpages' );
$desc = $page->getDescription();
- return "$wgSitename - $desc [$wgContLanguageCode]";
+ return "$wgSitename - $desc [$wgLanguageCode]";
}
protected function feedItem( $row ) {
@@ -434,6 +471,9 @@ class NewPagesPager extends ReverseChronologicalPager {
if ( $this->opts->getValue( 'hideredirs' ) ) {
$conds['page_is_redirect'] = 0;
}
+
+ // Allow changes to the New Pages query
+ wfRunHooks('SpecialNewpagesConditions', array(&$this, $this->opts, &$conds));
$info = array(
'tables' => array( 'recentchanges', 'page' ),
@@ -471,7 +511,7 @@ class NewPagesPager extends ReverseChronologicalPager {
function getStartBody() {
# Do a batch existence check on pages
$linkBatch = new LinkBatch();
- while( $row = $this->mResult->fetchObject() ) {
+ foreach ( $this->mResult as $row ) {
$linkBatch->add( NS_USER, $row->rc_user_text );
$linkBatch->add( NS_USER_TALK, $row->rc_user_text );
$linkBatch->add( $row->rc_namespace, $row->rc_title );
diff --git a/includes/specials/SpecialPopularpages.php b/includes/specials/SpecialPopularpages.php
index 88b90bc3..375cefdf 100644
--- a/includes/specials/SpecialPopularpages.php
+++ b/includes/specials/SpecialPopularpages.php
@@ -1,11 +1,29 @@
<?php
/**
+ * Implements Special:PopularPages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
- * implements Special:Popularpages
+ * A special page that list most viewed pages
+ *
* @ingroup SpecialPage
*/
class PopularPagesPage extends QueryPage {
diff --git a/includes/specials/SpecialPreferences.php b/includes/specials/SpecialPreferences.php
index 4c8bbb09..e63aeee6 100644
--- a/includes/specials/SpecialPreferences.php
+++ b/includes/specials/SpecialPreferences.php
@@ -1,5 +1,31 @@
<?php
-
+/**
+ * Implements Special:Preferences
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+/**
+ * A special page that allows users to change their preferences
+ *
+ * @ingroup SpecialPage
+ */
class SpecialPreferences extends SpecialPage {
function __construct() {
parent::__construct( 'Preferences' );
@@ -25,18 +51,19 @@ class SpecialPreferences extends SpecialPage {
$this->showResetForm();
return;
}
-
- $wgOut->addScriptFile( 'prefs.js' );
+
+ $wgOut->addModules( 'mediawiki.legacy.prefs' );
+ $wgOut->addModules( 'mediawiki.special.preferences' );
if ( $wgRequest->getCheck( 'success' ) ) {
$wgOut->wrapWikiMsg(
- '<div class="successbox"><strong>$1</strong></div><div id="mw-pref-clear"></div>',
+ "<div class=\"successbox\"><strong>\n$1\n</strong></div><div id=\"mw-pref-clear\"></div>",
'savedprefs'
);
}
if ( $wgRequest->getCheck( 'eauth' ) ) {
- $wgOut->wrapWikiMsg( "<div class='error' style='clear: both;'>\n$1</div>",
+ $wgOut->wrapWikiMsg( "<div class='error' style='clear: both;'>\n$1\n</div>",
'eauthentsent', $wgUser->getName() );
}
diff --git a/includes/specials/SpecialPrefixindex.php b/includes/specials/SpecialPrefixindex.php
index 8b5f0c93..09e7734c 100644
--- a/includes/specials/SpecialPrefixindex.php
+++ b/includes/specials/SpecialPrefixindex.php
@@ -1,7 +1,29 @@
<?php
+/**
+ * Implements Special:Prefixindex
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
/**
- * implements Special:Prefixindex
+ * Implements Special:Prefixindex
+ *
* @ingroup SpecialPage
*/
class SpecialPrefixindex extends SpecialAllpages {
@@ -22,7 +44,7 @@ class SpecialPrefixindex extends SpecialAllpages {
$this->outputHeader();
# GET values
- $from = $wgRequest->getVal( 'from' );
+ $from = $wgRequest->getVal( 'from', '' );
$prefix = $wgRequest->getVal( 'prefix', '' );
$namespace = $wgRequest->getInt( 'namespace' );
$namespaces = $wgContLang->getNamespaces();
@@ -32,12 +54,17 @@ class SpecialPrefixindex extends SpecialAllpages {
: wfMsg( 'prefixindex' )
);
+ $showme = '';
if( isset( $par ) ){
- $this->showPrefixChunk( $namespace, $par, $from );
- } elseif( isset( $prefix ) ){
- $this->showPrefixChunk( $namespace, $prefix, $from );
- } elseif( isset( $from ) ){
- $this->showPrefixChunk( $namespace, $from, $from );
+ $showme = $par;
+ } elseif( $prefix != '' ){
+ $showme = $prefix;
+ } elseif( $from != '' ){
+ // For back-compat with Special:Allpages
+ $showme = $from;
+ }
+ if ($showme != '' || $namespace) {
+ $this->showPrefixChunk( $namespace, $showme, $from );
} else {
$wgOut->addHTML( $this->namespacePrefixForm( $namespace, null ) );
}
@@ -45,8 +72,8 @@ class SpecialPrefixindex extends SpecialAllpages {
/**
* HTML for the top form
- * @param integer $namespace A namespace constant (default NS_MAIN).
- * @param string $from dbKey we are starting listing at.
+ * @param $namespace Integer: a namespace constant (default NS_MAIN).
+ * @param $from String: dbKey we are starting listing at.
*/
function namespacePrefixForm( $namespace = NS_MAIN, $from = '' ) {
global $wgScript;
@@ -54,7 +81,7 @@ class SpecialPrefixindex extends SpecialAllpages {
$out = Xml::openElement( 'div', array( 'class' => 'namespaceoptions' ) );
$out .= Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) );
- $out .= Xml::hidden( 'title', $t->getPrefixedText() );
+ $out .= Html::hidden( 'title', $t->getPrefixedText() );
$out .= Xml::openElement( 'fieldset' );
$out .= Xml::element( 'legend', null, wfMsg( 'allpages' ) );
$out .= Xml::openElement( 'table', array( 'id' => 'nsselect', 'class' => 'allpages' ) );
@@ -83,8 +110,9 @@ class SpecialPrefixindex extends SpecialAllpages {
}
/**
- * @param integer $namespace (Default NS_MAIN)
- * @param string $from list all pages from this name (default FALSE)
+ * @param $namespace Integer, default NS_MAIN
+ * @param $prefix String
+ * @param $from String: list all pages from this name (default FALSE)
*/
function showPrefixChunk( $namespace = NS_MAIN, $prefix, $from = null ) {
global $wgOut, $wgUser, $wgContLang, $wgLang;
@@ -105,7 +133,7 @@ class SpecialPrefixindex extends SpecialAllpages {
$namespace = NS_MAIN;
} else {
list( $namespace, $prefixKey, $prefix ) = $prefixList;
- list( /* $fromNs */, $fromKey, $from ) = $fromList;
+ list( /* $fromNS */, $fromKey, ) = $fromList;
### FIXME: should complain if $fromNs != $namespace
diff --git a/includes/specials/SpecialProtectedpages.php b/includes/specials/SpecialProtectedpages.php
index 8229770c..c676aa00 100644
--- a/includes/specials/SpecialProtectedpages.php
+++ b/includes/specials/SpecialProtectedpages.php
@@ -1,24 +1,45 @@
<?php
/**
+ * Implements Special:Protectedpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
- * @todo document
+ * A special page that lists protected pages
+ *
* @ingroup SpecialPage
*/
-class ProtectedPagesForm {
+class SpecialProtectedpages extends SpecialPage {
protected $IdLevel = 'level';
protected $IdType = 'type';
- public function showList( $msg = '' ) {
+ public function __construct() {
+ parent::__construct( 'Protectedpages' );
+ }
+
+ public function execute( $par ) {
global $wgOut, $wgRequest;
- if( $msg != "" ) {
- $wgOut->setSubtitle( $msg );
- }
+ $this->setHeaders();
+ $this->outputHeader();
// Purge expired entries on one in every 10 queries
if( !mt_rand( 0, 10 ) ) {
@@ -77,7 +98,6 @@ class ProtectedPagesForm {
$description_items[] = wfMsg( 'protect-summary-cascade' );
}
- $expiry_description = '';
$stxt = '';
if( $row->pr_expiry != 'infinity' && strlen($row->pr_expiry) ) {
@@ -123,14 +143,14 @@ class ProtectedPagesForm {
}
/**
- * @param $namespace int
- * @param $type string
- * @param $level string
- * @param $minsize int
- * @param $indefOnly bool
- * @param $cascadeOnly bool
- * @return string Input form
- * @private
+ * @param $namespace Integer
+ * @param $type String: restriction type
+ * @param $level String: restriction level
+ * @param $sizetype String: "min" or "max"
+ * @param $size Integer
+ * @param $indefOnly Boolean: only indefinie protection
+ * @param $cascadeOnly Boolean: only cascading protection
+ * @return String: input form
*/
protected function showOptions( $namespace, $type='edit', $level, $sizetype, $size, $indefOnly, $cascadeOnly ) {
global $wgScript;
@@ -138,17 +158,17 @@ class ProtectedPagesForm {
return Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) .
Xml::openElement( 'fieldset' ) .
Xml::element( 'legend', array(), wfMsg( 'protectedpages' ) ) .
- Xml::hidden( 'title', $title->getPrefixedDBkey() ) . "\n" .
- $this->getNamespaceMenu( $namespace ) . "&nbsp;\n" .
- $this->getTypeMenu( $type ) . "&nbsp;\n" .
- $this->getLevelMenu( $level ) . "&nbsp;\n" .
+ Html::hidden( 'title', $title->getPrefixedDBkey() ) . "\n" .
+ $this->getNamespaceMenu( $namespace ) . "&#160;\n" .
+ $this->getTypeMenu( $type ) . "&#160;\n" .
+ $this->getLevelMenu( $level ) . "&#160;\n" .
"<br /><span style='white-space: nowrap'>" .
- $this->getExpiryCheck( $indefOnly ) . "&nbsp;\n" .
- $this->getCascadeCheck( $cascadeOnly ) . "&nbsp;\n" .
+ $this->getExpiryCheck( $indefOnly ) . "&#160;\n" .
+ $this->getCascadeCheck( $cascadeOnly ) . "&#160;\n" .
"</span><br /><span style='white-space: nowrap'>" .
- $this->getSizeLimit( $sizetype, $size ) . "&nbsp;\n" .
+ $this->getSizeLimit( $sizetype, $size ) . "&#160;\n" .
"</span>" .
- "&nbsp;" . Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" .
+ "&#160;" . Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" .
Xml::closeElement( 'fieldset' ) .
Xml::closeElement( 'form' );
}
@@ -157,12 +177,12 @@ class ProtectedPagesForm {
* Prepare the namespace filter drop-down; standard namespace
* selector, sans the MediaWiki namespace
*
- * @param mixed $namespace Pre-select namespace
- * @return string
+ * @param $namespace Mixed: pre-select namespace
+ * @return String
*/
protected function getNamespaceMenu( $namespace = null ) {
return "<span style='white-space: nowrap'>" .
- Xml::label( wfMsg( 'namespace' ), 'namespace' ) . '&nbsp;'
+ Xml::label( wfMsg( 'namespace' ), 'namespace' ) . '&#160;'
. Xml::namespaceSelector( $namespace, '' ) . "</span>";
}
@@ -190,11 +210,11 @@ class ProtectedPagesForm {
return
Xml::radioLabel( wfMsg('minimum-size'), 'sizetype', 'min', 'wpmin', !$max ) .
- '&nbsp;' .
+ '&#160;' .
Xml::radioLabel( wfMsg('maximum-size'), 'sizetype', 'max', 'wpmax', $max ) .
- '&nbsp;' .
+ '&#160;' .
Xml::input( 'size', 9, $size, array( 'id' => 'wpsize' ) ) .
- '&nbsp;' .
+ '&#160;' .
Xml::label( wfMsg('pagesize'), 'wpsize' );
}
@@ -204,13 +224,11 @@ class ProtectedPagesForm {
* @return string Formatted HTML
*/
protected function getTypeMenu( $pr_type ) {
- global $wgRestrictionTypes;
-
$m = array(); // Temporary array
$options = array();
// First pass to load the log names
- foreach( $wgRestrictionTypes as $type ) {
+ foreach( Title::getFilteredRestrictionTypes( true ) as $type ) {
$text = wfMsg("restriction-$type");
$m[$text] = $type;
}
@@ -222,7 +240,7 @@ class ProtectedPagesForm {
}
return "<span style='white-space: nowrap'>" .
- Xml::label( wfMsg('restriction-type') , $this->IdType ) . '&nbsp;' .
+ Xml::label( wfMsg('restriction-type') , $this->IdType ) . '&#160;' .
Xml::tags( 'select',
array( 'id' => $this->IdType, 'name' => $this->IdType ),
implode( "\n", $options ) ) . "</span>";
@@ -288,7 +306,7 @@ class ProtectedPagesPager extends AlphabeticPager {
function getStartBody() {
# Do a link batch query
$lb = new LinkBatch;
- while( $row = $this->mResult->fetchObject() ) {
+ foreach ( $this->mResult as $row ) {
$lb->add( $row->page_namespace, $row->page_title );
}
$lb->execute();
@@ -334,11 +352,3 @@ class ProtectedPagesPager extends AlphabeticPager {
return 'pr_id';
}
}
-
-/**
- * Constructor
- */
-function wfSpecialProtectedpages() {
- $ppForm = new ProtectedPagesForm();
- $ppForm->showList();
-}
diff --git a/includes/specials/SpecialProtectedtitles.php b/includes/specials/SpecialProtectedtitles.php
index d65b3f79..5b18d87f 100644
--- a/includes/specials/SpecialProtectedtitles.php
+++ b/includes/specials/SpecialProtectedtitles.php
@@ -1,24 +1,45 @@
<?php
/**
+ * Implements Special:Protectedtitles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
- * @todo document
+ * A special page that list protected titles from creation
+ *
* @ingroup SpecialPage
*/
-class ProtectedTitlesForm {
+class SpecialProtectedtitles extends SpecialPage {
protected $IdLevel = 'level';
protected $IdType = 'type';
- function showList( $msg = '' ) {
+ public function __construct() {
+ parent::__construct( 'Protectedtitles' );
+ }
+
+ function execute( $par ) {
global $wgOut, $wgRequest;
- if ( $msg != "" ) {
- $wgOut->setSubtitle( $msg );
- }
+ $this->setHeaders();
+ $this->outputHeader();
// Purge expired entries on one in every 10 queries
if ( !mt_rand( 0, 10 ) ) {
@@ -33,7 +54,7 @@ class ProtectedTitlesForm {
$pager = new ProtectedTitlesPager( $this, array(), $type, $level, $NS, $sizetype, $size );
- $wgOut->addHTML( $this->showOptions( $NS, $type, $level, $sizetype, $size ) );
+ $wgOut->addHTML( $this->showOptions( $NS, $type, $level ) );
if ( $pager->getNumRows() ) {
$s = $pager->getNavigationBar();
@@ -51,7 +72,7 @@ class ProtectedTitlesForm {
* Callback function to output a restriction
*/
function formatRow( $row ) {
- global $wgUser, $wgLang, $wgContLang;
+ global $wgUser, $wgLang;
wfProfileIn( __METHOD__ );
@@ -69,7 +90,7 @@ class ProtectedTitlesForm {
$description_items[] = $protType;
- $expiry_description = ''; $stxt = '';
+ $stxt = '';
if ( $row->pt_expiry != 'infinity' && strlen($row->pt_expiry) ) {
$expiry = Block::decodeExpiry( $row->pt_expiry );
@@ -85,13 +106,12 @@ class ProtectedTitlesForm {
}
/**
- * @param $namespace int
+ * @param $namespace Integer:
* @param $type string
* @param $level string
- * @param $minsize int
* @private
*/
- function showOptions( $namespace, $type='edit', $level, $sizetype, $size ) {
+ function showOptions( $namespace, $type='edit', $level ) {
global $wgScript;
$action = htmlspecialchars( $wgScript );
$title = SpecialPage::getTitleFor( 'Protectedtitles' );
@@ -99,10 +119,10 @@ class ProtectedTitlesForm {
return "<form action=\"$action\" method=\"get\">\n" .
'<fieldset>' .
Xml::element( 'legend', array(), wfMsg( 'protectedtitles' ) ) .
- Xml::hidden( 'title', $special ) . "&nbsp;\n" .
- $this->getNamespaceMenu( $namespace ) . "&nbsp;\n" .
- $this->getLevelMenu( $level ) . "&nbsp;\n" .
- "&nbsp;" . Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" .
+ Html::hidden( 'title', $special ) . "&#160;\n" .
+ $this->getNamespaceMenu( $namespace ) . "&#160;\n" .
+ $this->getLevelMenu( $level ) . "&#160;\n" .
+ "&#160;" . Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" .
"</fieldset></form>";
}
@@ -110,12 +130,12 @@ class ProtectedTitlesForm {
* Prepare the namespace filter drop-down; standard namespace
* selector, sans the MediaWiki namespace
*
- * @param mixed $namespace Pre-select namespace
+ * @param $namespace Mixed: pre-select namespace
* @return string
*/
function getNamespaceMenu( $namespace = null ) {
return Xml::label( wfMsg( 'namespace' ), 'namespace' )
- . '&nbsp;'
+ . '&#160;'
. Xml::namespaceSelector( $namespace, '' );
}
@@ -147,7 +167,7 @@ class ProtectedTitlesForm {
}
return
- Xml::label( wfMsg('restriction-level') , $this->IdLevel ) . '&nbsp;' .
+ Xml::label( wfMsg('restriction-level') , $this->IdLevel ) . '&#160;' .
Xml::tags( 'select',
array( 'id' => $this->IdLevel, 'name' => $this->IdLevel ),
implode( "\n", $options ) );
@@ -158,7 +178,7 @@ class ProtectedTitlesForm {
* @todo document
* @ingroup Pager
*/
-class ProtectedtitlesPager extends AlphabeticPager {
+class ProtectedTitlesPager extends AlphabeticPager {
public $mForm, $mConds;
function __construct( $form, $conds = array(), $type, $level, $namespace, $sizetype='', $size=0 ) {
@@ -176,7 +196,7 @@ class ProtectedtitlesPager extends AlphabeticPager {
$this->mResult->seek( 0 );
$lb = new LinkBatch;
- while ( $row = $this->mResult->fetchObject() ) {
+ foreach ( $this->mResult as $row ) {
$lb->add( $row->pt_namespace, $row->pt_title );
}
@@ -208,12 +228,3 @@ class ProtectedtitlesPager extends AlphabeticPager {
}
}
-/**
- * Constructor
- */
-function wfSpecialProtectedtitles() {
-
- $ppForm = new ProtectedTitlesForm();
-
- $ppForm->showList();
-}
diff --git a/includes/specials/SpecialRandompage.php b/includes/specials/SpecialRandompage.php
index fd3f17f2..6299f384 100644
--- a/includes/specials/SpecialRandompage.php
+++ b/includes/specials/SpecialRandompage.php
@@ -1,11 +1,31 @@
<?php
+/**
+ * Implements Special:Randompage
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Rob Church <robchur@gmail.com>, Ilmari Karonen
+ */
/**
* Special page to direct the user to a random page
*
* @ingroup SpecialPage
- * @author Rob Church <robchur@gmail.com>, Ilmari Karonen
- * @license GNU General Public Licence 2.0 or later
*/
class RandomPage extends SpecialPage {
private $namespaces; // namespaces to select pages from
@@ -33,7 +53,7 @@ class RandomPage extends SpecialPage {
}
public function execute( $par ) {
- global $wgOut, $wgContLang;
+ global $wgOut, $wgContLang, $wgRequest;
if ($par) {
$this->setNamespace( $wgContLang->getNsIndex( $par ) );
@@ -48,7 +68,9 @@ class RandomPage extends SpecialPage {
return;
}
- $query = $this->isRedirect() ? 'redirect=no' : '';
+ $redirectParam = $this->isRedirect() ? array( 'redirect' => 'no' ) : array();
+ $query = array_merge( $wgRequest->getValues(), $redirectParam );
+ unset( $query['title'] );
$wgOut->redirect( $title->getFullUrl( $query ) );
}
diff --git a/includes/specials/SpecialRandomredirect.php b/includes/specials/SpecialRandomredirect.php
index 28cb2aae..88c81b31 100644
--- a/includes/specials/SpecialRandomredirect.php
+++ b/includes/specials/SpecialRandomredirect.php
@@ -1,11 +1,31 @@
<?php
+/**
+ * Implements Special:Randomredirect
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Rob Church <robchur@gmail.com>, Ilmari Karonen
+ */
/**
* Special page to direct the user to a random redirect page (minus the second redirect)
*
* @ingroup SpecialPage
- * @author Rob Church <robchur@gmail.com>, Ilmari Karonen
- * @license GNU General Public Licence 2.0 or later
*/
class SpecialRandomredirect extends RandomPage {
function __construct(){
diff --git a/includes/specials/SpecialRecentchanges.php b/includes/specials/SpecialRecentchanges.php
index 283eeaf4..c012beca 100644
--- a/includes/specials/SpecialRecentchanges.php
+++ b/includes/specials/SpecialRecentchanges.php
@@ -1,15 +1,36 @@
<?php
-
/**
* Implements Special:Recentchanges
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
* @ingroup SpecialPage
*/
-class SpecialRecentChanges extends SpecialPage {
+
+/**
+ * A special page that lists last changes made to the wiki
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialRecentChanges extends IncludableSpecialPage {
var $rcOptions, $rcSubpage;
- public function __construct() {
- parent::__construct( 'Recentchanges' );
- $this->includable( true );
+ public function __construct( $name = 'Recentchanges' ) {
+ parent::__construct( $name );
}
/**
@@ -91,7 +112,7 @@ class SpecialRecentChanges extends SpecialPage {
/**
* Main execution point
*
- * @param $subpage string
+ * @param $subpage String
*/
public function execute( $subpage ) {
global $wgRequest, $wgOut;
@@ -142,7 +163,7 @@ class SpecialRecentChanges extends SpecialPage {
/**
* Return an array with a ChangesFeed object and ChannelFeed object
*
- * @return array
+ * @return Array
*/
public function getFeedObject( $feedFormat ){
$changesFeed = new ChangesFeed( $feedFormat, 'rcfeed' );
@@ -186,7 +207,7 @@ class SpecialRecentChanges extends SpecialPage {
* update the timestamp
*
* @param $feedFormat String
- * @return string or false
+ * @return String or false
*/
public function checkLastModified( $feedFormat ) {
global $wgUseRCPatrol, $wgOut;
@@ -275,7 +296,7 @@ class SpecialRecentChanges extends SpecialPage {
/**
* Process the query
*
- * @param $conds array
+ * @param $conds Array
* @param $opts FormOptions
* @return database result or false (for Recentchangeslinked only)
*/
@@ -290,6 +311,7 @@ class SpecialRecentChanges extends SpecialPage {
$dbr = wfGetDB( DB_SLAVE );
$limit = $opts['limit'];
$namespace = $opts['namespace'];
+ $select = '*';
$invert = $opts['invert'];
// JOIN on watchlist for users
@@ -302,14 +324,17 @@ class SpecialRecentChanges extends SpecialPage {
$tables[] = 'page';
$join_conds['page'] = array('LEFT JOIN', 'rc_cur_id=page_id');
}
- // Tag stuff.
- $fields = array();
- // Fields are * in this case, so let the function modify an empty array to keep it happy.
- ChangeTags::modifyDisplayQuery(
- $tables, $fields, $conds, $join_conds, $query_options, $opts['tagfilter']
- );
+ if ( !$this->including() ) {
+ // Tag stuff.
+ // Doesn't work when transcluding. See bug 23293
+ $fields = array();
+ // Fields are * in this case, so let the function modify an empty array to keep it happy.
+ ChangeTags::modifyDisplayQuery(
+ $tables, $fields, $conds, $join_conds, $query_options, $opts['tagfilter']
+ );
+ }
- if ( !wfRunHooks( 'SpecialRecentChangesQuery', array( &$conds, &$tables, &$join_conds, $opts, &$query_options ) ) )
+ if ( !wfRunHooks( 'SpecialRecentChangesQuery', array( &$conds, &$tables, &$join_conds, $opts, &$query_options, &$select ) ) )
return false;
// Don't use the new_namespace_time timestamp index if:
@@ -317,8 +342,8 @@ class SpecialRecentChanges extends SpecialPage {
// (b) We want all pages NOT in a certain namespaces (inverted)
// (c) There is a tag to filter on (use tag index instead)
// (d) UNION + sort/limit is not an option for the DBMS
- if( is_null($namespace)
- || $invert
+ if( is_null( $namespace )
+ || ( $invert && !is_null( $namespace ) )
|| $opts['tagfilter'] != ''
|| !$dbr->unionSupportsOrderAndLimit() )
{
@@ -329,7 +354,7 @@ class SpecialRecentChanges extends SpecialPage {
// We have a new_namespace_time index! UNION over new=(0,1) and sort result set!
} else {
// New pages
- $sqlNew = $dbr->selectSQLText( $tables, '*',
+ $sqlNew = $dbr->selectSQLText( $tables, $select,
array( 'rc_new' => 1 ) + $conds,
__METHOD__,
array( 'ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => $limit,
@@ -354,7 +379,7 @@ class SpecialRecentChanges extends SpecialPage {
/**
* Send output to $wgOut, only called if not used feeds
*
- * @param $rows array of database rows
+ * @param $rows Array of database rows
* @param $opts FormOptions
*/
public function webOutput( $rows, $opts ) {
@@ -437,7 +462,8 @@ class SpecialRecentChanges extends SpecialPage {
$defaults = $opts->getAllValues();
$nondefaults = $opts->getChangedValues();
- $opts->consumeValues( array( 'namespace', 'invert', 'tagfilter' ) );
+ $opts->consumeValues( array( 'namespace', 'invert', 'tagfilter',
+ 'categories', 'categories_any' ) );
$panel = array();
$panel[] = $this->optionsPanel( $defaults, $nondefaults );
@@ -467,11 +493,11 @@ class SpecialRecentChanges extends SpecialPage {
$unconsumed = $opts->getUnconsumedValues();
foreach( $unconsumed as $key => $value ) {
- $out .= Xml::hidden( $key, $value );
+ $out .= Html::hidden( $key, $value );
}
$t = $this->getTitle();
- $out .= Xml::hidden( 'title', $t->getPrefixedText() );
+ $out .= Html::hidden( 'title', $t->getPrefixedText() );
$form = Xml::tags( 'form', array( 'action' => $wgScript ), $out );
$panel[] = $form;
$panelString = implode( "\n", $panel );
@@ -480,8 +506,6 @@ class SpecialRecentChanges extends SpecialPage {
Xml::fieldset( wfMsg( 'recentchanges-legend' ), $panelString, array( 'class' => 'rcoptions' ) )
);
- $wgOut->addHTML( ChangesList::flagLegend() );
-
$this->setBottomText( $wgOut, $opts );
}
@@ -489,7 +513,7 @@ class SpecialRecentChanges extends SpecialPage {
* Get options to be displayed in a form
*
* @param $opts FormOptions
- * @return array
+ * @return Array
*/
function getExtraOptions( $opts ){
$extraOpts = array();
@@ -531,7 +555,7 @@ class SpecialRecentChanges extends SpecialPage {
* Creates the choose namespace selection
*
* @param $opts FormOptions
- * @return string
+ * @return String
*/
protected function namespaceFilterForm( FormOptions $opts ) {
$nsSelect = Xml::namespaceSelector( $opts['namespace'], '' );
@@ -544,7 +568,7 @@ class SpecialRecentChanges extends SpecialPage {
* Create a input to filter changes by categories
*
* @param $opts FormOptions
- * @return array
+ * @return Array
*/
protected function categoryFilterForm( FormOptions $opts ) {
list( $label, $input ) = Xml::inputLabelSep( wfMsg('rc_categories'),
@@ -559,13 +583,13 @@ class SpecialRecentChanges extends SpecialPage {
/**
* Filter $rows by categories set in $opts
*
- * @param $rows array of database rows
+ * @param $rows Array of database rows
* @param $opts FormOptions
*/
function filterByCategories( &$rows, FormOptions $opts ) {
- $categories = array_map( 'trim', explode( "|" , $opts['categories'] ) );
+ $categories = array_map( 'trim', explode( '|' , $opts['categories'] ) );
- if( empty($categories) ) {
+ if( !count( $categories ) ) {
return;
}
@@ -573,32 +597,34 @@ class SpecialRecentChanges extends SpecialPage {
$cats = array();
foreach( $categories as $cat ) {
$cat = trim( $cat );
- if( $cat == "" ) continue;
+ if( $cat == '' ) continue;
$cats[] = $cat;
}
# Filter articles
$articles = array();
$a2r = array();
+ $rowsarr = array();
foreach( $rows AS $k => $r ) {
$nt = Title::makeTitle( $r->rc_namespace, $r->rc_title );
$id = $nt->getArticleID();
if( $id == 0 ) continue; # Page might have been deleted...
- if( !in_array($id, $articles) ) {
+ if( !in_array( $id, $articles ) ) {
$articles[] = $id;
}
- if( !isset($a2r[$id]) ) {
+ if( !isset( $a2r[$id] ) ) {
$a2r[$id] = array();
}
$a2r[$id][] = $k;
+ $rowsarr[$k] = $r;
}
# Shortcut?
- if( !count($articles) || !count($cats) )
+ if( !count( $articles ) || !count( $cats ) )
return ;
# Look up
- $c = new Categoryfinder ;
+ $c = new Categoryfinder;
$c->seed( $articles, $cats, $opts['categories_any'] ? "OR" : "AND" ) ;
$match = $c->run();
@@ -607,7 +633,7 @@ class SpecialRecentChanges extends SpecialPage {
foreach( $match AS $id ) {
foreach( $a2r[$id] AS $rev ) {
$k = $rev;
- $newrows[$k] = $rows[$k];
+ $newrows[$k] = $rowsarr[$k];
}
}
$rows = $newrows;
@@ -615,9 +641,11 @@ class SpecialRecentChanges extends SpecialPage {
/**
* Makes change an option link which carries all the other options
- * @param $title see Title
- * @param $override
- * @param $options
+ *
+ * @param $title Title
+ * @param $override Array: options to override
+ * @param $options Array: current options
+ * @param $active Boolean: whether to show the link in bold
*/
function makeOptionsLink( $title, $override, $options, $active = false ) {
global $wgUser;
@@ -633,8 +661,9 @@ class SpecialRecentChanges extends SpecialPage {
/**
* Creates the options panel.
- * @param $defaults array
- * @param $nondefaults array
+ *
+ * @param $defaults Array
+ * @param $nondefaults Array
*/
function optionsPanel( $defaults, $nondefaults ) {
global $wgLang, $wgUser, $wgRCLinkLimits, $wgRCLinkDays;
diff --git a/includes/specials/SpecialRecentchangeslinked.php b/includes/specials/SpecialRecentchangeslinked.php
index 3b549843..db0f554d 100644
--- a/includes/specials/SpecialRecentchangeslinked.php
+++ b/includes/specials/SpecialRecentchangeslinked.php
@@ -1,15 +1,36 @@
<?php
+/**
+ * Implements Special:Recentchangeslinked
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
/**
* This is to display changes made to all articles linked in an article.
+ *
* @ingroup SpecialPage
*/
-class SpecialRecentchangeslinked extends SpecialRecentchanges {
+class SpecialRecentchangeslinked extends SpecialRecentChanges {
var $rclTargetTitle;
function __construct(){
- SpecialPage::SpecialPage( 'Recentchangeslinked' );
- $this->includable( true );
+ parent::__construct( 'Recentchangeslinked' );
}
public function getDefaultOptions() {
@@ -52,7 +73,7 @@ class SpecialRecentchangeslinked extends SpecialRecentchanges {
}
$title = Title::newFromURL( $target );
if( !$title || $title->getInterwiki() != '' ){
- $wgOut->wrapWikiMsg( "<div class=\"errorbox\">\n$1</div><br style=\"clear: both\" />", 'allpagesbadtitle' );
+ $wgOut->wrapWikiMsg( "<div class=\"errorbox\">\n$1\n</div><br style=\"clear: both\" />", 'allpagesbadtitle' );
return false;
}
@@ -78,7 +99,8 @@ class SpecialRecentchangeslinked extends SpecialRecentchanges {
$query_options = array();
// left join with watchlist table to highlight watched rows
- if( $uid = $wgUser->getId() ) {
+ $uid = $wgUser->getId();
+ if( $uid ) {
$tables[] = 'watchlist';
$select[] = 'wl_user';
$join_conds['watchlist'] = array( 'LEFT JOIN', "wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace" );
@@ -88,12 +110,13 @@ class SpecialRecentchangeslinked extends SpecialRecentchanges {
$join_conds['page'] = array('LEFT JOIN', 'rc_cur_id=page_id');
$select[] = 'page_latest';
}
+ if ( !$this->including() ) { // bug 23293
+ ChangeTags::modifyDisplayQuery( $tables, $select, $conds, $join_conds,
+ $query_options, $opts['tagfilter'] );
+ }
- ChangeTags::modifyDisplayQuery( $tables, $select, $conds, $join_conds,
- $query_options, $opts['tagfilter'] );
-
- // XXX: parent class does this, should we too?
- // wfRunHooks('SpecialRecentChangesQuery', array( &$conds, &$tables, &$join_conds, $opts ) );
+ if ( !wfRunHooks( 'SpecialRecentChangesQuery', array( &$conds, &$tables, &$join_conds, $opts, &$query_options, &$select ) ) )
+ return false;
if( $ns == NS_CATEGORY && !$showlinkedto ) {
// special handling for categories
diff --git a/includes/specials/SpecialRemoveRestrictions.php b/includes/specials/SpecialRemoveRestrictions.php
deleted file mode 100644
index a3428a5a..00000000
--- a/includes/specials/SpecialRemoveRestrictions.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-
-function wfSpecialRemoveRestrictions() {
- global $wgOut, $wgRequest, $wgUser, $wgLang;
- $sk = $wgUser->getSkin();
- $title = SpecialPage::getTitleFor( 'RemoveRestrictions' );
- $id = $wgRequest->getVal( 'id' );
- if( !is_numeric( $id ) ) {
- $wgOut->addWikiMsg( 'removerestrictions-noid' );
- return;
- }
-
- UserRestriction::purgeExpired();
- $r = UserRestriction::newFromId( $id, true );
- if( !$r ) {
- $wgOut->addWikiMsg( 'removerestrictions-wrongid' );
- return;
- }
-
- $form = array();
- $form['removerestrictions-user'] = $sk->userLink( $r->getSubjectId(), $r->getSubjectText() ) .
- $sk->userToolLinks( $r->getSubjectId(), $r->getSubjectText() );
- $form['removerestrictions-type'] = UserRestriction::formatType( $r->getType() );
- if( $r->isPage() )
- $form['removerestrictions-page'] = $sk->link( $r->getPage() );
- if( $r->isNamespace() )
- $form['removerestrictions-namespace'] = $wgLang->getDisplayNsText( $r->getNamespace() );
- $form['removerestrictions-reason'] = Xml::input( 'reason' );
-
- $result = null;
- if( $wgRequest->wasPosted() && $wgUser->matchEditToken( $wgRequest->getVal( 'edittoken' ) ) )
- $result = wfSpecialRemoveRestrictionsProcess( $r );
-
- $wgOut->addWikiMsg( 'removerestrictions-intro' );
- $wgOut->addHTML( Xml::fieldset( wfMsgHtml( 'removerestrictions-legend' ) ) );
- if( $result )
- $wgOut->addHTML( '<strong class="success">' . wfMsgExt( 'removerestrictions-success',
- 'parseinline', $r->getSubjectText() ) . '</strong>' );
- $wgOut->addHTML( Xml::openElement( 'form', array( 'action' => $title->getLocalUrl( array( 'id' => $id ) ),
- 'method' => 'post' ) ) );
- $wgOut->addHTML( Xml::buildForm( $form, 'removerestrictions-submit' ) );
- $wgOut->addHTML( Xml::hidden( 'id', $r->getId() ) );
- $wgOut->addHTML( Xml::hidden( 'title', $title->getPrefixedDbKey() ) );
- $wgOut->addHTML( Xml::hidden( 'edittoken', $wgUser->editToken() ) );
- $wgOut->addHTML( "</form></fieldset>" );
-}
-
-function wfSpecialRemoveRestrictionsProcess( $r ) {
- global $wgRequest;
- $reason = $wgRequest->getVal( 'reason' );
- $result = $r->delete();
- $log = new LogPage( 'restrict' );
- $params = array( $r->getType() );
- if( $r->isPage() )
- $params[] = $r->getPage()->getPrefixedDbKey();
- if( $r->isNamespace() )
- $params[] = $r->getNamespace();
- $log->addEntry( 'remove', Title::makeTitle( NS_USER, $r->getSubjectText() ), $reason, $params );
- return $result;
-}
diff --git a/includes/specials/SpecialResetpass.php b/includes/specials/SpecialResetpass.php
index 967d2119..0af6fbf0 100644
--- a/includes/specials/SpecialResetpass.php
+++ b/includes/specials/SpecialResetpass.php
@@ -1,11 +1,29 @@
<?php
/**
+ * Implements Special:Resetpass
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
* Let users recover their password.
+ *
* @ingroup SpecialPage
*/
class SpecialResetpass extends SpecialPage {
@@ -19,6 +37,11 @@ class SpecialResetpass extends SpecialPage {
function execute( $par ) {
global $wgUser, $wgAuth, $wgOut, $wgRequest;
+ if ( wfReadOnly() ) {
+ $wgOut->readOnlyPage();
+ return;
+ }
+
$this->mUserName = $wgRequest->getVal( 'wpName' );
$this->mOldpass = $wgRequest->getVal( 'wpPassword' );
$this->mNewpass = $wgRequest->getVal( 'wpNewPassword' );
@@ -26,6 +49,7 @@ class SpecialResetpass extends SpecialPage {
$this->setHeaders();
$this->outputHeader();
+ $wgOut->disallowUserJs();
if( !$wgAuth->allowPasswordChange() ) {
$this->error( wfMsg( 'resetpass_forbidden' ) );
@@ -84,18 +108,18 @@ class SpecialResetpass extends SpecialPage {
function showForm() {
global $wgOut, $wgUser, $wgRequest;
- $wgOut->disallowUserJs();
-
- $self = SpecialPage::getTitleFor( 'Resetpass' );
+ $self = $this->getTitle();
if ( !$this->mUserName ) {
$this->mUserName = $wgUser->getName();
}
$rememberMe = '';
if ( !$wgUser->isLoggedIn() ) {
+ global $wgCookieExpiration, $wgLang;
$rememberMe = '<tr>' .
'<td></td>' .
'<td class="mw-input">' .
- Xml::checkLabel( wfMsg( 'remembermypassword' ),
+ Xml::checkLabel(
+ wfMsgExt( 'remembermypassword', 'parsemag', $wgLang->formatNum( ceil( $wgCookieExpiration / ( 3600 * 24 ) ) ) ),
'wpRemember', 'wpRemember',
$wgRequest->getCheck( 'wpRemember' ) ) .
'</td>' .
@@ -113,9 +137,9 @@ class SpecialResetpass extends SpecialPage {
'method' => 'post',
'action' => $self->getLocalUrl(),
'id' => 'mw-resetpass-form' ) ) . "\n" .
- Xml::hidden( 'token', $wgUser->editToken() ) . "\n" .
- Xml::hidden( 'wpName', $this->mUserName ) . "\n" .
- Xml::hidden( 'returnto', $wgRequest->getVal( 'returnto' ) ) . "\n" .
+ Html::hidden( 'token', $wgUser->editToken() ) . "\n" .
+ Html::hidden( 'wpName', $this->mUserName ) . "\n" .
+ Html::hidden( 'returnto', $wgRequest->getVal( 'returnto' ) ) . "\n" .
wfMsgExt( 'resetpass_text', array( 'parse' ) ) . "\n" .
Xml::openElement( 'table', array( 'id' => 'mw-resetpass-table' ) ) . "\n" .
$this->pretty( array(
@@ -196,7 +220,6 @@ class SpecialResetpass extends SpecialPage {
} catch( PasswordError $e ) {
wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'error' ) );
throw new PasswordError( $e->getMessage() );
- return;
}
$user->setCookies();
diff --git a/includes/specials/SpecialRevisiondelete.php b/includes/specials/SpecialRevisiondelete.php
index b2db869c..f77fc347 100644
--- a/includes/specials/SpecialRevisiondelete.php
+++ b/includes/specials/SpecialRevisiondelete.php
@@ -1,12 +1,32 @@
<?php
/**
- * Special page allowing users with the appropriate permissions to view
- * and hide revisions. Log items can also be hidden.
+ * Implements Special:Revisiondelete
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup SpecialPage
*/
+/**
+ * Special page allowing users with the appropriate permissions to view
+ * and hide revisions. Log items can also be hidden.
+ *
+ * @ingroup SpecialPage
+ */
class SpecialRevisionDelete extends UnlistedSpecialPage {
/** Skin object */
var $skin;
@@ -333,8 +353,6 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
$wgOut->addHTML( "<ul>" );
- $where = $revObjs = array();
-
$numRevisions = 0;
// Live revisions...
$list = $this->getList();
@@ -396,10 +414,10 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
'</td>' .
"</tr>\n" .
Xml::closeElement( 'table' ) .
- Xml::hidden( 'wpEditToken', $wgUser->editToken() ) .
- Xml::hidden( 'target', $this->targetObj->getPrefixedText() ) .
- Xml::hidden( 'type', $this->typeName ) .
- Xml::hidden( 'ids', implode( ',', $this->ids ) ) .
+ Html::hidden( 'wpEditToken', $wgUser->editToken() ) .
+ Html::hidden( 'target', $this->targetObj->getPrefixedText() ) .
+ Html::hidden( 'type', $this->typeName ) .
+ Html::hidden( 'ids', implode( ',', $this->ids ) ) .
Xml::closeElement( 'fieldset' ) . "\n";
} else {
$out = '';
@@ -533,7 +551,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
protected function success() {
global $wgOut;
$wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
- $wgOut->wrapWikiMsg( '<span class="success">$1</span>', $this->typeInfo['success'] );
+ $wgOut->wrapWikiMsg( "<span class=\"success\">\n$1\n</span>", $this->typeInfo['success'] );
$this->list->reloadFromMaster();
$this->showForm();
}
@@ -598,1250 +616,3 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
}
}
-/**
- * Temporary b/c interface, collection of static functions.
- * @ingroup SpecialPage
- */
-class RevisionDeleter {
- /**
- * Checks for a change in the bitfield for a certain option and updates the
- * provided array accordingly.
- *
- * @param $desc String: description to add to the array if the option was
- * enabled / disabled.
- * @param $field Integer: the bitmask describing the single option.
- * @param $diff Integer: the xor of the old and new bitfields.
- * @param $new Integer: the new bitfield
- * @param $arr Array: the array to update.
- */
- protected static function checkItem( $desc, $field, $diff, $new, &$arr ) {
- if( $diff & $field ) {
- $arr[ ( $new & $field ) ? 0 : 1 ][] = $desc;
- }
- }
-
- /**
- * Gets an array describing the changes made to the visibilit of the revision.
- * If the resulting array is $arr, then $arr[0] will contain an array of strings
- * describing the items that were hidden, $arr[2] will contain an array of strings
- * describing the items that were unhidden, and $arr[3] will contain an array with
- * a single string, which can be one of "applied restrictions to sysops",
- * "removed restrictions from sysops", or null.
- *
- * @param $n Integer: the new bitfield.
- * @param $o Integer: the old bitfield.
- * @return An array as described above.
- */
- protected static function getChanges( $n, $o ) {
- $diff = $n ^ $o;
- $ret = array( 0 => array(), 1 => array(), 2 => array() );
- // Build bitfield changes in language
- self::checkItem( wfMsgForContent( 'revdelete-content' ),
- Revision::DELETED_TEXT, $diff, $n, $ret );
- self::checkItem( wfMsgForContent( 'revdelete-summary' ),
- Revision::DELETED_COMMENT, $diff, $n, $ret );
- self::checkItem( wfMsgForContent( 'revdelete-uname' ),
- Revision::DELETED_USER, $diff, $n, $ret );
- // Restriction application to sysops
- if( $diff & Revision::DELETED_RESTRICTED ) {
- if( $n & Revision::DELETED_RESTRICTED )
- $ret[2][] = wfMsgForContent( 'revdelete-restricted' );
- else
- $ret[2][] = wfMsgForContent( 'revdelete-unrestricted' );
- }
- return $ret;
- }
-
- /**
- * Gets a log message to describe the given revision visibility change. This
- * message will be of the form "[hid {content, edit summary, username}];
- * [unhid {...}][applied restrictions to sysops] for $count revisions: $comment".
- *
- * @param $count Integer: The number of effected revisions.
- * @param $nbitfield Integer: The new bitfield for the revision.
- * @param $obitfield Integer: The old bitfield for the revision.
- * @param $isForLog Boolean
- */
- public static function getLogMessage( $count, $nbitfield, $obitfield, $isForLog = false ) {
- global $wgLang;
- $s = '';
- $changes = self::getChanges( $nbitfield, $obitfield );
- if( count( $changes[0] ) ) {
- $s .= wfMsgForContent( 'revdelete-hid', implode( ', ', $changes[0] ) );
- }
- if( count( $changes[1] ) ) {
- if ($s) $s .= '; ';
- $s .= wfMsgForContent( 'revdelete-unhid', implode( ', ', $changes[1] ) );
- }
- if( count( $changes[2] ) ) {
- $s .= $s ? ' (' . $changes[2][0] . ')' : $changes[2][0];
- }
- $msg = $isForLog ? 'logdelete-log-message' : 'revdelete-log-message';
- return wfMsgExt( $msg, array( 'parsemag', 'content' ), $s, $wgLang->formatNum($count) );
-
- }
-
- // Get DB field name for URL param...
- // Future code for other things may also track
- // other types of revision-specific changes.
- // @returns string One of log_id/rev_id/fa_id/ar_timestamp/oi_archive_name
- public static function getRelationType( $typeName ) {
- if ( isset( SpecialRevisionDelete::$deprecatedTypeMap[$typeName] ) ) {
- $typeName = SpecialRevisionDelete::$deprecatedTypeMap[$typeName];
- }
- if ( isset( SpecialRevisionDelete::$allowedTypes[$typeName] ) ) {
- $class = SpecialRevisionDelete::$allowedTypes[$typeName]['list-class'];
- $list = new $class( null, null, null );
- return $list->getIdField();
- } else {
- return null;
- }
- }
-}
-
-/**
- * Abstract base class for a list of deletable items
- */
-abstract class RevDel_List {
- var $special, $title, $ids, $res, $current;
- var $type = null; // override this
- var $idField = null; // override this
- var $dateField = false; // override this
- var $authorIdField = false; // override this
- var $authorNameField = false; // override this
-
- /**
- * @param $special The parent SpecialPage
- * @param $title The target title
- * @param $ids Array of IDs
- */
- public function __construct( $special, $title, $ids ) {
- $this->special = $special;
- $this->title = $title;
- $this->ids = $ids;
- }
-
- /**
- * Get the internal type name of this list. Equal to the table name.
- */
- public function getType() {
- return $this->type;
- }
-
- /**
- * Get the DB field name associated with the ID list
- */
- public function getIdField() {
- return $this->idField;
- }
-
- /**
- * Get the DB field name storing timestamps
- */
- public function getTimestampField() {
- return $this->dateField;
- }
-
- /**
- * Get the DB field name storing user ids
- */
- public function getAuthorIdField() {
- return $this->authorIdField;
- }
-
- /**
- * Get the DB field name storing user names
- */
- public function getAuthorNameField() {
- return $this->authorNameField;
- }
- /**
- * Set the visibility for the revisions in this list. Logging and
- * transactions are done here.
- *
- * @param $params Associative array of parameters. Members are:
- * value: The integer value to set the visibility to
- * comment: The log comment.
- * @return Status
- */
- public function setVisibility( $params ) {
- $bitPars = $params['value'];
- $comment = $params['comment'];
-
- $this->res = false;
- $dbw = wfGetDB( DB_MASTER );
- $this->doQuery( $dbw );
- $dbw->begin();
- $status = Status::newGood();
- $missing = array_flip( $this->ids );
- $this->clearFileOps();
- $idsForLog = array();
- $authorIds = $authorIPs = array();
-
- for ( $this->reset(); $this->current(); $this->next() ) {
- $item = $this->current();
- unset( $missing[ $item->getId() ] );
-
- $oldBits = $item->getBits();
- // Build the actual new rev_deleted bitfield
- $newBits = SpecialRevisionDelete::extractBitfield( $bitPars, $oldBits );
-
- if ( $oldBits == $newBits ) {
- $status->warning( 'revdelete-no-change', $item->formatDate(), $item->formatTime() );
- $status->failCount++;
- continue;
- } elseif ( $oldBits == 0 && $newBits != 0 ) {
- $opType = 'hide';
- } elseif ( $oldBits != 0 && $newBits == 0 ) {
- $opType = 'show';
- } else {
- $opType = 'modify';
- }
-
- if ( $item->isHideCurrentOp( $newBits ) ) {
- // Cannot hide current version text
- $status->error( 'revdelete-hide-current', $item->formatDate(), $item->formatTime() );
- $status->failCount++;
- continue;
- }
- if ( !$item->canView() ) {
- // Cannot access this revision
- $msg = ($opType == 'show') ?
- 'revdelete-show-no-access' : 'revdelete-modify-no-access';
- $status->error( $msg, $item->formatDate(), $item->formatTime() );
- $status->failCount++;
- continue;
- }
- // Cannot just "hide from Sysops" without hiding any fields
- if( $newBits == Revision::DELETED_RESTRICTED ) {
- $status->warning( 'revdelete-only-restricted', $item->formatDate(), $item->formatTime() );
- $status->failCount++;
- continue;
- }
-
- // Update the revision
- $ok = $item->setBits( $newBits );
-
- if ( $ok ) {
- $idsForLog[] = $item->getId();
- $status->successCount++;
- if( $item->getAuthorId() > 0 ) {
- $authorIds[] = $item->getAuthorId();
- } else if( IP::isIPAddress( $item->getAuthorName() ) ) {
- $authorIPs[] = $item->getAuthorName();
- }
- } else {
- $status->error( 'revdelete-concurrent-change', $item->formatDate(), $item->formatTime() );
- $status->failCount++;
- }
- }
-
- // Handle missing revisions
- foreach ( $missing as $id => $unused ) {
- $status->error( 'revdelete-modify-missing', $id );
- $status->failCount++;
- }
-
- if ( $status->successCount == 0 ) {
- $status->ok = false;
- $dbw->rollback();
- return $status;
- }
-
- // Save success count
- $successCount = $status->successCount;
-
- // Move files, if there are any
- $status->merge( $this->doPreCommitUpdates() );
- if ( !$status->isOK() ) {
- // Fatal error, such as no configured archive directory
- $dbw->rollback();
- return $status;
- }
-
- // Log it
- $this->updateLog( array(
- 'title' => $this->title,
- 'count' => $successCount,
- 'newBits' => $newBits,
- 'oldBits' => $oldBits,
- 'comment' => $comment,
- 'ids' => $idsForLog,
- 'authorIds' => $authorIds,
- 'authorIPs' => $authorIPs
- ) );
- $dbw->commit();
-
- // Clear caches
- $status->merge( $this->doPostCommitUpdates() );
- return $status;
- }
-
- /**
- * Reload the list data from the master DB. This can be done after setVisibility()
- * to allow $item->getHTML() to show the new data.
- */
- function reloadFromMaster() {
- $dbw = wfGetDB( DB_MASTER );
- $this->res = $this->doQuery( $dbw );
- }
-
- /**
- * Record a log entry on the action
- * @param $params Associative array of parameters:
- * newBits: The new value of the *_deleted bitfield
- * oldBits: The old value of the *_deleted bitfield.
- * title: The target title
- * ids: The ID list
- * comment: The log comment
- * authorsIds: The array of the user IDs of the offenders
- * authorsIPs: The array of the IP/anon user offenders
- */
- protected function updateLog( $params ) {
- // Get the URL param's corresponding DB field
- $field = RevisionDeleter::getRelationType( $this->getType() );
- if( !$field ) {
- throw new MWException( "Bad log URL param type!" );
- }
- // Put things hidden from sysops in the oversight log
- if ( ( $params['newBits'] | $params['oldBits'] ) & $this->getSuppressBit() ) {
- $logType = 'suppress';
- } else {
- $logType = 'delete';
- }
- // Add params for effected page and ids
- $logParams = $this->getLogParams( $params );
- // Actually add the deletion log entry
- $log = new LogPage( $logType );
- $logid = $log->addEntry( $this->getLogAction(), $params['title'],
- $params['comment'], $logParams );
- // Allow for easy searching of deletion log items for revision/log items
- $log->addRelations( $field, $params['ids'], $logid );
- $log->addRelations( 'target_author_id', $params['authorIds'], $logid );
- $log->addRelations( 'target_author_ip', $params['authorIPs'], $logid );
- }
-
- /**
- * Get the log action for this list type
- */
- public function getLogAction() {
- return 'revision';
- }
-
- /**
- * Get log parameter array.
- * @param $params Associative array of log parameters, same as updateLog()
- * @return array
- */
- public function getLogParams( $params ) {
- return array(
- $this->getType(),
- implode( ',', $params['ids'] ),
- "ofield={$params['oldBits']}",
- "nfield={$params['newBits']}"
- );
- }
-
- /**
- * Initialise the current iteration pointer
- */
- protected function initCurrent() {
- $row = $this->res->current();
- if ( $row ) {
- $this->current = $this->newItem( $row );
- } else {
- $this->current = false;
- }
- }
-
- /**
- * Start iteration. This must be called before current() or next().
- * @return First list item
- */
- public function reset() {
- if ( !$this->res ) {
- $this->res = $this->doQuery( wfGetDB( DB_SLAVE ) );
- } else {
- $this->res->rewind();
- }
- $this->initCurrent();
- return $this->current;
- }
-
- /**
- * Get the current list item, or false if we are at the end
- */
- public function current() {
- return $this->current;
- }
-
- /**
- * Move the iteration pointer to the next list item, and return it.
- */
- public function next() {
- $this->res->next();
- $this->initCurrent();
- return $this->current;
- }
-
- /**
- * Get the number of items in the list.
- */
- public function length() {
- if( !$this->res ) {
- return 0;
- } else {
- return $this->res->numRows();
- }
- }
-
- /**
- * Clear any data structures needed for doPreCommitUpdates() and doPostCommitUpdates()
- * STUB
- */
- public function clearFileOps() {
- }
-
- /**
- * A hook for setVisibility(): do batch updates pre-commit.
- * STUB
- * @return Status
- */
- public function doPreCommitUpdates() {
- return Status::newGood();
- }
-
- /**
- * A hook for setVisibility(): do any necessary updates post-commit.
- * STUB
- * @return Status
- */
- public function doPostCommitUpdates() {
- return Status::newGood();
- }
-
- /**
- * Create an item object from a DB result row
- * @param $row stdclass
- */
- abstract public function newItem( $row );
-
- /**
- * Do the DB query to iterate through the objects.
- * @param $db Database object to use for the query
- */
- abstract public function doQuery( $db );
-
- /**
- * Get the integer value of the flag used for suppression
- */
- abstract public function getSuppressBit();
-}
-
-/**
- * Abstract base class for deletable items
- */
-abstract class RevDel_Item {
- /** The parent SpecialPage */
- var $special;
-
- /** The parent RevDel_List */
- var $list;
-
- /** The DB result row */
- var $row;
-
- /**
- * @param $list RevDel_List
- * @param $row DB result row
- */
- public function __construct( $list, $row ) {
- $this->special = $list->special;
- $this->list = $list;
- $this->row = $row;
- }
-
- /**
- * Get the ID, as it would appear in the ids URL parameter
- */
- public function getId() {
- $field = $this->list->getIdField();
- return $this->row->$field;
- }
-
- /**
- * Get the date, formatted with $wgLang
- */
- public function formatDate() {
- global $wgLang;
- return $wgLang->date( $this->getTimestamp() );
- }
-
- /**
- * Get the time, formatted with $wgLang
- */
- public function formatTime() {
- global $wgLang;
- return $wgLang->time( $this->getTimestamp() );
- }
-
- /**
- * Get the timestamp in MW 14-char form
- */
- public function getTimestamp() {
- $field = $this->list->getTimestampField();
- return wfTimestamp( TS_MW, $this->row->$field );
- }
-
- /**
- * Get the author user ID
- */
- public function getAuthorId() {
- $field = $this->list->getAuthorIdField();
- return intval( $this->row->$field );
- }
-
- /**
- * Get the author user name
- */
- public function getAuthorName() {
- $field = $this->list->getAuthorNameField();
- return strval( $this->row->$field );
- }
-
- /**
- * Returns true if the item is "current", and the operation to set the given
- * bits can't be executed for that reason
- * STUB
- */
- public function isHideCurrentOp( $newBits ) {
- return false;
- }
-
- /**
- * Returns true if the current user can view the item
- */
- abstract public function canView();
-
- /**
- * Returns true if the current user can view the item text/file
- */
- abstract public function canViewContent();
-
- /**
- * Get the current deletion bitfield value
- */
- abstract public function getBits();
-
- /**
- * Get the HTML of the list item. Should be include <li></li> tags.
- * This is used to show the list in HTML form, by the special page.
- */
- abstract public function getHTML();
-
- /**
- * Set the visibility of the item. This should do any necessary DB queries.
- *
- * The DB update query should have a condition which forces it to only update
- * if the value in the DB matches the value fetched earlier with the SELECT.
- * If the update fails because it did not match, the function should return
- * false. This prevents concurrency problems.
- *
- * @return boolean success
- */
- abstract public function setBits( $newBits );
-}
-
-/**
- * List for revision table items
- */
-class RevDel_RevisionList extends RevDel_List {
- var $currentRevId;
- var $type = 'revision';
- var $idField = 'rev_id';
- var $dateField = 'rev_timestamp';
- var $authorIdField = 'rev_user';
- var $authorNameField = 'rev_user_text';
-
- public function doQuery( $db ) {
- $ids = array_map( 'intval', $this->ids );
- return $db->select( array('revision','page'), '*',
- array(
- 'rev_page' => $this->title->getArticleID(),
- 'rev_id' => $ids,
- 'rev_page = page_id'
- ),
- __METHOD__,
- array( 'ORDER BY' => 'rev_id DESC' )
- );
- }
-
- public function newItem( $row ) {
- return new RevDel_RevisionItem( $this, $row );
- }
-
- public function getCurrent() {
- if ( is_null( $this->currentRevId ) ) {
- $dbw = wfGetDB( DB_MASTER );
- $this->currentRevId = $dbw->selectField(
- 'page', 'page_latest', $this->title->pageCond(), __METHOD__ );
- }
- return $this->currentRevId;
- }
-
- public function getSuppressBit() {
- return Revision::DELETED_RESTRICTED;
- }
-
- public function doPreCommitUpdates() {
- $this->title->invalidateCache();
- return Status::newGood();
- }
-
- public function doPostCommitUpdates() {
- $this->title->purgeSquid();
- // Extensions that require referencing previous revisions may need this
- wfRunHooks( 'ArticleRevisionVisiblitySet', array( &$this->title ) );
- return Status::newGood();
- }
-}
-
-/**
- * Item class for a revision table row
- */
-class RevDel_RevisionItem extends RevDel_Item {
- var $revision;
-
- public function __construct( $list, $row ) {
- parent::__construct( $list, $row );
- $this->revision = new Revision( $row );
- }
-
- public function canView() {
- return $this->revision->userCan( Revision::DELETED_RESTRICTED );
- }
-
- public function canViewContent() {
- return $this->revision->userCan( Revision::DELETED_TEXT );
- }
-
- public function getBits() {
- return $this->revision->mDeleted;
- }
-
- public function setBits( $bits ) {
- $dbw = wfGetDB( DB_MASTER );
- // Update revision table
- $dbw->update( 'revision',
- array( 'rev_deleted' => $bits ),
- array(
- 'rev_id' => $this->revision->getId(),
- 'rev_page' => $this->revision->getPage(),
- 'rev_deleted' => $this->getBits()
- ),
- __METHOD__
- );
- if ( !$dbw->affectedRows() ) {
- // Concurrent fail!
- return false;
- }
- // Update recentchanges table
- $dbw->update( 'recentchanges',
- array(
- 'rc_deleted' => $bits,
- 'rc_patrolled' => 1
- ),
- array(
- 'rc_this_oldid' => $this->revision->getId(), // condition
- // non-unique timestamp index
- 'rc_timestamp' => $dbw->timestamp( $this->revision->getTimestamp() ),
- ),
- __METHOD__
- );
- return true;
- }
-
- public function isDeleted() {
- return $this->revision->isDeleted( Revision::DELETED_TEXT );
- }
-
- public function isHideCurrentOp( $newBits ) {
- return ( $newBits & Revision::DELETED_TEXT )
- && $this->list->getCurrent() == $this->getId();
- }
-
- /**
- * Get the HTML link to the revision text.
- * Overridden by RevDel_ArchiveItem.
- */
- protected function getRevisionLink() {
- global $wgLang;
- $date = $wgLang->timeanddate( $this->revision->getTimestamp(), true );
- if ( $this->isDeleted() && !$this->canViewContent() ) {
- return $date;
- }
- return $this->special->skin->link(
- $this->list->title,
- $date,
- array(),
- array(
- 'oldid' => $this->revision->getId(),
- 'unhide' => 1
- )
- );
- }
-
- /**
- * Get the HTML link to the diff.
- * Overridden by RevDel_ArchiveItem
- */
- protected function getDiffLink() {
- if ( $this->isDeleted() && !$this->canViewContent() ) {
- return wfMsgHtml('diff');
- } else {
- return
- $this->special->skin->link(
- $this->list->title,
- wfMsgHtml('diff'),
- array(),
- array(
- 'diff' => $this->revision->getId(),
- 'oldid' => 'prev',
- 'unhide' => 1
- ),
- array(
- 'known',
- 'noclasses'
- )
- );
- }
- }
-
- public function getHTML() {
- $difflink = $this->getDiffLink();
- $revlink = $this->getRevisionLink();
- $userlink = $this->special->skin->revUserLink( $this->revision );
- $comment = $this->special->skin->revComment( $this->revision );
- if ( $this->isDeleted() ) {
- $revlink = "<span class=\"history-deleted\">$revlink</span>";
- }
- return "<li>($difflink) $revlink $userlink $comment</li>";
- }
-}
-
-/**
- * List for archive table items, i.e. revisions deleted via action=delete
- */
-class RevDel_ArchiveList extends RevDel_RevisionList {
- var $type = 'archive';
- var $idField = 'ar_timestamp';
- var $dateField = 'ar_timestamp';
- var $authorIdField = 'ar_user';
- var $authorNameField = 'ar_user_text';
-
- public function doQuery( $db ) {
- $timestamps = array();
- foreach ( $this->ids as $id ) {
- $timestamps[] = $db->timestamp( $id );
- }
- return $db->select( 'archive', '*',
- array(
- 'ar_namespace' => $this->title->getNamespace(),
- 'ar_title' => $this->title->getDBkey(),
- 'ar_timestamp' => $timestamps
- ),
- __METHOD__,
- array( 'ORDER BY' => 'ar_timestamp DESC' )
- );
- }
-
- public function newItem( $row ) {
- return new RevDel_ArchiveItem( $this, $row );
- }
-
- public function doPreCommitUpdates() {
- return Status::newGood();
- }
-
- public function doPostCommitUpdates() {
- return Status::newGood();
- }
-}
-
-/**
- * Item class for a archive table row
- */
-class RevDel_ArchiveItem extends RevDel_RevisionItem {
- public function __construct( $list, $row ) {
- RevDel_Item::__construct( $list, $row );
- $this->revision = Revision::newFromArchiveRow( $row,
- array( 'page' => $this->list->title->getArticleId() ) );
- }
-
- public function getId() {
- # Convert DB timestamp to MW timestamp
- return $this->revision->getTimestamp();
- }
-
- public function setBits( $bits ) {
- $dbw = wfGetDB( DB_MASTER );
- $dbw->update( 'archive',
- array( 'ar_deleted' => $bits ),
- array( 'ar_namespace' => $this->list->title->getNamespace(),
- 'ar_title' => $this->list->title->getDBkey(),
- // use timestamp for index
- 'ar_timestamp' => $this->row->ar_timestamp,
- 'ar_rev_id' => $this->row->ar_rev_id,
- 'ar_deleted' => $this->getBits()
- ),
- __METHOD__ );
- return (bool)$dbw->affectedRows();
- }
-
- protected function getRevisionLink() {
- global $wgLang;
- $undelete = SpecialPage::getTitleFor( 'Undelete' );
- $date = $wgLang->timeanddate( $this->revision->getTimestamp(), true );
- if ( $this->isDeleted() && !$this->canViewContent() ) {
- return $date;
- }
- return $this->special->skin->link( $undelete, $date, array(),
- array(
- 'target' => $this->list->title->getPrefixedText(),
- 'timestamp' => $this->revision->getTimestamp()
- ) );
- }
-
- protected function getDiffLink() {
- if ( $this->isDeleted() && !$this->canViewContent() ) {
- return wfMsgHtml( 'diff' );
- }
- $undelete = SpecialPage::getTitleFor( 'Undelete' );
- return $this->special->skin->link( $undelete, wfMsgHtml('diff'), array(),
- array(
- 'target' => $this->list->title->getPrefixedText(),
- 'diff' => 'prev',
- 'timestamp' => $this->revision->getTimestamp()
- ) );
- }
-}
-
-/**
- * List for oldimage table items
- */
-class RevDel_FileList extends RevDel_List {
- var $type = 'oldimage';
- var $idField = 'oi_archive_name';
- var $dateField = 'oi_timestamp';
- var $authorIdField = 'oi_user';
- var $authorNameField = 'oi_user_text';
- var $storeBatch, $deleteBatch, $cleanupBatch;
-
- public function doQuery( $db ) {
- $archiveName = array();
- foreach( $this->ids as $timestamp ) {
- $archiveNames[] = $timestamp . '!' . $this->title->getDBkey();
- }
- return $db->select( 'oldimage', '*',
- array(
- 'oi_name' => $this->title->getDBkey(),
- 'oi_archive_name' => $archiveNames
- ),
- __METHOD__,
- array( 'ORDER BY' => 'oi_timestamp DESC' )
- );
- }
-
- public function newItem( $row ) {
- return new RevDel_FileItem( $this, $row );
- }
-
- public function clearFileOps() {
- $this->deleteBatch = array();
- $this->storeBatch = array();
- $this->cleanupBatch = array();
- }
-
- public function doPreCommitUpdates() {
- $status = Status::newGood();
- $repo = RepoGroup::singleton()->getLocalRepo();
- if ( $this->storeBatch ) {
- $status->merge( $repo->storeBatch( $this->storeBatch, FileRepo::OVERWRITE_SAME ) );
- }
- if ( !$status->isOK() ) {
- return $status;
- }
- if ( $this->deleteBatch ) {
- $status->merge( $repo->deleteBatch( $this->deleteBatch ) );
- }
- if ( !$status->isOK() ) {
- // Running cleanupDeletedBatch() after a failed storeBatch() with the DB already
- // modified (but destined for rollback) causes data loss
- return $status;
- }
- if ( $this->cleanupBatch ) {
- $status->merge( $repo->cleanupDeletedBatch( $this->cleanupBatch ) );
- }
- return $status;
- }
-
- public function doPostCommitUpdates() {
- $file = wfLocalFile( $this->title );
- $file->purgeCache();
- $file->purgeDescription();
- return Status::newGood();
- }
-
- public function getSuppressBit() {
- return File::DELETED_RESTRICTED;
- }
-}
-
-/**
- * Item class for an oldimage table row
- */
-class RevDel_FileItem extends RevDel_Item {
- var $file;
-
- public function __construct( $list, $row ) {
- parent::__construct( $list, $row );
- $this->file = RepoGroup::singleton()->getLocalRepo()->newFileFromRow( $row );
- }
-
- public function getId() {
- $parts = explode( '!', $this->row->oi_archive_name );
- return $parts[0];
- }
-
- public function canView() {
- return $this->file->userCan( File::DELETED_RESTRICTED );
- }
-
- public function canViewContent() {
- return $this->file->userCan( File::DELETED_FILE );
- }
-
- public function getBits() {
- return $this->file->getVisibility();
- }
-
- public function setBits( $bits ) {
- # Queue the file op
- # FIXME: move to LocalFile.php
- if ( $this->isDeleted() ) {
- if ( $bits & File::DELETED_FILE ) {
- # Still deleted
- } else {
- # Newly undeleted
- $key = $this->file->getStorageKey();
- $srcRel = $this->file->repo->getDeletedHashPath( $key ) . $key;
- $this->list->storeBatch[] = array(
- $this->file->repo->getVirtualUrl( 'deleted' ) . '/' . $srcRel,
- 'public',
- $this->file->getRel()
- );
- $this->list->cleanupBatch[] = $key;
- }
- } elseif ( $bits & File::DELETED_FILE ) {
- # Newly deleted
- $key = $this->file->getStorageKey();
- $dstRel = $this->file->repo->getDeletedHashPath( $key ) . $key;
- $this->list->deleteBatch[] = array( $this->file->getRel(), $dstRel );
- }
-
- # Do the database operations
- $dbw = wfGetDB( DB_MASTER );
- $dbw->update( 'oldimage',
- array( 'oi_deleted' => $bits ),
- array(
- 'oi_name' => $this->row->oi_name,
- 'oi_timestamp' => $this->row->oi_timestamp,
- 'oi_deleted' => $this->getBits()
- ),
- __METHOD__
- );
- return (bool)$dbw->affectedRows();
- }
-
- public function isDeleted() {
- return $this->file->isDeleted( File::DELETED_FILE );
- }
-
- /**
- * Get the link to the file.
- * Overridden by RevDel_ArchivedFileItem.
- */
- protected function getLink() {
- global $wgLang, $wgUser;
- $date = $wgLang->timeanddate( $this->file->getTimestamp(), true );
- if ( $this->isDeleted() ) {
- # Hidden files...
- if ( !$this->canViewContent() ) {
- $link = $date;
- } else {
- $link = $this->special->skin->link(
- $this->special->getTitle(),
- $date, array(),
- array(
- 'target' => $this->list->title->getPrefixedText(),
- 'file' => $this->file->getArchiveName(),
- 'token' => $wgUser->editToken( $this->file->getArchiveName() )
- )
- );
- }
- return '<span class="history-deleted">' . $link . '</span>';
- } else {
- # Regular files...
- $url = $this->file->getUrl();
- return Xml::element( 'a', array( 'href' => $this->file->getUrl() ), $date );
- }
- }
- /**
- * Generate a user tool link cluster if the current user is allowed to view it
- * @return string HTML
- */
- protected function getUserTools() {
- if( $this->file->userCan( Revision::DELETED_USER ) ) {
- $link = $this->special->skin->userLink( $this->file->user, $this->file->user_text ) .
- $this->special->skin->userToolLinks( $this->file->user, $this->file->user_text );
- } else {
- $link = wfMsgHtml( 'rev-deleted-user' );
- }
- if( $this->file->isDeleted( Revision::DELETED_USER ) ) {
- return '<span class="history-deleted">' . $link . '</span>';
- }
- return $link;
- }
-
- /**
- * Wrap and format the file's comment block, if the current
- * user is allowed to view it.
- *
- * @return string HTML
- */
- protected function getComment() {
- if( $this->file->userCan( File::DELETED_COMMENT ) ) {
- $block = $this->special->skin->commentBlock( $this->file->description );
- } else {
- $block = ' ' . wfMsgHtml( 'rev-deleted-comment' );
- }
- if( $this->file->isDeleted( File::DELETED_COMMENT ) ) {
- return "<span class=\"history-deleted\">$block</span>";
- }
- return $block;
- }
-
- public function getHTML() {
- global $wgLang;
- $data =
- wfMsg(
- 'widthheight',
- $wgLang->formatNum( $this->file->getWidth() ),
- $wgLang->formatNum( $this->file->getHeight() )
- ) .
- ' (' .
- wfMsgExt( 'nbytes', 'parsemag', $wgLang->formatNum( $this->file->getSize() ) ) .
- ')';
- $pageLink = $this->getLink();
-
- return '<li>' . $this->getLink() . ' ' . $this->getUserTools() . ' ' .
- $data . ' ' . $this->getComment(). '</li>';
- }
-}
-
-/**
- * List for filearchive table items
- */
-class RevDel_ArchivedFileList extends RevDel_FileList {
- var $type = 'filearchive';
- var $idField = 'fa_id';
- var $dateField = 'fa_timestamp';
- var $authorIdField = 'fa_user';
- var $authorNameField = 'fa_user_text';
-
- public function doQuery( $db ) {
- $ids = array_map( 'intval', $this->ids );
- return $db->select( 'filearchive', '*',
- array(
- 'fa_name' => $this->title->getDBkey(),
- 'fa_id' => $ids
- ),
- __METHOD__,
- array( 'ORDER BY' => 'fa_id DESC' )
- );
- }
-
- public function newItem( $row ) {
- return new RevDel_ArchivedFileItem( $this, $row );
- }
-}
-
-/**
- * Item class for a filearchive table row
- */
-class RevDel_ArchivedFileItem extends RevDel_FileItem {
- public function __construct( $list, $row ) {
- RevDel_Item::__construct( $list, $row );
- $this->file = ArchivedFile::newFromRow( $row );
- }
-
- public function getId() {
- return $this->row->fa_id;
- }
-
- public function setBits( $bits ) {
- $dbw = wfGetDB( DB_MASTER );
- $dbw->update( 'filearchive',
- array( 'fa_deleted' => $bits ),
- array(
- 'fa_id' => $this->row->fa_id,
- 'fa_deleted' => $this->getBits(),
- ),
- __METHOD__
- );
- return (bool)$dbw->affectedRows();
- }
-
- protected function getLink() {
- global $wgLang, $wgUser;
- $date = $wgLang->timeanddate( $this->file->getTimestamp(), true );
- $undelete = SpecialPage::getTitleFor( 'Undelete' );
- $key = $this->file->getKey();
- # Hidden files...
- if( !$this->canViewContent() ) {
- $link = $date;
- } else {
- $link = $this->special->skin->link( $undelete, $date, array(),
- array(
- 'target' => $this->list->title->getPrefixedText(),
- 'file' => $key,
- 'token' => $wgUser->editToken( $key )
- )
- );
- }
- if( $this->isDeleted() ) {
- $link = '<span class="history-deleted">' . $link . '</span>';
- }
- return $link;
- }
-}
-
-/**
- * List for logging table items
- */
-class RevDel_LogList extends RevDel_List {
- var $type = 'logging';
- var $idField = 'log_id';
- var $dateField = 'log_timestamp';
- var $authorIdField = 'log_user';
- var $authorNameField = 'log_user_text';
-
- public function doQuery( $db ) {
- global $wgMessageCache;
- $wgMessageCache->loadAllMessages();
- $ids = array_map( 'intval', $this->ids );
- return $db->select( 'logging', '*',
- array( 'log_id' => $ids ),
- __METHOD__,
- array( 'ORDER BY' => 'log_id DESC' )
- );
- }
-
- public function newItem( $row ) {
- return new RevDel_LogItem( $this, $row );
- }
-
- public function getSuppressBit() {
- return Revision::DELETED_RESTRICTED;
- }
-
- public function getLogAction() {
- return 'event';
- }
-
- public function getLogParams( $params ) {
- return array(
- implode( ',', $params['ids'] ),
- "ofield={$params['oldBits']}",
- "nfield={$params['newBits']}"
- );
- }
-}
-
-/**
- * Item class for a logging table row
- */
-class RevDel_LogItem extends RevDel_Item {
- public function canView() {
- return LogEventsList::userCan( $this->row, Revision::DELETED_RESTRICTED );
- }
-
- public function canViewContent() {
- return true; // none
- }
-
- public function getBits() {
- return $this->row->log_deleted;
- }
-
- public function setBits( $bits ) {
- $dbw = wfGetDB( DB_MASTER );
- $dbw->update( 'recentchanges',
- array(
- 'rc_deleted' => $bits,
- 'rc_patrolled' => 1
- ),
- array(
- 'rc_logid' => $this->row->log_id,
- 'rc_timestamp' => $this->row->log_timestamp // index
- ),
- __METHOD__
- );
- $dbw->update( 'logging',
- array( 'log_deleted' => $bits ),
- array(
- 'log_id' => $this->row->log_id,
- 'log_deleted' => $this->getBits()
- ),
- __METHOD__
- );
- return (bool)$dbw->affectedRows();
- }
-
- public function getHTML() {
- global $wgLang;
-
- $date = htmlspecialchars( $wgLang->timeanddate( $this->row->log_timestamp ) );
- $paramArray = LogPage::extractParams( $this->row->log_params );
- $title = Title::makeTitle( $this->row->log_namespace, $this->row->log_title );
-
- // Log link for this page
- $loglink = $this->special->skin->link(
- SpecialPage::getTitleFor( 'Log' ),
- wfMsgHtml( 'log' ),
- array(),
- array( 'page' => $title->getPrefixedText() )
- );
- // Action text
- if( !$this->canView() ) {
- $action = '<span class="history-deleted">' . wfMsgHtml('rev-deleted-event') . '</span>';
- } else {
- $action = LogPage::actionText( $this->row->log_type, $this->row->log_action, $title,
- $this->special->skin, $paramArray, true, true );
- if( $this->row->log_deleted & LogPage::DELETED_ACTION )
- $action = '<span class="history-deleted">' . $action . '</span>';
- }
- // User links
- $userLink = $this->special->skin->userLink( $this->row->log_user,
- User::WhoIs( $this->row->log_user ) );
- if( LogEventsList::isDeleted($this->row,LogPage::DELETED_USER) ) {
- $userLink = '<span class="history-deleted">' . $userLink . '</span>';
- }
- // Comment
- $comment = $wgLang->getDirMark() . $this->special->skin->commentBlock( $this->row->log_comment );
- if( LogEventsList::isDeleted($this->row,LogPage::DELETED_COMMENT) ) {
- $comment = '<span class="history-deleted">' . $comment . '</span>';
- }
- return "<li>($loglink) $date $userLink $action $comment</li>";
- }
-}
diff --git a/includes/specials/SpecialSearch.php b/includes/specials/SpecialSearch.php
index 40b28236..fd6e858e 100644
--- a/includes/specials/SpecialSearch.php
+++ b/includes/specials/SpecialSearch.php
@@ -1,24 +1,24 @@
<?php
-# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
-# http://www.mediawiki.org/
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-# http://www.gnu.org/copyleft/gpl.html
-
/**
- * Run text & title search and display the output
+ * Implements Special:Search
+ *
+ * Copyright © 2004 Brion Vibber <brion@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
@@ -29,7 +29,9 @@
* @param $par String: (default '')
*/
function wfSpecialSearch( $par = '' ) {
- global $wgRequest, $wgUser;
+ global $wgRequest, $wgUser, $wgOut;
+ $wgOut->allowClickjacking();
+
// 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 );
@@ -56,11 +58,10 @@ class SpecialSearch {
* Set up basic search parameters from the request and user settings.
* Typically you'll pass $wgRequest and $wgUser.
*
- * @param WebRequest $request
- * @param User $user
- * @public
+ * @param $request WebRequest
+ * @param $user User
*/
- function __construct( &$request, &$user ) {
+ public function __construct( &$request, &$user ) {
list( $this->limit, $this->offset ) = $request->getLimitOffset( 20, 'searchlimit' );
$this->mPrefix = $request->getVal('prefix', '');
# Extract requested namespaces
@@ -68,7 +69,7 @@ class SpecialSearch {
if( empty( $this->namespaces ) ) {
$this->namespaces = SearchEngine::userNamespaces( $user );
}
- $this->searchRedirects = $request->getcheck( 'redirs' ) ? true : false;
+ $this->searchRedirects = $request->getCheck( 'redirs' );
$this->searchAdvanced = $request->getVal( 'advanced' );
$this->active = 'advanced';
$this->sk = $user->getSkin();
@@ -78,7 +79,8 @@ class SpecialSearch {
/**
* If an exact title match can be found, jump straight ahead to it.
- * @param string $term
+ *
+ * @param $term String
*/
public function goResult( $term ) {
global $wgOut;
@@ -91,6 +93,12 @@ class SpecialSearch {
}
# If there's an exact or very near match, jump right there.
$t = SearchEngine::getNearMatch( $term );
+
+ if ( !wfRunHooks( 'SpecialSearchGo', array( &$t, &$term ) ) ) {
+ # Hook requested termination
+ return;
+ }
+
if( !is_null( $t ) ) {
$wgOut->redirect( $t->getFullURL() );
return;
@@ -100,6 +108,8 @@ class SpecialSearch {
if( !is_null( $t ) ) {
global $wgGoToEdit;
wfRunHooks( 'SpecialSearchNogomatch', array( &$t ) );
+ wfDebugLog( 'nogomatch', $t->getText(), false );
+
# If the feature is enabled, go straight to the edit page
if( $wgGoToEdit ) {
$wgOut->redirect( $t->getFullURL( array( 'action' => 'edit' ) ) );
@@ -110,7 +120,7 @@ class SpecialSearch {
}
/**
- * @param string $term
+ * @param $term String
*/
public function showResults( $term ) {
global $wgOut, $wgUser, $wgDisableTextSearch, $wgContLang, $wgScript;
@@ -220,7 +230,6 @@ class SpecialSearch {
$filePrefix = $wgContLang->getFormattedNsText(NS_FILE).':';
if( trim( $term ) === '' || $filePrefix === trim( $term ) ) {
- $wgOut->addHTML( $this->searchFocus() );
$wgOut->addHTML( $this->formHeader($term, 0, 0));
if( $this->searchAdvanced ) {
$wgOut->addHTML( $this->powerSearchBox( $term ) );
@@ -302,13 +311,10 @@ class SpecialSearch {
$textMatches->free();
}
if( $num === 0 ) {
- $wgOut->addWikiMsg( 'search-nonefound', wfEscapeWikiText( $term ) );
+ $wgOut->wrapWikiMsg( "<p class=\"mw-search-nonefound\">\n$1</p>", array( 'search-nonefound', wfEscapeWikiText( $term ) ) );
$this->showCreateLink( $t );
}
$wgOut->addHtml( "</div>" );
- if( $num === 0 ) {
- $wgOut->addHTML( $this->searchFocus() );
- }
if( $num || $this->offset ) {
$wgOut->addHTML( "<p class='mw-search-pager-bottom'>{$prevnext}</p>\n" );
@@ -326,10 +332,12 @@ class SpecialSearch {
$messageName = 'searchmenu-exists';
} elseif( $t->userCan( 'create' ) ) {
$messageName = 'searchmenu-new';
+ } else {
+ $messageName = 'searchmenu-new-nocreate';
}
}
if( $messageName ) {
- $wgOut->addWikiMsg( $messageName, wfEscapeWikiText( $t->getPrefixedText() ) );
+ $wgOut->wrapWikiMsg( "<p class=\"mw-search-createlink\">\n$1</p>", array( $messageName, wfEscapeWikiText( $t->getPrefixedText() ) ) );
} else {
// preserve the paragraph for margins etc...
$wgOut->addHtml( '<p></p>' );
@@ -342,10 +350,9 @@ class SpecialSearch {
protected function setupPage( $term ) {
global $wgOut;
// Figure out the active search profile header
- $nsAllSet = array_keys( SearchEngine::searchableNamespaces() );
- if( $this->searchAdvanced )
+ if( $this->searchAdvanced ) {
$this->active = 'advanced';
- else {
+ } else {
$profiles = $this->getSearchProfiles();
foreach( $profiles as $key => $data ) {
@@ -363,16 +370,16 @@ class SpecialSearch {
$wgOut->setArticleRelated( false );
$wgOut->setRobotPolicy( 'noindex,nofollow' );
// add javascript specific to special:search
- $wgOut->addScriptFile( 'search.js' );
- $wgOut->allowClickjacking();
+ $wgOut->addModules( 'mediawiki.legacy.search' );
+ $wgOut->addModules( 'mediawiki.special.search' );
}
/**
* Extract "power search" namespace settings from the request object,
* returning a list of index numbers to search.
*
- * @param WebRequest $request
- * @return array
+ * @param $request WebRequest
+ * @return Array
*/
protected function powerSearch( &$request ) {
$arr = array();
@@ -386,7 +393,8 @@ class SpecialSearch {
/**
* Reconstruct the 'power search' options for links
- * @return array
+ *
+ * @return Array
*/
protected function powerSearchOptions() {
$opt = array();
@@ -403,7 +411,7 @@ class SpecialSearch {
/**
* Show whole set of results
*
- * @param SearchResultSet $matches
+ * @param $matches SearchResultSet
*/
protected function showMatches( &$matches ) {
global $wgContLang;
@@ -416,7 +424,6 @@ class SpecialSearch {
if( !is_null($infoLine) ) {
$out .= "\n<!-- {$infoLine} -->\n";
}
- $off = $this->offset + 1;
$out .= "<ul class='mw-search-results'>\n";
while( $result = $matches->next() ) {
$out .= $this->showHit( $result, $terms );
@@ -431,11 +438,12 @@ class SpecialSearch {
/**
* Format a single hit result
- * @param SearchResult $result
- * @param array $terms terms to highlight
+ *
+ * @param $result SearchResult
+ * @param $terms Array: terms to highlight
*/
protected function showHit( $result, $terms ) {
- global $wgContLang, $wgLang, $wgUser;
+ global $wgLang, $wgUser;
wfProfileIn( __METHOD__ );
if( $result->isBrokenTitle() ) {
@@ -539,6 +547,18 @@ class SpecialSearch {
$this->sk->formatSize( $byteSize ),
$wgLang->formatNum( $wordCount )
);
+
+ if( $t->getNamespace() == NS_CATEGORY ) {
+ $cat = Category::newFromTitle( $t );
+ $size = wfMsgExt(
+ 'search-result-category-size',
+ array( 'parsemag', 'escape' ),
+ $wgLang->formatNum( $cat->getPageCount() ),
+ $wgLang->formatNum( $cat->getSubcatCount() ),
+ $wgLang->formatNum( $cat->getFileCount() )
+ );
+ }
+
$date = $wgLang->timeanddate( $timestamp );
// link to related articles if supported
@@ -567,7 +587,7 @@ class SpecialSearch {
if( $img ) {
$thumb = $img->transform( array( 'width' => 120, 'height' => 120 ) );
if( $thumb ) {
- $desc = $img->getShortDesc();
+ $desc = wfMsg( 'parentheses', $img->getShortDesc() );
wfProfileOut( __METHOD__ );
// Float doesn't seem to interact well with the bullets.
// Table messes up vertical alignment of the bullets.
@@ -591,7 +611,7 @@ class SpecialSearch {
}
wfProfileOut( __METHOD__ );
- return "<li>{$link} {$redirect} {$section} {$extract}\n" .
+ return "<li><div class='mw-search-result-heading'>{$link} {$redirect} {$section}</div> {$extract}\n" .
"<div class='mw-search-result-data'>{$score}{$size} - {$date}{$related}</div>" .
"</li>\n";
@@ -600,7 +620,8 @@ class SpecialSearch {
/**
* Show results from other wikis
*
- * @param SearchResultSet $matches
+ * @param $matches SearchResultSet
+ * @param $query String
*/
protected function showInterwiki( &$matches, $query ) {
global $wgContLang;
@@ -609,7 +630,6 @@ class SpecialSearch {
$out = "<div id='mw-search-interwiki'><div id='mw-search-interwiki-caption'>".
wfMsg('search-interwiki-caption')."</div>\n";
- $off = $this->offset + 1;
$out .= "<ul class='mw-search-iwresults'>\n";
// work out custom project captions
@@ -638,15 +658,14 @@ class SpecialSearch {
/**
* Show single interwiki link
*
- * @param SearchResult $result
- * @param string $lastInterwiki
- * @param array $terms
- * @param string $query
- * @param array $customCaptions iw prefix -> caption
+ * @param $result SearchResult
+ * @param $lastInterwiki String
+ * @param $terms Array
+ * @param $query String
+ * @param $customCaptions Array: iw prefix -> caption
*/
protected function showInterwikiHit( $result, $lastInterwiki, $terms, $query, $customCaptions) {
wfProfileIn( __METHOD__ );
- global $wgContLang, $wgLang;
if( $result->isBrokenTitle() ) {
wfProfileOut( __METHOD__ );
@@ -719,12 +738,11 @@ class SpecialSearch {
/**
* Generates the power search box at bottom of [[Special:Search]]
- * @param $term string: search term
- * @return $out string: HTML form
+ *
+ * @param $term String: search term
+ * @return String: HTML form
*/
protected function powerSearchBox( $term ) {
- global $wgScript, $wgContLang;
-
// Groups namespaces into rows according to subject
$rows = array();
foreach( SearchEngine::searchableNamespaces() as $namespace => $name ) {
@@ -809,19 +827,11 @@ class SpecialSearch {
$namespaceTables .
Xml::element( 'div', array( 'class' => 'divider' ), '', false ) .
$redirects .
- Xml::hidden( 'title', SpecialPage::getTitleFor( 'Search' )->getPrefixedText() ) .
- Xml::hidden( 'advanced', $this->searchAdvanced ) .
- Xml::hidden( 'fulltext', 'Advanced search' ) .
+ Html::hidden( 'title', SpecialPage::getTitleFor( 'Search' )->getPrefixedText() ) .
+ Html::hidden( 'advanced', $this->searchAdvanced ) .
+ Html::hidden( 'fulltext', 'Advanced search' ) .
Xml::closeElement( 'fieldset' );
}
-
- protected function searchFocus() {
- $id = $this->searchAdvanced ? 'powerSearchText' : 'searchText';
- return Html::inlineScript(
- "hookEvent(\"load\", function() {" .
- "document.getElementById('$id').focus();" .
- "});" );
- }
protected function getSearchProfiles() {
// Builds list of Search Types (profiles)
@@ -864,7 +874,7 @@ class SpecialSearch {
wfRunHooks( 'SpecialSearchProfiles', array( &$profiles ) );
- foreach( $profiles as $key => &$data ) {
+ foreach( $profiles as &$data ) {
sort($data['namespaces']);
}
@@ -872,7 +882,7 @@ class SpecialSearch {
}
protected function formHeader( $term, $resultsShown, $totalNum ) {
- global $wgContLang, $wgLang;
+ global $wgLang;
$out = Xml::openElement('div', array( 'class' => 'mw-search-formheader' ) );
@@ -882,7 +892,6 @@ class SpecialSearch {
$bareterm = substr( $term, strpos( $term, ':' ) + 1 );
}
-
$profiles = $this->getSearchProfiles();
// Outputs XML for Search Types
@@ -934,7 +943,7 @@ class SpecialSearch {
// Adds hidden namespace fields
if ( !$this->searchAdvanced ) {
foreach( $this->namespaces as $ns ) {
- $out .= Xml::hidden( "ns{$ns}", '1' );
+ $out .= Html::hidden( "ns{$ns}", '1' );
}
}
@@ -943,7 +952,6 @@ class SpecialSearch {
protected function shortDialog( $term ) {
$searchTitle = SpecialPage::getTitleFor( 'Search' );
- $searchable = SearchEngine::searchableNamespaces();
$out = Html::hidden( 'title', $searchTitle->getPrefixedText() ) . "\n";
// Keep redirect setting
$out .= Html::hidden( "redirs", (int)$this->searchRedirects ) . "\n";
@@ -958,7 +966,16 @@ class SpecialSearch {
return $out . $this->didYouMeanHtml;
}
- /** Make a search link with some target namespaces */
+ /**
+ * Make a search link with some target namespaces
+ *
+ * @param $term String
+ * @param $namespaces Array
+ * @param $label String: link's text
+ * @param $tooltip String: link's tooltip
+ * @param $params Array: query string parameters
+ * @return String: HTML fragment
+ */
protected function makeSearchLink( $term, $namespaces, $label, $tooltip, $params=array() ) {
$opt = $params;
foreach( $namespaces as $n ) {
@@ -986,7 +1003,12 @@ class SpecialSearch {
);
}
- /** Check if query starts with image: prefix */
+ /**
+ * Check if query starts with image: prefix
+ *
+ * @param $term String: the string to check
+ * @return Boolean
+ */
protected function startsWithImage( $term ) {
global $wgContLang;
@@ -997,7 +1019,12 @@ class SpecialSearch {
return false;
}
- /** Check if query starts with all: prefix */
+ /**
+ * Check if query starts with all: prefix
+ *
+ * @param $term String: the string to check
+ * @return Boolean
+ */
protected function startsWithAll( $term ) {
$allkeyword = wfMsgForContent('searchall');
diff --git a/includes/specials/SpecialShortpages.php b/includes/specials/SpecialShortpages.php
index c41b15c5..989e4c07 100644
--- a/includes/specials/SpecialShortpages.php
+++ b/includes/specials/SpecialShortpages.php
@@ -1,5 +1,22 @@
<?php
/**
+ * Implements Special:Shortpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
@@ -7,6 +24,7 @@
/**
* SpecialShortpages extends QueryPage. It is used to return the shortest
* pages in the database.
+ *
* @ingroup SpecialPage
*/
class ShortPagesPage extends QueryPage {
@@ -54,11 +72,13 @@ class ShortPagesPage extends QueryPage {
# the page must exist for it to have been pulled out of the table
if( $this->isCached() ) {
$batch = new LinkBatch();
- while( $row = $db->fetchObject( $res ) )
+ foreach ( $res as $row ) {
$batch->add( $row->namespace, $row->title );
+ }
$batch->execute();
- if( $db->numRows( $res ) > 0 )
+ if ( $db->numRows( $res ) > 0 ) {
$db->dataSeek( $res, 0 );
+ }
}
}
@@ -83,11 +103,11 @@ class ShortPagesPage extends QueryPage {
$plink = $this->isCached()
? $skin->link( $title )
: $skin->linkKnown( $title );
- $size = wfMsgExt( 'nbytes', array( 'parsemag', 'escape' ), $wgLang->formatNum( htmlspecialchars( $result->value ) ) );
+ $size = wfMessage( 'nbytes', $wgLang->formatNum( $result->value ) )->escaped();
return $title->exists()
? "({$hlink}) {$dm}{$plink} {$dm}[{$size}]"
- : "<s>({$hlink}) {$dm}{$plink} {$dm}[{$size}]</s>";
+ : "<del>({$hlink}) {$dm}{$plink} {$dm}[{$size}]</del>";
}
}
diff --git a/includes/specials/SpecialSpecialpages.php b/includes/specials/SpecialSpecialpages.php
index 8e97f9b7..19bc6b00 100644
--- a/includes/specials/SpecialSpecialpages.php
+++ b/includes/specials/SpecialSpecialpages.php
@@ -1,84 +1,138 @@
<?php
/**
+ * Implements Special:Specialpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
+ * A special page that lists special pages
*
+ * @ingroup SpecialPage
*/
-function wfSpecialSpecialpages() {
- global $wgOut, $wgUser, $wgMessageCache, $wgSortSpecialPages;
+class SpecialSpecialpages extends UnlistedSpecialPage {
+
+ function __construct() {
+ parent::__construct( 'Specialpages' );
+ }
- $wgMessageCache->loadAllMessages();
+ function execute( $par ) {
+ global $wgOut;
+ $this->setHeaders();
+ $this->outputHeader();
+ $wgOut->allowClickjacking();
- $wgOut->setRobotPolicy( 'noindex,nofollow' ); # Is this really needed?
- $wgOut->allowClickjacking();
- $sk = $wgUser->getSkin();
+ $groups = $this->getPageGroups();
- $pages = SpecialPage::getUsablePages();
+ if ( $groups === false ) {
+ return;
+ }
- if( count( $pages ) == 0 ) {
- # Yeah, that was pointless. Thanks for coming.
- return;
+ $this->outputPageList( $groups );
}
- /** Put them into a sortable array */
- $groups = array();
- foreach ( $pages as $page ) {
- if ( $page->isListed() ) {
- $group = SpecialPage::getGroup( $page );
- if( !isset($groups[$group]) ) {
- $groups[$group] = array();
+ private function getPageGroups() {
+ global $wgSortSpecialPages;
+
+ $pages = SpecialPage::getUsablePages();
+
+ if( !count( $pages ) ) {
+ # Yeah, that was pointless. Thanks for coming.
+ return false;
+ }
+
+ /** Put them into a sortable array */
+ $groups = array();
+ foreach ( $pages as $page ) {
+ if ( $page->isListed() ) {
+ $group = SpecialPage::getGroup( $page );
+ if( !isset( $groups[$group] ) ) {
+ $groups[$group] = array();
+ }
+ $groups[$group][$page->getDescription()] = array( $page->getTitle(), $page->isRestricted() );
}
- $groups[$group][$page->getDescription()] = array( $page->getTitle(), $page->isRestricted() );
}
- }
- /** Sort */
- if ( $wgSortSpecialPages ) {
- foreach( $groups as $group => $sortedPages ) {
- ksort( $groups[$group] );
+ /** Sort */
+ if ( $wgSortSpecialPages ) {
+ foreach( $groups as $group => $sortedPages ) {
+ ksort( $groups[$group] );
+ }
}
- }
- /** Always move "other" to end */
- if( array_key_exists('other',$groups) ) {
- $other = $groups['other'];
- unset( $groups['other'] );
- $groups['other'] = $other;
+ /** Always move "other" to end */
+ if( array_key_exists( 'other', $groups ) ) {
+ $other = $groups['other'];
+ unset( $groups['other'] );
+ $groups['other'] = $other;
+ }
+
+ return $groups;
}
- $includesRestrictedPages = false;
- /** Now output the HTML */
- foreach ( $groups as $group => $sortedPages ) {
- $middle = ceil( count($sortedPages)/2 );
- $total = count($sortedPages);
- $count = 0;
-
- $wgOut->wrapWikiMsg( "<h4 class=\"mw-specialpagesgroup\" id=\"mw-specialpagesgroup-$group\">$1</h4>\n", "specialpages-group-$group" );
- $wgOut->addHTML( "<table style='width: 100%;' class='mw-specialpages-table'><tr>" );
- $wgOut->addHTML( "<td width='30%' valign='top'><ul>\n" );
- foreach( $sortedPages as $desc => $specialpage ) {
- list( $title, $restricted ) = $specialpage;
- $link = $sk->linkKnown( $title , htmlspecialchars( $desc ) );
- if( $restricted ) {
- $includesRestrictedPages = true;
- $wgOut->addHTML( "<li class='mw-specialpages-page mw-specialpagerestricted'><strong>{$link}</strong></li>\n" );
- } else {
- $wgOut->addHTML( "<li>{$link}</li>\n" );
- }
+ private function outputPageList( $groups ) {
+ global $wgUser, $wgOut;
- # Split up the larger groups
- $count++;
- if( $total > 3 && $count == $middle ) {
- $wgOut->addHTML( "</ul></td><td width='10%'></td><td width='30%' valign='top'><ul>" );
+ $sk = $wgUser->getSkin();
+ $includesRestrictedPages = false;
+
+ foreach ( $groups as $group => $sortedPages ) {
+ $middle = ceil( count( $sortedPages )/2 );
+ $total = count( $sortedPages );
+ $count = 0;
+
+ $wgOut->wrapWikiMsg( "<h4 class=\"mw-specialpagesgroup\" id=\"mw-specialpagesgroup-$group\">$1</h4>\n", "specialpages-group-$group" );
+ $wgOut->addHTML(
+ Html::openElement( 'table', array( 'style' => 'width:100%;', 'class' => 'mw-specialpages-table' ) ) ."\n" .
+ Html::openElement( 'tr' ) . "\n" .
+ Html::openElement( 'td', array( 'style' => 'width:30%;vertical-align:top' ) ) . "\n" .
+ Html::openElement( 'ul' ) . "\n"
+ );
+ foreach( $sortedPages as $desc => $specialpage ) {
+ list( $title, $restricted ) = $specialpage;
+ $link = $sk->linkKnown( $title , htmlspecialchars( $desc ) );
+ if( $restricted ) {
+ $includesRestrictedPages = true;
+ $wgOut->addHTML( Html::rawElement( 'li', array( 'class' => 'mw-specialpages-page mw-specialpagerestricted' ), Html::rawElement( 'strong', array(), $link ) ) . "\n" );
+ } else {
+ $wgOut->addHTML( Html::rawElement( 'li', array(), $link ) . "\n" );
+ }
+
+ # Split up the larger groups
+ $count++;
+ if( $total > 3 && $count == $middle ) {
+ $wgOut->addHTML(
+ Html::closeElement( 'ul' ) . Html::closeElement( 'td' ) .
+ Html::element( 'td', array( 'style' => 'width:10%' ), '' ) .
+ Html::openElement( 'td', array( 'style' => 'width:30%' ) ) . Html::openElement( 'ul' ) . "\n"
+ );
+ }
}
+ $wgOut->addHTML(
+ Html::closeElement( 'ul' ) . Html::closeElement( 'td' ) .
+ Html::element( 'td', array( 'style' => 'width:30%' ), '' ) .
+ Html::closeElement( 'tr' ) . Html::closeElement( 'table' ) . "\n"
+ );
}
- $wgOut->addHTML( "</ul></td><td width='30%' valign='top'></td></tr></table>\n" );
- }
- if ( $includesRestrictedPages ) {
- $wgOut->wrapWikiMsg( "<div class=\"mw-specialpages-notes\">\n$1\n</div>", 'specialpages-note' );
+ if ( $includesRestrictedPages ) {
+ $wgOut->wrapWikiMsg( "<div class=\"mw-specialpages-notes\">\n$1\n</div>", 'specialpages-note' );
+ }
}
}
diff --git a/includes/specials/SpecialStatistics.php b/includes/specials/SpecialStatistics.php
index 2e785b8b..b0d0246e 100644
--- a/includes/specials/SpecialStatistics.php
+++ b/includes/specials/SpecialStatistics.php
@@ -1,31 +1,44 @@
<?php
-
/**
- * Special page lists various statistics, including the contents of
- * `site_stats`, plus page view details if enabled
+ * Implements Special:Statistics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup SpecialPage
*/
/**
- * Show the special page
+ * Special page lists various statistics, including the contents of
+ * `site_stats`, plus page view details if enabled
*
- * @param mixed $par (not used)
+ * @ingroup SpecialPage
*/
class SpecialStatistics extends SpecialPage {
private $views, $edits, $good, $images, $total, $users,
- $activeUsers, $admins, $numJobs = 0;
+ $activeUsers, $admins = 0;
public function __construct() {
parent::__construct( 'Statistics' );
}
public function execute( $par ) {
- global $wgOut, $wgRequest, $wgMessageCache, $wgMemc;
+ global $wgOut, $wgMemc;
global $wgDisableCounters, $wgMiserMode;
- $wgMessageCache->loadAllMessages();
$this->setHeaders();
@@ -37,7 +50,6 @@ class SpecialStatistics extends SpecialPage {
$this->users = SiteStats::users();
$this->activeUsers = SiteStats::activeUsers();
$this->admins = SiteStats::numberingroup('sysop');
- $this->numJobs = SiteStats::jobs();
$this->hook = '';
# Staticic - views
@@ -56,11 +68,6 @@ class SpecialStatistics extends SpecialPage {
$wgMemc->set( $key, '1', 24*3600 ); // don't update for 1 day
}
}
-
- # Do raw output
- if( $wgRequest->getVal( 'action' ) == 'raw' ) {
- $this->doRawOutput();
- }
$text = Xml::openElement( 'table', array( 'class' => 'wikitable mw-statistics-table' ) );
@@ -101,15 +108,14 @@ class SpecialStatistics extends SpecialPage {
/**
* Format a row
- * @param string $text description of the row
- * @param float $number a number
- * @param array $trExtraParams
- * @param string $descMsg
- * @param string $descMsgParam
+ * @param $text String: description of the row
+ * @param $number Float: a statistical number
+ * @param $trExtraParams Array: params to table row, see Html::elememt
+ * @param $descMsg String: message key
+ * @param $descMsgParam Array: message params
* @return string table row in HTML format
*/
private function formatRow( $text, $number, $trExtraParams = array(), $descMsg = '', $descMsgParam = '' ) {
- global $wgStylePath;
if( $descMsg ) {
$descriptionText = wfMsgExt( $descMsg, array( 'parseinline' ), $descMsgParam );
if ( !wfEmptyMsg( $descMsg, $descriptionText ) ) {
@@ -118,10 +124,11 @@ class SpecialStatistics extends SpecialPage {
$descriptionText );
}
}
- return Xml::openElement( 'tr', $trExtraParams ) .
- Xml::openElement( 'td' ) . $text . Xml::closeElement( 'td' ) .
- Xml::openElement( 'td', array( 'class' => 'mw-statistics-numbers' ) ) . $number . Xml::closeElement( 'td' ) .
- Xml::closeElement( 'tr' );
+ return
+ Html::rawElement( 'tr', $trExtraParams,
+ Html::rawElement( 'td', array(), $text ) .
+ Html::rawElement( 'td', array( 'class' => 'mw-statistics-numbers' ), $number )
+ );
}
/**
@@ -155,13 +162,11 @@ class SpecialStatistics extends SpecialPage {
array( 'class' => 'mw-statistics-edits' ) ) .
$this->formatRow( wfMsgExt( 'statistics-edits-average', array( 'parseinline' ) ),
$wgLang->formatNum( sprintf( '%.2f', $this->total ? $this->edits / $this->total : 0 ) ),
- array( 'class' => 'mw-statistics-edits-average' ) ) .
- $this->formatRow( wfMsgExt( 'statistics-jobqueue', array( 'parseinline' ) ),
- $wgLang->formatNum( $this->numJobs ),
- array( 'class' => 'mw-statistics-jobqueue' ) );
+ array( 'class' => 'mw-statistics-edits-average' ) );
}
+
private function getUserStats() {
- global $wgLang, $wgUser, $wgRCMaxAge;
+ global $wgLang, $wgUser, $wgActiveUserDays;
$sk = $wgUser->getSkin();
return Xml::openElement( 'tr' ) .
Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-users', array( 'parseinline' ) ) ) .
@@ -180,8 +185,9 @@ class SpecialStatistics extends SpecialPage {
$wgLang->formatNum( $this->activeUsers ),
array( 'class' => 'mw-statistics-users-active' ),
'statistics-users-active-desc',
- $wgLang->formatNum( ceil( $wgRCMaxAge / ( 3600 * 24 ) ) ) );
+ $wgLang->formatNum( $wgActiveUserDays ) );
}
+
private function getGroupStats() {
global $wgGroupPermissions, $wgImplicitGroups, $wgLang, $wgUser;
$sk = $wgUser->getSkin();
@@ -228,6 +234,7 @@ class SpecialStatistics extends SpecialPage {
}
return $text;
}
+
private function getViewsStats() {
global $wgLang;
return Xml::openElement( 'tr' ) .
@@ -235,12 +242,13 @@ class SpecialStatistics extends SpecialPage {
Xml::closeElement( 'tr' ) .
$this->formatRow( wfMsgExt( 'statistics-views-total', array( 'parseinline' ) ),
$wgLang->formatNum( $this->views ),
- array ( 'class' => 'mw-statistics-views-total' ) ) .
+ array ( 'class' => 'mw-statistics-views-total' ), 'statistics-views-total-desc' ) .
$this->formatRow( wfMsgExt( 'statistics-views-peredit', array( 'parseinline' ) ),
$wgLang->formatNum( sprintf( '%.2f', $this->edits ?
$this->views / $this->edits : 0 ) ),
array ( 'class' => 'mw-statistics-views-peredit' ) );
}
+
private function getMostViewedPages() {
global $wgLang, $wgUser;
$text = '';
@@ -267,7 +275,7 @@ class SpecialStatistics extends SpecialPage {
$text .= Xml::openElement( 'tr' );
$text .= Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-mostpopular', array( 'parseinline' ) ) );
$text .= Xml::closeElement( 'tr' );
- while( $row = $res->fetchObject() ) {
+ foreach ( $res as $row ) {
$title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
if( $title instanceof Title ) {
$text .= $this->formatRow( $sk->link( $title ),
@@ -279,7 +287,7 @@ class SpecialStatistics extends SpecialPage {
}
return $text;
}
-
+
private function getOtherStats( $stats ) {
global $wgLang;
@@ -299,20 +307,4 @@ class SpecialStatistics extends SpecialPage {
return $return;
}
-
- /**
- * Do the action=raw output for this page. Legacy, but we support
- * it for backwards compatibility
- * http://lists.wikimedia.org/pipermail/wikitech-l/2008-August/039202.html
- */
- private function doRawOutput() {
- global $wgOut;
- $wgOut->disable();
- header( 'Pragma: nocache' );
- echo "total=" . $this->total . ";good=" . $this->good . ";views=" .
- $this->views . ";edits=" . $this->edits . ";users=" . $this->users . ";";
- echo "activeusers=" . $this->activeUsers . ";admins=" . $this->admins .
- ";images=" . $this->images . ";jobs=" . $this->numJobs . "\n";
- return;
- }
-} \ No newline at end of file
+}
diff --git a/includes/specials/SpecialTags.php b/includes/specials/SpecialTags.php
index 57feeae7..c2aecf47 100644
--- a/includes/specials/SpecialTags.php
+++ b/includes/specials/SpecialTags.php
@@ -1,8 +1,34 @@
<?php
+/**
+ * Implements Special:Tags
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
if (!defined('MEDIAWIKI'))
die;
+/**
+ * A special page that lists tags for edits
+ *
+ * @ingroup SpecialPage
+ */
class SpecialTags extends SpecialPage {
function __construct() {
@@ -10,16 +36,12 @@ class SpecialTags extends SpecialPage {
}
function execute( $par ) {
- global $wgOut, $wgUser, $wgMessageCache;
+ global $wgOut;
- $wgMessageCache->loadAllMessages();
-
- $sk = $wgUser->getSkin();
$wgOut->setPageTitle( wfMsg( 'tags-title' ) );
- $wgOut->wrapWikiMsg( "<div class='mw-tags-intro'>\n$1</div>", 'tags-intro' );
+ $wgOut->wrapWikiMsg( "<div class='mw-tags-intro'>\n$1\n</div>", 'tags-intro' );
// Write the headers
- $html = '';
$html = Xml::tags( 'tr', null, Xml::tags( 'th', null, wfMsgExt( 'tags-tag', 'parseinline' ) ) .
Xml::tags( 'th', null, wfMsgExt( 'tags-display-header', 'parseinline' ) ) .
Xml::tags( 'th', null, wfMsgExt( 'tags-description-header', 'parseinline' ) ) .
@@ -28,7 +50,7 @@ class SpecialTags extends SpecialPage {
$dbr = wfGetDB( DB_SLAVE );
$res = $dbr->select( 'change_tag', array( 'ct_tag', 'count(*) as hitcount' ), array(), __METHOD__, array( 'GROUP BY' => 'ct_tag', 'ORDER BY' => 'hitcount DESC' ) );
- while ( $row = $res->fetchObject() ) {
+ foreach ( $res as $row ) {
$html .= $this->doTagRow( $row->ct_tag, $row->hitcount );
}
@@ -72,4 +94,4 @@ class SpecialTags extends SpecialPage {
return Xml::tags( 'tr', null, $newRow ) . "\n";
}
-} \ No newline at end of file
+}
diff --git a/includes/specials/SpecialUncategorizedcategories.php b/includes/specials/SpecialUncategorizedcategories.php
index f23e89ce..9574af70 100644
--- a/includes/specials/SpecialUncategorizedcategories.php
+++ b/includes/specials/SpecialUncategorizedcategories.php
@@ -1,15 +1,33 @@
<?php
/**
+ * Implements Special:Uncategorizedcategories
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
- * implements Special:Uncategorizedcategories
+ * A special page that lists uncategorized categories
+ *
* @ingroup SpecialPage
*/
class UncategorizedCategoriesPage extends UncategorizedPagesPage {
- function UncategorizedCategoriesPage() {
+ function __construct() {
$this->requestedNamespace = NS_CATEGORY;
}
diff --git a/includes/specials/SpecialUncategorizedimages.php b/includes/specials/SpecialUncategorizedimages.php
index 25310081..c4254039 100644
--- a/includes/specials/SpecialUncategorizedimages.php
+++ b/includes/specials/SpecialUncategorizedimages.php
@@ -1,6 +1,21 @@
<?php
/**
- * Special page lists images which haven't been categorised
+ * Implements Special:Uncategorizedimages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup SpecialPage
@@ -8,6 +23,8 @@
*/
/**
+ * Special page lists images which haven't been categorised
+ *
* @ingroup SpecialPage
*/
class UncategorizedImagesPage extends ImageQueryPage {
diff --git a/includes/specials/SpecialUncategorizedpages.php b/includes/specials/SpecialUncategorizedpages.php
index e7f0aaca..c7fef5d2 100644
--- a/includes/specials/SpecialUncategorizedpages.php
+++ b/includes/specials/SpecialUncategorizedpages.php
@@ -1,11 +1,29 @@
<?php
/**
+ * Implements Special:Uncategorizedpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
* A special page looking for page without any category.
+ *
* @ingroup SpecialPage
*/
class UncategorizedPagesPage extends PageQueryPage {
diff --git a/includes/specials/SpecialUncategorizedtemplates.php b/includes/specials/SpecialUncategorizedtemplates.php
index 7e6fd24b..aa4e979d 100644
--- a/includes/specials/SpecialUncategorizedtemplates.php
+++ b/includes/specials/SpecialUncategorizedtemplates.php
@@ -1,7 +1,25 @@
<?php
/**
+ * Implements Special:Uncategorizedtemplates
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
+ * @author Rob Church <robchur@gmail.com>
*/
/**
@@ -9,7 +27,6 @@
* template namespace
*
* @ingroup SpecialPage
- * @author Rob Church <robchur@gmail.com>
*/
class UncategorizedTemplatesPage extends UncategorizedPagesPage {
diff --git a/includes/specials/SpecialUndelete.php b/includes/specials/SpecialUndelete.php
index 4db4e633..1cf61d26 100644
--- a/includes/specials/SpecialUndelete.php
+++ b/includes/specials/SpecialUndelete.php
@@ -1,25 +1,29 @@
<?php
-
/**
- * Special page allowing users with the appropriate permissions to view
- * and restore deleted content
+ * Implements Special:Undelete
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup SpecialPage
*/
/**
- * Constructor
- */
-function wfSpecialUndelete( $par ) {
- global $wgRequest;
-
- $form = new UndeleteForm( $wgRequest, $par );
- $form->execute();
-}
-
-/**
* Used to show archived pages and eventually restore them.
+ *
* @ingroup SpecialPage
*/
class PageArchive {
@@ -28,7 +32,7 @@ class PageArchive {
function __construct( $title ) {
if( is_null( $title ) ) {
- throw new MWException( 'Archiver() given a null title.');
+ throw new MWException( __METHOD__ . ' given a null title.' );
}
$this->title = $title;
}
@@ -50,6 +54,7 @@ class PageArchive {
* given title prefix.
* Returns result wrapper with (ar_namespace, ar_title, count) fields.
*
+ * @param $prefix String: title prefix
* @return ResultWrapper
*/
public static function listPagesByPrefix( $prefix ) {
@@ -153,7 +158,8 @@ class PageArchive {
* Fetch (and decompress if necessary) the stored text for the deleted
* revision of the page with the given timestamp.
*
- * @return string
+ * @param $timestamp String
+ * @return String
* @deprecated Use getRevision() for more flexible information
*/
function getRevisionText( $timestamp ) {
@@ -164,7 +170,8 @@ class PageArchive {
/**
* Return a Revision object containing data for the deleted revision.
* Note that the result *may* or *may not* have a null page ID.
- * @param string $timestamp
+ *
+ * @param $timestamp String
* @return Revision
*/
function getRevision( $timestamp ) {
@@ -200,7 +207,7 @@ class PageArchive {
* May produce unexpected results in case of history merges or other
* unusual time issues.
*
- * @param string $timestamp
+ * @param $timestamp String
* @return Revision or null
*/
function getPreviousRevision( $timestamp ) {
@@ -248,6 +255,9 @@ class PageArchive {
/**
* Get the text from an archive row containing ar_text, ar_flags and ar_text_id
+ *
+ * @param $row Object: database row
+ * @return Revision
*/
function getTextFromRow( $row ) {
if( is_null( $row->ar_text_id ) ) {
@@ -272,7 +282,7 @@ class PageArchive {
*
* If there are no archived revisions for the page, returns NULL.
*
- * @return string
+ * @return String
*/
function getLastRevisionText() {
$dbr = wfGetDB( DB_SLAVE );
@@ -280,7 +290,7 @@ class PageArchive {
array( 'ar_text', 'ar_flags', 'ar_text_id' ),
array( 'ar_namespace' => $this->title->getNamespace(),
'ar_title' => $this->title->getDBkey() ),
- 'PageArchive::getLastRevisionText',
+ __METHOD__,
array( 'ORDER BY' => 'ar_timestamp DESC' ) );
if( $row ) {
return $this->getTextFromRow( $row );
@@ -291,7 +301,8 @@ class PageArchive {
/**
* Quick check if any archived revisions are present for the page.
- * @return bool
+ *
+ * @return Boolean
*/
function isDeleted() {
$dbr = wfGetDB( DB_SLAVE );
@@ -306,10 +317,10 @@ class PageArchive {
* Once restored, the items will be removed from the archive tables.
* The deletion log will be updated with an undeletion notice.
*
- * @param array $timestamps Pass an empty array to restore all revisions, otherwise list the ones to undelete.
- * @param string $comment
- * @param array $fileVersions
- * @param bool $unsuppress
+ * @param $timestamps Array: pass an empty array to restore all revisions, otherwise list the ones to undelete.
+ * @param $comment String
+ * @param $fileVersions Array
+ * @param $unsuppress Boolean
*
* @return array(number of file revisions restored, number of image revisions restored, log message)
* on success, false on failure
@@ -369,12 +380,11 @@ class PageArchive {
* to the cur/old tables. If the page currently exists, all revisions will
* be stuffed into old, otherwise the most recent will go into cur.
*
- * @param array $timestamps Pass an empty array to restore all revisions, otherwise list the ones to undelete.
- * @param string $comment
- * @param array $fileVersions
- * @param bool $unsuppress, remove all ar_deleted/fa_deleted restrictions of seletected revs
+ * @param $timestamps Array: pass an empty array to restore all revisions, otherwise list the ones to undelete.
+ * @param $comment String
+ * @param $unsuppress Boolean: remove all ar_deleted/fa_deleted restrictions of seletected revs
*
- * @return mixed number of revisions restored or false on failure
+ * @return Mixed: number of revisions restored or false on failure
*/
private function undeleteRevisions( $timestamps, $unsuppress = false, $comment = '' ) {
if ( wfReadOnly() )
@@ -482,7 +492,7 @@ class PageArchive {
$revision = null;
$restored = 0;
- while( $row = $ret->fetchObject() ) {
+ foreach ( $ret as $row ) {
// Check for key dupes due to shitty archive integrity.
if( $row->ar_rev_id ) {
$exists = $dbw->selectField( 'revision', '1', array('rev_id' => $row->ar_rev_id), __METHOD__ );
@@ -490,12 +500,12 @@ class PageArchive {
}
// Insert one revision at a time...maintaining deletion status
// unless we are specifically removing all restrictions...
- $revision = Revision::newFromArchiveRow( $row,
- array(
- 'page' => $pageId,
+ $revision = Revision::newFromArchiveRow( $row,
+ array(
+ 'page' => $pageId,
'deleted' => $unsuppress ? 0 : $row->ar_deleted
) );
-
+
$revision->insertOn( $dbw );
$restored++;
@@ -508,7 +518,7 @@ class PageArchive {
'ar_title' => $this->title->getDBkey(),
$oldones ),
__METHOD__ );
-
+
// Was anything restored at all?
if( $restored == 0 )
return 0;
@@ -535,7 +545,8 @@ class PageArchive {
}
} else {
// Revision couldn't be created. This is very weird
- return self::UNDELETE_UNKNOWNERR;
+ wfDebug( "Undelete: unknown error...\n" );
+ return false;
}
return $restored;
@@ -545,36 +556,45 @@ class PageArchive {
}
/**
- * The HTML form for Special:Undelete, which allows users with the appropriate
- * permissions to view and restore deleted content.
+ * Special page allowing users with the appropriate permissions to view
+ * and restore deleted content.
+ *
* @ingroup SpecialPage
*/
-class UndeleteForm {
+class UndeleteForm extends SpecialPage {
var $mAction, $mTarget, $mTimestamp, $mRestore, $mInvert, $mTargetObj;
- var $mTargetTimestamp, $mAllowed, $mCanView, $mComment, $mToken;
+ var $mTargetTimestamp, $mAllowed, $mCanView, $mComment, $mToken, $mRequest;
- function UndeleteForm( $request, $par = "" ) {
+ function __construct( $request = null ) {
+ parent::__construct( 'Undelete', 'deletedhistory' );
+
+ if ( $request === null ) {
+ global $wgRequest;
+ $this->mRequest = $wgRequest;
+ } else {
+ $this->mRequest = $request;
+ }
+ }
+
+ function loadRequest() {
global $wgUser;
- $this->mAction = $request->getVal( 'action' );
- $this->mTarget = $request->getVal( 'target' );
- $this->mSearchPrefix = $request->getText( 'prefix' );
- $time = $request->getVal( 'timestamp' );
+ $this->mAction = $this->mRequest->getVal( 'action' );
+ $this->mTarget = $this->mRequest->getVal( 'target' );
+ $this->mSearchPrefix = $this->mRequest->getText( 'prefix' );
+ $time = $this->mRequest->getVal( 'timestamp' );
$this->mTimestamp = $time ? wfTimestamp( TS_MW, $time ) : '';
- $this->mFile = $request->getVal( 'file' );
-
- $posted = $request->wasPosted() &&
- $wgUser->matchEditToken( $request->getVal( 'wpEditToken' ) );
- $this->mRestore = $request->getCheck( 'restore' ) && $posted;
- $this->mInvert = $request->getCheck( 'invert' ) && $posted;
- $this->mPreview = $request->getCheck( 'preview' ) && $posted;
- $this->mDiff = $request->getCheck( 'diff' );
- $this->mComment = $request->getText( 'wpComment' );
- $this->mUnsuppress = $request->getVal( 'wpUnsuppress' ) && $wgUser->isAllowed( 'suppressrevision' );
- $this->mToken = $request->getVal( 'token' );
-
- if( $par != "" ) {
- $this->mTarget = $par;
- }
+ $this->mFile = $this->mRequest->getVal( 'file' );
+
+ $posted = $this->mRequest->wasPosted() &&
+ $wgUser->matchEditToken( $this->mRequest->getVal( 'wpEditToken' ) );
+ $this->mRestore = $this->mRequest->getCheck( 'restore' ) && $posted;
+ $this->mInvert = $this->mRequest->getCheck( 'invert' ) && $posted;
+ $this->mPreview = $this->mRequest->getCheck( 'preview' ) && $posted;
+ $this->mDiff = $this->mRequest->getCheck( 'diff' );
+ $this->mComment = $this->mRequest->getText( 'wpComment' );
+ $this->mUnsuppress = $this->mRequest->getVal( 'wpUnsuppress' ) && $wgUser->isAllowed( 'suppressrevision' );
+ $this->mToken = $this->mRequest->getVal( 'token' );
+
if ( $wgUser->isAllowed( 'undelete' ) && !$wgUser->isBlocked() ) {
$this->mAllowed = true; // user can restore
$this->mCanView = true; // user can view content
@@ -587,11 +607,7 @@ class UndeleteForm {
$this->mTimestamp = '';
$this->mRestore = false;
}
- if ( $this->mTarget !== "" ) {
- $this->mTargetObj = Title::newFromURL( $this->mTarget );
- } else {
- $this->mTargetObj = null;
- }
+
if( $this->mRestore || $this->mInvert ) {
$timestamps = array();
$this->mFileVersions = array();
@@ -610,14 +626,33 @@ class UndeleteForm {
}
}
- function execute() {
+ function execute( $par ) {
global $wgOut, $wgUser;
+
+ $this->setHeaders();
+ if ( !$this->userCanExecute( $wgUser ) ) {
+ $this->displayRestrictionError();
+ return;
+ }
+ $this->outputHeader();
+
+ $this->loadRequest();
+
if ( $this->mAllowed ) {
$wgOut->setPagetitle( wfMsg( "undeletepage" ) );
} else {
$wgOut->setPagetitle( wfMsg( "viewdeletedpage" ) );
}
+ if( $par != '' ) {
+ $this->mTarget = $par;
+ }
+ if ( $this->mTarget !== '' ) {
+ $this->mTargetObj = Title::newFromURL( $this->mTarget );
+ } else {
+ $this->mTargetObj = null;
+ }
+
if( is_null( $this->mTargetObj ) ) {
# Not all users can just browse every deleted page from the list
if( $wgUser->isAllowed( 'browsearchive' ) ) {
@@ -659,7 +694,7 @@ class UndeleteForm {
if( $this->mRestore && $this->mAction == "submit" ) {
global $wgUploadMaintenance;
if( $wgUploadMaintenance && $this->mTargetObj && $this->mTargetObj->getNamespace() == NS_FILE ) {
- $wgOut->wrapWikiMsg( "<div class='error'>\n$1</div>\n", array( 'filedelete-maintenance' ) );
+ $wgOut->wrapWikiMsg( "<div class='error'>\n$1\n</div>\n", array( 'filedelete-maintenance' ) );
return;
}
return $this->undelete();
@@ -679,8 +714,8 @@ class UndeleteForm {
'method' => 'get',
'action' => $wgScript ) ) .
Xml::fieldset( wfMsg( 'undelete-search-box' ) ) .
- Xml::hidden( 'title',
- SpecialPage::getTitleFor( 'Undelete' )->getPrefixedDbKey() ) .
+ Html::hidden( 'title',
+ $this->getTitle()->getPrefixedDbKey() ) .
Xml::inputLabel( wfMsg( 'undelete-search-prefix' ),
'prefix', 'prefix', 20,
$this->mSearchPrefix ) . ' ' .
@@ -692,7 +727,7 @@ class UndeleteForm {
// Generic list of deleted pages
private function showList( $result ) {
- global $wgLang, $wgContLang, $wgUser, $wgOut;
+ global $wgLang, $wgUser, $wgOut;
if( $result->numRows() == 0 ) {
$wgOut->addWikiMsg( 'undelete-no-results' );
@@ -702,9 +737,9 @@ class UndeleteForm {
$wgOut->addWikiMsg( 'undeletepagetext', $wgLang->formatNum( $result->numRows() ) );
$sk = $wgUser->getSkin();
- $undelete = SpecialPage::getTitleFor( 'Undelete' );
+ $undelete = $this->getTitle();
$wgOut->addHTML( "<ul>\n" );
- while( $row = $result->fetchObject() ) {
+ foreach ( $result as $row ) {
$title = Title::makeTitleSafe( $row->ar_namespace, $row->ar_title );
$link = $sk->linkKnown(
$undelete,
@@ -725,7 +760,7 @@ class UndeleteForm {
private function showRevision( $timestamp ) {
global $wgLang, $wgUser, $wgOut;
- $self = SpecialPage::getTitleFor( 'Undelete' );
+
$skin = $wgUser->getSkin();
if(!preg_match("/[0-9]{14}/",$timestamp)) return 0;
@@ -740,10 +775,10 @@ class UndeleteForm {
if( $rev->isDeleted(Revision::DELETED_TEXT) ) {
if( !$rev->userCan(Revision::DELETED_TEXT) ) {
- $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1</div>\n", 'rev-deleted-text-permission' );
+ $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", 'rev-deleted-text-permission' );
return;
} else {
- $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1</div>\n", 'rev-deleted-text-view' );
+ $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", 'rev-deleted-text-view' );
$wgOut->addHTML( '<br />' );
// and we are allowed to see...
}
@@ -752,7 +787,7 @@ class UndeleteForm {
$wgOut->setPageTitle( wfMsg( 'undeletepage' ) );
$link = $skin->linkKnown(
- SpecialPage::getTitleFor( 'Undelete', $this->mTargetObj->getPrefixedDBkey() ),
+ $this->getTitle( $this->mTargetObj->getPrefixedDBkey() ),
htmlspecialchars( $this->mTargetObj->getPrefixedText() )
);
@@ -823,7 +858,7 @@ class UndeleteForm {
Xml::openElement( 'div' ) .
Xml::openElement( 'form', array(
'method' => 'post',
- 'action' => $self->getLocalURL( array( 'action' => 'submit' ) ) ) ) .
+ 'action' => $this->getTitle()->getLocalURL( array( 'action' => 'submit' ) ) ) ) .
Xml::element( 'input', array(
'type' => 'hidden',
'name' => 'target',
@@ -851,14 +886,15 @@ class UndeleteForm {
/**
* Build a diff display between this and the previous either deleted
* or non-deleted edit.
- * @param Revision $previousRev
- * @param Revision $currentRev
- * @return string HTML
+ *
+ * @param $previousRev Revision
+ * @param $currentRev Revision
+ * @return String: HTML
*/
function showDiff( $previousRev, $currentRev ) {
global $wgOut;
- $diffEngine = new DifferenceEngine();
+ $diffEngine = new DifferenceEngine( $previousRev->getTitle() );
$diffEngine->showDiffStyle();
$wgOut->addHTML(
"<div>" .
@@ -888,7 +924,7 @@ class UndeleteForm {
$isDeleted = !( $rev->getId() && $rev->getTitle() );
if( $isDeleted ) {
/// @todo Fixme: $rev->getTitle() is null for deleted revs...?
- $targetPage = SpecialPage::getTitleFor( 'Undelete' );
+ $targetPage = $this->getTitle();
$targetQuery = array(
'target' => $this->mTargetObj->getPrefixedText(),
'timestamp' => wfTimestamp( TS_MW, $rev->getTimestamp() )
@@ -905,7 +941,7 @@ class UndeleteForm {
if( !$rev->userCan( Revision::DELETED_RESTRICTED ) ) {
$del .= $sk->revDeleteLinkDisabled( $canHide ); // revision was hidden from sysops
} else {
- $query = array(
+ $query = array(
'type' => 'archive',
'target' => $this->mTargetObj->getPrefixedDbkey(),
'ids' => $rev->getTimestamp()
@@ -948,10 +984,10 @@ class UndeleteForm {
$this->mTargetObj->getText(),
$wgLang->date( $file->getTimestamp() ),
$wgLang->time( $file->getTimestamp() ) );
- $wgOut->addHTML(
- Xml::openElement( 'form', array(
+ $wgOut->addHTML(
+ Xml::openElement( 'form', array(
'method' => 'POST',
- 'action' => SpecialPage::getTitleFor( 'Undelete' )->getLocalUrl(
+ 'action' => $this->getTitle()->getLocalUrl(
'target=' . urlencode( $this->mTarget ) .
'&file=' . urlencode( $key ) .
'&token=' . urlencode( $wgUser->editToken( $key ) ) )
@@ -979,13 +1015,13 @@ class UndeleteForm {
global $IP;
require_once( "$IP/includes/StreamFile.php" );
- $repo = RepoGroup::singleton()->getLocalRepo();
+ $repo = RepoGroup::singleton()->getLocalRepo();
$path = $repo->getZonePath( 'deleted' ) . '/' . $repo->getDeletedHashPath( $key ) . $key;
wfStreamFile( $path );
}
private function showHistory( ) {
- global $wgLang, $wgUser, $wgOut;
+ global $wgUser, $wgOut;
$sk = $wgUser->getSkin();
if( $this->mAllowed ) {
@@ -994,7 +1030,7 @@ class UndeleteForm {
$wgOut->setPagetitle( wfMsg( 'viewdeletedpage' ) );
}
- $wgOut->wrapWikiMsg( "<div class='mw-undelete-pagetitle'>\n$1</div>\n", array ( 'undeletepagetitle', $this->mTargetObj->getPrefixedText() ) );
+ $wgOut->wrapWikiMsg( "<div class='mw-undelete-pagetitle'>\n$1\n</div>\n", array ( 'undeletepagetitle', $this->mTargetObj->getPrefixedText() ) );
$archive = new PageArchive( $this->mTargetObj );
/*
@@ -1023,7 +1059,7 @@ class UndeleteForm {
# Batch existence check on user and talk pages
if( $haveRevisions ) {
$batch = new LinkBatch();
- while( $row = $revisions->fetchObject() ) {
+ foreach ( $revisions as $row ) {
$batch->addObj( Title::makeTitleSafe( NS_USER, $row->ar_user_text ) );
$batch->addObj( Title::makeTitleSafe( NS_USER_TALK, $row->ar_user_text ) );
}
@@ -1032,7 +1068,7 @@ class UndeleteForm {
}
if( $haveFiles ) {
$batch = new LinkBatch();
- while( $row = $files->fetchObject() ) {
+ foreach ( $files as $row ) {
$batch->addObj( Title::makeTitleSafe( NS_USER, $row->fa_user_text ) );
$batch->addObj( Title::makeTitleSafe( NS_USER_TALK, $row->fa_user_text ) );
}
@@ -1041,8 +1077,7 @@ class UndeleteForm {
}
if ( $this->mAllowed ) {
- $titleObj = SpecialPage::getTitleFor( "Undelete" );
- $action = $titleObj->getLocalURL( array( 'action' => 'submit' ) );
+ $action = $this->getTitle()->getLocalURL( array( 'action' => 'submit' ) );
# Start the form here
$top = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $action, 'id' => 'undelete' ) );
$wgOut->addHTML( $top );
@@ -1063,7 +1098,7 @@ class UndeleteForm {
if( $wgUser->isAllowed( 'suppressrevision' ) ) {
$unsuppressBox =
"<tr>
- <td>&nbsp;</td>
+ <td>&#160;</td>
<td class='mw-input'>" .
Xml::checkLabel( wfMsg('revdelete-unsuppress'), 'wpUnsuppress',
'mw-undelete-unsuppress', $this->mUnsuppress ).
@@ -1089,7 +1124,7 @@ class UndeleteForm {
"</td>
</tr>
<tr>
- <td>&nbsp;</td>
+ <td>&#160;</td>
<td class='mw-submit'>" .
Xml::submitButton( wfMsg( 'undeletebtn' ), array( 'name' => 'restore', 'id' => 'mw-undelete-submit' ) ) . ' ' .
Xml::element( 'input', array( 'type' => 'reset', 'value' => wfMsg( 'undeletereset' ), 'id' => 'mw-undelete-reset' ) ) . ' ' .
@@ -1108,11 +1143,10 @@ class UndeleteForm {
if( $haveRevisions ) {
# The page's stored (deleted) history:
$wgOut->addHTML("<ul>");
- $target = urlencode( $this->mTarget );
$remaining = $revisions->numRows();
$earliestLiveTime = $this->mTargetObj->getEarliestRevTime();
- while( $row = $revisions->fetchObject() ) {
+ foreach ( $revisions as $row ) {
$remaining--;
$wgOut->addHTML( $this->formatRevisionRow( $row, $earliestLiveTime, $remaining, $sk ) );
}
@@ -1125,7 +1159,7 @@ class UndeleteForm {
if( $haveFiles ) {
$wgOut->addHTML( Xml::element( 'h2', null, wfMsg( 'filehist' ) ) . "\n" );
$wgOut->addHTML( "<ul>" );
- while( $row = $files->fetchObject() ) {
+ foreach ( $files as $row ) {
$wgOut->addHTML( $this->formatFileRow( $row, $sk ) );
}
$files->free();
@@ -1134,8 +1168,8 @@ class UndeleteForm {
if ( $this->mAllowed ) {
# Slip in the hidden controls here
- $misc = Xml::hidden( 'target', $this->mTarget );
- $misc .= Xml::hidden( 'wpEditToken', $wgUser->editToken() );
+ $misc = Html::hidden( 'target', $this->mTarget );
+ $misc .= Html::hidden( 'wpEditToken', $wgUser->editToken() );
$misc .= Xml::closeElement( 'form' );
$wgOut->addHTML( $misc );
}
@@ -1146,7 +1180,7 @@ class UndeleteForm {
private function formatRevisionRow( $row, $earliestLiveTime, $remaining, $sk ) {
global $wgUser, $wgLang;
- $rev = Revision::newFromArchiveRow( $row,
+ $rev = Revision::newFromArchiveRow( $row,
array( 'page' => $this->mTargetObj->getArticleId() ) );
$stxt = '';
$ts = wfTimestamp( TS_MW, $row->ar_timestamp );
@@ -1166,7 +1200,7 @@ class UndeleteForm {
}
// Build page & diff links...
if( $this->mCanView ) {
- $titleObj = SpecialPage::getTitleFor( "Undelete" );
+ $titleObj = $this->getTitle();
# Last link
if( !$rev->userCan( Revision::DELETED_TEXT ) ) {
$pageLink = htmlspecialchars( $wgLang->timeanddate( $ts, true ) );
@@ -1228,14 +1262,12 @@ class UndeleteForm {
if( $this->mAllowed && $row->fa_storage_key ) {
$checkBox = Xml::check( "fileid" . $row->fa_id );
$key = urlencode( $row->fa_storage_key );
- $target = urlencode( $this->mTarget );
- $titleObj = SpecialPage::getTitleFor( "Undelete" );
- $pageLink = $this->getFileLink( $file, $titleObj, $ts, $key, $sk );
+ $pageLink = $this->getFileLink( $file, $this->getTitle(), $ts, $key, $sk );
} else {
$checkBox = '';
$pageLink = $wgLang->timeanddate( $ts, true );
}
- $userLink = $this->getFileUser( $file, $sk );
+ $userLink = $this->getFileUser( $file, $sk );
$data =
wfMsg( 'widthheight',
$wgLang->formatNum( $row->fa_width ),
@@ -1294,7 +1326,8 @@ class UndeleteForm {
/**
* Fetch image view link if it's available to all users
- * @return string
+ *
+ * @return String: HTML fragment
*/
function getFileLink( $file, $titleObj, $ts, $key, $sk ) {
global $wgLang, $wgUser;
@@ -1320,7 +1353,8 @@ class UndeleteForm {
/**
* Fetch file's user id if it's available to this user
- * @return string
+ *
+ * @return String: HTML fragment
*/
function getFileUser( $file, $sk ) {
if( !$file->userCan(File::DELETED_USER) ) {
@@ -1336,7 +1370,8 @@ class UndeleteForm {
/**
* Fetch file upload comment if it's available to this user
- * @return string
+ *
+ * @return String: HTML fragment
*/
function getFileComment( $file, $sk ) {
if( !$file->userCan(File::DELETED_COMMENT) ) {
diff --git a/includes/specials/SpecialUnlockdb.php b/includes/specials/SpecialUnlockdb.php
index fe38a48a..c71b554b 100644
--- a/includes/specials/SpecialUnlockdb.php
+++ b/includes/specials/SpecialUnlockdb.php
@@ -1,39 +1,62 @@
<?php
/**
+ * Implements Special:Unlockdb
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
+ * Implements Special:Unlockdb
*
+ * @ingroup SpecialPage
*/
-function wfSpecialUnlockdb() {
- global $wgUser, $wgOut, $wgRequest;
+class SpecialUnlockdb extends SpecialPage {
- if( !$wgUser->isAllowed( 'siteadmin' ) ) {
- $wgOut->permissionRequired( 'siteadmin' );
- return;
+ public function __construct() {
+ parent::__construct( 'Unlockdb', 'siteadmin' );
}
- $action = $wgRequest->getVal( 'action' );
- $f = new DBUnlockForm();
+ public function execute( $par ) {
+ global $wgUser, $wgOut, $wgRequest;
+
+ $this->setHeaders();
+
+ if( !$wgUser->isAllowed( 'siteadmin' ) ) {
+ $wgOut->permissionRequired( 'siteadmin' );
+ return;
+ }
+
+ $this->outputHeader();
+
+ $action = $wgRequest->getVal( 'action' );
- if ( "success" == $action ) {
- $f->showSuccess();
- } else if ( "submit" == $action && $wgRequest->wasPosted() &&
- $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
- $f->doSubmit();
- } else {
- $f->showForm( "" );
+ if ( $action == 'success' ) {
+ $this->showSuccess();
+ } else if ( $action == 'submit' && $wgRequest->wasPosted() &&
+ $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
+ $this->doSubmit();
+ } else {
+ $this->showForm();
+ }
}
-}
-/**
- * @ingroup SpecialPage
- */
-class DBUnlockForm {
- function showForm( $err )
- {
+ private function showForm( $err = '' ) {
global $wgOut, $wgUser;
global $wgReadOnlyFile;
@@ -42,65 +65,57 @@ class DBUnlockForm {
return;
}
- $wgOut->setPagetitle( wfMsg( "unlockdb" ) );
- $wgOut->addWikiMsg( "unlockdbtext" );
+ $wgOut->addWikiMsg( 'unlockdbtext' );
- if ( $err != "" ) {
- $wgOut->setSubtitle( wfMsg( "formerror" ) );
+ if ( $err != '' ) {
+ $wgOut->setSubtitle( wfMsg( 'formerror' ) );
$wgOut->addHTML( '<p class="error">' . htmlspecialchars( $err ) . "</p>\n" );
}
- $lc = htmlspecialchars( wfMsg( "unlockconfirm" ) );
- $lb = htmlspecialchars( wfMsg( "unlockbtn" ) );
- $titleObj = SpecialPage::getTitleFor( "Unlockdb" );
- $action = $titleObj->escapeLocalURL( "action=submit" );
- $token = htmlspecialchars( $wgUser->editToken() );
- $wgOut->addHTML( <<<HTML
-
-<form id="unlockdb" method="post" action="{$action}">
-<table border="0">
+ $wgOut->addHTML(
+ Html::openElement( 'form', array( 'id' => 'unlockdb', 'method' => 'POST',
+ 'action' => $this->getTitle()->getLocalURL( 'action=submit' ) ) ) . "
+<table>
<tr>
- <td align="right">
- <input type="checkbox" name="wpLockConfirm" />
+ " . Html::openElement( 'td', array( 'style' => 'text-align:right' ) ) . "
+ " . Html::input( 'wpLockConfirm', null, 'checkbox' ) . "
</td>
- <td align="left">{$lc}</td>
+ " . Html::openElement( 'td', array( 'style' => 'text-align:left' ) ) .
+ wfMsgHtml( 'unlockconfirm' ) . "</td>
</tr>
<tr>
- <td>&nbsp;</td>
- <td align="left">
- <input type="submit" name="wpLock" value="{$lb}" />
+ <td>&#160;</td>
+ " . Html::openElement( 'td', array( 'style' => 'text-align:left' ) ) . "
+ " . Html::input( 'wpLock', wfMsg( 'unlockbtn' ), 'submit' ) . "
</td>
</tr>
-</table>
-<input type="hidden" name="wpEditToken" value="{$token}" />
-</form>
-HTML
-);
+</table>\n" .
+ Html::hidden( 'wpEditToken', $wgUser->editToken() ) . "\n" .
+ Html::closeElement( 'form' )
+ );
}
- function doSubmit() {
+ private function doSubmit() {
global $wgOut, $wgRequest, $wgReadOnlyFile;
$wpLockConfirm = $wgRequest->getCheck( 'wpLockConfirm' );
- if ( ! $wpLockConfirm ) {
- $this->showForm( wfMsg( "locknoconfirm" ) );
+ if ( !$wpLockConfirm ) {
+ $this->showForm( wfMsg( 'locknoconfirm' ) );
return;
}
- if ( @! unlink( $wgReadOnlyFile ) ) {
+ if ( @!unlink( $wgReadOnlyFile ) ) {
$wgOut->showFileDeleteError( $wgReadOnlyFile );
return;
}
- $titleObj = SpecialPage::getTitleFor( "Unlockdb" );
- $success = $titleObj->getFullURL( "action=success" );
- $wgOut->redirect( $success );
+
+ $wgOut->redirect( $this->getTitle()->getFullURL( 'action=success' ) );
}
- function showSuccess() {
+ private function showSuccess() {
global $wgOut;
- $wgOut->setPagetitle( wfMsg( "unlockdb" ) );
- $wgOut->setSubtitle( wfMsg( "unlockdbsuccesssub" ) );
- $wgOut->addWikiMsg( "unlockdbsuccesstext" );
+ $wgOut->setSubtitle( wfMsg( 'unlockdbsuccesssub' ) );
+ $wgOut->addWikiMsg( 'unlockdbsuccesstext' );
}
}
diff --git a/includes/specials/SpecialUnusedcategories.php b/includes/specials/SpecialUnusedcategories.php
index fe7d7a17..a20efe09 100644
--- a/includes/specials/SpecialUnusedcategories.php
+++ b/includes/specials/SpecialUnusedcategories.php
@@ -1,5 +1,22 @@
<?php
/**
+ * Implements Special:Unusedcategories
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
diff --git a/includes/specials/SpecialUnusedimages.php b/includes/specials/SpecialUnusedimages.php
index 9d9868f6..091ec3a3 100644
--- a/includes/specials/SpecialUnusedimages.php
+++ b/includes/specials/SpecialUnusedimages.php
@@ -1,11 +1,29 @@
<?php
/**
+ * Implements Special:Unusedimages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
- * implements Special:Unusedimages
+ * A special page that lists unused images
+ *
* @ingroup SpecialPage
*/
class UnusedimagesPage extends ImageQueryPage {
@@ -22,22 +40,11 @@ class UnusedimagesPage extends ImageQueryPage {
function isSyndicated() { return false; }
function getSQL() {
- global $wgCountCategorizedImagesAsUsed, $wgDBtype;
+ global $wgCountCategorizedImagesAsUsed;
+
$dbr = wfGetDB( DB_SLAVE );
- switch ($wgDBtype) {
- case 'mysql':
- $epoch = 'UNIX_TIMESTAMP(img_timestamp)';
- break;
- case 'oracle':
- $epoch = '((trunc(img_timestamp) - to_date(\'19700101\',\'YYYYMMDD\')) * 86400)';
- break;
- case 'sqlite':
- $epoch = 'img_timestamp';
- break;
- default:
- $epoch = 'EXTRACT(epoch FROM img_timestamp)';
- }
+ $epoch = $dbr->unixTimestamp( 'img_timestamp' );
if ( $wgCountCategorizedImagesAsUsed ) {
list( $page, $image, $imagelinks, $categorylinks ) = $dbr->tableNamesN( 'page', 'image', 'imagelinks', 'categorylinks' );
diff --git a/includes/specials/SpecialUnusedtemplates.php b/includes/specials/SpecialUnusedtemplates.php
index 6ddbab32..68bf95a2 100644
--- a/includes/specials/SpecialUnusedtemplates.php
+++ b/includes/specials/SpecialUnusedtemplates.php
@@ -1,14 +1,32 @@
<?php
/**
+ * Implements Special:Unusedtemplates
+ *
+ * Copyright © 2006 Rob Church
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
+ * @author Rob Church <robchur@gmail.com>
*/
/**
- * implements Special:Unusedtemplates
- * @author Rob Church <robchur@gmail.com>
- * @copyright © 2006 Rob Church
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ * A special page that lists unused templates
+ *
* @ingroup SpecialPage
*/
class UnusedtemplatesPage extends QueryPage {
diff --git a/includes/specials/SpecialUnwatchedpages.php b/includes/specials/SpecialUnwatchedpages.php
index 483afdaa..ecd62cb7 100644
--- a/includes/specials/SpecialUnwatchedpages.php
+++ b/includes/specials/SpecialUnwatchedpages.php
@@ -1,17 +1,33 @@
<?php
/**
+ * Implements Special:Unwatchedpages
+ *
+ * Copyright © 2005 Ævar Arnfjörð Bjarmason
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
+ * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
*/
/**
* A special page that displays a list of pages that are not on anyones watchlist.
- * Implements Special:Unwatchedpages
*
* @ingroup SpecialPage
- * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
class UnwatchedpagesPage extends QueryPage {
diff --git a/includes/specials/SpecialUpload.php b/includes/specials/SpecialUpload.php
index 68ee8efc..893e4be2 100644
--- a/includes/specials/SpecialUpload.php
+++ b/includes/specials/SpecialUpload.php
@@ -1,18 +1,38 @@
<?php
/**
+ * Implements Special:Upload
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
* @ingroup Upload
- *
+ */
+
+/**
* Form for handling uploads and special page.
*
+ * @ingroup SpecialPage
+ * @ingroup Upload
*/
-
class SpecialUpload extends SpecialPage {
/**
* Constructor : initialise object
* Get data POSTed through the form and assign them to the object
- * @param WebRequest $request Data posted.
+ * @param $request WebRequest : data posted.
*/
public function __construct( $request = null ) {
global $wgRequest;
@@ -50,12 +70,11 @@ class SpecialUpload extends SpecialPage {
/** Text injection points for hooks not using HTMLForm **/
public $uploadFormTextTop;
public $uploadFormTextAfterSummary;
-
/**
* Initialize instance variables from request and create an Upload handler
*
- * @param WebRequest $request The request to extract variables from
+ * @param $request WebRequest: the request to extract variables from
*/
protected function loadRequest( $request ) {
global $wgUser;
@@ -63,14 +82,15 @@ class SpecialUpload extends SpecialPage {
$this->mRequest = $request;
$this->mSourceType = $request->getVal( 'wpSourceType', 'file' );
$this->mUpload = UploadBase::createFromRequest( $request );
- $this->mUploadClicked = $request->wasPosted()
- && ( $request->getCheck( 'wpUpload' )
+ $this->mUploadClicked = $request->wasPosted()
+ && ( $request->getCheck( 'wpUpload' )
|| $request->getCheck( 'wpUploadIgnoreWarning' ) );
// Guess the desired name from the filename if not provided
$this->mDesiredDestName = $request->getText( 'wpDestFile' );
- if( !$this->mDesiredDestName && $request->getFileName( 'wpUploadFile' ) !== null )
+ if( !$this->mDesiredDestName && $request->getFileName( 'wpUploadFile' ) !== null ) {
$this->mDesiredDestName = $request->getFileName( 'wpUploadFile' );
+ }
$this->mComment = $request->getText( 'wpUploadDescription' );
$this->mLicense = $request->getText( 'wpLicense' );
@@ -97,7 +117,7 @@ class SpecialUpload extends SpecialPage {
} else {
$this->mTokenOk = $wgUser->matchEditToken( $token );
}
-
+
$this->uploadFormTextTop = '';
$this->uploadFormTextAfterSummary = '';
}
@@ -107,8 +127,8 @@ class SpecialUpload extends SpecialPage {
* Handle permission checking elsewhere in order to be able to show
* custom error messages.
*
- * @param User $user
- * @return bool
+ * @param $user User object
+ * @return Boolean
*/
public function userCanExecute( $user ) {
return UploadBase::isEnabled() && parent::userCanExecute( $user );
@@ -118,7 +138,7 @@ class SpecialUpload extends SpecialPage {
* Special page entry point
*/
public function execute( $par ) {
- global $wgUser, $wgOut, $wgRequest;
+ global $wgUser, $wgOut;
$this->setHeaders();
$this->outputHeader();
@@ -131,13 +151,14 @@ class SpecialUpload extends SpecialPage {
# Check permissions
global $wgGroupPermissions;
- if( !$wgUser->isAllowed( 'upload' ) ) {
+ $permissionRequired = UploadBase::isAllowed( $wgUser );
+ 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( 'upload' );
+ $wgOut->permissionRequired( $permissionRequired );
}
return;
}
@@ -156,69 +177,76 @@ class SpecialUpload extends SpecialPage {
# Unsave the temporary file in case this was a cancelled upload
if ( $this->mCancelUpload ) {
- if ( !$this->unsaveUploadedFile() )
+ if ( !$this->unsaveUploadedFile() ) {
# Something went wrong, so unsaveUploadedFile showed a warning
return;
+ }
}
# Process upload or show a form
- if ( $this->mTokenOk && !$this->mCancelUpload
- && ( $this->mUpload && $this->mUploadClicked ) ) {
+ if (
+ $this->mTokenOk && !$this->mCancelUpload &&
+ ( $this->mUpload && $this->mUploadClicked )
+ )
+ {
$this->processUpload();
} else {
# Backwards compatibility hook
- if( !wfRunHooks( 'UploadForm:initial', array( &$this ) ) )
- {
+ if( !wfRunHooks( 'UploadForm:initial', array( &$this ) ) ) {
wfDebug( "Hook 'UploadForm:initial' broke output of the upload form" );
return;
}
+
$this->showUploadForm( $this->getUploadForm() );
}
# Cleanup
- if ( $this->mUpload )
+ if ( $this->mUpload ) {
$this->mUpload->cleanupTempFile();
+ }
}
/**
- * Show the main upload form
+ * Show the main upload form
*
- * @param mixed $form An HTMLForm instance or HTML string to show
+ * @param $form Mixed: an HTMLForm instance or HTML string to show
*/
protected function showUploadForm( $form ) {
# Add links if file was previously deleted
if ( !$this->mDesiredDestName ) {
$this->showViewDeletedLinks();
}
-
+
if ( $form instanceof HTMLForm ) {
$form->show();
} else {
global $wgOut;
$wgOut->addHTML( $form );
}
-
+
}
/**
* Get an UploadForm instance with title and text properly set.
*
- * @param string $message HTML string to add to the form
- * @param string $sessionKey Session key in case this is a stashed upload
+ * @param $message String: HTML string to add to the form
+ * @param $sessionKey String: session key in case this is a stashed upload
+ * @param $hideIgnoreWarning Boolean: whether to hide "ignore warning" check box
* @return UploadForm
*/
protected function getUploadForm( $message = '', $sessionKey = '', $hideIgnoreWarning = false ) {
global $wgOut;
-
+
# Initialize form
$form = new UploadForm( array(
- 'watch' => $this->getWatchCheck(),
- 'forreupload' => $this->mForReUpload,
+ 'watch' => $this->getWatchCheck(),
+ 'forreupload' => $this->mForReUpload,
'sessionkey' => $sessionKey,
'hideignorewarning' => $hideIgnoreWarning,
'destwarningack' => (bool)$this->mDestWarningAck,
-
+
+ 'description' => $this->mComment,
'texttop' => $this->uploadFormTextTop,
'textaftersummary' => $this->uploadFormTextAfterSummary,
'destfile' => $this->mDesiredDestName,
@@ -226,26 +254,44 @@ class SpecialUpload extends SpecialPage {
$form->setTitle( $this->getTitle() );
# Check the token, but only if necessary
- if( !$this->mTokenOk && !$this->mCancelUpload
- && ( $this->mUpload && $this->mUploadClicked ) ) {
+ if(
+ !$this->mTokenOk && !$this->mCancelUpload &&
+ ( $this->mUpload && $this->mUploadClicked )
+ )
+ {
$form->addPreText( wfMsgExt( 'session_fail_preview', 'parseinline' ) );
}
+ # Give a notice if the user is uploading a file that has been deleted or moved
+ # Note that this is independent from the message 'filewasdeleted' that requires JS
+ $desiredTitleObj = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
+ $delNotice = ''; // empty by default
+ if ( $desiredTitleObj instanceof Title && !$desiredTitleObj->exists() ) {
+ LogEventsList::showLogExtract( $delNotice, array( 'delete', 'move' ),
+ $desiredTitleObj->getPrefixedText(),
+ '', array( 'lim' => 10,
+ 'conds' => array( "log_action != 'revision'" ),
+ 'showIfEmpty' => false,
+ 'msgKey' => array( 'upload-recreate-warning' ) )
+ );
+ }
+ $form->addPreText( $delNotice );
+
# Add text to form
$form->addPreText( '<div id="uploadtext">' .
wfMsgExt( 'uploadtext', 'parse', array( $this->mDesiredDestName ) ) .
'</div>' );
# Add upload error message
$form->addPreText( $message );
-
+
# Add footer to form
$uploadFooter = wfMsgNoTrans( 'uploadfooter' );
if ( $uploadFooter != '-' && !wfEmptyMsg( 'uploadfooter', $uploadFooter ) ) {
$form->addPostText( '<div id="mw-upload-footer-message">'
. $wgOut->parse( $uploadFooter ) . "</div>\n" );
}
-
- return $form;
+
+ return $form;
}
@@ -287,13 +333,13 @@ class SpecialUpload extends SpecialPage {
* essentially means that UploadBase::VERIFICATION_ERROR and
* UploadBase::EMPTY_FILE should not be passed here.
*
- * @param string $message HTML message to be passed to mainUploadForm
+ * @param $message String: HTML message to be passed to mainUploadForm
*/
protected function showRecoverableUploadError( $message ) {
$sessionKey = $this->mUpload->stashSession();
$message = '<h2>' . wfMsgHtml( 'uploadwarning' ) . "</h2>\n" .
'<div class="error">' . $message . "</div>\n";
-
+
$form = $this->getUploadForm( $message, $sessionKey );
$form->setSubmitText( wfMsg( 'upload-tryagain' ) );
$this->showUploadForm( $form );
@@ -302,13 +348,11 @@ class SpecialUpload extends SpecialPage {
* Stashes the upload, shows the main form, but adds an "continue anyway button".
* Also checks whether there are actually warnings to display.
*
- * @param array $warnings
- * @return boolean true if warnings were displayed, false if there are no
+ * @param $warnings Array
+ * @return boolean true if warnings were displayed, false if there are no
* warnings and the should continue processing like there was no warning
*/
protected function showUploadWarning( $warnings ) {
- global $wgUser;
-
# If there are no warnings, or warnings we can ignore, return early.
# mDestWarningAck is set when some javascript has shown the warning
# to the user. mForReUpload is set when the user clicks the "upload a
@@ -322,28 +366,26 @@ class SpecialUpload extends SpecialPage {
$sessionKey = $this->mUpload->stashSession();
- $sk = $wgUser->getSkin();
-
$warningHtml = '<h2>' . wfMsgHtml( 'uploadwarning' ) . "</h2>\n"
. '<ul class="warning">';
foreach( $warnings as $warning => $args ) {
- $msg = '';
- if( $warning == 'exists' ) {
- $msg = "\t<li>" . self::getExistsWarning( $args ) . "</li>\n";
- } elseif( $warning == 'duplicate' ) {
- $msg = self::getDupeWarning( $args );
- } elseif( $warning == 'duplicate-archive' ) {
- $msg = "\t<li>" . wfMsgExt( 'file-deleted-duplicate', 'parseinline',
- array( Title::makeTitle( NS_FILE, $args )->getPrefixedText() ) )
- . "</li>\n";
- } else {
- if ( $args === true )
- $args = array();
- elseif ( !is_array( $args ) )
- $args = array( $args );
- $msg = "\t<li>" . wfMsgExt( $warning, 'parseinline', $args ) . "</li>\n";
+ if( $warning == 'exists' ) {
+ $msg = "\t<li>" . self::getExistsWarning( $args ) . "</li>\n";
+ } elseif( $warning == 'duplicate' ) {
+ $msg = self::getDupeWarning( $args );
+ } elseif( $warning == 'duplicate-archive' ) {
+ $msg = "\t<li>" . wfMsgExt( 'file-deleted-duplicate', 'parseinline',
+ array( Title::makeTitle( NS_FILE, $args )->getPrefixedText() ) )
+ . "</li>\n";
+ } else {
+ if ( $args === true ) {
+ $args = array();
+ } elseif ( !is_array( $args ) ) {
+ $args = array( $args );
}
- $warningHtml .= $msg;
+ $msg = "\t<li>" . wfMsgExt( $warning, 'parseinline', $args ) . "</li>\n";
+ }
+ $warningHtml .= $msg;
}
$warningHtml .= "</ul>\n";
$warningHtml .= wfMsgExt( 'uploadwarning-text', 'parse' );
@@ -354,7 +396,7 @@ class SpecialUpload extends SpecialPage {
$form->addButton( 'wpCancelUpload', wfMsg( 'reuploaddesc' ) );
$this->showUploadForm( $form );
-
+
# Indicate that we showed a form
return true;
}
@@ -362,7 +404,7 @@ class SpecialUpload extends SpecialPage {
/**
* Show the upload form with error message, but do not stash the file.
*
- * @param string $message
+ * @param $message HTML string
*/
protected function showUploadError( $message ) {
$message = '<h2>' . wfMsgHtml( 'uploadwarning' ) . "</h2>\n" .
@@ -377,25 +419,21 @@ class SpecialUpload extends SpecialPage {
protected function processUpload() {
global $wgUser, $wgOut;
- // Verify permissions
- $permErrors = $this->mUpload->verifyPermissions( $wgUser );
- if( $permErrors !== true ) {
- $wgOut->showPermissionsErrorPage( $permErrors );
- return;
- }
-
// Fetch the file if required
$status = $this->mUpload->fetchFile();
if( !$status->isOK() ) {
- $this->showUploadForm( $this->getUploadForm( $wgOut->parse( $status->getWikiText() ) ) );
+ $this->showUploadError( $wgOut->parse( $status->getWikiText() ) );
return;
}
- // Deprecated backwards compatibility hook
- if( !wfRunHooks( 'UploadForm:BeforeProcessing', array( &$this ) ) )
- {
+ if( !wfRunHooks( 'UploadForm:BeforeProcessing', array( &$this ) ) ) {
wfDebug( "Hook 'UploadForm:BeforeProcessing' broke processing the file.\n" );
- return array( 'status' => UploadBase::BEFORE_PROCESSING );
+ // This code path is deprecated. If you want to break upload processing
+ // do so by hooking into the appropriate hooks in UploadBase::verifyUpload
+ // and UploadBase::verifyFile.
+ // If you use this hook to break uploading, the user will be returned
+ // an empty form with no error message whatsoever.
+ return;
}
@@ -405,6 +443,15 @@ class SpecialUpload extends SpecialPage {
$this->processVerificationError( $details );
return;
}
+
+ // Verify permissions for this title
+ $permErrors = $this->mUpload->verifyPermissions( $wgUser );
+ if( $permErrors !== true ) {
+ $code = array_shift( $permErrors[0] );
+ $this->showRecoverableUploadError( wfMsgExt( $code,
+ 'parseinline', $permErrors[0] ) );
+ return;
+ }
$this->mLocalFile = $this->mUpload->getLocalFile();
@@ -433,28 +480,41 @@ class SpecialUpload extends SpecialPage {
$this->mUploadSuccessful = true;
wfRunHooks( 'SpecialUploadComplete', array( &$this ) );
$wgOut->redirect( $this->mLocalFile->getTitle()->getFullURL() );
-
}
/**
* Get the initial image page text based on a comment and optional file status information
*/
public static function getInitialPageText( $comment = '', $license = '', $copyStatus = '', $source = '' ) {
- global $wgUseCopyrightUpload;
+ global $wgUseCopyrightUpload, $wgForceUIMsgAsContentMsg;
+ $wgForceUIMsgAsContentMsg = (array) $wgForceUIMsgAsContentMsg;
+
+ /* 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.
+ */
+ foreach( array( 'license-header', 'filedesc', 'filestatus', 'filesource' ) as $msgName ) {
+ if ( in_array( $msgName, $wgForceUIMsgAsContentMsg ) ) {
+ $msg[$msgName] = "{{int:$msgName}}";
+ } else {
+ $msg[$msgName] = wfMsgForContent( $msgName );
+ }
+ }
+
if ( $wgUseCopyrightUpload ) {
$licensetxt = '';
if ( $license != '' ) {
- $licensetxt = '== ' . wfMsgForContent( 'license-header' ) . " ==\n" . '{{' . $license . '}}' . "\n";
+ $licensetxt = '== ' . $msg[ 'license-header' ] . " ==\n" . '{{' . $license . '}}' . "\n";
}
- $pageText = '== ' . wfMsgForContent ( 'filedesc' ) . " ==\n" . $comment . "\n" .
- '== ' . wfMsgForContent ( 'filestatus' ) . " ==\n" . $copyStatus . "\n" .
- "$licensetxt" .
- '== ' . wfMsgForContent ( 'filesource' ) . " ==\n" . $source ;
+ $pageText = '== ' . $msg[ 'filedesc' ] . " ==\n" . $comment . "\n" .
+ '== ' . $msg[ 'filestatus' ] . " ==\n" . $copyStatus . "\n" .
+ "$licensetxt" .
+ '== ' . $msg[ 'filesource' ] . " ==\n" . $source;
} else {
if ( $license != '' ) {
- $filedesc = $comment == '' ? '' : '== ' . wfMsgForContent ( 'filedesc' ) . " ==\n" . $comment . "\n";
- $pageText = $filedesc .
- '== ' . wfMsgForContent ( 'license-header' ) . " ==\n" . '{{' . $license . '}}' . "\n";
+ $filedesc = $comment == '' ? '' : '== ' . $msg[ 'filedesc' ] . " ==\n" . $comment . "\n";
+ $pageText = $filedesc .
+ '== ' . $msg[ 'license-header' ] . " ==\n" . '{{' . $license . '}}' . "\n";
} else {
$pageText = $comment;
}
@@ -495,7 +555,7 @@ class SpecialUpload extends SpecialPage {
/**
* Provides output to the user for a result of UploadBase::verifyUpload
*
- * @param array $details Result of UploadBase::verifyUpload
+ * @param $details Array: result of UploadBase::verifyUpload
*/
protected function processVerificationError( $details ) {
global $wgFileExtensions, $wgLang;
@@ -510,10 +570,6 @@ class SpecialUpload extends SpecialPage {
$this->showRecoverableUploadError( wfMsgExt( 'illegalfilename',
'parseinline', $details['filtered'] ) );
break;
- case UploadBase::OVERWRITE_EXISTING_FILE:
- $this->showRecoverableUploadError( wfMsgExt( $details['overwrite'],
- 'parseinline' ) );
- break;
case UploadBase::FILETYPE_MISSING:
$this->showRecoverableUploadError( wfMsgExt( 'filetype-missing',
'parseinline' ) );
@@ -521,7 +577,10 @@ class SpecialUpload extends SpecialPage {
/** Statuses that require reuploading **/
case UploadBase::EMPTY_FILE:
- $this->showUploadForm( $this->getUploadForm( wfMsgHtml( 'emptyfile' ) ) );
+ $this->showUploadError( wfMsgHtml( 'emptyfile' ) );
+ break;
+ case UploadBase::FILE_TOO_LARGE:
+ $this->showUploadError( wfMsgHtml( 'largefileserver' ) );
break;
case UploadBase::FILETYPE_BADTYPE:
$finalExt = $details['finalExt'];
@@ -560,15 +619,16 @@ class SpecialUpload extends SpecialPage {
/**
* Remove a temporarily kept file stashed by saveTempUploadedFile().
- * @access private
- * @return success
+ *
+ * @return Boolean: success
*/
protected function unsaveUploadedFile() {
global $wgOut;
- if ( !( $this->mUpload instanceof UploadFromStash ) )
+ if ( !( $this->mUpload instanceof UploadFromStash ) ) {
return true;
+ }
$success = $this->mUpload->unsaveUploadedFile();
- if ( ! $success ) {
+ if ( !$success ) {
$wgOut->showFileDeleteError( $this->mUpload->getTempPath() );
return false;
} else {
@@ -582,14 +642,15 @@ class SpecialUpload extends SpecialPage {
* Formats a result of UploadBase::getExistsWarning as HTML
* This check is static and can be done pre-upload via AJAX
*
- * @param array $exists The result of UploadBase::getExistsWarning
- * @return string Empty string if there is no warning or an HTML fragment
+ * @param $exists Array: the result of UploadBase::getExistsWarning
+ * @return String: empty string if there is no warning or an HTML fragment
*/
public static function getExistsWarning( $exists ) {
- global $wgUser, $wgContLang;
+ global $wgUser;
- if ( !$exists )
+ if ( !$exists ) {
return '';
+ }
$file = $exists['file'];
$filename = $file->getTitle()->getPrefixedText();
@@ -638,8 +699,8 @@ class SpecialUpload extends SpecialPage {
/**
* Get a list of warnings
*
- * @param string local filename, e.g. 'file exists', 'non-descriptive filename'
- * @return array list of warning messages
+ * @param $filename String: local filename, e.g. 'file exists', 'non-descriptive filename'
+ * @return Array: list of warning messages
*/
public static function ajaxGetExistsWarning( $filename ) {
$file = wfFindFile( $filename );
@@ -648,7 +709,7 @@ class SpecialUpload extends SpecialPage {
// if there isn't an exact match...
$file = wfLocalFile( $filename );
}
- $s = '&nbsp;';
+ $s = '&#160;';
if ( $file ) {
$exists = UploadBase::getExistsWarning( $file );
$warning = self::getExistsWarning( $exists );
@@ -665,15 +726,15 @@ class SpecialUpload extends SpecialPage {
public static function getDupeWarning( $dupes ) {
if( $dupes ) {
global $wgOut;
- $msg = "<gallery>";
+ $msg = '<gallery>';
foreach( $dupes as $file ) {
$title = $file->getTitle();
$msg .= $title->getPrefixedText() .
- "|" . $title->getText() . "\n";
+ '|' . $title->getText() . "\n";
}
- $msg .= "</gallery>";
- return "<li>" .
- wfMsgExt( "file-exists-duplicate", array( "parse" ), count( $dupes ) ) .
+ $msg .= '</gallery>';
+ return '<li>' .
+ wfMsgExt( 'file-exists-duplicate', array( 'parse' ), count( $dupes ) ) .
$wgOut->parse( $msg ) .
"</li>\n";
} else {
@@ -694,25 +755,30 @@ class UploadForm extends HTMLForm {
protected $mDestWarningAck;
protected $mDestFile;
+ protected $mComment;
protected $mTextTop;
protected $mTextAfterSummary;
-
+
protected $mSourceIds;
public function __construct( $options = array() ) {
- global $wgLang;
-
$this->mWatch = !empty( $options['watch'] );
$this->mForReUpload = !empty( $options['forreupload'] );
- $this->mSessionKey = isset( $options['sessionkey'] )
+ $this->mSessionKey = isset( $options['sessionkey'] )
? $options['sessionkey'] : '';
$this->mHideIgnoreWarning = !empty( $options['hideignorewarning'] );
$this->mDestWarningAck = !empty( $options['destwarningack'] );
-
- $this->mTextTop = $options['texttop'];
- $this->mTextAfterSummary = $options['textaftersummary'];
$this->mDestFile = isset( $options['destfile'] ) ? $options['destfile'] : '';
+ $this->mComment = isset( $options['description'] ) ?
+ $options['description'] : '';
+
+ $this->mTextTop = isset( $options['texttop'] )
+ ? $options['texttop'] : '';
+
+ $this->mTextAfterSummary = isset( $options['textaftersummary'] )
+ ? $options['textaftersummary'] : '';
+
$sourceDescriptor = $this->getSourceSection();
$descriptor = $sourceDescriptor
+ $this->getDescriptionSection()
@@ -724,34 +790,37 @@ class UploadForm extends HTMLForm {
# Set some form properties
$this->setSubmitText( wfMsg( 'uploadbtn' ) );
$this->setSubmitName( 'wpUpload' );
+ # Used message keys: 'accesskey-upload', 'tooltip-upload'
$this->setSubmitTooltip( 'upload' );
$this->setId( 'mw-upload-form' );
# Build a list of IDs for javascript insertion
$this->mSourceIds = array();
- foreach ( $sourceDescriptor as $key => $field ) {
- if ( !empty( $field['id'] ) )
+ foreach ( $sourceDescriptor as $field ) {
+ if ( !empty( $field['id'] ) ) {
$this->mSourceIds[] = $field['id'];
+ }
}
}
/**
- * Get the descriptor of the fieldset that contains the file source
+ * Get the descriptor of the fieldset that contains the file source
* selection. The section is 'source'
- *
- * @return array Descriptor array
+ *
+ * @return Array: descriptor array
*/
protected function getSourceSection() {
global $wgLang, $wgUser, $wgRequest;
+ global $wgMaxUploadSize;
if ( $this->mSessionKey ) {
return array(
- 'wpSessionKey' => array(
+ 'SessionKey' => array(
'type' => 'hidden',
'default' => $this->mSessionKey,
),
- 'wpSourceType' => array(
+ 'SourceType' => array(
'type' => 'hidden',
'default' => 'Stash',
),
@@ -771,25 +840,28 @@ class UploadForm extends HTMLForm {
'raw' => true,
);
}
-
+
$descriptor['UploadFile'] = array(
- 'class' => 'UploadSourceField',
- 'section' => 'source',
- 'type' => 'file',
- 'id' => 'wpUploadFile',
- 'label-message' => 'sourcefilename',
- 'upload-type' => 'File',
- 'radio' => &$radio,
- 'help' => wfMsgExt( 'upload-maxfilesize',
- array( 'parseinline', 'escapenoentities' ),
- $wgLang->formatSize(
- wfShorthandToInteger( ini_get( 'upload_max_filesize' ) )
- )
- ) . ' ' . wfMsgHtml( 'upload_source_file' ),
- 'checked' => $selectedSourceType == 'file',
+ 'class' => 'UploadSourceField',
+ 'section' => 'source',
+ 'type' => 'file',
+ 'id' => 'wpUploadFile',
+ 'label-message' => 'sourcefilename',
+ 'upload-type' => 'File',
+ 'radio' => &$radio,
+ 'help' => wfMsgExt( 'upload-maxfilesize',
+ array( 'parseinline', 'escapenoentities' ),
+ $wgLang->formatSize(
+ wfShorthandToInteger( min(
+ wfShorthandToInteger(
+ ini_get( 'upload_max_filesize' )
+ ), $wgMaxUploadSize
+ ) )
+ )
+ ) . ' ' . wfMsgHtml( 'upload_source_file' ),
+ 'checked' => $selectedSourceType == 'file',
);
if ( $canUploadByUrl ) {
- global $wgMaxUploadSize;
$descriptor['UploadFileURL'] = array(
'class' => 'UploadSourceField',
'section' => 'source',
@@ -815,11 +887,10 @@ class UploadForm extends HTMLForm {
return $descriptor;
}
-
/**
* Get the messages indicating which extensions are preferred and prohibitted.
- *
- * @return string HTML string containing the message
+ *
+ * @return String: HTML string containing the message
*/
protected function getExtensionsMessage() {
# Print a list of allowed file extensions, if so configured. We ignore
@@ -827,7 +898,6 @@ class UploadForm extends HTMLForm {
global $wgLang, $wgCheckFileExtensions, $wgStrictFileExtensions,
$wgFileExtensions, $wgFileBlacklist;
- $allowedExtensions = '';
if( $wgCheckFileExtensions ) {
if( $wgStrictFileExtensions ) {
# Everything not permitted is banned
@@ -855,16 +925,11 @@ class UploadForm extends HTMLForm {
/**
* Get the descriptor of the fieldset that contains the file description
* input. The section is 'description'
- *
- * @return array Descriptor array
+ *
+ * @return Array: descriptor array
*/
protected function getDescriptionSection() {
- global $wgUser, $wgOut;
-
- $cols = intval( $wgUser->getOption( 'cols' ) );
- if( $wgUser->getOption( 'editwidth' ) ) {
- $wgOut->addInlineStyle( '#mw-htmlform-description { width: 100%; }' );
- }
+ global $wgUser;
$descriptor = array(
'DestFile' => array(
@@ -884,7 +949,8 @@ class UploadForm extends HTMLForm {
'label-message' => $this->mForReUpload
? 'filereuploadsummary'
: 'fileuploadsummary',
- 'cols' => $cols,
+ 'default' => $this->mComment,
+ 'cols' => intval( $wgUser->getOption( 'cols' ) ),
'rows' => 8,
)
);
@@ -896,22 +962,25 @@ class UploadForm extends HTMLForm {
'raw' => true,
);
}
-
+
$descriptor += array(
'EditTools' => array(
'type' => 'edittools',
'section' => 'description',
- ),
- 'License' => array(
+ )
+ );
+
+ if ( $this->mForReUpload ) {
+ $descriptor['DestFile']['readonly'] = true;
+ } else {
+ $descriptor['License'] = array(
'type' => 'select',
'class' => 'Licenses',
'section' => 'description',
'id' => 'wpLicense',
'label-message' => 'license',
- ),
- );
- if ( $this->mForReUpload )
- $descriptor['DestFile']['readonly'] = true;
+ );
+ }
global $wgUseCopyrightUpload;
if ( $wgUseCopyrightUpload ) {
@@ -933,15 +1002,15 @@ class UploadForm extends HTMLForm {
}
/**
- * Get the descriptor of the fieldset that contains the upload options,
+ * Get the descriptor of the fieldset that contains the upload options,
* such as "watch this file". The section is 'options'
- *
- * @return array Descriptor array
+ *
+ * @return Array: descriptor array
*/
protected function getOptionsSection() {
- global $wgUser, $wgOut;
+ global $wgUser;
- if( $wgUser->isLoggedIn() ) {
+ if ( $wgUser->isLoggedIn() ) {
$descriptor = array(
'Watchthis' => array(
'type' => 'check',
@@ -952,7 +1021,7 @@ class UploadForm extends HTMLForm {
)
);
}
- if( !$this->mHideIgnoreWarning ) {
+ if ( !$this->mHideIgnoreWarning ) {
$descriptor['IgnoreWarning'] = array(
'type' => 'check',
'id' => 'wpIgnoreWarning',
@@ -961,14 +1030,14 @@ class UploadForm extends HTMLForm {
);
}
- $descriptor['wpDestFileWarningAck'] = array(
+ $descriptor['DestFileWarningAck'] = array(
'type' => 'hidden',
'id' => 'wpDestFileWarningAck',
'default' => $this->mDestWarningAck ? '1' : '',
);
if ( $this->mForReUpload ) {
- $descriptor['wpForReUpload'] = array(
+ $descriptor['ForReUpload'] = array(
'type' => 'hidden',
'id' => 'wpForReUpload',
'default' => '1',
@@ -976,7 +1045,6 @@ class UploadForm extends HTMLForm {
}
return $descriptor;
-
}
/**
@@ -989,12 +1057,9 @@ class UploadForm extends HTMLForm {
/**
* Add upload JS to $wgOut
- *
- * @param bool $autofill Whether or not to autofill the destination
- * filename text box
*/
- protected function addUploadJS( ) {
- global $wgUseAjax, $wgAjaxUploadDestCheck, $wgAjaxLicensePreview, $wgEnableAPI;
+ protected function addUploadJS() {
+ global $wgUseAjax, $wgAjaxUploadDestCheck, $wgAjaxLicensePreview, $wgEnableAPI, $wgStrictFileExtensions;
global $wgOut;
$useAjaxDestCheck = $wgUseAjax && $wgAjaxUploadDestCheck;
@@ -1008,18 +1073,19 @@ class UploadForm extends HTMLForm {
// the wpDestFile textbox
$this->mDestFile === '',
'wgUploadSourceIds' => $this->mSourceIds,
+ 'wgStrictFileExtensions' => $wgStrictFileExtensions,
+ 'wgCapitalizeUploads' => MWNamespace::isCapitalized( NS_FILE ),
);
$wgOut->addScript( Skin::makeVariablesScript( $scriptVars ) );
-
+
// For <charinsert> support
- $wgOut->addScriptFile( 'edit.js' );
- $wgOut->addScriptFile( 'upload.js' );
+ $wgOut->addModules( array( 'mediawiki.legacy.edit', 'mediawiki.legacy.upload' ) );
}
/**
* Empty function; submission is handled elsewhere.
- *
+ *
* @return bool false
*/
function trySubmit() {
@@ -1032,9 +1098,9 @@ class UploadForm extends HTMLForm {
* A form field that contains a radio box in the label
*/
class UploadSourceField extends HTMLTextField {
- function getLabelHtml() {
+ function getLabelHtml( $cellAttributes = array() ) {
$id = "wpSourceType{$this->mParams['upload-type']}";
- $label = Html::rawElement( 'label', array( 'for' => $id ), $this->mLabel );
+ $label = Html::rawElement( 'label', array( 'for' => $id ), $this->mLabel );
if ( !empty( $this->mParams['radio'] ) ) {
$attribs = array(
@@ -1043,13 +1109,15 @@ class UploadSourceField extends HTMLTextField {
'id' => $id,
'value' => $this->mParams['upload-type'],
);
- if ( !empty( $this->mParams['checked'] ) )
+ if ( !empty( $this->mParams['checked'] ) ) {
$attribs['checked'] = 'checked';
+ }
$label .= Html::element( 'input', $attribs );
}
- return Html::rawElement( 'td', array( 'class' => 'mw-label' ), $label );
+ return Html::rawElement( 'td', array( 'class' => 'mw-label' ) + $cellAttributes, $label );
}
+
function getSize() {
return isset( $this->mParams['size'] )
? $this->mParams['size']
diff --git a/includes/specials/SpecialUploadStash.php b/includes/specials/SpecialUploadStash.php
new file mode 100644
index 00000000..48a41a5e
--- /dev/null
+++ b/includes/specials/SpecialUploadStash.php
@@ -0,0 +1,394 @@
+<?php
+/**
+ * Implements Special:UploadStash
+ *
+ * Web access for files temporarily stored by UploadStash.
+ *
+ * For example -- files that were uploaded with the UploadWizard extension are stored temporarily
+ * before committing them to the db. But we want to see their thumbnails and get other information
+ * about them.
+ *
+ * Since this is based on the user's session, in effect this creates a private temporary file area.
+ * However, the URLs for the files cannot be shared.
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @ingroup Upload
+ */
+
+class SpecialUploadStash extends UnlistedSpecialPage {
+ // UploadStash
+ private $stash;
+
+ // is the edit request authorized? boolean
+ private $isEditAuthorized;
+
+ // did the user request us to clear the stash? boolean
+ private $requestedClear;
+
+ // Since we are directly writing the file to STDOUT,
+ // we should not be reading in really big files and serving them out.
+ //
+ // We also don't want people using this as a file drop, even if they
+ // share credentials.
+ //
+ // This service is really for thumbnails and other such previews while
+ // uploading.
+ const MAX_SERVE_BYTES = 262144; // 256K
+
+ public function __construct( $request = null ) {
+ global $wgRequest;
+
+ parent::__construct( 'UploadStash', 'upload' );
+ try {
+ $this->stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash();
+ } catch ( UploadStashNotAvailableException $e ) {
+ return null;
+ }
+
+ $this->loadRequest( is_null( $request ) ? $wgRequest : $request );
+ }
+
+ /**
+ * Execute page -- can output a file directly or show a listing of them.
+ *
+ * @param $subPage String: subpage, e.g. in http://example.com/wiki/Special:UploadStash/foo.jpg, the "foo.jpg" part
+ * @return Boolean: success
+ */
+ public function execute( $subPage ) {
+ global $wgUser;
+
+ if ( !$this->userCanExecute( $wgUser ) ) {
+ $this->displayRestrictionError();
+ return;
+ }
+
+ if ( !isset( $subPage ) || $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.
+ *
+ * @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();
+
+ try {
+ $params = $this->parseKey( $key );
+ if ( $params['type'] === 'thumb' ) {
+ return $this->outputThumbFromStash( $params['file'], $params['params'] );
+ } else {
+ return $this->outputLocalFile( $params['file'] );
+ }
+ } catch( UploadStashFileNotFoundException $e ) {
+ $code = 404;
+ $message = $e->getMessage();
+ } catch( UploadStashZeroLengthFileException $e ) {
+ $code = 500;
+ $message = $e->getMessage();
+ } catch( UploadStashBadPathException $e ) {
+ $code = 500;
+ $message = $e->getMessage();
+ } catch( SpecialUploadStashTooLargeException $e ) {
+ $code = 500;
+ $message = 'Cannot serve a file larger than ' . self::MAX_SERVE_BYTES . ' bytes. ' . $e->getMessage();
+ } catch( Exception $e ) {
+ $code = 500;
+ $message = $e->getMessage();
+ }
+
+ wfHttpError( $code, OutputPage::getStatusMessage( $code ), $message );
+ return false;
+ }
+
+ /**
+ * Parse the key passed to the SpecialPage. Returns an array containing
+ * the associated file object, the type ('file' or 'thumb') and if
+ * application the transform parameters
+ *
+ * @param string $key
+ * @return array
+ */
+ private function parseKey( $key ) {
+ $type = strtok( $key, '/' );
+
+ if ( $type !== 'file' && $type !== 'thumb' ) {
+ throw new UploadStashBadPathException( "Unknown type '$type'" );
+ }
+ $fileName = strtok( '/' );
+ $thumbPart = strtok( '/' );
+ $file = $this->stash->getFile( $fileName );
+ if ( $type === 'thumb' ) {
+ $srcNamePos = strrpos( $thumbPart, $fileName );
+ if ( $srcNamePos === false || $srcNamePos < 1 ) {
+ throw new UploadStashBadPathException( 'Unrecognized thumb name' );
+ }
+ $paramString = substr( $thumbPart, 0, $srcNamePos - 1 );
+
+ $handler = $file->getHandler();
+ $params = $handler->parseParamString( $paramString );
+ return array( 'file' => $file, 'type' => $type, 'params' => $params );
+ }
+
+ return array( 'file' => $file, 'type' => $type );
+ }
+
+
+
+
+ /**
+ * Get a thumbnail for file, either generated locally or remotely, and stream it out
+ * @param String $key: key for the file in the stash
+ * @param int $width: width of desired thumbnail
+ * @return boolean success
+ */
+ private function outputThumbFromStash( $file, $params ) {
+
+ // this global, if it exists, points to a "scaler", as you might find in the Wikimedia Foundation cluster. See outputRemoteScaledThumb()
+ // this is part of our horrible NFS-based system, we create a file on a mount point here, but fetch the scaled file from somewhere else that
+ // happens to share it over NFS
+ global $wgUploadStashScalerBaseUrl;
+
+ $flags = 0;
+ if ( $wgUploadStashScalerBaseUrl ) {
+ $this->outputRemoteScaledThumb( $file, $params, $flags );
+ } else {
+ $this->outputLocallyScaledThumb( $file, $params, $flags );
+ }
+
+
+ }
+
+
+ /**
+ * Scale a file (probably with a locally installed imagemagick, or similar) and output it to STDOUT.
+ * @param $file: File object
+ * @param $params: scaling parameters ( e.g. array( width => '50' ) );
+ * @param $flags: scaling flags ( see File:: constants )
+ * @throws MWException
+ * @return boolean success
+ */
+ private function outputLocallyScaledThumb( $file, $params, $flags ) {
+
+ // n.b. this is stupid, we insist on re-transforming the file every time we are invoked. We rely
+ // on HTTP caching to ensure this doesn't happen.
+
+ $flags |= File::RENDER_NOW;
+
+ $thumbnailImage = $file->transform( $params, $flags );
+ if ( !$thumbnailImage ) {
+ throw new MWException( 'Could not obtain thumbnail' );
+ }
+
+ // we should have just generated it locally
+ if ( ! $thumbnailImage->getPath() ) {
+ 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 ) {
+ throw new UploadStashFileNotFoundException( "couldn't create local file object for thumbnail" );
+ }
+
+ return $this->outputLocalFile( $thumbFile );
+
+ }
+
+ /**
+ * Scale a file with a remote "scaler", as exists on the Wikimedia Foundation cluster, and output it to STDOUT.
+ * Note: unlike the usual thumbnail process, the web client never sees the cluster URL; we do the whole HTTP transaction to the scaler ourselves
+ * and cat the results out.
+ * Note: We rely on NFS to have propagated the file contents to the scaler. However, we do not rely on the thumbnail being created in NFS and then
+ * propagated back to our filesystem. Instead we take the results of the HTTP request instead.
+ * Note: no caching is being done here, although we are instructing the client to cache it forever.
+ * @param $file: File object
+ * @param $params: scaling parameters ( e.g. array( width => '50' ) );
+ * @param $flags: scaling flags ( see File:: constants )
+ * @throws MWException
+ * @return boolean success
+ */
+ private function outputRemoteScaledThumb( $file, $params, $flags ) {
+
+ // this global probably looks something like 'http://upload.wikimedia.org/wikipedia/test/thumb/temp'
+ // do not use trailing slash
+ global $wgUploadStashScalerBaseUrl;
+
+ $scalerThumbName = $file->getParamThumbName( $file->name, $params );
+ $scalerThumbUrl = $wgUploadStashScalerBaseUrl . '/' . $file->getRel() . '/' . $scalerThumbName;
+
+ // make a curl call to the scaler to create a thumbnail
+ $httpOptions = array(
+ 'method' => 'GET',
+ 'timeout' => 'default'
+ );
+ $req = MWHttpRequest::factory( $scalerThumbUrl, $httpOptions );
+ $status = $req->execute();
+ if ( ! $status->isOK() ) {
+ $errors = $status->getErrorsArray();
+ throw new MWException( "Fetching thumbnail failed: " . join( ", ", $errors ) );
+ }
+ $contentType = $req->getResponseHeader( "content-type" );
+ if ( ! $contentType ) {
+ throw new MWException( "Missing content-type header" );
+ }
+ return $this->outputContents( $req->getContent(), $contentType );
+ }
+
+ /**
+ * 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 ) {
+ if ( $file->getSize() > self::MAX_SERVE_BYTES ) {
+ throw new SpecialUploadStashTooLargeException();
+ }
+ self::outputFileHeaders( $file->getMimeType(), $file->getSize() );
+ readfile( $file->getPath() );
+ return true;
+ }
+
+ /**
+ * Output HTTP response of raw content
+ * Side effect: writes HTTP response to STDOUT.
+ * @param String $content: content
+ * @param String $mimeType: mime type
+ */
+ private function outputContents( $content, $contentType ) {
+ $size = strlen( $content );
+ if ( $size > self::MAX_SERVE_BYTES ) {
+ throw new SpecialUploadStashTooLargeException();
+ }
+ self::outputFileHeaders( $contentType, $size );
+ print $content;
+ return true;
+ }
+
+ /**
+ * Output headers for streaming
+ * XXX unsure about encoding as binary; if we received from HTTP perhaps we should use that encoding, concatted with semicolon to mimeType as it usually is.
+ * Side effect: preps PHP to write headers to STDOUT.
+ * @param String $contentType : string suitable for content-type header
+ * @param String $size: length in bytes
+ */
+ private static function outputFileHeaders( $contentType, $size ) {
+ header( "Content-Type: $contentType", true );
+ header( 'Content-Transfer-Encoding: binary', true );
+ header( 'Expires: Sun, 17-Jan-2038 19:14:07 GMT', true );
+ header( "Content-Length: $size", true );
+ }
+
+
+ /**
+ * Initialize authorization & actions to take, from the request
+ * @param $request: WebRequest
+ */
+ private function loadRequest( $request ) {
+ global $wgUser;
+ if ( $request->wasPosted() ) {
+
+ $token = $request->getVal( 'wpEditToken' );
+ $this->isEditAuthorized = $wgUser->matchEditToken( $token );
+
+ $this->requestedClear = $request->getBool( 'clear' );
+
+ }
+ }
+
+ /**
+ * Static callback for the HTMLForm in showUploads, to process
+ * Note the stash has to be recreated since this is being called in a static context.
+ * This works, because there really is only one stash per logged-in user, despite appearances.
+ *
+ * @return Status
+ */
+ public static function tryClearStashedUploads( $formData ) {
+ wfDebug( __METHOD__ . " form data : " . print_r( $formData, 1 ) );
+ if ( isset( $formData['clear'] ) and $formData['clear'] ) {
+ $stash = new UploadStash();
+ wfDebug( "stash has: " . print_r( $stash->listFiles(), 1 ) );
+ if ( ! $stash->clear() ) {
+ return Status::newFatal( 'uploadstash-errclear' );
+ }
+ }
+ return Status::newGood();
+ }
+
+ /**
+ * Default action when we don't have a subpage -- just show links to the uploads we have,
+ * Also show a button to clear stashed files
+ * @param Status : $status - the result of processRequest
+ */
+ private function showUploads( $status = null ) {
+ global $wgOut;
+ if ( $status === null ) {
+ $status = Status::newGood();
+ }
+
+ // sets the title, etc.
+ $this->setHeaders();
+ $this->outputHeader();
+
+
+ // create the form, which will also be used to execute a callback to process incoming form data
+ // this design is extremely dubious, but supposedly HTMLForm is our standard now?
+
+ $form = new HTMLForm( array(
+ 'Clear' => array(
+ 'type' => 'hidden',
+ 'default' => true,
+ 'name' => 'clear',
+ )
+ ), 'clearStashedUploads' );
+ $form->setSubmitCallback( array( __CLASS__, 'tryClearStashedUploads' ) );
+ $form->setTitle( $this->getTitle() );
+ $form->addHiddenField( 'clear', true, array( 'type' => 'boolean' ) );
+ $form->setSubmitText( wfMsg( 'uploadstash-clear' ) );
+
+ $form->prepareForm();
+ $formResult = $form->tryAuthorizedSubmit();
+
+
+ // show the files + form, if there are any, or just say there are none
+ $refreshHtml = Html::element( 'a', array( 'href' => $this->getTitle()->getLocalURL() ), wfMsg( 'uploadstash-refresh' ) );
+ $files = $this->stash->listFiles();
+ if ( count( $files ) ) {
+ sort( $files );
+ $fileListItemsHtml = '';
+ foreach ( $files as $file ) {
+ $fileListItemsHtml .= Html::rawElement( 'li', array(),
+ Html::element( 'a', array( 'href' =>
+ $this->getTitle( "file/$file" )->getLocalURL() ), $file )
+ );
+ }
+ $wgOut->addHtml( Html::rawElement( 'ul', array(), $fileListItemsHtml ) );
+ $form->displayForm( $formResult );
+ $wgOut->addHtml( Html::rawElement( 'p', array(), $refreshHtml ) );
+ } else {
+ $wgOut->addHtml( Html::rawElement( 'p', array(),
+ Html::element( 'span', array(), wfMsg( 'uploadstash-nofiles' ) )
+ . ' '
+ . $refreshHtml
+ ) );
+ }
+
+ return true;
+ }
+}
+
+class SpecialUploadStashTooLargeException extends MWException {};
diff --git a/includes/specials/SpecialUserlogin.php b/includes/specials/SpecialUserlogin.php
index 8b8d0e9e..ccace79d 100644
--- a/includes/specials/SpecialUserlogin.php
+++ b/includes/specials/SpecialUserlogin.php
@@ -1,11 +1,28 @@
<?php
/**
+ * Implements Special:UserLogin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
- * constructor
+ * Constructor
*/
function wfSpecialUserlogin( $par = '' ) {
global $wgRequest;
@@ -18,7 +35,8 @@ function wfSpecialUserlogin( $par = '' ) {
}
/**
- * implements Special:Login
+ * Implements Special:UserLogin
+ *
* @ingroup SpecialPage
*/
class LoginForm {
@@ -41,7 +59,7 @@ class LoginForm {
var $mName, $mPassword, $mRetype, $mReturnTo, $mCookieCheck, $mPosted;
var $mAction, $mCreateaccount, $mCreateaccountMail, $mMailmypassword;
var $mLoginattempt, $mRemember, $mEmail, $mDomain, $mLanguage;
- var $mSkipCookieCheck, $mReturnToQuery, $mToken;
+ var $mSkipCookieCheck, $mReturnToQuery, $mToken, $mStickHTTPS;
private $mExtUser = null;
@@ -50,7 +68,7 @@ class LoginForm {
* @param $request WebRequest: a WebRequest object passed by reference
* @param $par String: subpage parameter
*/
- function LoginForm( &$request, $par = '' ) {
+ function __construct( &$request, $par = '' ) {
global $wgAuth, $wgHiddenPrefs, $wgEnableEmail, $wgRedirectOnLogin;
$this->mType = ( $par == 'signup' ) ? $par : $request->getText( 'type' ); # Check for [[Special:Userlogin/signup]]
@@ -58,6 +76,7 @@ class LoginForm {
$this->mPassword = $request->getText( 'wpPassword' );
$this->mRetype = $request->getText( 'wpRetype' );
$this->mDomain = $request->getText( 'wpDomain' );
+ $this->mReason = $request->getText( 'wpReason' );
$this->mReturnTo = $request->getVal( 'returnto' );
$this->mReturnToQuery = $request->getVal( 'returntoquery' );
$this->mCookieCheck = $request->getVal( 'wpCookieCheck' );
@@ -70,9 +89,10 @@ class LoginForm {
$this->mLoginattempt = $request->getCheck( 'wpLoginattempt' );
$this->mAction = $request->getVal( 'action' );
$this->mRemember = $request->getCheck( 'wpRemember' );
+ $this->mStickHTTPS = $request->getCheck( 'wpStickHTTPS' );
$this->mLanguage = $request->getText( 'uselang' );
$this->mSkipCookieCheck = $request->getCheck( 'wpSkipCookieCheck' );
- $this->mToken = ($this->mType == 'signup' ) ? $request->getVal( 'wpCreateaccountToken' ) : $request->getVal( 'wpLoginToken' );
+ $this->mToken = ( $this->mType == 'signup' ) ? $request->getVal( 'wpCreateaccountToken' ) : $request->getVal( 'wpLoginToken' );
if ( $wgRedirectOnLogin ) {
$this->mReturnTo = $wgRedirectOnLogin;
@@ -107,14 +127,14 @@ class LoginForm {
if ( !is_null( $this->mCookieCheck ) ) {
$this->onCookieRedirectCheck( $this->mCookieCheck );
return;
- } else if( $this->mPosted ) {
+ } elseif( $this->mPosted ) {
if( $this->mCreateaccount ) {
return $this->addNewAccount();
- } else if ( $this->mCreateaccountMail ) {
+ } elseif ( $this->mCreateaccountMail ) {
return $this->addNewAccountMailPassword();
- } else if ( $this->mMailmypassword ) {
+ } elseif ( $this->mMailmypassword ) {
return $this->mailPassword();
- } else if ( ( 'submitlogin' == $this->mAction ) || $this->mLoginattempt ) {
+ } elseif ( ( 'submitlogin' == $this->mAction ) || $this->mLoginattempt ) {
return $this->processLogin();
}
}
@@ -128,13 +148,13 @@ class LoginForm {
global $wgOut;
if ( $this->mEmail == '' ) {
- $this->mainLoginForm( wfMsg( 'noemail', htmlspecialchars( $this->mName ) ) );
+ $this->mainLoginForm( wfMsgExt( 'noemailcreate', array( 'parsemag', 'escape' ) ) );
return;
}
$u = $this->addNewaccountInternal();
- if ($u == null) {
+ if ( $u == null ) {
return;
}
@@ -144,47 +164,46 @@ class LoginForm {
$result = $this->mailPasswordInternal( $u, false, 'createaccount-title', 'createaccount-text' );
wfRunHooks( 'AddNewAccount', array( $u, true ) );
- $u->addNewUserLogEntry();
+ $u->addNewUserLogEntry( true, $this->mReason );
$wgOut->setPageTitle( wfMsg( 'accmailtitle' ) );
$wgOut->setRobotPolicy( 'noindex,nofollow' );
$wgOut->setArticleRelated( false );
- if( WikiError::isError( $result ) ) {
- $this->mainLoginForm( wfMsg( 'mailerror', $result->getMessage() ) );
+ if( !$result->isGood() ) {
+ $this->mainLoginForm( wfMsg( 'mailerror', $result->getWikiText() ) );
} else {
$wgOut->addWikiMsg( 'accmailtext', $u->getName(), $u->getEmail() );
$wgOut->returnToMain( false );
}
- $u = 0;
}
-
/**
* @private
*/
function addNewAccount() {
- global $wgUser, $wgEmailAuthentication;
+ global $wgUser, $wgEmailAuthentication, $wgOut;
# Create the account and abort if there's a problem doing so
$u = $this->addNewAccountInternal();
- if( $u == null )
+ if( $u == null ) {
return;
+ }
# 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 )
+ if( $wgLoginLanguageSelector && $this->mLanguage ) {
$u->setOption( 'language', $this->mLanguage );
+ }
# Send out an email authentication message if needed
if( $wgEmailAuthentication && User::isValidEmailAddr( $u->getEmail() ) ) {
- global $wgOut;
- $error = $u->sendConfirmationMail();
- if( WikiError::isError( $error ) ) {
- $wgOut->addWikiMsg( 'confirmemail_sendfailed', $error->getMessage() );
- } else {
+ $status = $u->sendConfirmationMail();
+ if( $status->isGood() ) {
$wgOut->addWikiMsg( 'confirmemail_oncreate' );
+ } else {
+ $wgOut->addWikiText( $status->getWikiText( 'confirmemail_sendfailed' ) );
}
}
@@ -206,7 +225,6 @@ class LoginForm {
}
} else {
# Confirm that the account was created
- global $wgOut;
$self = SpecialPage::getTitleFor( 'Userlogin' );
$wgOut->setPageTitle( wfMsgHtml( 'accountcreated' ) );
$wgOut->setArticleRelated( false );
@@ -214,7 +232,7 @@ class LoginForm {
$wgOut->addHTML( wfMsgWikiHtml( 'accountcreatedtext', $u->getName() ) );
$wgOut->returnToMain( false, $self );
wfRunHooks( 'AddNewAccount', array( $u, false ) );
- $u->addNewUserLogEntry();
+ $u->addNewUserLogEntry( false, $this->mReason );
return true;
}
}
@@ -254,16 +272,16 @@ class LoginForm {
# Request forgery checks.
if ( !self::getCreateaccountToken() ) {
self::setCreateaccountToken();
- $this->mainLoginForm( wfMsg( 'sessionfailure' ) );
+ $this->mainLoginForm( wfMsgExt( 'nocookiesnew', array( 'parseinline' ) ) );
return false;
}
-
+
# The user didn't pass a createaccount token
if ( !$this->mToken ) {
$this->mainLoginForm( wfMsg( 'sessionfailure' ) );
return false;
}
-
+
# Validate the createaccount token
if ( $this->mToken !== self::getCreateaccountToken() ) {
$this->mainLoginForm( wfMsg( 'sessionfailure' ) );
@@ -272,7 +290,7 @@ class LoginForm {
# Check permissions
if ( !$wgUser->isAllowed( 'createaccount' ) ) {
- $this->userNotPrivilegedMessage();
+ $wgOut->permissionRequired( 'createaccount' );
return false;
} elseif ( $wgUser->isBlockedFromCreateAccount() ) {
$this->userBlockedMessage();
@@ -359,7 +377,7 @@ class LoginForm {
return false;
}
- self::clearCreateaccountToken();
+ self::clearCreateaccountToken();
return $this->initUser( $u, false );
}
@@ -413,16 +431,17 @@ class LoginForm {
* creation.
*/
public function authenticateUserData() {
- global $wgUser, $wgAuth;
+ global $wgUser, $wgAuth, $wgMemc;
+
if ( $this->mName == '' ) {
return self::NO_NAME;
}
-
+
// We require a login token to prevent login CSRF
// Handle part of this before incrementing the throttle so
// token-less login attempts don't count towards the throttle
// but wrong-token attempts do.
-
+
// If the user doesn't have a login token yet, set one.
if ( !self::getLoginToken() ) {
self::setLoginToken();
@@ -432,7 +451,7 @@ class LoginForm {
if ( !$this->mToken ) {
return self::NEED_TOKEN;
}
-
+
global $wgPasswordAttemptThrottle;
$throttleCount = 0;
@@ -440,18 +459,17 @@ class LoginForm {
$throttleKey = wfMemcKey( 'password-throttle', wfGetIP(), md5( $this->mName ) );
$count = $wgPasswordAttemptThrottle['count'];
$period = $wgPasswordAttemptThrottle['seconds'];
-
- global $wgMemc;
+
$throttleCount = $wgMemc->get( $throttleKey );
if ( !$throttleCount ) {
$wgMemc->add( $throttleKey, 1, $period ); // start counter
- } else if ( $throttleCount < $count ) {
- $wgMemc->incr($throttleKey);
- } else if ( $throttleCount >= $count ) {
+ } elseif ( $throttleCount < $count ) {
+ $wgMemc->incr( $throttleKey );
+ } elseif ( $throttleCount >= $count ) {
return self::THROTTLED;
}
}
-
+
// Validate the login token
if ( $this->mToken !== self::getLoginToken() ) {
return self::WRONG_TOKEN;
@@ -464,7 +482,7 @@ class LoginForm {
// for user existence using User::newFromName($name)->getId() below
// will effectively be using stale data.
if ( $wgUser->getName() === $this->mName ) {
- wfDebug( __METHOD__.": already logged in as {$this->mName}\n" );
+ wfDebug( __METHOD__ . ": already logged in as {$this->mName}\n" );
return self::SUCCESS;
}
@@ -505,7 +523,7 @@ class LoginForm {
}
global $wgBlockDisablesLogin;
- if (!$u->checkPassword( $this->mPassword )) {
+ if ( !$u->checkPassword( $this->mPassword ) ) {
if( $u->checkTemporaryPassword( $this->mPassword ) ) {
// The e-mailed temporary password should not be used for actu-
// al logins; that's a very sloppy habit, and insecure if an
@@ -533,7 +551,7 @@ class LoginForm {
// faces etc will probably just fail cleanly here.
$retval = self::RESET_PASS;
} else {
- $retval = ($this->mPassword == '') ? self::EMPTY_PASS : self::WRONG_PASS;
+ $retval = ( $this->mPassword == '' ) ? self::EMPTY_PASS : self::WRONG_PASS;
}
} elseif ( $wgBlockDisablesLogin && $u->isBlocked() ) {
// If we've enabled it, make it so that a blocked user cannot login
@@ -543,8 +561,8 @@ class LoginForm {
$wgUser = $u;
// Please reset throttle for successful logins, thanks!
- if($throttleCount) {
- $wgMemc->delete($throttleKey);
+ if( $throttleCount ) {
+ $wgMemc->delete( $throttleKey );
}
if ( $isAutoCreated ) {
@@ -567,7 +585,7 @@ class LoginForm {
global $wgAuth, $wgUser, $wgAutocreatePolicy;
if ( $wgUser->isBlockedFromCreateAccount() ) {
- wfDebug( __METHOD__.": user is blocked from account creation\n" );
+ wfDebug( __METHOD__ . ": user is blocked from account creation\n" );
return self::CREATE_BLOCKED;
}
@@ -591,22 +609,22 @@ class LoginForm {
return self::NOT_EXISTS;
}
if ( !$wgAuth->userExists( $user->getName() ) ) {
- wfDebug( __METHOD__.": user does not exist\n" );
+ wfDebug( __METHOD__ . ": user does not exist\n" );
return self::NOT_EXISTS;
}
if ( !$wgAuth->authenticate( $user->getName(), $this->mPassword ) ) {
- wfDebug( __METHOD__.": \$wgAuth->authenticate() returned false, aborting\n" );
+ wfDebug( __METHOD__ . ": \$wgAuth->authenticate() returned false, aborting\n" );
return self::WRONG_PLUGIN_PASS;
}
}
- wfDebug( __METHOD__.": creating account\n" );
- $user = $this->initUser( $user, true );
+ wfDebug( __METHOD__ . ": creating account\n" );
+ $this->initUser( $user, true );
return self::SUCCESS;
}
function processLogin() {
- global $wgUser, $wgAuth;
+ global $wgUser;
switch ( $this->authenticateUserData() ) {
case self::SUCCESS:
@@ -637,8 +655,10 @@ class LoginForm {
return $this->cookieRedirectCheck( 'login' );
}
break;
-
+
case self::NEED_TOKEN:
+ $this->mainLoginForm( wfMsgExt( 'nocookieslogin', array( 'parseinline' ) ) );
+ break;
case self::WRONG_TOKEN:
$this->mainLoginForm( wfMsg( 'sessionfailure' ) );
break;
@@ -650,7 +670,7 @@ class LoginForm {
$this->mainLoginForm( wfMsg( 'wrongpassword' ) );
break;
case self::NOT_EXISTS:
- if( $wgUser->isAllowed( 'createaccount' ) ){
+ if( $wgUser->isAllowed( 'createaccount' ) ) {
$this->mainLoginForm( wfMsgWikiHtml( 'nosuchuser', htmlspecialchars( $this->mName ) ) );
} else {
$this->mainLoginForm( wfMsg( 'nosuchusershort', htmlspecialchars( $this->mName ) ) );
@@ -676,7 +696,7 @@ class LoginForm {
array( 'parsemag', 'escape' ), $this->mName ) );
break;
default:
- throw new MWException( "Unhandled case value" );
+ throw new MWException( 'Unhandled case value' );
}
}
@@ -692,27 +712,27 @@ class LoginForm {
*/
function mailPassword() {
global $wgUser, $wgOut, $wgAuth;
-
+
if ( wfReadOnly() ) {
$wgOut->readOnlyPage();
return false;
}
-
+
if( !$wgAuth->allowPasswordChange() ) {
$this->mainLoginForm( wfMsg( 'resetpass_forbidden' ) );
return;
}
- # Check against blocked IPs so blocked users can't flood admins
+ # Check against blocked IPs so blocked users can't flood admins
# with password resets
if( $wgUser->isBlocked() ) {
$this->mainLoginForm( wfMsg( 'blocked-mailpassword' ) );
return;
}
-
+
# Check for hooks
$error = null;
- if ( ! wfRunHooks( 'UserLoginMailPassword', array( $this->mName, &$error ) ) ) {
+ if ( !wfRunHooks( 'UserLoginMailPassword', array( $this->mName, &$error ) ) ) {
$this->mainLoginForm( $error );
return;
}
@@ -729,7 +749,7 @@ class LoginForm {
$this->mainLoginForm( wfMsg( 'sessionfailure' ) );
return;
}
-
+
# Check against the rate limiter
if( $wgUser->pingLimiter( 'mailpassword' ) ) {
$wgOut->rateLimited();
@@ -767,11 +787,11 @@ class LoginForm {
}
$result = $this->mailPasswordInternal( $u, true, 'passwordremindertitle', 'passwordremindertext' );
- if( WikiError::isError( $result ) ) {
- $this->mainLoginForm( wfMsg( 'mailerror', $result->getMessage() ) );
- } else {
+ if( $result->isGood() ) {
$this->mainLoginForm( wfMsg( 'passwordsent', $u->getName() ), 'success' );
self::clearLoginToken();
+ } else {
+ $this->mainLoginForm( $result->getWikiText( 'mailerror' ) );
}
}
@@ -781,21 +801,21 @@ class LoginForm {
* @param $throttle Boolean
* @param $emailTitle String: message name of email title
* @param $emailText String: message name of email text
- * @return Mixed: true on success, WikiError on failure
+ * @return Status object
* @private
*/
function mailPasswordInternal( $u, $throttle = true, $emailTitle = 'passwordremindertitle', $emailText = 'passwordremindertext' ) {
global $wgServer, $wgScript, $wgUser, $wgNewPasswordExpiry;
if ( $u->getEmail() == '' ) {
- return new WikiError( wfMsg( 'noemail', $u->getName() ) );
+ return Status::newFatal( 'noemail', $u->getName() );
}
$ip = wfGetIP();
if( !$ip ) {
- return new WikiError( wfMsg( 'badipaddress' ) );
+ return Status::newFatal( 'badipaddress' );
}
-
- wfRunHooks( 'User::mailPasswordInternal', array(&$wgUser, &$ip, &$u) );
+
+ wfRunHooks( 'User::mailPasswordInternal', array( &$wgUser, &$ip, &$u ) );
$np = $u->randomPassword();
$u->setNewpassword( $np, $throttle );
@@ -824,7 +844,7 @@ class LoginForm {
# Run any hooks; display injected HTML if any, else redirect
$injected_html = '';
- wfRunHooks('UserLoginComplete', array(&$wgUser, &$injected_html));
+ wfRunHooks( 'UserLoginComplete', array( &$wgUser, &$injected_html ) );
if( $injected_html !== '' ) {
$this->displaySuccessfulLogin( 'loginsuccess', $injected_html );
@@ -833,7 +853,12 @@ class LoginForm {
if ( !$titleObj instanceof Title ) {
$titleObj = Title::newMainPage();
}
- $wgOut->redirect( $titleObj->getFullURL( $this->mReturnToQuery ) );
+ $redirectUrl = $titleObj->getFullURL( $this->mReturnToQuery );
+ global $wgSecureLogin;
+ if( $wgSecureLogin && !$this->mStickHTTPS ) {
+ $redirectUrl = preg_replace( '/^https:/', 'http:', $redirectUrl );
+ }
+ $wgOut->redirect( $redirectUrl );
}
}
@@ -844,11 +869,10 @@ class LoginForm {
* @private
*/
function successfulCreation() {
- global $wgUser, $wgOut;
-
+ global $wgUser;
# Run any hooks; display injected HTML
$injected_html = '';
- wfRunHooks('UserLoginComplete', array(&$wgUser, &$injected_html));
+ wfRunHooks( 'UserLoginComplete', array( &$wgUser, &$injected_html ) );
$this->displaySuccessfulLogin( 'welcomecreation', $injected_html );
}
@@ -873,22 +897,6 @@ class LoginForm {
}
/** */
- function userNotPrivilegedMessage($errors) {
- global $wgOut;
-
- $wgOut->setPageTitle( wfMsg( 'permissionserrors' ) );
- $wgOut->setRobotPolicy( 'noindex,nofollow' );
- $wgOut->setArticleRelated( false );
-
- $wgOut->addWikitext( $wgOut->formatPermissionsErrorMessage( $errors, 'createaccount' ) );
- // Stuff that might want to be added at the end. For example, instruc-
- // tions if blocked.
- $wgOut->addWikiMsg( 'cantcreateaccount-nonblock-text' );
-
- $wgOut->returnToMain( false );
- }
-
- /** */
function userBlockedMessage() {
global $wgOut, $wgUser;
@@ -920,14 +928,15 @@ class LoginForm {
*/
function mainLoginForm( $msg, $msgtype = 'error' ) {
global $wgUser, $wgOut, $wgHiddenPrefs, $wgEnableEmail;
- global $wgCookiePrefix, $wgLoginLanguageSelector;
+ global $wgRequest, $wgLoginLanguageSelector;
global $wgAuth, $wgEmailConfirmToEdit, $wgCookieExpiration;
-
+ global $wgSecureLogin;
+
$titleObj = SpecialPage::getTitleFor( 'Userlogin' );
-
+
if ( $this->mType == 'signup' ) {
- // Block signup here if in readonly. Keeps user from
- // going through the process (filling out data, etc)
+ // 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();
@@ -945,12 +954,10 @@ class LoginForm {
if ( $wgUser->isLoggedIn() ) {
$this->mName = $wgUser->getName();
} else {
- $this->mName = isset( $_COOKIE[$wgCookiePrefix.'UserName'] ) ? $_COOKIE[$wgCookiePrefix.'UserName'] : null;
+ $this->mName = $wgRequest->getCookie( 'UserName' );
}
}
- $titleObj = SpecialPage::getTitleFor( 'Userlogin' );
-
if ( $this->mType == 'signup' ) {
$template = new UsercreateTemplate();
$q = 'action=submitlogin&type=signup';
@@ -965,26 +972,29 @@ class LoginForm {
if ( !empty( $this->mReturnTo ) ) {
$returnto = '&returnto=' . wfUrlencode( $this->mReturnTo );
- if ( !empty( $this->mReturnToQuery ) )
+ if ( !empty( $this->mReturnToQuery ) ) {
$returnto .= '&returntoquery=' .
wfUrlencode( $this->mReturnToQuery );
+ }
$q .= $returnto;
$linkq .= $returnto;
}
# Pass any language selection on to the mode switch link
- if( $wgLoginLanguageSelector && $this->mLanguage )
+ if( $wgLoginLanguageSelector && $this->mLanguage ) {
$linkq .= '&uselang=' . $this->mLanguage;
+ }
- $link = '<a href="' . htmlspecialchars ( $titleObj->getLocalUrl( $linkq ) ) . '">';
+ $link = '<a href="' . htmlspecialchars ( $titleObj->getLocalURL( $linkq ) ) . '">';
$link .= wfMsgHtml( $linkmsg . 'link' ); # Calling either 'gotaccountlink' or 'nologinlink'
$link .= '</a>';
# Don't show a "create account" link if the user can't
- if( $this->showCreateOrLoginLink( $wgUser ) )
- $template->set( 'link', wfMsgWikiHtml( $linkmsg, $link ) );
- else
+ if( $this->showCreateOrLoginLink( $wgUser ) ) {
+ $template->set( 'link', wfMsgExt( $linkmsg, array( 'parseinline', 'replaceafter' ), $link ) );
+ } else {
$template->set( 'link', '' );
+ }
$template->set( 'header', '' );
$template->set( 'name', $this->mName );
@@ -993,8 +1003,9 @@ class LoginForm {
$template->set( 'email', $this->mEmail );
$template->set( 'realname', $this->mRealName );
$template->set( 'domain', $this->mDomain );
+ $template->set( 'reason', $this->mReason );
- $template->set( 'action', $titleObj->getLocalUrl( $q ) );
+ $template->set( 'action', $titleObj->getLocalURL( $q ) );
$template->set( 'message', $msg );
$template->set( 'messagetype', $msgtype );
$template->set( 'createemail', $wgEnableEmail && $wgUser->isLoggedIn() );
@@ -1003,7 +1014,10 @@ class LoginForm {
$template->set( 'emailrequired', $wgEmailConfirmToEdit );
$template->set( 'canreset', $wgAuth->allowPasswordChange() );
$template->set( 'canremember', ( $wgCookieExpiration > 0 ) );
- $template->set( 'remember', $wgUser->getOption( 'rememberpassword' ) or $this->mRemember );
+ $template->set( 'usereason', $wgUser->isLoggedIn() );
+ $template->set( 'remember', $wgUser->getOption( 'rememberpassword' ) || $this->mRemember );
+ $template->set( 'cansecurelogin', ( $wgSecureLogin === true ) );
+ $template->set( 'stickHTTPS', $this->mStickHTTPS );
if ( $this->mType == 'signup' ) {
if ( !self::getCreateaccountToken() ) {
@@ -1016,7 +1030,7 @@ class LoginForm {
}
$template->set( 'token', self::getLoginToken() );
}
-
+
# Prepare language selection links as needed
if( $wgLoginLanguageSelector ) {
$template->set( 'languages', $this->makeLanguageSelector() );
@@ -1032,7 +1046,7 @@ class LoginForm {
wfRunHooks( 'UserLoginForm', array( &$template ) );
}
- //Changes the title depending on permissions for creating account
+ // Changes the title depending on permissions for creating account
if ( $wgUser->isAllowed( 'createaccount' ) ) {
$wgOut->setPageTitle( wfMsg( 'userlogin' ) );
} else {
@@ -1041,7 +1055,7 @@ class LoginForm {
$wgOut->setRobotPolicy( 'noindex,nofollow' );
$wgOut->setArticleRelated( false );
- $wgOut->disallowUserJs(); // just in case...
+ $wgOut->disallowUserJs(); // just in case...
$wgOut->addTemplate( $template );
}
@@ -1071,7 +1085,7 @@ class LoginForm {
global $wgDisableCookieCheck, $wgRequest;
return $wgDisableCookieCheck ? true : $wgRequest->checkSessionCookie();
}
-
+
/**
* Get the login token from the current session
*/
@@ -1079,7 +1093,7 @@ class LoginForm {
global $wgRequest;
return $wgRequest->getSessionData( 'wsLoginToken' );
}
-
+
/**
* Randomly generate a new login token and attach it to the current session
*/
@@ -1089,7 +1103,7 @@ class LoginForm {
// because the latter reuses $_SESSION['wsEditToken']
$wgRequest->setSessionData( 'wsLoginToken', User::generateToken() );
}
-
+
/**
* Remove any login token attached to the current session
*/
@@ -1105,7 +1119,7 @@ class LoginForm {
global $wgRequest;
return $wgRequest->getSessionData( 'wsCreateaccountToken' );
}
-
+
/**
* Randomly generate a new createaccount token and attach it to the current session
*/
@@ -1113,7 +1127,7 @@ class LoginForm {
global $wgRequest;
$wgRequest->setSessionData( 'wsCreateaccountToken', User::generateToken() );
}
-
+
/**
* Remove any createaccount token attached to the current session
*/
@@ -1130,7 +1144,9 @@ class LoginForm {
$titleObj = SpecialPage::getTitleFor( 'Userlogin' );
$query = array( 'wpCookieCheck' => $type );
- if ( $this->mReturnTo ) $query['returnto'] = $this->mReturnTo;
+ if ( $this->mReturnTo ) {
+ $query['returnto'] = $this->mReturnTo;
+ }
$check = $titleObj->getFullURL( $query );
return $wgOut->redirect( $check );
@@ -1143,7 +1159,7 @@ class LoginForm {
if ( !$this->hasSessionCookie() ) {
if ( $type == 'new' ) {
return $this->mainLoginForm( wfMsgExt( 'nocookiesnew', array( 'parseinline' ) ) );
- } else if ( $type == 'login' ) {
+ } elseif ( $type == 'login' ) {
return $this->mainLoginForm( wfMsgExt( 'nocookieslogin', array( 'parseinline' ) ) );
} else {
# shouldn't happen
@@ -1177,7 +1193,7 @@ class LoginForm {
foreach( $langs as $lang ) {
$lang = trim( $lang, '* ' );
$parts = explode( '|', $lang );
- if (count($parts) >= 2) {
+ if ( count( $parts ) >= 2 ) {
$links[] = $this->makeLanguageSelectorLink( $parts[0], $parts[1] );
}
}
@@ -1198,10 +1214,12 @@ class LoginForm {
global $wgUser;
$self = SpecialPage::getTitleFor( 'Userlogin' );
$attr = array( 'uselang' => $lang );
- if( $this->mType == 'signup' )
+ if( $this->mType == 'signup' ) {
$attr['type'] = 'signup';
- if( $this->mReturnTo )
+ }
+ if( $this->mReturnTo ) {
$attr['returnto'] = $this->mReturnTo;
+ }
$skin = $wgUser->getSkin();
return $skin->linkKnown(
$self,
diff --git a/includes/specials/SpecialUserlogout.php b/includes/specials/SpecialUserlogout.php
index e23df612..39b5b284 100644
--- a/includes/specials/SpecialUserlogout.php
+++ b/includes/specials/SpecialUserlogout.php
@@ -1,33 +1,63 @@
<?php
/**
+ * Implements Special:Upload
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
- * constructor
+ * Implements Special:Userlogout
+ *
+ * @ingroup SpecialPage
*/
-function wfSpecialUserlogout() {
- global $wgUser, $wgOut;
-
- /**
- * Some satellite ISPs use broken precaching schemes that log people out straight after
- * they're logged in (bug 17790). Luckily, there's a way to detect such requests.
- */
- if ( isset( $_SERVER['REQUEST_URI'] ) && strpos( $_SERVER['REQUEST_URI'], '&amp;' ) !== false ) {
- wfDebug( "Special:Userlogout request {$_SERVER['REQUEST_URI']} looks suspicious, denying.\n" );
- wfHttpError( 400, wfMsg( 'loginerror' ), wfMsg( 'suspicious-userlogout' ) );
- return;
+class SpecialUserlogout extends UnlistedSpecialPage {
+
+ function __construct() {
+ parent::__construct( 'Userlogout' );
}
-
- $oldName = $wgUser->getName();
- $wgUser->logout();
- $wgOut->setRobotPolicy( 'noindex,nofollow' );
- // Hook.
- $injected_html = '';
- wfRunHooks( 'UserLogoutComplete', array(&$wgUser, &$injected_html, $oldName) );
+ function execute( $par ) {
+ global $wgUser, $wgOut;
+
+ /**
+ * Some satellite ISPs use broken precaching schemes that log people out straight after
+ * they're logged in (bug 17790). Luckily, there's a way to detect such requests.
+ */
+ if ( isset( $_SERVER['REQUEST_URI'] ) && strpos( $_SERVER['REQUEST_URI'], '&amp;' ) !== false ) {
+ wfDebug( "Special:Userlogout request {$_SERVER['REQUEST_URI']} looks suspicious, denying.\n" );
+ wfHttpError( 400, wfMsg( 'loginerror' ), wfMsg( 'suspicious-userlogout' ) );
+ return;
+ }
+
+ $this->setHeaders();
+ $this->outputHeader();
- $wgOut->addHTML( wfMsgExt( 'logouttext', array( 'parse' ) ) . $injected_html );
- $wgOut->returnToMain();
+ $oldName = $wgUser->getName();
+ $wgUser->logout();
+
+ $wgOut->addWikiMsg( 'logouttext' );
+
+ // Hook.
+ $injected_html = '';
+ wfRunHooks( 'UserLogoutComplete', array( &$wgUser, &$injected_html, $oldName ) );
+ $wgOut->addHTML( $injected_html );
+
+ $wgOut->returnToMain();
+ }
}
diff --git a/includes/specials/SpecialUserrights.php b/includes/specials/SpecialUserrights.php
index 36caf9a6..6ea8668b 100644
--- a/includes/specials/SpecialUserrights.php
+++ b/includes/specials/SpecialUserrights.php
@@ -1,13 +1,29 @@
<?php
/**
- * Special page to allow managing user group membership
+ * Implements Special:Userrights
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup SpecialPage
*/
/**
- * A class to manage user levels rights.
+ * Special page to allow managing user group membership
+ *
* @ingroup SpecialPage
*/
class UserrightsPage extends SpecialPage {
@@ -32,10 +48,10 @@ class UserrightsPage extends SpecialPage {
public function userCanChangeRights( $user, $checkIfSelf = true ) {
$available = $this->changeableGroups();
return !empty( $available['add'] )
- or !empty( $available['remove'] )
- or ( ( $this->isself || !$checkIfSelf ) and
+ || !empty( $available['remove'] )
+ || ( ( $this->isself || !$checkIfSelf ) &&
( !empty( $available['add-self'] )
- or !empty( $available['remove-self'] ) ) );
+ || !empty( $available['remove-self'] ) ) );
}
/**
@@ -49,7 +65,7 @@ class UserrightsPage extends SpecialPage {
// any groups, it's a bit silly to give them the user search prompt.
global $wgUser, $wgRequest, $wgOut;
- if( $par ) {
+ if( $par !== null ) {
$this->mTarget = $par;
} else {
$this->mTarget = $wgRequest->getVal( 'user' );
@@ -67,7 +83,7 @@ class UserrightsPage extends SpecialPage {
$available = $this->changeableGroups();
- if ( !$this->mTarget ) {
+ if ( $this->mTarget === null ) {
/*
* If the user specified no target, and they can only
* edit their own groups, automatically set them as the
@@ -77,8 +93,9 @@ class UserrightsPage extends SpecialPage {
$this->mTarget = $wgUser->getName();
}
- if ( $this->mTarget == $wgUser->getName() )
+ if ( User::getCanonicalName( $this->mTarget ) == $wgUser->getName() ) {
$this->isself = true;
+ }
if( !$this->userCanChangeRights( $wgUser, true ) ) {
// fixme... there may be intermediate groups we can mention.
@@ -99,8 +116,9 @@ class UserrightsPage extends SpecialPage {
$this->setHeaders();
// show the general form
- if ( count( $available['add'] ) || count( $available['remove'] ) )
+ if ( count( $available['add'] ) || count( $available['remove'] ) ) {
$this->switchForm();
+ }
if( $wgRequest->wasPosted() ) {
// save settings
@@ -121,7 +139,7 @@ class UserrightsPage extends SpecialPage {
}
// show some more forms
- if( $this->mTarget ) {
+ if( $this->mTarget !== null ) {
$this->editUserGroupsForm( $this->mTarget );
}
}
@@ -139,12 +157,14 @@ class UserrightsPage extends SpecialPage {
* @return null
*/
function saveUserGroups( $username, $reason = '' ) {
- global $wgRequest, $wgUser, $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
+ global $wgRequest, $wgOut;
- $user = $this->fetchUser( $username );
- if( $user instanceof WikiErrorMsg ) {
- $wgOut->addWikiMsgArray( $user->getMessageKey(), $user->getMessageArgs() );
+ $status = $this->fetchUser( $username );
+ if( !$status->isOK() ) {
+ $wgOut->addWikiText( $status->getWikiText() );
return;
+ } else {
+ $user = $status->value;
}
$allgroups = $this->getAllGroups();
@@ -162,7 +182,7 @@ class UserrightsPage extends SpecialPage {
$removegroup[] = $group;
}
}
-
+
$this->doSaveUserGroups( $user, $addgroup, $removegroup, $reason );
}
@@ -247,10 +267,12 @@ class UserrightsPage extends SpecialPage {
function editUserGroupsForm( $username ) {
global $wgOut;
- $user = $this->fetchUser( $username );
- if( $user instanceof WikiErrorMsg ) {
- $wgOut->addWikiMsgArray( $user->getMessageKey(), $user->getMessageArgs() );
+ $status = $this->fetchUser( $username );
+ if( !$status->isOK() ) {
+ $wgOut->addWikiText( $status->getWikiText() );
return;
+ } else {
+ $user = $status->value;
}
$groups = $user->getGroups();
@@ -267,7 +289,7 @@ class UserrightsPage extends SpecialPage {
* return a user (or proxy) object for manipulating it.
*
* Side effects: error output for invalid access
- * @return mixed User, UserRightsProxy, or WikiErrorMsg
+ * @return Status object
*/
public function fetchUser( $username ) {
global $wgUser, $wgUserrightsInterwikiDelimiter;
@@ -278,21 +300,21 @@ class UserrightsPage extends SpecialPage {
$database = '';
} else {
list( $name, $database ) = array_map( 'trim', $parts );
-
+
if( $database == wfWikiID() ) {
$database = '';
} else {
if( !$wgUser->isAllowed( 'userrights-interwiki' ) ) {
- return new WikiErrorMsg( 'userrights-no-interwiki' );
+ return Status::newFatal( 'userrights-no-interwiki' );
}
if( !UserRightsProxy::validDatabase( $database ) ) {
- return new WikiErrorMsg( 'userrights-nodatabase', $database );
+ return Status::newFatal( 'userrights-nodatabase', $database );
}
}
}
- if( $name == '' ) {
- return new WikiErrorMsg( 'nouserspecified' );
+ if( $name === '' ) {
+ return Status::newFatal( 'nouserspecified' );
}
if( $name{0} == '#' ) {
@@ -307,13 +329,13 @@ class UserrightsPage extends SpecialPage {
}
if( !$name ) {
- return new WikiErrorMsg( 'noname' );
+ return Status::newFatal( 'noname' );
}
} else {
$name = User::getCanonicalName( $name );
- if( !$name ) {
+ if( $name === false ) {
// invalid name
- return new WikiErrorMsg( 'nosuchusershort', $username );
+ return Status::newFatal( 'nosuchusershort', $username );
}
}
@@ -324,10 +346,10 @@ class UserrightsPage extends SpecialPage {
}
if( !$user || $user->isAnon() ) {
- return new WikiErrorMsg( 'nosuchusershort', $username );
+ return Status::newFatal( 'nosuchusershort', $username );
}
- return $user;
+ return Status::newGood( $user );
}
function makeGroupNameList( $ids ) {
@@ -352,14 +374,13 @@ class UserrightsPage extends SpecialPage {
function switchForm() {
global $wgOut, $wgScript;
$wgOut->addHTML(
- Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'name' => 'uluser', 'id' => 'mw-userrights-form1' ) ) .
- Xml::hidden( 'title', $this->getTitle()->getPrefixedText() ) .
- Xml::openElement( 'fieldset' ) .
- Xml::element( 'legend', array(), wfMsg( 'userrights-lookup-user' ) ) .
- Xml::inputLabel( wfMsg( 'userrights-user-editname' ), 'user', 'username', 30, $this->mTarget ) . ' ' .
+ Html::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'name' => 'uluser', 'id' => 'mw-userrights-form1' ) ) .
+ Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) .
+ Xml::fieldset( wfMsg( 'userrights-lookup-user' ) ) .
+ Xml::inputLabel( wfMsg( 'userrights-user-editname' ), 'user', 'username', 30, str_replace( '_', ' ', $this->mTarget ) ) . ' ' .
Xml::submitButton( wfMsg( 'editusergroup' ) ) .
- Xml::closeElement( 'fieldset' ) .
- Xml::closeElement( 'form' ) . "\n"
+ Html::closeElement( 'fieldset' ) .
+ Html::closeElement( 'form' ) . "\n"
);
}
@@ -396,8 +417,9 @@ class UserrightsPage extends SpecialPage {
global $wgOut, $wgUser, $wgLang;
$list = array();
- foreach( $groups as $group )
+ foreach( $groups as $group ) {
$list[] = self::buildGroupLink( $group );
+ }
$autolist = array();
if ( $user instanceof User ) {
@@ -417,8 +439,8 @@ class UserrightsPage extends SpecialPage {
}
$wgOut->addHTML(
Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalURL(), 'name' => 'editGroup', 'id' => 'mw-userrights-form2' ) ) .
- Xml::hidden( 'user', $this->mTarget ) .
- Xml::hidden( 'wpEditToken', $wgUser->editToken( $this->mTarget ) ) .
+ Html::hidden( 'user', $this->mTarget ) .
+ Html::hidden( 'wpEditToken', $wgUser->editToken( $this->mTarget ) ) .
Xml::openElement( 'fieldset' ) .
Xml::element( 'legend', array(), wfMsg( 'userrights-editusergroup' ) ) .
wfMsgExt( 'editinguser', array( 'parse' ), wfEscapeWikiText( $user->getName() ) ) .
@@ -437,7 +459,8 @@ class UserrightsPage extends SpecialPage {
<tr>
<td></td>
<td class='mw-submit'>" .
- Xml::submitButton( wfMsg( 'saveusergroups' ), array( 'name' => 'saveusergroups', 'accesskey' => 's' ) ) .
+ Xml::submitButton( wfMsg( 'saveusergroups' ),
+ array( 'name' => 'saveusergroups' ) + $wgUser->getSkin()->tooltipAndAccessKeyAttribs( 'userrights-set' ) ) .
"</td>
</tr>" .
Xml::closeElement( 'table' ) . "\n" .
@@ -511,7 +534,7 @@ class UserrightsPage extends SpecialPage {
foreach( $columns as $name => $column ) {
if( $column === array() )
continue;
- $ret .= xml::element( 'th', null, wfMsg( 'userrights-' . $name . '-col' ) );
+ $ret .= Xml::element( 'th', null, wfMsg( 'userrights-' . $name . '-col' ) );
}
$ret.= "</tr>\n<tr>\n";
foreach( $columns as $column ) {
@@ -522,7 +545,7 @@ class UserrightsPage extends SpecialPage {
$attr = $checkbox['disabled'] ? array( 'disabled' => 'disabled' ) : array();
if ( $checkbox['irreversible'] ) {
- $text = htmlspecialchars( wfMsg( 'userrights-irreversible-marker',
+ $text = htmlspecialchars( wfMsg( 'userrights-irreversible-marker',
User::getGroupMember( $group ) ) );
} else {
$text = htmlspecialchars( User::getGroupMember( $group ) );
diff --git a/includes/specials/SpecialVersion.php b/includes/specials/SpecialVersion.php
index ebc50bab..101823db 100644
--- a/includes/specials/SpecialVersion.php
+++ b/includes/specials/SpecialVersion.php
@@ -1,35 +1,56 @@
<?php
+/**
+ * Implements Special:Version
+ *
+ * Copyright © 2005 Ævar Arnfjörð Bjarmason
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
/**
* Give information about the version of MediaWiki, PHP, the DB and extensions
*
* @ingroup SpecialPage
- *
- * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
class SpecialVersion extends SpecialPage {
- private $firstExtOpened = true;
+
+ protected $firstExtOpened = false;
- static $viewvcUrls = array(
+ protected static $extensionTypes = false;
+
+ 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',
);
- function __construct(){
+ public function __construct(){
parent::__construct( 'Version' );
}
/**
* main()
*/
- function execute( $par ) {
- global $wgOut, $wgMessageCache, $wgSpecialVersionShowHooks, $wgContLang;
- $wgMessageCache->loadAllMessages();
-
+ public function execute( $par ) {
+ global $wgOut, $wgSpecialVersionShowHooks, $wgContLang;
+
$this->setHeaders();
$this->outputHeader();
$wgOut->allowClickjacking();
@@ -37,74 +58,76 @@ class SpecialVersion extends SpecialPage {
$wgOut->addHTML( Xml::openElement( 'div',
array( 'dir' => $wgContLang->getDir() ) ) );
$text =
- $this->MediaWikiCredits() .
+ $this->getMediaWikiCredits() .
$this->softwareInformation() .
- $this->extensionCredits();
+ $this->getExtensionCredits();
if ( $wgSpecialVersionShowHooks ) {
- $text .= $this->wgHooks();
+ $text .= $this->getWgHooks();
}
+
$wgOut->addWikiText( $text );
$wgOut->addHTML( $this->IPInfo() );
$wgOut->addHTML( '</div>' );
}
- /**#@+
- * @private
- */
-
/**
- * @return wiki text showing the license information
+ * Returns wiki text showing the license information.
+ *
+ * @return string
*/
- static function MediaWikiCredits() {
- global $wgContLang;
-
+ private static function getMediaWikiCredits() {
$ret = Xml::element( 'h2', array( 'id' => 'mw-version-license' ), wfMsg( 'version-license' ) );
// This text is always left-to-right.
- $ret .= '<div dir="ltr">';
+ $ret .= '<div>';
$ret .= "__NOTOC__
- This wiki is powered by '''[http://www.mediawiki.org/ MediaWiki]''',
- copyright © 2001-2010 Magnus Manske, Brion Vibber, Lee Daniel Crocker,
- Tim Starling, Erik Möller, Gabriel Wicke, Ævar Arnfjörð Bjarmason,
- Niklas Laxström, Domas Mituzas, Rob Church, Yuri Astrakhan, Aryeh Gregor,
- Aaron Schulz, Andrew Garrett, Raimond Spekking, Alexandre Emsenhuber,
- Siebrand Mazeland, Chad Horohoe and others.
-
- MediaWiki is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- MediaWiki is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU General Public License]
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- or [http://www.gnu.org/licenses/old-licenses/gpl-2.0.html read it online].
- ";
+ " . self::getCopyrightAndAuthorList() . "\n
+ " . wfMsg( 'version-license-info' );
$ret .= '</div>';
return str_replace( "\t\t", '', $ret ) . "\n";
}
/**
- * @return wiki text showing the third party software versions (apache, php, mysql).
+ * Get the "MediaWiki is copyright 2001-20xx by lots of cool guys" text
+ *
+ * @return String
+ */
+ public static function getCopyrightAndAuthorList() {
+ global $wgLang;
+
+ $authorList = array(
+ 'Magnus Manske', 'Brion Vibber', 'Lee Daniel Crocker',
+ 'Tim Starling', 'Erik Möller', 'Gabriel Wicke', 'Ævar Arnfjörð Bjarmason',
+ 'Niklas Laxström', 'Domas Mituzas', 'Rob Church', 'Yuri Astrakhan',
+ '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',
+ wfMsg( 'version-poweredby-others' )
+ );
+
+ return wfMsg( 'version-poweredby-credits', date( 'Y' ),
+ $wgLang->listToText( $authorList ) );
+ }
+
+ /**
+ * Returns wiki text showing the third party software versions (apache, php, mysql).
+ *
+ * @return string
*/
static function softwareInformation() {
$dbr = wfGetDB( DB_SLAVE );
// Put the software in an array of form 'name' => 'version'. All messages should
// be loaded here, so feel free to use wfMsg*() in the 'name'. Raw HTML or wikimarkup
- // can be used
+ // can be used.
$software = array();
$software['[http://www.mediawiki.org/ MediaWiki]'] = self::getVersionLinked();
$software['[http://www.php.net/ PHP]'] = phpversion() . " (" . php_sapi_name() . ")";
- $software[$dbr->getSoftwareLink()] = $dbr->getServerVersion();
+ $software[$dbr->getSoftwareLink()] = $dbr->getServerInfo();
- // Allow a hook to add/remove items
+ // Allow a hook to add/remove items.
wfRunHooks( 'SoftwareInfo', array( &$software ) );
$out = Xml::element( 'h2', array( 'id' => 'mw-version-software' ), wfMsg( 'version-software' ) ) .
@@ -113,17 +136,19 @@ class SpecialVersion extends SpecialPage {
<th>" . wfMsg( 'version-software-product' ) . "</th>
<th>" . wfMsg( 'version-software-version' ) . "</th>
</tr>\n";
+
foreach( $software as $name => $version ) {
$out .= "<tr>
<td>" . $name . "</td>
<td>" . $version . "</td>
</tr>\n";
- }
+ }
+
return $out . Xml::closeElement( 'table' );
}
/**
- * Return a string of the MediaWiki version with SVN revision if available
+ * Return a string of the MediaWiki version with SVN revision if available.
*
* @return mixed
*/
@@ -151,20 +176,23 @@ class SpecialVersion extends SpecialPage {
/**
* Return a wikitext-formatted string of the MediaWiki version with a link to
- * the SVN revision if available
+ * the SVN revision if available.
*
* @return mixed
*/
public static function getVersionLinked() {
global $wgVersion, $IP;
wfProfileIn( __METHOD__ );
+
$info = self::getSvnInfo( $IP );
- if ( isset( $info['checkout-rev'] ) ) {
+
+ if ( isset( $info['checkout-rev'] ) ) {
$linkText = wfMsg(
'version-svn-revision',
isset( $info['directory-rev'] ) ? $info['directory-rev'] : '',
$info['checkout-rev']
);
+
if ( isset( $info['viewvc-url'] ) ) {
$version = "$wgVersion [{$info['viewvc-url']} $linkText]";
} else {
@@ -173,54 +201,115 @@ class SpecialVersion extends SpecialPage {
} else {
$version = $wgVersion;
}
+
wfProfileOut( __METHOD__ );
return $version;
}
- /** Generate wikitext showing extensions name, URL, author and description */
- function extensionCredits() {
+ /**
+ * Returns an array with the base extension types.
+ * Type is stored as array key, the message as array value.
+ *
+ * TODO: ideally this would return all extension types, including
+ * those added by SpecialVersionExtensionTypes. This is not possible
+ * since this hook is passing along $this though.
+ *
+ * @since 1.17
+ *
+ * @return array
+ */
+ public static function getExtensionTypes() {
+ if ( self::$extensionTypes === false ) {
+ self::$extensionTypes = array(
+ 'specialpage' => wfMsg( 'version-specialpages' ),
+ 'parserhook' => wfMsg( 'version-parserhooks' ),
+ 'variable' => wfMsg( 'version-variables' ),
+ 'media' => wfMsg( 'version-mediahandlers' ),
+ 'skin' => wfMsg( 'version-skins' ),
+ 'other' => wfMsg( 'version-other' ),
+ );
+
+ wfRunHooks( 'ExtensionTypes', array( &self::$extensionTypes ) );
+ }
+
+ return self::$extensionTypes;
+ }
+
+ /**
+ * Returns the internationalized name for an extension type.
+ *
+ * @since 1.17
+ *
+ * @param $type String
+ *
+ * @return string
+ */
+ public static function getExtensionTypeName( $type ) {
+ $types = self::getExtensionTypes();
+ return isset( $types[$type] ) ? $types[$type] : $types['other'];
+ }
+
+ /**
+ * Generate wikitext showing extensions name, URL, author and description.
+ *
+ * @return String: Wikitext
+ */
+ function getExtensionCredits() {
global $wgExtensionCredits, $wgExtensionFunctions, $wgParser, $wgSkinExtensionFunctions;
- if ( ! count( $wgExtensionCredits ) && ! count( $wgExtensionFunctions ) && ! count( $wgSkinExtensionFunctions ) )
+ if ( !count( $wgExtensionCredits ) && !count( $wgExtensionFunctions ) && !count( $wgSkinExtensionFunctions ) ) {
return '';
+ }
- $extensionTypes = array(
- 'specialpage' => wfMsg( 'version-specialpages' ),
- 'parserhook' => wfMsg( 'version-parserhooks' ),
- 'variable' => wfMsg( 'version-variables' ),
- 'media' => wfMsg( 'version-mediahandlers' ),
- 'other' => wfMsg( 'version-other' ),
- );
+ $extensionTypes = self::getExtensionTypes();
+
+ /**
+ * @deprecated as of 1.17, use hook ExtensionTypes instead.
+ */
wfRunHooks( 'SpecialVersionExtensionTypes', array( &$this, &$extensionTypes ) );
$out = Xml::element( 'h2', array( 'id' => 'mw-version-ext' ), wfMsg( 'version-extensions' ) ) .
Xml::openElement( 'table', array( 'class' => 'wikitable', 'id' => 'sv-ext' ) );
- foreach ( $extensionTypes as $type => $text ) {
- if ( isset ( $wgExtensionCredits[$type] ) && count ( $wgExtensionCredits[$type] ) ) {
- $out .= $this->openExtType( $text, 'credits-' . $type );
-
- usort( $wgExtensionCredits[$type], array( $this, 'compare' ) );
-
- foreach ( $wgExtensionCredits[$type] as $extension ) {
- $out .= $this->formatCredits( $extension );
- }
+ // Make sure the 'other' type is set to an array.
+ if ( !array_key_exists( 'other', $wgExtensionCredits ) ) {
+ $wgExtensionCredits['other'] = array();
+ }
+
+ // Find all extensions that do not have a valid type and give them the type 'other'.
+ foreach ( $wgExtensionCredits as $type => $extensions ) {
+ if ( !array_key_exists( $type, $extensionTypes ) ) {
+ $wgExtensionCredits['other'] = array_merge( $wgExtensionCredits['other'], $extensions );
+ }
+ }
+
+ // Loop through the extension categories to display their extensions in the list.
+ foreach ( $extensionTypes as $type => $message ) {
+ if ( $type != 'other' ) {
+ $out .= $this->getExtensionCategory( $type, $message );
}
}
+
+ // We want the 'other' type to be last in the list.
+ $out .= $this->getExtensionCategory( 'other', $extensionTypes['other'] );
if ( count( $wgExtensionFunctions ) ) {
$out .= $this->openExtType( wfMsg( 'version-extension-functions' ), 'extension-functions' );
$out .= '<tr><td colspan="4">' . $this->listToText( $wgExtensionFunctions ) . "</td></tr>\n";
}
- if ( $cnt = count( $tags = $wgParser->getTags() ) ) {
- for ( $i = 0; $i < $cnt; ++$i )
+ $tags = $wgParser->getTags();
+ $cnt = count( $tags );
+
+ if ( $cnt ) {
+ for ( $i = 0; $i < $cnt; ++$i ) {
$tags[$i] = "&lt;{$tags[$i]}&gt;";
+ }
$out .= $this->openExtType( wfMsg( 'version-parser-extensiontags' ), 'parser-tags' );
$out .= '<tr><td colspan="4">' . $this->listToText( $tags ). "</td></tr>\n";
}
- if( $cnt = count( $fhooks = $wgParser->getFunctionHooks() ) ) {
+ if( count( $fhooks = $wgParser->getFunctionHooks() ) ) {
$out .= $this->openExtType( wfMsg( 'version-parser-function-hooks' ), 'parser-function-hooks' );
$out .= '<tr><td colspan="4">' . $this->listToText( $fhooks ) . "</td></tr>\n";
}
@@ -229,11 +318,43 @@ class SpecialVersion extends SpecialPage {
$out .= $this->openExtType( wfMsg( 'version-skin-extension-functions' ), 'skin-extension-functions' );
$out .= '<tr><td colspan="4">' . $this->listToText( $wgSkinExtensionFunctions ) . "</td></tr>\n";
}
+
$out .= Xml::closeElement( 'table' );
+
return $out;
}
+
+ /**
+ * Creates and returns the HTML for a single extension category.
+ *
+ * @since 1.17
+ *
+ * @param $type String
+ * @param $message String
+ *
+ * @return string
+ */
+ protected function getExtensionCategory( $type, $message ) {
+ global $wgExtensionCredits;
+
+ $out = '';
+
+ if ( array_key_exists( $type, $wgExtensionCredits ) && count( $wgExtensionCredits[$type] ) > 0 ) {
+ $out .= $this->openExtType( $message, 'credits-' . $type );
+
+ usort( $wgExtensionCredits[$type], array( $this, 'compare' ) );
+
+ foreach ( $wgExtensionCredits[$type] as $extension ) {
+ $out .= $this->getCreditsForExtension( $extension );
+ }
+ }
- /** Callback to sort extensions by type */
+ return $out;
+ }
+
+ /**
+ * Callback to sort extensions by type.
+ */
function compare( $a, $b ) {
global $wgLang;
if( $a['name'] === $b['name'] ) {
@@ -245,8 +366,16 @@ class SpecialVersion extends SpecialPage {
}
}
- function formatCredits( $extension ) {
+ /**
+ * Creates and formats the creidts for a single extension and returns this.
+ *
+ * @param $extension Array
+ *
+ * @return string
+ */
+ function getCreditsForExtension( array $extension ) {
$name = isset( $extension['name'] ) ? $extension['name'] : '[no name]';
+
if ( isset( $extension['path'] ) ) {
$svnInfo = self::getSvnInfo( dirname($extension['path']) );
$directoryRev = isset( $svnInfo['directory-rev'] ) ? $svnInfo['directory-rev'] : null;
@@ -258,12 +387,13 @@ class SpecialVersion extends SpecialPage {
$viewvcUrl = null;
}
- # Make main link (or just the name if there is no URL)
+ # Make main link (or just the name if there is no URL).
if ( isset( $extension['url'] ) ) {
$mainLink = "[{$extension['url']} $name]";
} else {
$mainLink = $name;
}
+
if ( isset( $extension['version'] ) ) {
$versionText = '<span class="mw-version-ext-version">' .
wfMsg( 'version-version', $extension['version'] ) .
@@ -272,7 +402,7 @@ class SpecialVersion extends SpecialPage {
$versionText = '';
}
- # Make subversion text/link
+ # Make subversion text/link.
if ( $checkoutRev ) {
$svnText = wfMsg( 'version-svn-revision', $directoryRev, $checkoutRev );
$svnText = isset( $viewvcUrl ) ? "[$viewvcUrl $svnText]" : $svnText;
@@ -280,11 +410,13 @@ class SpecialVersion extends SpecialPage {
$svnText = false;
}
- # Make description text
+ # Make description text.
$description = isset ( $extension['description'] ) ? $extension['description'] : '';
+
if( isset ( $extension['descriptionmsg'] ) ) {
- # Look for a localized description
+ # Look for a localized description.
$descriptionMsg = $extension['descriptionmsg'];
+
if( is_array( $descriptionMsg ) ) {
$descriptionMsgKey = $descriptionMsg[0]; // Get the message key
array_shift( $descriptionMsg ); // Shift out the message key to get the parameters only
@@ -306,17 +438,21 @@ class SpecialVersion extends SpecialPage {
$extNameVer = "<tr>
<td colspan=\"2\"><em>$mainLink $versionText</em></td>";
}
+
$author = isset ( $extension['author'] ) ? $extension['author'] : array();
$extDescAuthor = "<td>$description</td>
<td>" . $this->listToText( (array)$author, false ) . "</td>
</tr>\n";
+
return $extNameVer . $extDescAuthor;
}
/**
- * @return string
+ * Generate wikitext showing hooks in $wgHooks.
+ *
+ * @return String: wikitext
*/
- function wgHooks() {
+ private function getWgHooks() {
global $wgHooks;
if ( count( $wgHooks ) ) {
@@ -346,32 +482,39 @@ class SpecialVersion extends SpecialPage {
$opt = array( 'colspan' => 4 );
$out = '';
- if( !$this->firstExtOpened ) {
+ if( $this->firstExtOpened ) {
// Insert a spacing line
- $out .= '<tr class="sv-space">' . Xml::element( 'td', $opt ) . "</tr>\n";
+ $out .= '<tr class="sv-space">' . Html::element( 'td', $opt ) . "</tr>\n";
}
- $this->firstExtOpened = false;
-
- if( $name )
+ $this->firstExtOpened = true;
+
+ if( $name ) {
$opt['id'] = "sv-$name";
+ }
$out .= "<tr>" . Xml::element( 'th', $opt, $text ) . "</tr>\n";
+
return $out;
}
/**
- * @return string
+ * Get information about client's IP address.
+ *
+ * @return String: HTML fragment
*/
- function IPInfo() {
+ private function IPInfo() {
$ip = str_replace( '--', ' - ', htmlspecialchars( wfGetIP() ) );
return "<!-- visited from $ip -->\n" .
"<span style='display:none'>visited from $ip</span>";
}
/**
- * @param array $list
- * @param bool $sort
- * @return string
+ * Convert an array of items into a list for display.
+ *
+ * @param $list Array of elements to display
+ * @param $sort Boolean: whether to sort the items in $list
+ *
+ * @return String
*/
function listToText( $list, $sort = true ) {
$cnt = count( $list );
@@ -391,9 +534,12 @@ class SpecialVersion extends SpecialPage {
}
/**
- * @param mixed $list Will convert an array to string if given and return
- * the paramater unaltered otherwise
- * @return mixed
+ * Convert an array or object to a string for display.
+ *
+ * @param $list Mixed: will convert an array to string if given and return
+ * the paramater unaltered otherwise
+ *
+ * @return Mixed
*/
static function arrayToString( $list ) {
if( is_array( $list ) && count( $list ) == 1 )
@@ -462,41 +608,47 @@ class SpecialVersion extends SpecialPage {
}
}
}
+
return false;
}
- // subversion is release 1.4 or above
+ // Subversion is release 1.4 or above.
if ( count( $lines ) < 11 ) {
return false;
}
+
$info = array(
'checkout-rev' => intval( trim( $lines[3] ) ),
'url' => trim( $lines[4] ),
'repo-url' => trim( $lines[5] ),
'directory-rev' => intval( trim( $lines[10] ) )
);
+
if ( isset( self::$viewvcUrls[$info['repo-url']] ) ) {
$viewvc = str_replace(
$info['repo-url'],
self::$viewvcUrls[$info['repo-url']],
$info['url']
);
- $pathRelativeToRepo = substr( $info['url'], strlen( $info['repo-url'] ) );
+
$viewvc .= '/?pathrev=';
$viewvc .= urlencode( $info['checkout-rev'] );
$info['viewvc-url'] = $viewvc;
}
+
return $info;
}
/**
* Retrieve the revision number of a Subversion working directory.
*
- * @param String $dir Directory of the svn checkout
- * @return int revision number as int
+ * @param $dir String: directory of the svn checkout
+ *
+ * @return Integer: revision number as int
*/
public static function getSvnRevision( $dir ) {
$info = self::getSvnInfo( $dir );
+
if ( $info === false ) {
return false;
} elseif ( isset( $info['checkout-rev'] ) ) {
@@ -506,5 +658,4 @@ class SpecialVersion extends SpecialPage {
}
}
- /**#@-*/
}
diff --git a/includes/specials/SpecialWantedcategories.php b/includes/specials/SpecialWantedcategories.php
index 5e5a4f17..b588dbf0 100644
--- a/includes/specials/SpecialWantedcategories.php
+++ b/includes/specials/SpecialWantedcategories.php
@@ -1,5 +1,24 @@
<?php
/**
+ * Implements Special:Wantedcategories
+ *
+ * Copyright © 2005 Ævar Arnfjörð Bjarmason
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
@@ -8,10 +27,6 @@
* A querypage to list the most wanted categories - implements Special:Wantedcategories
*
* @ingroup SpecialPage
- *
- * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
class WantedCategoriesPage extends WantedQueryPage {
diff --git a/includes/specials/SpecialWantedfiles.php b/includes/specials/SpecialWantedfiles.php
index 189b9d8b..d6c1157b 100644
--- a/includes/specials/SpecialWantedfiles.php
+++ b/includes/specials/SpecialWantedfiles.php
@@ -1,17 +1,33 @@
<?php
-/*
+/**
+ * Implements Special:Wantedfiles
+ *
+ * Copyright © 2008 Soxred93
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
+ * @author Soxred93 <soxred93@gmail.com>
*/
/**
- * Querypage that lists the most wanted files - implements Special:Wantedfiles
+ * Querypage that lists the most wanted files
*
* @ingroup SpecialPage
- *
- * @author Soxred93 <soxred93@gmail.com>
- * @copyright Copyright © 2008, Soxred93
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
class WantedFilesPage extends WantedQueryPage {
@@ -19,9 +35,19 @@ class WantedFilesPage extends WantedQueryPage {
return 'Wantedfiles';
}
+ /**
+ * KLUGE: The results may contain false positives for files
+ * that exist e.g. in a shared repo. Setting this at least
+ * keeps them from showing up as redlinks in the output, even
+ * if it doesn't fix the real problem (bug 6220).
+ */
+ function forceExistenceCheck() {
+ return true;
+ }
+
function getSQL() {
$dbr = wfGetDB( DB_SLAVE );
- list( $imagelinks, $page ) = $dbr->tableNamesN( 'imagelinks', 'page' );
+ list( $imagelinks, $image ) = $dbr->tableNamesN( 'imagelinks', 'image' );
$name = $dbr->addQuotes( $this->getName() );
return
"
@@ -31,8 +57,8 @@ class WantedFilesPage extends WantedQueryPage {
il_to as title,
COUNT(*) as value
FROM $imagelinks
- LEFT JOIN $page ON il_to = page_title AND page_namespace = ". NS_FILE ."
- WHERE page_title IS NULL
+ LEFT JOIN $image ON il_to = img_name
+ WHERE img_name IS NULL
GROUP BY il_to
";
}
diff --git a/includes/specials/SpecialWantedpages.php b/includes/specials/SpecialWantedpages.php
index eeca87ab..4e1611bc 100644
--- a/includes/specials/SpecialWantedpages.php
+++ b/includes/specials/SpecialWantedpages.php
@@ -1,17 +1,35 @@
<?php
/**
+ * Implements Special:Wantedpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
*/
/**
- * implements Special:Wantedpages
+ * A special page that lists most linked pages that does not exist
+ *
* @ingroup SpecialPage
*/
class WantedPagesPage extends WantedQueryPage {
var $nlinks;
- function WantedPagesPage( $inc = false, $nlinks = true ) {
+ function __construct( $inc = false, $nlinks = true ) {
$this->setListoutput( $inc );
$this->nlinks = $nlinks;
}
diff --git a/includes/specials/SpecialWantedtemplates.php b/includes/specials/SpecialWantedtemplates.php
index 329d7a3f..ae43c237 100644
--- a/includes/specials/SpecialWantedtemplates.php
+++ b/includes/specials/SpecialWantedtemplates.php
@@ -1,19 +1,35 @@
<?php
/**
+ * Implements Special:Wantedtemplates
+ *
+ * Copyright © 2008, Danny B.
+ * Based on SpecialWantedcategories.php by Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ * makeWlhLink() taken from SpecialMostlinkedtemplates by Rob Church <robchur@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
+ * @author Danny B.
*/
/**
- * A querypage to list the most wanted templates - implements Special:Wantedtemplates
- * based on SpecialWantedcategories.php by Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * makeWlhLink() taken from SpecialMostlinkedtemplates by Rob Church <robchur@gmail.com>
+ * A querypage to list the most wanted templates
*
* @ingroup SpecialPage
- *
- * @author Danny B.
- * @copyright Copyright © 2008, Danny B.
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
class WantedTemplatesPage extends WantedQueryPage {
diff --git a/includes/specials/SpecialWatchlist.php b/includes/specials/SpecialWatchlist.php
index c32af2ae..bb1c194d 100644
--- a/includes/specials/SpecialWatchlist.php
+++ b/includes/specials/SpecialWatchlist.php
@@ -1,5 +1,22 @@
<?php
/**
+ * Implements Special:Watchlist
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage Watchlist
*/
@@ -21,7 +38,7 @@ function wfSpecialWatchlist( $par ) {
$wgUser->saveSettings();
}
- global $wgServer, $wgScriptPath, $wgFeedClasses;
+ global $wgFeedClasses;
$apiParams = array( 'action' => 'feedwatchlist', 'allrev' => 'allrev',
'wlowner' => $wgUser->getName(), 'wltoken' => $wlToken );
$feedTemplate = wfScript('api').'?';
@@ -51,8 +68,7 @@ function wfSpecialWatchlist( $par ) {
$wgOut->setPageTitle( wfMsg( 'watchlist' ) );
- $sub = wfMsgExt( 'watchlistfor', 'parseinline', $wgUser->getName() );
- $sub .= '<br />' . WatchlistEditor::buildTools( $wgUser->getSkin() );
+ $sub = wfMsgExt( 'watchlistfor2', array( 'parseinline', 'replaceafter' ), $wgUser->getName(), WatchlistEditor::buildTools( $wgUser->getSkin() ) );
$wgOut->setSubtitle( $sub );
if( ( $mode = WatchlistEditor::getMode( $wgRequest, $par ) ) !== false ) {
@@ -89,7 +105,7 @@ function wfSpecialWatchlist( $par ) {
$prefs['days'] = floatval( $wgUser->getOption( 'watchlistdays' ) );
$prefs['hideminor'] = $wgUser->getBoolOption( 'watchlisthideminor' );
$prefs['hidebots'] = $wgUser->getBoolOption( 'watchlisthidebots' );
- $prefs['hideanons'] = $wgUser->getBoolOption( 'watchlisthideanon' );
+ $prefs['hideanons'] = $wgUser->getBoolOption( 'watchlisthideanons' );
$prefs['hideliu'] = $wgUser->getBoolOption( 'watchlisthideliu' );
$prefs['hideown' ] = $wgUser->getBoolOption( 'watchlisthideown' );
$prefs['hidepatrolled' ] = $wgUser->getBoolOption( 'watchlisthidepatrolled' );
@@ -155,10 +171,11 @@ function wfSpecialWatchlist( $par ) {
return;
}
- if( $days <= 0 ) {
- $andcutoff = '';
- } else {
- $andcutoff = "rc_timestamp > '".$dbr->timestamp( time() - intval( $days * 86400 ) )."'";
+ # Possible where conditions
+ $conds = array();
+
+ if( $days > 0 ) {
+ $conds[] = "rc_timestamp > '".$dbr->timestamp( time() - intval( $days * 86400 ) )."'";
}
# If the watchlist is relatively short, it's simplest to zip
@@ -170,21 +187,35 @@ function wfSpecialWatchlist( $par ) {
# Up estimate of watched items by 15% to compensate for talk pages...
# Toggles
- $andHideOwn = $hideOwn ? "rc_user != $uid" : '';
- $andHideBots = $hideBots ? "rc_bot = 0" : '';
- $andHideMinor = $hideMinor ? "rc_minor = 0" : '';
- $andHideLiu = $hideLiu ? "rc_user = 0" : '';
- $andHideAnons = $hideAnons ? "rc_user != 0" : '';
- $andHidePatrolled = $wgUser->useRCPatrol() && $hidePatrolled ? "rc_patrolled != 1" : '';
+ if( $hideOwn ) {
+ $conds[] = "rc_user != $uid";
+ }
+ if( $hideBots ) {
+ $conds[] = 'rc_bot = 0';
+ }
+ if( $hideMinor ) {
+ $conds[] = 'rc_minor = 0';
+ }
+ if( $hideLiu ) {
+ $conds[] = 'rc_user = 0';
+ }
+ if( $hideAnons ) {
+ $conds[] = 'rc_user != 0';
+ }
+ if ( $wgUser->useRCPatrol() && $hidePatrolled ) {
+ $conds[] = 'rc_patrolled != 1';
+ }
+ if( $nameSpaceClause ) {
+ $conds[] = $nameSpaceClause;
+ }
# Toggle watchlist content (all recent edits or just the latest)
if( $wgUser->getOption( 'extendwatchlist' )) {
- $andLatest='';
$limitWatchlist = intval( $wgUser->getOption( 'wllimit' ) );
$usePage = false;
} else {
# Top log Ids for a page are not stored
- $andLatest = 'rc_this_oldid=page_latest OR rc_type=' . RC_LOG;
+ $conds[] = 'rc_this_oldid=page_latest OR rc_type=' . RC_LOG;
$limitWatchlist = 0;
$usePage = true;
}
@@ -208,14 +239,13 @@ function wfSpecialWatchlist( $par ) {
'id' => 'mw-watchlist-resetbutton' ) ) .
wfMsgExt( 'wlheader-showupdated', array( 'parseinline' ) ) . ' ' .
Xml::submitButton( wfMsg( 'enotif_reset' ), array( 'name' => 'dummy' ) ) .
- Xml::hidden( 'reset', 'all' ) .
+ Html::hidden( 'reset', 'all' ) .
Xml::closeElement( 'form' );
}
$form .= '<hr />';
$tables = array( 'recentchanges', 'watchlist' );
$fields = array( "{$recentchanges}.*" );
- $conds = array();
$join_conds = array(
'watchlist' => array('INNER JOIN',"wl_user='{$uid}' AND wl_namespace=rc_namespace AND wl_title=rc_title"),
);
@@ -226,15 +256,6 @@ function wfSpecialWatchlist( $par ) {
if( $limitWatchlist ) {
$options['LIMIT'] = $limitWatchlist;
}
- if( $andcutoff ) $conds[] = $andcutoff;
- if( $andLatest ) $conds[] = $andLatest;
- if( $andHideOwn ) $conds[] = $andHideOwn;
- if( $andHideBots ) $conds[] = $andHideBots;
- if( $andHideMinor ) $conds[] = $andHideMinor;
- if( $andHideLiu ) $conds[] = $andHideLiu;
- if( $andHideAnons ) $conds[] = $andHideAnons;
- if( $andHidePatrolled ) $conds[] = $andHidePatrolled;
- if( $nameSpaceClause ) $conds[] = $nameSpaceClause;
$rollbacker = $wgUser->isAllowed('rollback');
if ( $usePage || $rollbacker ) {
@@ -287,29 +308,27 @@ function wfSpecialWatchlist( $par ) {
$form .= $wlInfo;
$form .= $cutofflinks;
$form .= $wgLang->pipeList( $links );
- $form .= Xml::openElement( 'form', array( 'method' => 'post', 'action' => $thisTitle->getLocalUrl() ) );
+ $form .= Xml::openElement( 'form', array( 'method' => 'post', 'action' => $thisTitle->getLocalUrl(), 'id' => 'mw-watchlist-form-namespaceselector' ) );
$form .= '<hr /><p>';
- $form .= Xml::label( wfMsg( 'namespace' ), 'namespace' ) . '&nbsp;';
- $form .= Xml::namespaceSelector( $nameSpace, '' ) . '&nbsp;';
- $form .= Xml::checkLabel( wfMsg('invert'), 'invert', 'nsinvert', $invert ) . '&nbsp;';
+ $form .= Xml::label( wfMsg( 'namespace' ), 'namespace' ) . '&#160;';
+ $form .= Xml::namespaceSelector( $nameSpace, '' ) . '&#160;';
+ $form .= Xml::checkLabel( wfMsg('invert'), 'invert', 'nsinvert', $invert ) . '&#160;';
$form .= Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . '</p>';
- $form .= Xml::hidden( 'days', $days );
+ $form .= Html::hidden( 'days', $days );
if( $hideMinor )
- $form .= Xml::hidden( 'hideMinor', 1 );
+ $form .= Html::hidden( 'hideMinor', 1 );
if( $hideBots )
- $form .= Xml::hidden( 'hideBots', 1 );
+ $form .= Html::hidden( 'hideBots', 1 );
if( $hideAnons )
- $form .= Xml::hidden( 'hideAnons', 1 );
+ $form .= Html::hidden( 'hideAnons', 1 );
if( $hideLiu )
- $form .= Xml::hidden( 'hideLiu', 1 );
+ $form .= Html::hidden( 'hideLiu', 1 );
if( $hideOwn )
- $form .= Xml::hidden( 'hideOwn', 1 );
+ $form .= Html::hidden( 'hideOwn', 1 );
$form .= Xml::closeElement( 'form' );
$form .= Xml::closeElement( 'fieldset' );
$wgOut->addHTML( $form );
- $wgOut->addHTML( ChangesList::flagLegend() );
-
# If there's nothing to show, stop here
if( $numRows == 0 ) {
$wgOut->addWikiMsg( 'watchnochange' );
@@ -320,7 +339,7 @@ function wfSpecialWatchlist( $par ) {
/* Do link batch query */
$linkBatch = new LinkBatch;
- while ( $row = $dbr->fetchObject( $res ) ) {
+ foreach ( $res as $row ) {
$userNameUnderscored = str_replace( ' ', '_', $row->rc_user_text );
if ( $row->rc_user != 0 ) {
$linkBatch->add( NS_USER, $userNameUnderscored );
@@ -337,7 +356,7 @@ function wfSpecialWatchlist( $par ) {
$s = $list->beginRecentChangesList();
$counter = 1;
- while ( $obj = $dbr->fetchObject( $res ) ) {
+ foreach ( $res as $obj ) {
# Make RC entry
$rc = RecentChange::newFromRow( $obj );
$rc->counter = $counter++;
@@ -364,7 +383,6 @@ function wfSpecialWatchlist( $par ) {
}
$s .= $list->endRecentChangesList();
- $dbr->freeResult( $res );
$wgOut->addHTML( $s );
}
@@ -444,8 +462,9 @@ function wlCutoffLinks( $days, $page = 'Watchlist', $options = array() ) {
/**
* Count the number of items on a user's watchlist
*
- * @param $talk Include talk pages
- * @return integer
+ * @param $user User object
+ * @param $talk Boolean: include talk pages
+ * @return Integer
*/
function wlCountItems( &$user, $talk = true ) {
$dbr = wfGetDB( DB_SLAVE, 'watchlist' );
@@ -455,7 +474,6 @@ function wlCountItems( &$user, $talk = true ) {
array( 'wl_user' => $user->mId ), 'wlCountItems' );
$row = $dbr->fetchObject( $res );
$count = $row->count;
- $dbr->freeResult( $res );
# Halve to remove talk pages if needed
if( !$talk )
diff --git a/includes/specials/SpecialWhatlinkshere.php b/includes/specials/SpecialWhatlinkshere.php
index b63c0eee..360f3f68 100644
--- a/includes/specials/SpecialWhatlinkshere.php
+++ b/includes/specials/SpecialWhatlinkshere.php
@@ -1,13 +1,29 @@
<?php
/**
- * @todo Use some variant of Pager or something; the pagination here is lousy.
+ * Implements Special:Whatlinkshere
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
*
* @file
- * @ingroup SpecialPage
+ * @todo Use some variant of Pager or something; the pagination here is lousy.
*/
/**
- * implements Special:Whatlinkshere
+ * Implements Special:Whatlinkshere
+ *
* @ingroup SpecialPage
*/
class SpecialWhatLinksHere extends SpecialPage {
@@ -60,7 +76,7 @@ class SpecialWhatLinksHere extends SpecialPage {
return;
}
- $this->selfTitle = SpecialPage::getTitleFor( 'Whatlinkshere', $this->target->getPrefixedDBkey() );
+ $this->selfTitle = $this->getTitle( $this->target->getPrefixedDBkey() );
$wgOut->setPageTitle( wfMsg( 'whatlinkshere-title', $this->target->getPrefixedText() ) );
$wgOut->setSubtitle( wfMsg( 'whatlinkshere-backlink', $this->skin->link( $this->target, $this->target->getPrefixedText(), array(), array( 'redirect' => 'no' ) ) ) );
@@ -171,29 +187,25 @@ class SpecialWhatLinksHere extends SpecialPage {
// templatelinks comes second so that the templatelinks row overwrites the
// pagelinks row, so we get (inclusion) rather than nothing
if( $fetchlinks ) {
- while ( $row = $dbr->fetchObject( $plRes ) ) {
+ foreach ( $plRes as $row ) {
$row->is_template = 0;
$row->is_image = 0;
$rows[$row->page_id] = $row;
}
- $dbr->freeResult( $plRes );
-
}
if( !$hidetrans ) {
- while ( $row = $dbr->fetchObject( $tlRes ) ) {
+ foreach ( $tlRes as $row ) {
$row->is_template = 1;
$row->is_image = 0;
$rows[$row->page_id] = $row;
}
- $dbr->freeResult( $tlRes );
}
if( !$hideimages ) {
- while ( $row = $dbr->fetchObject( $ilRes ) ) {
+ foreach ( $ilRes as $row ) {
$row->is_template = 0;
$row->is_image = 1;
$rows[$row->page_id] = $row;
}
- $dbr->freeResult( $ilRes );
}
// Sort by key and then change the keys to 0-based indices
@@ -224,7 +236,7 @@ class SpecialWhatLinksHere extends SpecialPage {
$wgOut->addHTML( $prevnext );
}
- $wgOut->addHTML( $this->listStart() );
+ $wgOut->addHTML( $this->listStart( $level ) );
foreach ( $rows as $row ) {
$nt = Title::makeTitle( $row->page_namespace, $row->page_title );
@@ -244,8 +256,8 @@ class SpecialWhatLinksHere extends SpecialPage {
}
}
- protected function listStart() {
- return Xml::openElement( 'ul', array ( 'id' => 'mw-whatlinkshere-list' ) );
+ protected function listStart( $level ) {
+ return Xml::openElement( 'ul', ( $level ? array() : array( 'id' => 'mw-whatlinkshere-list' ) ) );
}
protected function listItem( $row, $nt, $notClose = false ) {
@@ -303,7 +315,7 @@ class SpecialWhatLinksHere extends SpecialPage {
protected function wlhLink( Title $target, $text ) {
static $title = null;
if ( $title === null )
- $title = SpecialPage::getTitleFor( 'Whatlinkshere' );
+ $title = $this->getTitle();
return $this->skin->linkKnown(
$title,
@@ -368,9 +380,9 @@ class SpecialWhatLinksHere extends SpecialPage {
$f = Xml::openElement( 'form', array( 'action' => $wgScript ) );
# Values that should not be forgotten
- $f .= Xml::hidden( 'title', SpecialPage::getTitleFor( 'Whatlinkshere' )->getPrefixedText() );
+ $f .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() );
foreach ( $this->opts->getUnconsumedValues() as $name => $value ) {
- $f .= Xml::hidden( $name, $value );
+ $f .= Html::hidden( $name, $value );
}
$f .= Xml::fieldset( wfMsg( 'whatlinkshere' ) );
@@ -382,7 +394,7 @@ class SpecialWhatLinksHere extends SpecialPage {
$f .= ' ';
# Namespace selector
- $f .= Xml::label( wfMsg( 'namespace' ), 'namespace' ) . '&nbsp;' .
+ $f .= Xml::label( wfMsg( 'namespace' ), 'namespace' ) . '&#160;' .
Xml::namespaceSelector( $namespace, '' );
$f .= ' ';
diff --git a/includes/specials/SpecialWithoutinterwiki.php b/includes/specials/SpecialWithoutinterwiki.php
index a5d60d2f..90c1f441 100644
--- a/includes/specials/SpecialWithoutinterwiki.php
+++ b/includes/specials/SpecialWithoutinterwiki.php
@@ -1,14 +1,31 @@
<?php
/**
+ * Implements Special:Withoutinterwiki
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup SpecialPage
+ * @author Rob Church <robchur@gmail.com>
*/
/**
* Special page lists pages without language links
*
* @ingroup SpecialPage
- * @author Rob Church <robchur@gmail.com>
*/
class WithoutInterwikiPage extends PageQueryPage {
private $prefix = '';
@@ -31,7 +48,7 @@ class WithoutInterwikiPage extends PageQueryPage {
return Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) .
Xml::openElement( 'fieldset' ) .
Xml::element( 'legend', null, wfMsg( 'withoutinterwiki-legend' ) ) .
- Xml::hidden( 'title', $t->getPrefixedText() ) .
+ Html::hidden( 'title', $t->getPrefixedText() ) .
Xml::inputLabel( wfMsg( 'allpagesprefix' ), 'prefix', 'wiprefix', 20, $prefix ) . ' ' .
Xml::submitButton( wfMsg( 'withoutinterwiki-submit' ) ) .
Xml::closeElement( 'fieldset' ) .
@@ -75,7 +92,7 @@ class WithoutInterwikiPage extends PageQueryPage {
}
function wfSpecialWithoutinterwiki() {
- global $wgRequest, $wgContLang;
+ global $wgRequest;
list( $limit, $offset ) = wfCheckLimits();
// Only searching the mainspace anyway
$prefix = Title::capitalize( $wgRequest->getVal( 'prefix' ), NS_MAIN );