From 06daf807ca31500e9253a3d5bd04bf7ceb92cb02 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bartosz=20Dziewo=C5=84ski?= Date: Tue, 12 Sep 2017 23:03:26 +0200 Subject: [PATCH] Split off remaining helper classes for special pages to separate files includes/specials/formfields/ * EditWatchlistCheckboxSeriesField (for SpecialEditWatchlist) * UploadSourceField (for SpecialUpload) * Licenses (for SpecialUpload) includes/specials/forms/ * EditWatchlistNormalHTMLForm (for SpecialEditWatchlist) * PreferencesForm (for SpecialPreferences) * UploadForm (for SpecialUpload) includes/specials/helpers/ * ImportReporter (for SpecialImport) * License (for SpecialUpload) Change-Id: I58abcbb44dbf9bf1762b4252555f7552bfa7c253 --- autoload.php | 16 +- includes/Preferences.php | 122 ----- includes/specials/SpecialEditWatchlist.php | 35 -- includes/specials/SpecialImport.php | 171 ------- includes/specials/SpecialUpload.php | 474 ------------------ .../EditWatchlistCheckboxSeriesField.php | 37 ++ .../{ => specials/formfields}/Licenses.php | 21 - .../specials/formfields/UploadSourceField.php | 68 +++ .../forms/EditWatchlistNormalHTMLForm.php | 36 ++ includes/specials/forms/PreferencesForm.php | 143 ++++++ includes/specials/forms/UploadForm.php | 446 ++++++++++++++++ includes/specials/helpers/ImportReporter.php | 190 +++++++ includes/specials/helpers/License.php | 46 ++ 13 files changed, 974 insertions(+), 831 deletions(-) create mode 100644 includes/specials/formfields/EditWatchlistCheckboxSeriesField.php rename includes/{ => specials/formfields}/Licenses.php (91%) create mode 100644 includes/specials/formfields/UploadSourceField.php create mode 100644 includes/specials/forms/EditWatchlistNormalHTMLForm.php create mode 100644 includes/specials/forms/PreferencesForm.php create mode 100644 includes/specials/forms/UploadForm.php create mode 100644 includes/specials/helpers/ImportReporter.php create mode 100644 includes/specials/helpers/License.php diff --git a/autoload.php b/autoload.php index 4448204a5e..61fd192f0d 100644 --- a/autoload.php +++ b/autoload.php @@ -421,8 +421,8 @@ $wgAutoloadLocalClasses = [ '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', @@ -633,7 +633,7 @@ $wgAutoloadLocalClasses = [ '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', @@ -746,8 +746,8 @@ $wgAutoloadLocalClasses = [ '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', @@ -1135,7 +1135,7 @@ $wgAutoloadLocalClasses = [ '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', @@ -1532,14 +1532,14 @@ $wgAutoloadLocalClasses = [ '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', diff --git a/includes/Preferences.php b/includes/Preferences.php index c29c4b9c85..0bb1d28af3 100644 --- a/includes/Preferences.php +++ b/includes/Preferences.php @@ -1,7 +1,5 @@ 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 "" 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' ) ); - } -} diff --git a/includes/specials/SpecialEditWatchlist.php b/includes/specials/SpecialEditWatchlist.php index e1ecfe8cd5..d2940e4a02 100644 --- a/includes/specials/SpecialEditWatchlist.php +++ b/includes/specials/SpecialEditWatchlist.php @@ -770,38 +770,3 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { ); } } - -/** - * 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 ); - } -} diff --git a/includes/specials/SpecialImport.php b/includes/specials/SpecialImport.php index beb454d669..9ce52ef013 100644 --- a/includes/specials/SpecialImport.php +++ b/includes/specials/SpecialImport.php @@ -24,8 +24,6 @@ * @ingroup SpecialPage */ -use MediaWiki\MediaWikiServices; - /** * MediaWiki page data importer * @@ -524,172 +522,3 @@ class SpecialImport extends SpecialPage { 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( "\n" ); - - return Status::newFatal( 'importnopages' ); - } - $out->addHTML( "\n" ); - - return Status::newGood( $this->mPageCount ); - } -} diff --git a/includes/specials/SpecialUpload.php b/includes/specials/SpecialUpload.php index b98fad1997..59f97960bf 100644 --- a/includes/specials/SpecialUpload.php +++ b/includes/specials/SpecialUpload.php @@ -22,7 +22,6 @@ * @ingroup Upload */ -use MediaWiki\Linker\LinkRenderer; use MediaWiki\MediaWikiServices; /** @@ -846,476 +845,3 @@ class SpecialUpload extends SpecialPage { 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 = '

' . $licensesLink . '

'; - $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 = - '
' . - $this->msg( 'upload-permitted' ) - ->params( $this->getLanguage()->commaList( $fileExtensions ) ) - ->numParams( count( $fileExtensions ) ) - ->parseAsBlock() . - "
\n"; - } else { - # We have to list both preferred and prohibited - $fileBlacklist = array_unique( $config->get( 'FileBlacklist' ) ); - $extensionsList = - '
' . - $this->msg( 'upload-preferred' ) - ->params( $this->getLanguage()->commaList( $fileExtensions ) ) - ->numParams( count( $fileExtensions ) ) - ->parseAsBlock() . - "
\n" . - '
' . - $this->msg( 'upload-prohibited' ) - ->params( $this->getLanguage()->commaList( $fileBlacklist ) ) - ->numParams( count( $fileBlacklist ) ) - ->parseAsBlock() . - "
\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( - '
' . - Html::element( 'img', [ - 'src' => $mto->getUrl(), - 'class' => 'thumbimage', - ] ) . '
', '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; - } -} diff --git a/includes/specials/formfields/EditWatchlistCheckboxSeriesField.php b/includes/specials/formfields/EditWatchlistCheckboxSeriesField.php new file mode 100644 index 0000000000..cb93bb2cee --- /dev/null +++ b/includes/specials/formfields/EditWatchlistCheckboxSeriesField.php @@ -0,0 +1,37 @@ +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 ); - } -} diff --git a/includes/specials/formfields/UploadSourceField.php b/includes/specials/formfields/UploadSourceField.php new file mode 100644 index 0000000000..251a28667a --- /dev/null +++ b/includes/specials/formfields/UploadSourceField.php @@ -0,0 +1,68 @@ +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; + } +} diff --git a/includes/specials/forms/EditWatchlistNormalHTMLForm.php b/includes/specials/forms/EditWatchlistNormalHTMLForm.php new file mode 100644 index 0000000000..723093a772 --- /dev/null +++ b/includes/specials/forms/EditWatchlistNormalHTMLForm.php @@ -0,0 +1,36 @@ +msg( 'blanknamespace' )->escaped() + : htmlspecialchars( $this->getContext()->getLanguage()->getFormattedNsText( $namespace ) ); + } + + public function getBody() { + return $this->displaySection( $this->mFieldTree, '', 'editwatchlist-' ); + } +} diff --git a/includes/specials/forms/PreferencesForm.php b/includes/specials/forms/PreferencesForm.php new file mode 100644 index 0000000000..d4e5ef4fdd --- /dev/null +++ b/includes/specials/forms/PreferencesForm.php @@ -0,0 +1,143 @@ +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 "" 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' ) ); + } +} diff --git a/includes/specials/forms/UploadForm.php b/includes/specials/forms/UploadForm.php new file mode 100644 index 0000000000..44d91a8a26 --- /dev/null +++ b/includes/specials/forms/UploadForm.php @@ -0,0 +1,446 @@ +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 = '

