'EditAction' => __DIR__ . '/includes/actions/EditAction.php',
'EditCLI' => __DIR__ . '/maintenance/edit.php',
'EditPage' => __DIR__ . '/includes/EditPage.php',
- 'EditWatchlistCheckboxSeriesField' => __DIR__ . '/includes/specials/SpecialEditWatchlist.php',
- 'EditWatchlistNormalHTMLForm' => __DIR__ . '/includes/specials/SpecialEditWatchlist.php',
+ 'EditWatchlistCheckboxSeriesField' => __DIR__ . '/includes/specials/formfields/EditWatchlistCheckboxSeriesField.php',
+ 'EditWatchlistNormalHTMLForm' => __DIR__ . '/includes/specials/forms/EditWatchlistNormalHTMLForm.php',
'EmailConfirmation' => __DIR__ . '/includes/specials/SpecialConfirmemail.php',
'EmailInvalidation' => __DIR__ . '/includes/specials/SpecialEmailInvalidate.php',
'EmailNotification' => __DIR__ . '/includes/mail/EmailNotification.php',
'ImageQueryPage' => __DIR__ . '/includes/specialpage/ImageQueryPage.php',
'ImportImages' => __DIR__ . '/maintenance/importImages.php',
'ImportLogFormatter' => __DIR__ . '/includes/logging/ImportLogFormatter.php',
- 'ImportReporter' => __DIR__ . '/includes/specials/SpecialImport.php',
+ 'ImportReporter' => __DIR__ . '/includes/specials/helpers/ImportReporter.php',
'ImportSiteScripts' => __DIR__ . '/maintenance/importSiteScripts.php',
'ImportSites' => __DIR__ . '/maintenance/importSites.php',
'ImportSource' => __DIR__ . '/includes/import/ImportSource.php',
'Languages' => __DIR__ . '/maintenance/language/languages.inc',
'LayeredParameterizedPassword' => __DIR__ . '/includes/password/LayeredParameterizedPassword.php',
'LegacyLogFormatter' => __DIR__ . '/includes/logging/LogFormatter.php',
- 'License' => __DIR__ . '/includes/Licenses.php',
- 'Licenses' => __DIR__ . '/includes/Licenses.php',
+ 'License' => __DIR__ . '/includes/specials/helpers/License.php',
+ 'Licenses' => __DIR__ . '/includes/specials/formfields/Licenses.php',
'LinkBatch' => __DIR__ . '/includes/cache/LinkBatch.php',
'LinkCache' => __DIR__ . '/includes/cache/LinkCache.php',
'LinkFilter' => __DIR__ . '/includes/LinkFilter.php',
'PostgresInstaller' => __DIR__ . '/includes/installer/PostgresInstaller.php',
'PostgresUpdater' => __DIR__ . '/includes/installer/PostgresUpdater.php',
'Preferences' => __DIR__ . '/includes/Preferences.php',
- 'PreferencesForm' => __DIR__ . '/includes/Preferences.php',
+ 'PreferencesForm' => __DIR__ . '/includes/specials/forms/PreferencesForm.php',
'PrefixSearch' => __DIR__ . '/includes/PrefixSearch.php',
'PreprocessDump' => __DIR__ . '/maintenance/preprocessDump.php',
'Preprocessor' => __DIR__ . '/includes/parser/Preprocessor.php',
'UploadChunkVerificationException' => __DIR__ . '/includes/upload/UploadFromChunks.php',
'UploadChunkZeroLengthFileException' => __DIR__ . '/includes/upload/UploadFromChunks.php',
'UploadDumper' => __DIR__ . '/maintenance/dumpUploads.php',
- 'UploadForm' => __DIR__ . '/includes/specials/SpecialUpload.php',
+ 'UploadForm' => __DIR__ . '/includes/specials/forms/UploadForm.php',
'UploadFromChunks' => __DIR__ . '/includes/upload/UploadFromChunks.php',
'UploadFromFile' => __DIR__ . '/includes/upload/UploadFromFile.php',
'UploadFromStash' => __DIR__ . '/includes/upload/UploadFromStash.php',
'UploadFromUrl' => __DIR__ . '/includes/upload/UploadFromUrl.php',
'UploadLogFormatter' => __DIR__ . '/includes/logging/UploadLogFormatter.php',
'UploadSourceAdapter' => __DIR__ . '/includes/import/UploadSourceAdapter.php',
- 'UploadSourceField' => __DIR__ . '/includes/specials/SpecialUpload.php',
+ 'UploadSourceField' => __DIR__ . '/includes/specials/formfields/UploadSourceField.php',
'UploadStash' => __DIR__ . '/includes/upload/UploadStash.php',
'UploadStashBadPathException' => __DIR__ . '/includes/upload/UploadStash.php',
'UploadStashCleanup' => __DIR__ . '/maintenance/cleanupUploadStash.php',
+++ /dev/null
-<?php
-/**
- * License selector for use on 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
- * @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 License class for use on Special:Upload
- */
-class Licenses extends HTMLFormField {
- /** @var string */
- protected $msg;
-
- /** @var array */
- protected $licenses = [];
-
- /** @var string */
- protected $html;
- /**#@-*/
-
- /**
- * @param array $params
- */
- public function __construct( $params ) {
- parent::__construct( $params );
-
- $this->msg = empty( $params['licenses'] )
- ? wfMessage( 'licenses' )->inContentLanguage()->plain()
- : $params['licenses'];
- $this->selected = null;
-
- $this->makeLicenses();
- }
-
- /**
- * @private
- */
- protected function makeLicenses() {
- $levels = [];
- $lines = explode( "\n", $this->msg );
-
- foreach ( $lines as $line ) {
- if ( strpos( $line, '*' ) !== 0 ) {
- continue;
- } else {
- list( $level, $line ) = $this->trimStars( $line );
-
- if ( strpos( $line, '|' ) !== false ) {
- $obj = new License( $line );
- $this->stackItem( $this->licenses, $levels, $obj );
- } else {
- if ( $level < count( $levels ) ) {
- $levels = array_slice( $levels, 0, $level );
- }
- if ( $level == count( $levels ) ) {
- $levels[$level - 1] = $line;
- } elseif ( $level > count( $levels ) ) {
- $levels[] = $line;
- }
- }
- }
- }
- }
-
- /**
- * @param string $str
- * @return array
- */
- protected function trimStars( $str ) {
- $numStars = strspn( $str, '*' );
- return [ $numStars, ltrim( substr( $str, $numStars ), ' ' ) ];
- }
-
- /**
- * @param array &$list
- * @param array $path
- * @param mixed $item
- */
- protected function stackItem( &$list, $path, $item ) {
- $position =& $list;
- if ( $path ) {
- foreach ( $path as $key ) {
- $position =& $position[$key];
- }
- }
- $position[] = $item;
- }
-
- /**
- * @param array $tagset
- * @param int $depth
- */
- protected function makeHtml( $tagset, $depth = 0 ) {
- foreach ( $tagset as $key => $val ) {
- if ( is_array( $val ) ) {
- $this->html .= $this->outputOption(
- $key, '',
- [
- 'disabled' => 'disabled',
- 'style' => 'color: GrayText', // for MSIE
- ],
- $depth
- );
- $this->makeHtml( $val, $depth + 1 );
- } else {
- $this->html .= $this->outputOption(
- $val->text, $val->template,
- [ 'title' => '{{' . $val->template . '}}' ],
- $depth
- );
- }
- }
- }
-
- /**
- * @param string $message
- * @param string $value
- * @param null|array $attribs
- * @param int $depth
- * @return string
- */
- protected function outputOption( $message, $value, $attribs = null, $depth = 0 ) {
- $msgObj = $this->msg( $message );
- $text = $msgObj->exists() ? $msgObj->text() : $message;
- $attribs['value'] = $value;
- if ( $value === $this->selected ) {
- $attribs['selected'] = 'selected';
- }
-
- $val = str_repeat( /*   */ "\xc2\xa0", $depth * 2 ) . $text;
- return str_repeat( "\t", $depth ) . Xml::element( 'option', $attribs, $val ) . "\n";
- }
-
- /**#@-*/
-
- /**
- * Accessor for $this->licenses
- *
- * @return array
- */
- public function getLicenses() {
- return $this->licenses;
- }
-
- /**
- * Accessor for $this->html
- *
- * @param bool $value
- *
- * @return string
- */
- public function getInputHTML( $value ) {
- $this->selected = $value;
-
- $this->html = $this->outputOption( wfMessage( 'nolicense' )->text(), '',
- (bool)$this->selected ? null : [ 'selected' => 'selected' ] );
- $this->makeHtml( $this->getLicenses() );
-
- $attribs = [
- 'name' => $this->mName,
- 'id' => $this->mID
- ];
- if ( !empty( $this->mParams['disabled'] ) ) {
- $attibs['disabled'] = 'disabled';
- }
-
- return Html::rawElement( 'select', $attribs, $this->html );
- }
-}
-
-/**
- * A License class for use on Special:Upload (represents a single type of license).
- */
-class License {
- /** @var string */
- public $template;
-
- /** @var string */
- public $text;
-
- /**
- * @param string $str License name??
- */
- function __construct( $str ) {
- list( $text, $template ) = explode( '|', strrev( $str ), 2 );
-
- $this->template = strrev( $template );
- $this->text = strrev( $text );
- }
-}
<?php
/**
- * Form to edit user 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
return $timeZoneList;
}
}
-
-/** Some tweaks to allow js prefs to work */
-class PreferencesForm extends HTMLForm {
- // Override default value from HTMLForm
- protected $mSubSectionBeforeFields = false;
-
- private $modifiedUser;
-
- /**
- * @param User $user
- */
- public function setModifiedUser( $user ) {
- $this->modifiedUser = $user;
- }
-
- /**
- * @return User
- */
- public function getModifiedUser() {
- if ( $this->modifiedUser === null ) {
- return $this->getUser();
- } else {
- return $this->modifiedUser;
- }
- }
-
- /**
- * Get extra parameters for the query string when redirecting after
- * successful save.
- *
- * @return array
- */
- public function getExtraSuccessRedirectParameters() {
- return [];
- }
-
- /**
- * @param string $html
- * @return string
- */
- function wrapForm( $html ) {
- $html = Xml::tags( 'div', [ 'id' => 'preferences' ], $html );
-
- return parent::wrapForm( $html );
- }
-
- /**
- * @return string
- */
- function getButtons() {
- $attrs = [ 'id' => 'mw-prefs-restoreprefs' ];
-
- if ( !$this->getModifiedUser()->isAllowedAny( 'editmyprivateinfo', 'editmyoptions' ) ) {
- return '';
- }
-
- $html = parent::getButtons();
-
- if ( $this->getModifiedUser()->isAllowed( 'editmyoptions' ) ) {
- $t = $this->getTitle()->getSubpage( 'reset' );
-
- $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
- $html .= "\n" . $linkRenderer->makeLink( $t, $this->msg( 'restoreprefs' )->text(),
- Html::buttonAttributes( $attrs, [ 'mw-ui-quiet' ] ) );
-
- $html = Xml::tags( 'div', [ 'class' => 'mw-prefs-buttons' ], $html );
- }
-
- return $html;
- }
-
- /**
- * Separate multi-option preferences into multiple preferences, since we
- * have to store them separately
- * @param array $data
- * @return array
- */
- function filterDataForSubmit( $data ) {
- foreach ( $this->mFlatFields as $fieldname => $field ) {
- if ( $field instanceof HTMLNestedFilterable ) {
- $info = $field->mParams;
- $prefix = isset( $info['prefix'] ) ? $info['prefix'] : $fieldname;
- foreach ( $field->filterDataForSubmit( $data[$fieldname] ) as $key => $value ) {
- $data["$prefix$key"] = $value;
- }
- unset( $data[$fieldname] );
- }
- }
-
- return $data;
- }
-
- /**
- * Get the whole body of the form.
- * @return string
- */
- function getBody() {
- return $this->displaySection( $this->mFieldTree, '', 'mw-prefsection-' );
- }
-
- /**
- * Get the "<legend>" for a given section key. Normally this is the
- * prefs-$key message but we'll allow extensions to override it.
- * @param string $key
- * @return string
- */
- function getLegend( $key ) {
- $legend = parent::getLegend( $key );
- Hooks::run( 'PreferencesGetLegend', [ $this, $key, &$legend ] );
- return $legend;
- }
-
- /**
- * Get the keys of each top level preference section.
- * @return array of section keys
- */
- function getPreferenceSections() {
- return array_keys( array_filter( $this->mFieldTree, 'is_array' ) );
- }
-}
$info = $this->db->fieldInfo( $table, $field );
if ( $info->defaultValue() !== $default ) {
$this->output( "Changing '$table.$field' default value\n" );
- $this->db->query( "ALTER TABLE $table ALTER $field SET DEFAULT " . $default );
+ $this->db->query( "ALTER TABLE $table ALTER $field SET DEFAULT "
+ . $this->db->addQuotes( $default ) );
}
}
);
}
}
-
-/**
- * Extend HTMLForm purely so we can have a more sane way of getting the section headers
- */
-class EditWatchlistNormalHTMLForm extends HTMLForm {
- public function getLegend( $namespace ) {
- $namespace = substr( $namespace, 2 );
-
- return $namespace == NS_MAIN
- ? $this->msg( 'blanknamespace' )->escaped()
- : htmlspecialchars( $this->getContext()->getLanguage()->getFormattedNsText( $namespace ) );
- }
-
- public function getBody() {
- return $this->displaySection( $this->mFieldTree, '', 'editwatchlist-' );
- }
-}
-
-class EditWatchlistCheckboxSeriesField extends HTMLMultiSelectField {
- /**
- * HTMLMultiSelectField throws validation errors if we get input data
- * that doesn't match the data set in the form setup. This causes
- * problems if something gets removed from the watchlist while the
- * form is open (T34126), but we know that invalid items will
- * be harmless so we can override it here.
- *
- * @param string $value The value the field was submitted with
- * @param array $alldata The data collected from the form
- * @return bool|string Bool true on success, or String error to display.
- */
- function validate( $value, $alldata ) {
- // Need to call into grandparent to be a good citizen. :)
- return HTMLFormField::validate( $value, $alldata );
- }
-}
* @ingroup SpecialPage
*/
-use MediaWiki\MediaWikiServices;
-
/**
* MediaWiki page data importer
*
return 'pagetools';
}
}
-
-/**
- * Reporting callback
- * @ingroup SpecialPage
- */
-class ImportReporter extends ContextSource {
- private $reason = false;
- private $logTags = [];
- private $mOriginalLogCallback = null;
- private $mOriginalPageOutCallback = null;
- private $mLogItemCount = 0;
-
- /**
- * @param WikiImporter $importer
- * @param bool $upload
- * @param string $interwiki
- * @param string|bool $reason
- */
- function __construct( $importer, $upload, $interwiki, $reason = false ) {
- $this->mOriginalPageOutCallback =
- $importer->setPageOutCallback( [ $this, 'reportPage' ] );
- $this->mOriginalLogCallback =
- $importer->setLogItemCallback( [ $this, 'reportLogItem' ] );
- $importer->setNoticeCallback( [ $this, 'reportNotice' ] );
- $this->mPageCount = 0;
- $this->mIsUpload = $upload;
- $this->mInterwiki = $interwiki;
- $this->reason = $reason;
- }
-
- /**
- * Sets change tags to apply to the import log entry and null revision.
- *
- * @param array $tags
- * @since 1.29
- */
- public function setChangeTags( array $tags ) {
- $this->logTags = $tags;
- }
-
- function open() {
- $this->getOutput()->addHTML( "<ul>\n" );
- }
-
- function reportNotice( $msg, array $params ) {
- $this->getOutput()->addHTML(
- Html::element( 'li', [], $this->msg( $msg, $params )->text() )
- );
- }
-
- function reportLogItem( /* ... */ ) {
- $this->mLogItemCount++;
- if ( is_callable( $this->mOriginalLogCallback ) ) {
- call_user_func_array( $this->mOriginalLogCallback, func_get_args() );
- }
- }
-
- /**
- * @param Title $title
- * @param ForeignTitle $foreignTitle
- * @param int $revisionCount
- * @param int $successCount
- * @param array $pageInfo
- * @return void
- */
- public function reportPage( $title, $foreignTitle, $revisionCount,
- $successCount, $pageInfo ) {
- $args = func_get_args();
- call_user_func_array( $this->mOriginalPageOutCallback, $args );
-
- if ( $title === null ) {
- # Invalid or non-importable title; a notice is already displayed
- return;
- }
-
- $this->mPageCount++;
- $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
- if ( $successCount > 0 ) {
- // <bdi> prevents jumbling of the versions count
- // in RTL wikis in case the page title is LTR
- $this->getOutput()->addHTML(
- "<li>" . $linkRenderer->makeLink( $title ) . " " .
- "<bdi>" .
- $this->msg( 'import-revision-count' )->numParams( $successCount )->escaped() .
- "</bdi>" .
- "</li>\n"
- );
-
- $logParams = [ '4:number:count' => $successCount ];
- if ( $this->mIsUpload ) {
- $detail = $this->msg( 'import-logentry-upload-detail' )->numParams(
- $successCount )->inContentLanguage()->text();
- $action = 'upload';
- } else {
- $pageTitle = $foreignTitle->getFullText();
- $fullInterwikiPrefix = $this->mInterwiki;
- Hooks::run( 'ImportLogInterwikiLink', [ &$fullInterwikiPrefix, &$pageTitle ] );
-
- $interwikiTitleStr = $fullInterwikiPrefix . ':' . $pageTitle;
- $interwiki = '[[:' . $interwikiTitleStr . ']]';
- $detail = $this->msg( 'import-logentry-interwiki-detail' )->numParams(
- $successCount )->params( $interwiki )->inContentLanguage()->text();
- $action = 'interwiki';
- $logParams['5:title-link:interwiki'] = $interwikiTitleStr;
- }
- if ( $this->reason ) {
- $detail .= $this->msg( 'colon-separator' )->inContentLanguage()->text()
- . $this->reason;
- }
-
- $comment = $detail; // quick
- $dbw = wfGetDB( DB_MASTER );
- $latest = $title->getLatestRevID();
- $nullRevision = Revision::newNullRevision(
- $dbw,
- $title->getArticleID(),
- $comment,
- true,
- $this->getUser()
- );
-
- $nullRevId = null;
- if ( !is_null( $nullRevision ) ) {
- $nullRevId = $nullRevision->insertOn( $dbw );
- $page = WikiPage::factory( $title );
- # Update page record
- $page->updateRevisionOn( $dbw, $nullRevision );
- Hooks::run(
- 'NewRevisionFromEditComplete',
- [ $page, $nullRevision, $latest, $this->getUser() ]
- );
- }
-
- // Create the import log entry
- $logEntry = new ManualLogEntry( 'import', $action );
- $logEntry->setTarget( $title );
- $logEntry->setComment( $this->reason );
- $logEntry->setPerformer( $this->getUser() );
- $logEntry->setParameters( $logParams );
- $logid = $logEntry->insert();
- if ( count( $this->logTags ) ) {
- $logEntry->setTags( $this->logTags );
- }
- // Make sure the null revision will be tagged as well
- $logEntry->setAssociatedRevId( $nullRevId );
-
- $logEntry->publish( $logid );
-
- } else {
- $this->getOutput()->addHTML( "<li>" . $linkRenderer->makeKnownLink( $title ) . " " .
- $this->msg( 'import-nonewrevisions' )->escaped() . "</li>\n" );
- }
- }
-
- function close() {
- $out = $this->getOutput();
- if ( $this->mLogItemCount > 0 ) {
- $msg = $this->msg( 'imported-log-entries' )->numParams( $this->mLogItemCount )->parse();
- $out->addHTML( Xml::tags( 'li', null, $msg ) );
- } elseif ( $this->mPageCount == 0 && $this->mLogItemCount == 0 ) {
- $out->addHTML( "</ul>\n" );
-
- return Status::newFatal( 'importnopages' );
- }
- $out->addHTML( "</ul>\n" );
-
- return Status::newGood( $this->mPageCount );
- }
-}
* @ingroup Upload
*/
-use MediaWiki\Linker\LinkRenderer;
use MediaWiki\MediaWikiServices;
/**
return $bitmapHandler->autoRotateEnabled();
}
}
-
-/**
- * Sub class of HTMLForm that provides the form section of SpecialUpload
- */
-class UploadForm extends HTMLForm {
- protected $mWatch;
- protected $mForReUpload;
- protected $mSessionKey;
- protected $mHideIgnoreWarning;
- protected $mDestWarningAck;
- protected $mDestFile;
-
- protected $mComment;
- protected $mTextTop;
- protected $mTextAfterSummary;
-
- protected $mSourceIds;
-
- protected $mMaxFileSize = [];
-
- protected $mMaxUploadSize = [];
-
- public function __construct( array $options = [], IContextSource $context = null,
- LinkRenderer $linkRenderer = null
- ) {
- if ( $context instanceof IContextSource ) {
- $this->setContext( $context );
- }
-
- if ( !$linkRenderer ) {
- $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
- }
-
- $this->mWatch = !empty( $options['watch'] );
- $this->mForReUpload = !empty( $options['forreupload'] );
- $this->mSessionKey = isset( $options['sessionkey'] ) ? $options['sessionkey'] : '';
- $this->mHideIgnoreWarning = !empty( $options['hideignorewarning'] );
- $this->mDestWarningAck = !empty( $options['destwarningack'] );
- $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()
- + $this->getOptionsSection();
-
- Hooks::run( 'UploadFormInitDescriptor', [ &$descriptor ] );
- parent::__construct( $descriptor, $context, 'upload' );
-
- # Add a link to edit MediaWiki:Licenses
- if ( $this->getUser()->isAllowed( 'editinterface' ) ) {
- $this->getOutput()->addModuleStyles( 'mediawiki.special.upload.styles' );
- $licensesLink = $linkRenderer->makeKnownLink(
- $this->msg( 'licenses' )->inContentLanguage()->getTitle(),
- $this->msg( 'licenses-edit' )->text(),
- [],
- [ 'action' => 'edit' ]
- );
- $editLicenses = '<p class="mw-upload-editlicenses">' . $licensesLink . '</p>';
- $this->addFooterText( $editLicenses, 'description' );
- }
-
- # Set some form properties
- $this->setSubmitText( $this->msg( 'uploadbtn' )->text() );
- $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 = [];
- foreach ( $sourceDescriptor as $field ) {
- if ( !empty( $field['id'] ) ) {
- $this->mSourceIds[] = $field['id'];
- }
- }
- }
-
- /**
- * Get the descriptor of the fieldset that contains the file source
- * selection. The section is 'source'
- *
- * @return array Descriptor array
- */
- protected function getSourceSection() {
- if ( $this->mSessionKey ) {
- return [
- 'SessionKey' => [
- 'type' => 'hidden',
- 'default' => $this->mSessionKey,
- ],
- 'SourceType' => [
- 'type' => 'hidden',
- 'default' => 'Stash',
- ],
- ];
- }
-
- $canUploadByUrl = UploadFromUrl::isEnabled()
- && ( UploadFromUrl::isAllowed( $this->getUser() ) === true )
- && $this->getConfig()->get( 'CopyUploadsFromSpecialUpload' );
- $radio = $canUploadByUrl;
- $selectedSourceType = strtolower( $this->getRequest()->getText( 'wpSourceType', 'File' ) );
-
- $descriptor = [];
- if ( $this->mTextTop ) {
- $descriptor['UploadFormTextTop'] = [
- 'type' => 'info',
- 'section' => 'source',
- 'default' => $this->mTextTop,
- 'raw' => true,
- ];
- }
-
- $this->mMaxUploadSize['file'] = min(
- UploadBase::getMaxUploadSize( 'file' ),
- UploadBase::getMaxPhpUploadSize()
- );
-
- $help = $this->msg( 'upload-maxfilesize',
- $this->getContext()->getLanguage()->formatSize( $this->mMaxUploadSize['file'] )
- )->parse();
-
- // If the user can also upload by URL, there are 2 different file size limits.
- // This extra message helps stress which limit corresponds to what.
- if ( $canUploadByUrl ) {
- $help .= $this->msg( 'word-separator' )->escaped();
- $help .= $this->msg( 'upload_source_file' )->parse();
- }
-
- $descriptor['UploadFile'] = [
- 'class' => 'UploadSourceField',
- 'section' => 'source',
- 'type' => 'file',
- 'id' => 'wpUploadFile',
- 'radio-id' => 'wpSourceTypeFile',
- 'label-message' => 'sourcefilename',
- 'upload-type' => 'File',
- 'radio' => &$radio,
- 'help' => $help,
- 'checked' => $selectedSourceType == 'file',
- ];
-
- if ( $canUploadByUrl ) {
- $this->mMaxUploadSize['url'] = UploadBase::getMaxUploadSize( 'url' );
- $descriptor['UploadFileURL'] = [
- 'class' => 'UploadSourceField',
- 'section' => 'source',
- 'id' => 'wpUploadFileURL',
- 'radio-id' => 'wpSourceTypeurl',
- 'label-message' => 'sourceurl',
- 'upload-type' => 'url',
- 'radio' => &$radio,
- 'help' => $this->msg( 'upload-maxfilesize',
- $this->getContext()->getLanguage()->formatSize( $this->mMaxUploadSize['url'] )
- )->parse() .
- $this->msg( 'word-separator' )->escaped() .
- $this->msg( 'upload_source_url' )->parse(),
- 'checked' => $selectedSourceType == 'url',
- ];
- }
- Hooks::run( 'UploadFormSourceDescriptors', [ &$descriptor, &$radio, $selectedSourceType ] );
-
- $descriptor['Extensions'] = [
- 'type' => 'info',
- 'section' => 'source',
- 'default' => $this->getExtensionsMessage(),
- 'raw' => true,
- ];
-
- return $descriptor;
- }
-
- /**
- * Get the messages indicating which extensions are preferred and prohibitted.
- *
- * @return string HTML string containing the message
- */
- protected function getExtensionsMessage() {
- # Print a list of allowed file extensions, if so configured. We ignore
- # MIME type here, it's incomprehensible to most people and too long.
- $config = $this->getConfig();
-
- if ( $config->get( 'CheckFileExtensions' ) ) {
- $fileExtensions = array_unique( $config->get( 'FileExtensions' ) );
- if ( $config->get( 'StrictFileExtensions' ) ) {
- # Everything not permitted is banned
- $extensionsList =
- '<div id="mw-upload-permitted">' .
- $this->msg( 'upload-permitted' )
- ->params( $this->getLanguage()->commaList( $fileExtensions ) )
- ->numParams( count( $fileExtensions ) )
- ->parseAsBlock() .
- "</div>\n";
- } else {
- # We have to list both preferred and prohibited
- $fileBlacklist = array_unique( $config->get( 'FileBlacklist' ) );
- $extensionsList =
- '<div id="mw-upload-preferred">' .
- $this->msg( 'upload-preferred' )
- ->params( $this->getLanguage()->commaList( $fileExtensions ) )
- ->numParams( count( $fileExtensions ) )
- ->parseAsBlock() .
- "</div>\n" .
- '<div id="mw-upload-prohibited">' .
- $this->msg( 'upload-prohibited' )
- ->params( $this->getLanguage()->commaList( $fileBlacklist ) )
- ->numParams( count( $fileBlacklist ) )
- ->parseAsBlock() .
- "</div>\n";
- }
- } else {
- # Everything is permitted.
- $extensionsList = '';
- }
-
- return $extensionsList;
- }
-
- /**
- * Get the descriptor of the fieldset that contains the file description
- * input. The section is 'description'
- *
- * @return array Descriptor array
- */
- protected function getDescriptionSection() {
- $config = $this->getConfig();
- if ( $this->mSessionKey ) {
- $stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash( $this->getUser() );
- try {
- $file = $stash->getFile( $this->mSessionKey );
- } catch ( Exception $e ) {
- $file = null;
- }
- if ( $file ) {
- global $wgContLang;
-
- $mto = $file->transform( [ 'width' => 120 ] );
- if ( $mto ) {
- $this->addHeaderText(
- '<div class="thumb t' . $wgContLang->alignEnd() . '">' .
- Html::element( 'img', [
- 'src' => $mto->getUrl(),
- 'class' => 'thumbimage',
- ] ) . '</div>', 'description' );
- }
- }
- }
-
- $descriptor = [
- 'DestFile' => [
- 'type' => 'text',
- 'section' => 'description',
- 'id' => 'wpDestFile',
- 'label-message' => 'destfilename',
- 'size' => 60,
- 'default' => $this->mDestFile,
- # @todo FIXME: Hack to work around poor handling of the 'default' option in HTMLForm
- 'nodata' => strval( $this->mDestFile ) !== '',
- ],
- 'UploadDescription' => [
- 'type' => 'textarea',
- 'section' => 'description',
- 'id' => 'wpUploadDescription',
- 'label-message' => $this->mForReUpload
- ? 'filereuploadsummary'
- : 'fileuploadsummary',
- 'default' => $this->mComment,
- 'cols' => 80,
- 'rows' => 8,
- ]
- ];
- if ( $this->mTextAfterSummary ) {
- $descriptor['UploadFormTextAfterSummary'] = [
- 'type' => 'info',
- 'section' => 'description',
- 'default' => $this->mTextAfterSummary,
- 'raw' => true,
- ];
- }
-
- $descriptor += [
- 'EditTools' => [
- 'type' => 'edittools',
- 'section' => 'description',
- 'message' => 'edittools-upload',
- ]
- ];
-
- if ( $this->mForReUpload ) {
- $descriptor['DestFile']['readonly'] = true;
- } else {
- $descriptor['License'] = [
- 'type' => 'select',
- 'class' => 'Licenses',
- 'section' => 'description',
- 'id' => 'wpLicense',
- 'label-message' => 'license',
- ];
- }
-
- if ( $config->get( 'UseCopyrightUpload' ) ) {
- $descriptor['UploadCopyStatus'] = [
- 'type' => 'text',
- 'section' => 'description',
- 'id' => 'wpUploadCopyStatus',
- 'label-message' => 'filestatus',
- ];
- $descriptor['UploadSource'] = [
- 'type' => 'text',
- 'section' => 'description',
- 'id' => 'wpUploadSource',
- 'label-message' => 'filesource',
- ];
- }
-
- return $descriptor;
- }
-
- /**
- * Get the descriptor of the fieldset that contains the upload options,
- * such as "watch this file". The section is 'options'
- *
- * @return array Descriptor array
- */
- protected function getOptionsSection() {
- $user = $this->getUser();
- if ( $user->isLoggedIn() ) {
- $descriptor = [
- 'Watchthis' => [
- 'type' => 'check',
- 'id' => 'wpWatchthis',
- 'label-message' => 'watchthisupload',
- 'section' => 'options',
- 'default' => $this->mWatch,
- ]
- ];
- }
- if ( !$this->mHideIgnoreWarning ) {
- $descriptor['IgnoreWarning'] = [
- 'type' => 'check',
- 'id' => 'wpIgnoreWarning',
- 'label-message' => 'ignorewarnings',
- 'section' => 'options',
- ];
- }
-
- $descriptor['DestFileWarningAck'] = [
- 'type' => 'hidden',
- 'id' => 'wpDestFileWarningAck',
- 'default' => $this->mDestWarningAck ? '1' : '',
- ];
-
- if ( $this->mForReUpload ) {
- $descriptor['ForReUpload'] = [
- 'type' => 'hidden',
- 'id' => 'wpForReUpload',
- 'default' => '1',
- ];
- }
-
- return $descriptor;
- }
-
- /**
- * Add the upload JS and show the form.
- */
- public function show() {
- $this->addUploadJS();
- parent::show();
- }
-
- /**
- * Add upload JS to the OutputPage
- */
- protected function addUploadJS() {
- $config = $this->getConfig();
-
- $useAjaxDestCheck = $config->get( 'UseAjax' ) && $config->get( 'AjaxUploadDestCheck' );
- $useAjaxLicensePreview = $config->get( 'UseAjax' ) &&
- $config->get( 'AjaxLicensePreview' ) && $config->get( 'EnableAPI' );
- $this->mMaxUploadSize['*'] = UploadBase::getMaxUploadSize();
-
- $scriptVars = [
- 'wgAjaxUploadDestCheck' => $useAjaxDestCheck,
- 'wgAjaxLicensePreview' => $useAjaxLicensePreview,
- 'wgUploadAutoFill' => !$this->mForReUpload &&
- // If we received mDestFile from the request, don't autofill
- // the wpDestFile textbox
- $this->mDestFile === '',
- 'wgUploadSourceIds' => $this->mSourceIds,
- 'wgCheckFileExtensions' => $config->get( 'CheckFileExtensions' ),
- 'wgStrictFileExtensions' => $config->get( 'StrictFileExtensions' ),
- 'wgFileExtensions' => array_values( array_unique( $config->get( 'FileExtensions' ) ) ),
- 'wgCapitalizeUploads' => MWNamespace::isCapitalized( NS_FILE ),
- 'wgMaxUploadSize' => $this->mMaxUploadSize,
- 'wgFileCanRotate' => SpecialUpload::rotationEnabled(),
- ];
-
- $out = $this->getOutput();
- $out->addJsConfigVars( $scriptVars );
-
- $out->addModules( [
- 'mediawiki.special.upload', // Extras for thumbnail and license preview.
- ] );
- }
-
- /**
- * Empty function; submission is handled elsewhere.
- *
- * @return bool False
- */
- function trySubmit() {
- return false;
- }
-}
-
-/**
- * A form field that contains a radio box in the label
- */
-class UploadSourceField extends HTMLTextField {
-
- /**
- * @param array $cellAttributes
- * @return string
- */
- function getLabelHtml( $cellAttributes = [] ) {
- $id = $this->mParams['id'];
- $label = Html::rawElement( 'label', [ 'for' => $id ], $this->mLabel );
-
- if ( !empty( $this->mParams['radio'] ) ) {
- if ( isset( $this->mParams['radio-id'] ) ) {
- $radioId = $this->mParams['radio-id'];
- } else {
- // Old way. For the benefit of extensions that do not define
- // the 'radio-id' key.
- $radioId = 'wpSourceType' . $this->mParams['upload-type'];
- }
-
- $attribs = [
- 'name' => 'wpSourceType',
- 'type' => 'radio',
- 'id' => $radioId,
- 'value' => $this->mParams['upload-type'],
- ];
-
- if ( !empty( $this->mParams['checked'] ) ) {
- $attribs['checked'] = 'checked';
- }
-
- $label .= Html::element( 'input', $attribs );
- }
-
- return Html::rawElement( 'td', [ 'class' => 'mw-label' ] + $cellAttributes, $label );
- }
-
- /**
- * @return int
- */
- function getSize() {
- return isset( $this->mParams['size'] )
- ? $this->mParams['size']
- : 60;
- }
-}
--- /dev/null
+<?php
+/**
+ * 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
+ */
+
+class EditWatchlistCheckboxSeriesField extends HTMLMultiSelectField {
+ /**
+ * HTMLMultiSelectField throws validation errors if we get input data
+ * that doesn't match the data set in the form setup. This causes
+ * problems if something gets removed from the watchlist while the
+ * form is open (T34126), but we know that invalid items will
+ * be harmless so we can override it here.
+ *
+ * @param string $value The value the field was submitted with
+ * @param array $alldata The data collected from the form
+ * @return bool|string Bool true on success, or String error to display.
+ */
+ function validate( $value, $alldata ) {
+ // Need to call into grandparent to be a good citizen. :)
+ return HTMLFormField::validate( $value, $alldata );
+ }
+}
--- /dev/null
+<?php
+/**
+ * License selector for use on 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
+ * @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 License class for use on Special:Upload
+ */
+class Licenses extends HTMLFormField {
+ /** @var string */
+ protected $msg;
+
+ /** @var array */
+ protected $licenses = [];
+
+ /** @var string */
+ protected $html;
+ /**#@-*/
+
+ /**
+ * @param array $params
+ */
+ public function __construct( $params ) {
+ parent::__construct( $params );
+
+ $this->msg = empty( $params['licenses'] )
+ ? wfMessage( 'licenses' )->inContentLanguage()->plain()
+ : $params['licenses'];
+ $this->selected = null;
+
+ $this->makeLicenses();
+ }
+
+ /**
+ * @private
+ */
+ protected function makeLicenses() {
+ $levels = [];
+ $lines = explode( "\n", $this->msg );
+
+ foreach ( $lines as $line ) {
+ if ( strpos( $line, '*' ) !== 0 ) {
+ continue;
+ } else {
+ list( $level, $line ) = $this->trimStars( $line );
+
+ if ( strpos( $line, '|' ) !== false ) {
+ $obj = new License( $line );
+ $this->stackItem( $this->licenses, $levels, $obj );
+ } else {
+ if ( $level < count( $levels ) ) {
+ $levels = array_slice( $levels, 0, $level );
+ }
+ if ( $level == count( $levels ) ) {
+ $levels[$level - 1] = $line;
+ } elseif ( $level > count( $levels ) ) {
+ $levels[] = $line;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @param string $str
+ * @return array
+ */
+ protected function trimStars( $str ) {
+ $numStars = strspn( $str, '*' );
+ return [ $numStars, ltrim( substr( $str, $numStars ), ' ' ) ];
+ }
+
+ /**
+ * @param array &$list
+ * @param array $path
+ * @param mixed $item
+ */
+ protected function stackItem( &$list, $path, $item ) {
+ $position =& $list;
+ if ( $path ) {
+ foreach ( $path as $key ) {
+ $position =& $position[$key];
+ }
+ }
+ $position[] = $item;
+ }
+
+ /**
+ * @param array $tagset
+ * @param int $depth
+ */
+ protected function makeHtml( $tagset, $depth = 0 ) {
+ foreach ( $tagset as $key => $val ) {
+ if ( is_array( $val ) ) {
+ $this->html .= $this->outputOption(
+ $key, '',
+ [
+ 'disabled' => 'disabled',
+ 'style' => 'color: GrayText', // for MSIE
+ ],
+ $depth
+ );
+ $this->makeHtml( $val, $depth + 1 );
+ } else {
+ $this->html .= $this->outputOption(
+ $val->text, $val->template,
+ [ 'title' => '{{' . $val->template . '}}' ],
+ $depth
+ );
+ }
+ }
+ }
+
+ /**
+ * @param string $message
+ * @param string $value
+ * @param null|array $attribs
+ * @param int $depth
+ * @return string
+ */
+ protected function outputOption( $message, $value, $attribs = null, $depth = 0 ) {
+ $msgObj = $this->msg( $message );
+ $text = $msgObj->exists() ? $msgObj->text() : $message;
+ $attribs['value'] = $value;
+ if ( $value === $this->selected ) {
+ $attribs['selected'] = 'selected';
+ }
+
+ $val = str_repeat( /*   */ "\xc2\xa0", $depth * 2 ) . $text;
+ return str_repeat( "\t", $depth ) . Xml::element( 'option', $attribs, $val ) . "\n";
+ }
+
+ /**#@-*/
+
+ /**
+ * Accessor for $this->licenses
+ *
+ * @return array
+ */
+ public function getLicenses() {
+ return $this->licenses;
+ }
+
+ /**
+ * Accessor for $this->html
+ *
+ * @param bool $value
+ *
+ * @return string
+ */
+ public function getInputHTML( $value ) {
+ $this->selected = $value;
+
+ $this->html = $this->outputOption( wfMessage( 'nolicense' )->text(), '',
+ (bool)$this->selected ? null : [ 'selected' => 'selected' ] );
+ $this->makeHtml( $this->getLicenses() );
+
+ $attribs = [
+ 'name' => $this->mName,
+ 'id' => $this->mID
+ ];
+ if ( !empty( $this->mParams['disabled'] ) ) {
+ $attibs['disabled'] = 'disabled';
+ }
+
+ return Html::rawElement( 'select', $attribs, $this->html );
+ }
+}
--- /dev/null
+<?php
+/**
+ * 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
+ */
+
+/**
+ * A form field that contains a radio box in the label
+ */
+class UploadSourceField extends HTMLTextField {
+
+ /**
+ * @param array $cellAttributes
+ * @return string
+ */
+ function getLabelHtml( $cellAttributes = [] ) {
+ $id = $this->mParams['id'];
+ $label = Html::rawElement( 'label', [ 'for' => $id ], $this->mLabel );
+
+ if ( !empty( $this->mParams['radio'] ) ) {
+ if ( isset( $this->mParams['radio-id'] ) ) {
+ $radioId = $this->mParams['radio-id'];
+ } else {
+ // Old way. For the benefit of extensions that do not define
+ // the 'radio-id' key.
+ $radioId = 'wpSourceType' . $this->mParams['upload-type'];
+ }
+
+ $attribs = [
+ 'name' => 'wpSourceType',
+ 'type' => 'radio',
+ 'id' => $radioId,
+ 'value' => $this->mParams['upload-type'],
+ ];
+
+ if ( !empty( $this->mParams['checked'] ) ) {
+ $attribs['checked'] = 'checked';
+ }
+
+ $label .= Html::element( 'input', $attribs );
+ }
+
+ return Html::rawElement( 'td', [ 'class' => 'mw-label' ] + $cellAttributes, $label );
+ }
+
+ /**
+ * @return int
+ */
+ function getSize() {
+ return isset( $this->mParams['size'] )
+ ? $this->mParams['size']
+ : 60;
+ }
+}
--- /dev/null
+<?php
+/**
+ * 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
+ */
+
+/**
+ * Extend HTMLForm purely so we can have a more sane way of getting the section headers
+ */
+class EditWatchlistNormalHTMLForm extends HTMLForm {
+ public function getLegend( $namespace ) {
+ $namespace = substr( $namespace, 2 );
+
+ return $namespace == NS_MAIN
+ ? $this->msg( 'blanknamespace' )->escaped()
+ : htmlspecialchars( $this->getContext()->getLanguage()->getFormattedNsText( $namespace ) );
+ }
+
+ public function getBody() {
+ return $this->displaySection( $this->mFieldTree, '', 'editwatchlist-' );
+ }
+}
--- /dev/null
+<?php
+/**
+ * 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
+ */
+
+use MediaWiki\MediaWikiServices;
+
+/**
+ * Form to edit user preferences.
+ */
+class PreferencesForm extends HTMLForm {
+ // Override default value from HTMLForm
+ protected $mSubSectionBeforeFields = false;
+
+ private $modifiedUser;
+
+ /**
+ * @param User $user
+ */
+ public function setModifiedUser( $user ) {
+ $this->modifiedUser = $user;
+ }
+
+ /**
+ * @return User
+ */
+ public function getModifiedUser() {
+ if ( $this->modifiedUser === null ) {
+ return $this->getUser();
+ } else {
+ return $this->modifiedUser;
+ }
+ }
+
+ /**
+ * Get extra parameters for the query string when redirecting after
+ * successful save.
+ *
+ * @return array
+ */
+ public function getExtraSuccessRedirectParameters() {
+ return [];
+ }
+
+ /**
+ * @param string $html
+ * @return string
+ */
+ function wrapForm( $html ) {
+ $html = Xml::tags( 'div', [ 'id' => 'preferences' ], $html );
+
+ return parent::wrapForm( $html );
+ }
+
+ /**
+ * @return string
+ */
+ function getButtons() {
+ $attrs = [ 'id' => 'mw-prefs-restoreprefs' ];
+
+ if ( !$this->getModifiedUser()->isAllowedAny( 'editmyprivateinfo', 'editmyoptions' ) ) {
+ return '';
+ }
+
+ $html = parent::getButtons();
+
+ if ( $this->getModifiedUser()->isAllowed( 'editmyoptions' ) ) {
+ $t = $this->getTitle()->getSubpage( 'reset' );
+
+ $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+ $html .= "\n" . $linkRenderer->makeLink( $t, $this->msg( 'restoreprefs' )->text(),
+ Html::buttonAttributes( $attrs, [ 'mw-ui-quiet' ] ) );
+
+ $html = Xml::tags( 'div', [ 'class' => 'mw-prefs-buttons' ], $html );
+ }
+
+ return $html;
+ }
+
+ /**
+ * Separate multi-option preferences into multiple preferences, since we
+ * have to store them separately
+ * @param array $data
+ * @return array
+ */
+ function filterDataForSubmit( $data ) {
+ foreach ( $this->mFlatFields as $fieldname => $field ) {
+ if ( $field instanceof HTMLNestedFilterable ) {
+ $info = $field->mParams;
+ $prefix = isset( $info['prefix'] ) ? $info['prefix'] : $fieldname;
+ foreach ( $field->filterDataForSubmit( $data[$fieldname] ) as $key => $value ) {
+ $data["$prefix$key"] = $value;
+ }
+ unset( $data[$fieldname] );
+ }
+ }
+
+ return $data;
+ }
+
+ /**
+ * Get the whole body of the form.
+ * @return string
+ */
+ function getBody() {
+ return $this->displaySection( $this->mFieldTree, '', 'mw-prefsection-' );
+ }
+
+ /**
+ * Get the "<legend>" for a given section key. Normally this is the
+ * prefs-$key message but we'll allow extensions to override it.
+ * @param string $key
+ * @return string
+ */
+ function getLegend( $key ) {
+ $legend = parent::getLegend( $key );
+ Hooks::run( 'PreferencesGetLegend', [ $this, $key, &$legend ] );
+ return $legend;
+ }
+
+ /**
+ * Get the keys of each top level preference section.
+ * @return array of section keys
+ */
+ function getPreferenceSections() {
+ return array_keys( array_filter( $this->mFieldTree, 'is_array' ) );
+ }
+}
--- /dev/null
+<?php
+/**
+ * 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
+ */
+
+use MediaWiki\Linker\LinkRenderer;
+use MediaWiki\MediaWikiServices;
+
+/**
+ * Sub class of HTMLForm that provides the form section of SpecialUpload
+ */
+class UploadForm extends HTMLForm {
+ protected $mWatch;
+ protected $mForReUpload;
+ protected $mSessionKey;
+ protected $mHideIgnoreWarning;
+ protected $mDestWarningAck;
+ protected $mDestFile;
+
+ protected $mComment;
+ protected $mTextTop;
+ protected $mTextAfterSummary;
+
+ protected $mSourceIds;
+
+ protected $mMaxFileSize = [];
+
+ protected $mMaxUploadSize = [];
+
+ public function __construct( array $options = [], IContextSource $context = null,
+ LinkRenderer $linkRenderer = null
+ ) {
+ if ( $context instanceof IContextSource ) {
+ $this->setContext( $context );
+ }
+
+ if ( !$linkRenderer ) {
+ $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+ }
+
+ $this->mWatch = !empty( $options['watch'] );
+ $this->mForReUpload = !empty( $options['forreupload'] );
+ $this->mSessionKey = isset( $options['sessionkey'] ) ? $options['sessionkey'] : '';
+ $this->mHideIgnoreWarning = !empty( $options['hideignorewarning'] );
+ $this->mDestWarningAck = !empty( $options['destwarningack'] );
+ $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()
+ + $this->getOptionsSection();
+
+ Hooks::run( 'UploadFormInitDescriptor', [ &$descriptor ] );
+ parent::__construct( $descriptor, $context, 'upload' );
+
+ # Add a link to edit MediaWiki:Licenses
+ if ( $this->getUser()->isAllowed( 'editinterface' ) ) {
+ $this->getOutput()->addModuleStyles( 'mediawiki.special.upload.styles' );
+ $licensesLink = $linkRenderer->makeKnownLink(
+ $this->msg( 'licenses' )->inContentLanguage()->getTitle(),
+ $this->msg( 'licenses-edit' )->text(),
+ [],
+ [ 'action' => 'edit' ]
+ );
+ $editLicenses = '<p class="mw-upload-editlicenses">' . $licensesLink . '</p>';
+ $this->addFooterText( $editLicenses, 'description' );
+ }
+
+ # Set some form properties
+ $this->setSubmitText( $this->msg( 'uploadbtn' )->text() );
+ $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 = [];
+ foreach ( $sourceDescriptor as $field ) {
+ if ( !empty( $field['id'] ) ) {
+ $this->mSourceIds[] = $field['id'];
+ }
+ }
+ }
+
+ /**
+ * Get the descriptor of the fieldset that contains the file source
+ * selection. The section is 'source'
+ *
+ * @return array Descriptor array
+ */
+ protected function getSourceSection() {
+ if ( $this->mSessionKey ) {
+ return [
+ 'SessionKey' => [
+ 'type' => 'hidden',
+ 'default' => $this->mSessionKey,
+ ],
+ 'SourceType' => [
+ 'type' => 'hidden',
+ 'default' => 'Stash',
+ ],
+ ];
+ }
+
+ $canUploadByUrl = UploadFromUrl::isEnabled()
+ && ( UploadFromUrl::isAllowed( $this->getUser() ) === true )
+ && $this->getConfig()->get( 'CopyUploadsFromSpecialUpload' );
+ $radio = $canUploadByUrl;
+ $selectedSourceType = strtolower( $this->getRequest()->getText( 'wpSourceType', 'File' ) );
+
+ $descriptor = [];
+ if ( $this->mTextTop ) {
+ $descriptor['UploadFormTextTop'] = [
+ 'type' => 'info',
+ 'section' => 'source',
+ 'default' => $this->mTextTop,
+ 'raw' => true,
+ ];
+ }
+
+ $this->mMaxUploadSize['file'] = min(
+ UploadBase::getMaxUploadSize( 'file' ),
+ UploadBase::getMaxPhpUploadSize()
+ );
+
+ $help = $this->msg( 'upload-maxfilesize',
+ $this->getContext()->getLanguage()->formatSize( $this->mMaxUploadSize['file'] )
+ )->parse();
+
+ // If the user can also upload by URL, there are 2 different file size limits.
+ // This extra message helps stress which limit corresponds to what.
+ if ( $canUploadByUrl ) {
+ $help .= $this->msg( 'word-separator' )->escaped();
+ $help .= $this->msg( 'upload_source_file' )->parse();
+ }
+
+ $descriptor['UploadFile'] = [
+ 'class' => 'UploadSourceField',
+ 'section' => 'source',
+ 'type' => 'file',
+ 'id' => 'wpUploadFile',
+ 'radio-id' => 'wpSourceTypeFile',
+ 'label-message' => 'sourcefilename',
+ 'upload-type' => 'File',
+ 'radio' => &$radio,
+ 'help' => $help,
+ 'checked' => $selectedSourceType == 'file',
+ ];
+
+ if ( $canUploadByUrl ) {
+ $this->mMaxUploadSize['url'] = UploadBase::getMaxUploadSize( 'url' );
+ $descriptor['UploadFileURL'] = [
+ 'class' => 'UploadSourceField',
+ 'section' => 'source',
+ 'id' => 'wpUploadFileURL',
+ 'radio-id' => 'wpSourceTypeurl',
+ 'label-message' => 'sourceurl',
+ 'upload-type' => 'url',
+ 'radio' => &$radio,
+ 'help' => $this->msg( 'upload-maxfilesize',
+ $this->getContext()->getLanguage()->formatSize( $this->mMaxUploadSize['url'] )
+ )->parse() .
+ $this->msg( 'word-separator' )->escaped() .
+ $this->msg( 'upload_source_url' )->parse(),
+ 'checked' => $selectedSourceType == 'url',
+ ];
+ }
+ Hooks::run( 'UploadFormSourceDescriptors', [ &$descriptor, &$radio, $selectedSourceType ] );
+
+ $descriptor['Extensions'] = [
+ 'type' => 'info',
+ 'section' => 'source',
+ 'default' => $this->getExtensionsMessage(),
+ 'raw' => true,
+ ];
+
+ return $descriptor;
+ }
+
+ /**
+ * Get the messages indicating which extensions are preferred and prohibitted.
+ *
+ * @return string HTML string containing the message
+ */
+ protected function getExtensionsMessage() {
+ # Print a list of allowed file extensions, if so configured. We ignore
+ # MIME type here, it's incomprehensible to most people and too long.
+ $config = $this->getConfig();
+
+ if ( $config->get( 'CheckFileExtensions' ) ) {
+ $fileExtensions = array_unique( $config->get( 'FileExtensions' ) );
+ if ( $config->get( 'StrictFileExtensions' ) ) {
+ # Everything not permitted is banned
+ $extensionsList =
+ '<div id="mw-upload-permitted">' .
+ $this->msg( 'upload-permitted' )
+ ->params( $this->getLanguage()->commaList( $fileExtensions ) )
+ ->numParams( count( $fileExtensions ) )
+ ->parseAsBlock() .
+ "</div>\n";
+ } else {
+ # We have to list both preferred and prohibited
+ $fileBlacklist = array_unique( $config->get( 'FileBlacklist' ) );
+ $extensionsList =
+ '<div id="mw-upload-preferred">' .
+ $this->msg( 'upload-preferred' )
+ ->params( $this->getLanguage()->commaList( $fileExtensions ) )
+ ->numParams( count( $fileExtensions ) )
+ ->parseAsBlock() .
+ "</div>\n" .
+ '<div id="mw-upload-prohibited">' .
+ $this->msg( 'upload-prohibited' )
+ ->params( $this->getLanguage()->commaList( $fileBlacklist ) )
+ ->numParams( count( $fileBlacklist ) )
+ ->parseAsBlock() .
+ "</div>\n";
+ }
+ } else {
+ # Everything is permitted.
+ $extensionsList = '';
+ }
+
+ return $extensionsList;
+ }
+
+ /**
+ * Get the descriptor of the fieldset that contains the file description
+ * input. The section is 'description'
+ *
+ * @return array Descriptor array
+ */
+ protected function getDescriptionSection() {
+ $config = $this->getConfig();
+ if ( $this->mSessionKey ) {
+ $stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash( $this->getUser() );
+ try {
+ $file = $stash->getFile( $this->mSessionKey );
+ } catch ( Exception $e ) {
+ $file = null;
+ }
+ if ( $file ) {
+ global $wgContLang;
+
+ $mto = $file->transform( [ 'width' => 120 ] );
+ if ( $mto ) {
+ $this->addHeaderText(
+ '<div class="thumb t' . $wgContLang->alignEnd() . '">' .
+ Html::element( 'img', [
+ 'src' => $mto->getUrl(),
+ 'class' => 'thumbimage',
+ ] ) . '</div>', 'description' );
+ }
+ }
+ }
+
+ $descriptor = [
+ 'DestFile' => [
+ 'type' => 'text',
+ 'section' => 'description',
+ 'id' => 'wpDestFile',
+ 'label-message' => 'destfilename',
+ 'size' => 60,
+ 'default' => $this->mDestFile,
+ # @todo FIXME: Hack to work around poor handling of the 'default' option in HTMLForm
+ 'nodata' => strval( $this->mDestFile ) !== '',
+ ],
+ 'UploadDescription' => [
+ 'type' => 'textarea',
+ 'section' => 'description',
+ 'id' => 'wpUploadDescription',
+ 'label-message' => $this->mForReUpload
+ ? 'filereuploadsummary'
+ : 'fileuploadsummary',
+ 'default' => $this->mComment,
+ 'cols' => 80,
+ 'rows' => 8,
+ ]
+ ];
+ if ( $this->mTextAfterSummary ) {
+ $descriptor['UploadFormTextAfterSummary'] = [
+ 'type' => 'info',
+ 'section' => 'description',
+ 'default' => $this->mTextAfterSummary,
+ 'raw' => true,
+ ];
+ }
+
+ $descriptor += [
+ 'EditTools' => [
+ 'type' => 'edittools',
+ 'section' => 'description',
+ 'message' => 'edittools-upload',
+ ]
+ ];
+
+ if ( $this->mForReUpload ) {
+ $descriptor['DestFile']['readonly'] = true;
+ } else {
+ $descriptor['License'] = [
+ 'type' => 'select',
+ 'class' => 'Licenses',
+ 'section' => 'description',
+ 'id' => 'wpLicense',
+ 'label-message' => 'license',
+ ];
+ }
+
+ if ( $config->get( 'UseCopyrightUpload' ) ) {
+ $descriptor['UploadCopyStatus'] = [
+ 'type' => 'text',
+ 'section' => 'description',
+ 'id' => 'wpUploadCopyStatus',
+ 'label-message' => 'filestatus',
+ ];
+ $descriptor['UploadSource'] = [
+ 'type' => 'text',
+ 'section' => 'description',
+ 'id' => 'wpUploadSource',
+ 'label-message' => 'filesource',
+ ];
+ }
+
+ return $descriptor;
+ }
+
+ /**
+ * Get the descriptor of the fieldset that contains the upload options,
+ * such as "watch this file". The section is 'options'
+ *
+ * @return array Descriptor array
+ */
+ protected function getOptionsSection() {
+ $user = $this->getUser();
+ if ( $user->isLoggedIn() ) {
+ $descriptor = [
+ 'Watchthis' => [
+ 'type' => 'check',
+ 'id' => 'wpWatchthis',
+ 'label-message' => 'watchthisupload',
+ 'section' => 'options',
+ 'default' => $this->mWatch,
+ ]
+ ];
+ }
+ if ( !$this->mHideIgnoreWarning ) {
+ $descriptor['IgnoreWarning'] = [
+ 'type' => 'check',
+ 'id' => 'wpIgnoreWarning',
+ 'label-message' => 'ignorewarnings',
+ 'section' => 'options',
+ ];
+ }
+
+ $descriptor['DestFileWarningAck'] = [
+ 'type' => 'hidden',
+ 'id' => 'wpDestFileWarningAck',
+ 'default' => $this->mDestWarningAck ? '1' : '',
+ ];
+
+ if ( $this->mForReUpload ) {
+ $descriptor['ForReUpload'] = [
+ 'type' => 'hidden',
+ 'id' => 'wpForReUpload',
+ 'default' => '1',
+ ];
+ }
+
+ return $descriptor;
+ }
+
+ /**
+ * Add the upload JS and show the form.
+ */
+ public function show() {
+ $this->addUploadJS();
+ parent::show();
+ }
+
+ /**
+ * Add upload JS to the OutputPage
+ */
+ protected function addUploadJS() {
+ $config = $this->getConfig();
+
+ $useAjaxDestCheck = $config->get( 'UseAjax' ) && $config->get( 'AjaxUploadDestCheck' );
+ $useAjaxLicensePreview = $config->get( 'UseAjax' ) &&
+ $config->get( 'AjaxLicensePreview' ) && $config->get( 'EnableAPI' );
+ $this->mMaxUploadSize['*'] = UploadBase::getMaxUploadSize();
+
+ $scriptVars = [
+ 'wgAjaxUploadDestCheck' => $useAjaxDestCheck,
+ 'wgAjaxLicensePreview' => $useAjaxLicensePreview,
+ 'wgUploadAutoFill' => !$this->mForReUpload &&
+ // If we received mDestFile from the request, don't autofill
+ // the wpDestFile textbox
+ $this->mDestFile === '',
+ 'wgUploadSourceIds' => $this->mSourceIds,
+ 'wgCheckFileExtensions' => $config->get( 'CheckFileExtensions' ),
+ 'wgStrictFileExtensions' => $config->get( 'StrictFileExtensions' ),
+ 'wgFileExtensions' => array_values( array_unique( $config->get( 'FileExtensions' ) ) ),
+ 'wgCapitalizeUploads' => MWNamespace::isCapitalized( NS_FILE ),
+ 'wgMaxUploadSize' => $this->mMaxUploadSize,
+ 'wgFileCanRotate' => SpecialUpload::rotationEnabled(),
+ ];
+
+ $out = $this->getOutput();
+ $out->addJsConfigVars( $scriptVars );
+
+ $out->addModules( [
+ 'mediawiki.special.upload', // Extras for thumbnail and license preview.
+ ] );
+ }
+
+ /**
+ * Empty function; submission is handled elsewhere.
+ *
+ * @return bool False
+ */
+ function trySubmit() {
+ return false;
+ }
+}
--- /dev/null
+<?php
+/**
+ * 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
+ */
+
+use MediaWiki\MediaWikiServices;
+
+/**
+ * Reporting callback
+ * @ingroup SpecialPage
+ */
+class ImportReporter extends ContextSource {
+ private $reason = false;
+ private $logTags = [];
+ private $mOriginalLogCallback = null;
+ private $mOriginalPageOutCallback = null;
+ private $mLogItemCount = 0;
+
+ /**
+ * @param WikiImporter $importer
+ * @param bool $upload
+ * @param string $interwiki
+ * @param string|bool $reason
+ */
+ function __construct( $importer, $upload, $interwiki, $reason = false ) {
+ $this->mOriginalPageOutCallback =
+ $importer->setPageOutCallback( [ $this, 'reportPage' ] );
+ $this->mOriginalLogCallback =
+ $importer->setLogItemCallback( [ $this, 'reportLogItem' ] );
+ $importer->setNoticeCallback( [ $this, 'reportNotice' ] );
+ $this->mPageCount = 0;
+ $this->mIsUpload = $upload;
+ $this->mInterwiki = $interwiki;
+ $this->reason = $reason;
+ }
+
+ /**
+ * Sets change tags to apply to the import log entry and null revision.
+ *
+ * @param array $tags
+ * @since 1.29
+ */
+ public function setChangeTags( array $tags ) {
+ $this->logTags = $tags;
+ }
+
+ function open() {
+ $this->getOutput()->addHTML( "<ul>\n" );
+ }
+
+ function reportNotice( $msg, array $params ) {
+ $this->getOutput()->addHTML(
+ Html::element( 'li', [], $this->msg( $msg, $params )->text() )
+ );
+ }
+
+ function reportLogItem( /* ... */ ) {
+ $this->mLogItemCount++;
+ if ( is_callable( $this->mOriginalLogCallback ) ) {
+ call_user_func_array( $this->mOriginalLogCallback, func_get_args() );
+ }
+ }
+
+ /**
+ * @param Title $title
+ * @param ForeignTitle $foreignTitle
+ * @param int $revisionCount
+ * @param int $successCount
+ * @param array $pageInfo
+ * @return void
+ */
+ public function reportPage( $title, $foreignTitle, $revisionCount,
+ $successCount, $pageInfo ) {
+ $args = func_get_args();
+ call_user_func_array( $this->mOriginalPageOutCallback, $args );
+
+ if ( $title === null ) {
+ # Invalid or non-importable title; a notice is already displayed
+ return;
+ }
+
+ $this->mPageCount++;
+ $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+ if ( $successCount > 0 ) {
+ // <bdi> prevents jumbling of the versions count
+ // in RTL wikis in case the page title is LTR
+ $this->getOutput()->addHTML(
+ "<li>" . $linkRenderer->makeLink( $title ) . " " .
+ "<bdi>" .
+ $this->msg( 'import-revision-count' )->numParams( $successCount )->escaped() .
+ "</bdi>" .
+ "</li>\n"
+ );
+
+ $logParams = [ '4:number:count' => $successCount ];
+ if ( $this->mIsUpload ) {
+ $detail = $this->msg( 'import-logentry-upload-detail' )->numParams(
+ $successCount )->inContentLanguage()->text();
+ $action = 'upload';
+ } else {
+ $pageTitle = $foreignTitle->getFullText();
+ $fullInterwikiPrefix = $this->mInterwiki;
+ Hooks::run( 'ImportLogInterwikiLink', [ &$fullInterwikiPrefix, &$pageTitle ] );
+
+ $interwikiTitleStr = $fullInterwikiPrefix . ':' . $pageTitle;
+ $interwiki = '[[:' . $interwikiTitleStr . ']]';
+ $detail = $this->msg( 'import-logentry-interwiki-detail' )->numParams(
+ $successCount )->params( $interwiki )->inContentLanguage()->text();
+ $action = 'interwiki';
+ $logParams['5:title-link:interwiki'] = $interwikiTitleStr;
+ }
+ if ( $this->reason ) {
+ $detail .= $this->msg( 'colon-separator' )->inContentLanguage()->text()
+ . $this->reason;
+ }
+
+ $comment = $detail; // quick
+ $dbw = wfGetDB( DB_MASTER );
+ $latest = $title->getLatestRevID();
+ $nullRevision = Revision::newNullRevision(
+ $dbw,
+ $title->getArticleID(),
+ $comment,
+ true,
+ $this->getUser()
+ );
+
+ $nullRevId = null;
+ if ( !is_null( $nullRevision ) ) {
+ $nullRevId = $nullRevision->insertOn( $dbw );
+ $page = WikiPage::factory( $title );
+ # Update page record
+ $page->updateRevisionOn( $dbw, $nullRevision );
+ Hooks::run(
+ 'NewRevisionFromEditComplete',
+ [ $page, $nullRevision, $latest, $this->getUser() ]
+ );
+ }
+
+ // Create the import log entry
+ $logEntry = new ManualLogEntry( 'import', $action );
+ $logEntry->setTarget( $title );
+ $logEntry->setComment( $this->reason );
+ $logEntry->setPerformer( $this->getUser() );
+ $logEntry->setParameters( $logParams );
+ $logid = $logEntry->insert();
+ if ( count( $this->logTags ) ) {
+ $logEntry->setTags( $this->logTags );
+ }
+ // Make sure the null revision will be tagged as well
+ $logEntry->setAssociatedRevId( $nullRevId );
+
+ $logEntry->publish( $logid );
+
+ } else {
+ $this->getOutput()->addHTML( "<li>" . $linkRenderer->makeKnownLink( $title ) . " " .
+ $this->msg( 'import-nonewrevisions' )->escaped() . "</li>\n" );
+ }
+ }
+
+ function close() {
+ $out = $this->getOutput();
+ if ( $this->mLogItemCount > 0 ) {
+ $msg = $this->msg( 'imported-log-entries' )->numParams( $this->mLogItemCount )->parse();
+ $out->addHTML( Xml::tags( 'li', null, $msg ) );
+ } elseif ( $this->mPageCount == 0 && $this->mLogItemCount == 0 ) {
+ $out->addHTML( "</ul>\n" );
+
+ return Status::newFatal( 'importnopages' );
+ }
+ $out->addHTML( "</ul>\n" );
+
+ return Status::newGood( $this->mPageCount );
+ }
+}
--- /dev/null
+<?php
+/**
+ * License selector for use on 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
+ * @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 License class for use on Special:Upload (represents a single type of license).
+ */
+class License {
+ /** @var string */
+ public $template;
+
+ /** @var string */
+ public $text;
+
+ /**
+ * @param string $str License name??
+ */
+ function __construct( $str ) {
+ list( $text, $template ) = explode( '|', strrev( $str ), 2 );
+
+ $this->template = strrev( $template );
+ $this->text = strrev( $text );
+ }
+}
'上签约' => '上簽約',
'上签署' => '上簽署',
'上签订' => '上簽訂',
+'上签证' => '上簽證',
'上签' => '上籤',
'上系上' => '上繫上',
'上课钟' => '上課鐘',
'下签约' => '下簽約',
'下签署' => '下簽署',
'下签订' => '下簽訂',
+'下签证' => '下簽證',
'下签' => '下籤',
'下课钟' => '下課鐘',
'不干不净' => '不乾不淨',
'中签约' => '中簽約',
'中签署' => '中簽署',
'中签订' => '中簽訂',
+'中签证' => '中簽證',
'中签' => '中籤',
'中风后' => '中風後',
'丰仪' => '丰儀',
'台子女' => '台子女',
'台子孙' => '台子孫',
'台州' => '台州',
-'台布景' => '台布景',
'台历史' => '台歷史',
'台钟' => '台鐘',
'台风奖' => '台風獎',
'尸祝' => '尸祝',
'尸祿' => '尸祿',
'尸禄' => '尸祿',
+'尸罗' => '尸羅',
+'尸羅' => '尸羅',
'尸罗精舍' => '尸羅精舍',
'尸羅精舍' => '尸羅精舍',
'尸臣' => '尸臣',
'星历' => '星曆',
'星期后' => '星期後',
'星历史' => '星歷史',
+'星露谷物语' => '星露谷物語',
'春游' => '春遊',
'春香斗学' => '春香鬥學',
'昭惠后' => '昭惠后',
'架钟' => '架鐘',
'某只' => '某隻',
'染殿后' => '染殿后',
+'染发生' => '染發生',
'染发' => '染髮',
'柜上' => '柜上',
'柜子' => '柜子',
'杆菌' => '桿菌',
'梁上君子' => '梁上君子',
'梁启超' => '梁啓超',
-'条干' => '條幹',
'条文里' => '條文裡',
'梨干' => '梨乾',
'梯冲' => '梯衝',
'横征暴敛' => '橫徵暴斂',
'横梁' => '橫樑',
'横冲' => '橫衝',
-'台布' => '檯布',
'台历' => '檯曆',
'台灯' => '檯燈',
'台球' => '檯球',
'闯荡' => '闖蕩',
'闯炼' => '闖鍊',
'关系' => '關係',
+'关系列' => '關系列',
+'关系所' => '關系所',
+'关系科' => '關系科',
+'关系统' => '關系統',
'辟佛' => '闢佛',
'辟作' => '闢作',
'辟划' => '闢劃',
'圞' => '𪢮',
'坿' => '附',
'垜' => '垛',
+'垻' => '坝',
'埡' => '垭',
'執' => '执',
'堅' => '坚',
'崑崙' => '昆仑',
'崑劇' => '昆剧',
'崑山' => '昆山',
+'崑島' => '昆岛',
'崑曲' => '昆曲',
'崑腔' => '昆腔',
'崑蘇' => '昆苏',
'哥特式' => '哥德式',
'哥斯达黎加' => '哥斯大黎加',
'哥斯達黎加' => '哥斯大黎加',
+'唐纳德·特朗普' => '唐納·川普',
+'當勞·特朗普' => '唐納·川普',
+'當奴·特朗普' => '唐納·川普',
'卡拉奇' => '喀拉蚩',
'乔治·奥威尔' => '喬治·歐威爾',
'佐治亚' => '喬治亞',
'尼日尔' => '尼日',
'尼日爾' => '尼日',
'雅马哈' => '山葉',
+'特朗普' => '川普',
'机床' => '工具機',
'機床' => '工具機',
'珍寶客機' => '巨無霸客機',
'奥巴马' => '歐巴馬',
'奧巴馬' => '歐巴馬',
'正在叱咤' => '正在叱咤',
+'圣佩德罗苏拉' => '汕埠',
'文莱' => '汶萊',
'沙律' => '沙拉',
'沙地阿拉伯' => '沙烏地阿拉伯',
'毛里塔尼亞' => '茅利塔尼亞',
'霍尔木兹' => '荷姆茲',
'霍爾木茲' => '荷姆茲',
-'荷李活道' => '荷李活道',
+'荷里活廣場' => '荷里活廣場',
+'荷里活道' => '荷里活道',
'莫桑比克' => '莫三比克',
'瓦文萨' => '華勒沙',
'華里沙' => '華勒沙',
'屏幕' => '螢幕',
'行人路权' => '行人路權',
'行人路權' => '行人路權',
+'流動作業系統' => '行動作業系統',
+'移动操作系统' => '行動作業系統',
'流動網絡' => '行動網路',
'移动网络' => '行動網路',
'流動電話' => '行動電話',
'占高枝' => '佔高枝',
'維德角' => '佛得角',
'作品里' => '作品裏',
+'操作系统' => '作業系統',
'來著' => '來着',
'來著作' => '來著作',
'來著名' => '來著名',
'數碼訊號' => '數碼訊號',
'数字电视' => '數碼電視',
'數位電視' => '數碼電視',
+'数字音乐' => '數碼音樂',
+'數位音樂' => '數碼音樂',
'數著作' => '數著作',
'數著名' => '數著名',
'數著稱' => '數著稱',
'枕著述' => '枕著述',
'枕著錄' => '枕著錄',
'檯' => '枱',
-'台布' => '枱布',
'台历' => '枱曆',
'台灯' => '枱燈',
'台面上' => '枱面上',
'活著者' => '活著者',
'活著述' => '活著述',
'活著錄' => '活著錄',
+'移动操作系统' => '流動作業系統',
+'行動作業系統' => '流動作業系統',
'移动网络' => '流動網絡',
'行動網路' => '流動網絡',
'移动电话' => '流動電話',
'畫著稱' => '畫著稱',
'畫著者' => '畫著者',
'画里' => '畫裏',
+'唐納·川普' => '當勞·特朗普',
+'唐纳德·特朗普' => '當勞·特朗普',
'當著' => '當着',
'當著作' => '當著作',
'過著作' => '當著作',
'哭著稱' => '哭著称',
'哭著者' => '哭著者',
'哭著述' => '哭著述',
+'唐納·川普' => '唐纳德·特朗普',
+'當勞·特朗普' => '唐纳德·特朗普',
+'當奴·特朗普' => '唐纳德·特朗普',
'唱著' => '唱着',
'唱著書' => '唱著书',
'唱著作' => '唱著作',
'土魯斯' => '图卢兹',
'吐瓦魯' => '图瓦卢',
'原子筆' => '圆珠笔',
+'汕埠' => '圣佩德罗苏拉',
'聖露西亞' => '圣卢西亚',
'聖克里斯多福及尼維斯' => '圣基茨和尼维斯',
'聖吉斯納域斯' => '圣基茨和尼维斯',
'艾菲爾' => '埃菲尔',
'葉里溫' => '埃里温',
'功能變數名稱' => '域名',
+'網域名稱' => '域名',
'吉里巴斯' => '基里巴斯',
'堂姊' => '堂姐',
'坎培拉' => '堪培拉',
'數位技術' => '数字技术',
'數位電視' => '数字电视',
'數碼電視' => '数字电视',
+'數位音樂' => '数字音乐',
'資料庫' => '数据库',
'數著' => '数着',
'數位照相機' => '数码照相机',
'梳著者' => '梳著者',
'梳著述' => '梳著述',
'梵谷' => '梵高',
-'機率' => '概率',
'欠帳' => '欠账',
'死帳' => '死账',
'庇里牛斯' => '比利牛斯',
+'披索' => '比索',
'畢卡索' => '毕加索',
'茅利塔尼亞' => '毛里塔尼亚',
'模里西斯' => '毛里求斯',
'葛摩' => '科摩罗',
'象牙海岸' => '科特迪瓦',
'積極份子' => '积极分子',
+'流動作業系統' => '移动操作系统',
+'行動作業系統' => '移动操作系统',
'流動電話' => '移动电话',
'行動電話' => '移动电话',
'流動網絡' => '移动网络',
'螢光棒' => '荧光棒',
'螢屏' => '荧屏',
'霍爾斯坦' => '荷尔斯泰因',
+'荷里活廣場' => '荷里活广场',
+'荷里活道' => '荷里活道',
'莫三比克' => '莫桑比克',
'雷伊泰灣' => '莱特湾',
'賴索托' => '莱索托',
行動電話 移动电话
流動電話 移动电话
數據機 调制解调器
+網域名稱 域名
葉門 也门
貝里斯 伯利兹
維德角 佛得角
馬爾地夫 马尔代夫
馬爾他 马耳他
馬利共和國 马里共和国
+汕埠 圣佩德罗苏拉
笨豬跳 蹦极跳
绑紧跳 蹦极跳
狗隻 犬只
賓拉登 本拉登
賓·拉登 本·拉登
歐巴馬 奥巴马
+唐納·川普 唐纳德·特朗普
+當勞·特朗普 唐纳德·特朗普
+當奴·特朗普 唐纳德·特朗普
北韓 北朝鲜
台北韓 台北韩
寮人民民主共和國 老挝人民民主共和国
百慕達 百慕大
三藩市 旧金山
荷里活 好莱坞
+荷里活道 荷里活道
+荷里活廣場 荷里活广场
麻薩諸塞 马萨诸塞
伊利諾 伊利诺伊
伊利諾伊 伊利诺伊
韌體 固件
唯讀 只读
作業系統 操作系统
+行動作業系統 移动操作系统
+流動作業系統 移动操作系统
外掛程式 插件
電晶體 晶体管
顯示卡 显卡
芮氏規模 里氏震级
芮氏地震規模 里氏地震规模
黎克特制 里氏
-機率 概率
行政總裁 首席执行官
執行長, 首席执行官,
執行長、 首席执行官、
數位技術 数字技术
數位訊號 数字信号
數碼訊號 数字信号
+數位音樂 数字音乐
數位化 数字化
行動網路 移动网络
流動網絡 移动网络
行人路权 行人路权
塑膠袋 塑料袋
烏龍麵 乌冬面
+披索 比索
妆台 妝枱
弹珠台 彈珠枱
折台 摺枱
-台布 枱布
台历 枱曆
台灯 枱燈
写字台 寫字枱
機器人 機械人
移动电话 流動電話
行動電話 流動電話
+操作系统 作業系統
+移动操作系统 流動作業系統
+行動作業系統 流動作業系統
數據機 調制解調器
短信 短訊
簡訊 短訊
賓拉登 本拉登
賓·拉登 本·拉登
歐巴馬 奧巴馬
+唐納·川普 當勞·特朗普
+唐纳德·特朗普 當勞·特朗普
戈登·布朗 白高敦
狂牛症 瘋牛症
A肝 甲肝
數位技術 數碼技術
数字信号 數碼訊號
數碼訊號 數碼訊號
+数字音乐 數碼音樂
+數位音樂 數碼音樂
数字化 數碼化
數位化 數碼化
行動網路 流動網絡
崑腔 昆腔
崑蘇 昆苏
崑調 昆调
+崑島 昆岛
諠譁 喧哗
慫慂 怂恿
陈元扞 陈元扞
馬利蘭 馬里蘭
里士满 里奇蒙
荷里活 好萊塢
-荷李活道 荷李活道
+荷里活道 荷里活道
+荷里活廣場 荷里活廣場
维尔京群岛 維京群島
維爾京群島 維京群島
纽黑文 紐哈芬
蒙特利爾 蒙特婁
斯堪的纳维亚 斯堪地那維亞
斯堪的納維亞 斯堪地那維亞
+圣佩德罗苏拉 汕埠
麦克尔 麥可
迈克尔 麥可
魯賓斯·巴里切羅 魯本·巴瑞切羅
肯尼迪 甘迺迪
奥巴马 歐巴馬
奧巴馬 歐巴馬
+特朗普 川普
+唐纳德·特朗普 唐納·川普
+當勞·特朗普 唐納·川普
+當奴·特朗普 唐納·川普
概率 機率
疯牛症 狂牛症
甲肝 A肝
智能卡 智慧卡
數據庫 資料庫
操作系统 作業系統
+移动操作系统 行動作業系統
+流動作業系統 行動作業系統
人机交互 人機互動
交互设计 互動設計
互联网络 網際網路
U+05705圅|U+051FD函|
U+0577F坿|U+09644附|
U+0579C垜|U+0579B垛|
+U+057BB垻|U+0575D坝|
U+0585A塚|U+051A2冢|
U+0585F塟|U+0846C葬|
U+05872塲|U+0573A场|
雪窗螢几
燕几
隱几
+几筵
饑饉
乾薑
毛薑
上簽發
上簽約
上簽了
+上簽證
中簽名
中簽字
中簽收
中簽發
中簽約
中簽了
+中簽證
下簽名
下簽字
下簽收
下簽發
下簽約
下簽了
+下簽證
犖确
磽确
确瘠
山谷 #分詞用
溝谷
曼谷
+星露谷物語
于美人
緊緻
曰云
可自制
台子女
台子孫
-台布景
台州
台風穩健
穩健的台風
尸鳩
尸佼
尸子
+尸羅
尸羅精舍
毗婆尸佛
尸棄佛
蛋白發
發狀態
發狀況
+染發生
古人有云
昔人有云
云敞
性別扭曲
箇舊市
雲南箇舊
+關系列
+關系統
+關系所
+關系科
* @covers Sanitizer::escapeIdForLink()
* @covers Sanitizer::escapeIdForExternalInterwiki()
* @covers Sanitizer::escapeIdInternal()
- * @covers Sanitizer::urlEscapeId()
*
* @param string $stuff
* @param string[] $config