' . $licensesLink . '

'; + $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 = + '
' . + $this->msg( 'upload-permitted' ) + ->params( $this->getLanguage()->commaList( $fileExtensions ) ) + ->numParams( count( $fileExtensions ) ) + ->parseAsBlock() . + "
\n"; + } else { + # We have to list both preferred and prohibited + $fileBlacklist = array_unique( $config->get( 'FileBlacklist' ) ); + $extensionsList = + '
' . + $this->msg( 'upload-preferred' ) + ->params( $this->getLanguage()->commaList( $fileExtensions ) ) + ->numParams( count( $fileExtensions ) ) + ->parseAsBlock() . + "
\n" . + '
' . + $this->msg( 'upload-prohibited' ) + ->params( $this->getLanguage()->commaList( $fileBlacklist ) ) + ->numParams( count( $fileBlacklist ) ) + ->parseAsBlock() . + "
\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( + '
' . + Html::element( 'img', [ + 'src' => $mto->getUrl(), + 'class' => 'thumbimage', + ] ) . '
', '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; + } +} diff --git a/includes/specials/helpers/ImportReporter.php b/includes/specials/helpers/ImportReporter.php new file mode 100644 index 0000000000..63addb8772 --- /dev/null +++ b/includes/specials/helpers/ImportReporter.php @@ -0,0 +1,190 @@ +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( "
    \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 ) { + // prevents jumbling of the versions count + // in RTL wikis in case the page title is LTR + $this->getOutput()->addHTML( + "
  • " . $linkRenderer->makeLink( $title ) . " " . + "" . + $this->msg( 'import-revision-count' )->numParams( $successCount )->escaped() . + "" . + "
  • \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( "
  • " . $linkRenderer->makeKnownLink( $title ) . " " . + $this->msg( 'import-nonewrevisions' )->escaped() . "
  • \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( "
\n" ); + + return Status::newFatal( 'importnopages' ); + } + $out->addHTML( "\n" ); + + return Status::newGood( $this->mPageCount ); + } +} diff --git a/includes/specials/helpers/License.php b/includes/specials/helpers/License.php new file mode 100644 index 0000000000..4f94b4d232 --- /dev/null +++ b/includes/specials/helpers/License.php @@ -0,0 +1,46 @@ + + * @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 ); + } +} -- 2.20.1