3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
21 use MediaWiki\Linker\LinkRenderer
;
22 use MediaWiki\MediaWikiServices
;
25 * Sub class of HTMLForm that provides the form section of SpecialUpload
27 class UploadForm
extends HTMLForm
{
29 protected $mForReUpload;
30 protected $mSessionKey;
31 protected $mHideIgnoreWarning;
32 protected $mDestWarningAck;
37 protected $mTextAfterSummary;
39 protected $mSourceIds;
41 protected $mMaxFileSize = [];
44 protected $mMaxUploadSize = [];
46 public function __construct( array $options = [], IContextSource
$context = null,
47 LinkRenderer
$linkRenderer = null
49 if ( $context instanceof IContextSource
) {
50 $this->setContext( $context );
53 if ( !$linkRenderer ) {
54 $linkRenderer = MediaWikiServices
::getInstance()->getLinkRenderer();
57 $this->mWatch
= !empty( $options['watch'] );
58 $this->mForReUpload
= !empty( $options['forreupload'] );
59 $this->mSessionKey
= $options['sessionkey'] ??
'';
60 $this->mHideIgnoreWarning
= !empty( $options['hideignorewarning'] );
61 $this->mDestWarningAck
= !empty( $options['destwarningack'] );
62 $this->mDestFile
= $options['destfile'] ??
'';
64 $this->mComment
= $options['description'] ??
'';
66 $this->mTextTop
= $options['texttop'] ??
'';
68 $this->mTextAfterSummary
= $options['textaftersummary'] ??
'';
70 $sourceDescriptor = $this->getSourceSection();
71 $descriptor = $sourceDescriptor
72 +
$this->getDescriptionSection()
73 +
$this->getOptionsSection();
75 Hooks
::run( 'UploadFormInitDescriptor', [ &$descriptor ] );
76 parent
::__construct( $descriptor, $context, 'upload' );
78 # Add a link to edit MediaWiki:Licenses
79 if ( MediaWikiServices
::getInstance()
80 ->getPermissionManager()
81 ->userHasRight( $this->getUser(), 'editinterface' )
83 $this->getOutput()->addModuleStyles( 'mediawiki.special' );
84 $licensesLink = $linkRenderer->makeKnownLink(
85 $this->msg( 'licenses' )->inContentLanguage()->getTitle(),
86 $this->msg( 'licenses-edit' )->text(),
88 [ 'action' => 'edit' ]
90 $editLicenses = '<p class="mw-upload-editlicenses">' . $licensesLink . '</p>';
91 $this->addFooterText( $editLicenses, 'description' );
94 # Set some form properties
95 $this->setSubmitText( $this->msg( 'uploadbtn' )->text() );
96 $this->setSubmitName( 'wpUpload' );
97 # Used message keys: 'accesskey-upload', 'tooltip-upload'
98 $this->setSubmitTooltip( 'upload' );
99 $this->setId( 'mw-upload-form' );
101 # Build a list of IDs for javascript insertion
102 $this->mSourceIds
= [];
103 foreach ( $sourceDescriptor as $field ) {
104 if ( !empty( $field['id'] ) ) {
105 $this->mSourceIds
[] = $field['id'];
111 * Get the descriptor of the fieldset that contains the file source
112 * selection. The section is 'source'
114 * @return array Descriptor array
116 protected function getSourceSection() {
117 if ( $this->mSessionKey
) {
121 'default' => $this->mSessionKey
,
125 'default' => 'Stash',
130 $canUploadByUrl = UploadFromUrl
::isEnabled()
131 && ( UploadFromUrl
::isAllowed( $this->getUser() ) === true )
132 && $this->getConfig()->get( 'CopyUploadsFromSpecialUpload' );
133 $radio = $canUploadByUrl;
134 $selectedSourceType = strtolower( $this->getRequest()->getText( 'wpSourceType', 'File' ) );
137 if ( $this->mTextTop
) {
138 $descriptor['UploadFormTextTop'] = [
140 'section' => 'source',
141 'default' => $this->mTextTop
,
146 $this->mMaxUploadSize
['file'] = min(
147 UploadBase
::getMaxUploadSize( 'file' ),
148 UploadBase
::getMaxPhpUploadSize()
151 $help = $this->msg( 'upload-maxfilesize',
152 $this->getContext()->getLanguage()->formatSize( $this->mMaxUploadSize
['file'] )
155 // If the user can also upload by URL, there are 2 different file size limits.
156 // This extra message helps stress which limit corresponds to what.
157 if ( $canUploadByUrl ) {
158 $help .= $this->msg( 'word-separator' )->escaped();
159 $help .= $this->msg( 'upload_source_file' )->parse();
162 $descriptor['UploadFile'] = [
163 'class' => UploadSourceField
::class,
164 'section' => 'source',
166 'id' => 'wpUploadFile',
167 'radio-id' => 'wpSourceTypeFile',
168 'label-message' => 'sourcefilename',
169 'upload-type' => 'File',
172 'checked' => $selectedSourceType == 'file',
175 if ( $canUploadByUrl ) {
176 $this->mMaxUploadSize
['url'] = UploadBase
::getMaxUploadSize( 'url' );
177 $descriptor['UploadFileURL'] = [
178 'class' => UploadSourceField
::class,
179 'section' => 'source',
180 'id' => 'wpUploadFileURL',
181 'radio-id' => 'wpSourceTypeurl',
182 'label-message' => 'sourceurl',
183 'upload-type' => 'url',
185 'help' => $this->msg( 'upload-maxfilesize',
186 $this->getContext()->getLanguage()->formatSize( $this->mMaxUploadSize
['url'] )
188 $this->msg( 'word-separator' )->escaped() .
189 $this->msg( 'upload_source_url' )->parse(),
190 'checked' => $selectedSourceType == 'url',
193 Hooks
::run( 'UploadFormSourceDescriptors', [ &$descriptor, &$radio, $selectedSourceType ] );
195 $descriptor['Extensions'] = [
197 'section' => 'source',
198 'default' => $this->getExtensionsMessage(),
206 * Get the messages indicating which extensions are preferred and prohibitted.
208 * @return string HTML string containing the message
210 protected function getExtensionsMessage() {
211 # Print a list of allowed file extensions, if so configured. We ignore
212 # MIME type here, it's incomprehensible to most people and too long.
213 $config = $this->getConfig();
215 if ( $config->get( 'CheckFileExtensions' ) ) {
216 $fileExtensions = array_unique( $config->get( 'FileExtensions' ) );
217 if ( $config->get( 'StrictFileExtensions' ) ) {
218 # Everything not permitted is banned
220 '<div id="mw-upload-permitted">' .
221 $this->msg( 'upload-permitted' )
222 ->params( $this->getLanguage()->commaList( $fileExtensions ) )
223 ->numParams( count( $fileExtensions ) )
227 # We have to list both preferred and prohibited
228 $fileBlacklist = array_unique( $config->get( 'FileBlacklist' ) );
230 '<div id="mw-upload-preferred">' .
231 $this->msg( 'upload-preferred' )
232 ->params( $this->getLanguage()->commaList( $fileExtensions ) )
233 ->numParams( count( $fileExtensions ) )
236 '<div id="mw-upload-prohibited">' .
237 $this->msg( 'upload-prohibited' )
238 ->params( $this->getLanguage()->commaList( $fileBlacklist ) )
239 ->numParams( count( $fileBlacklist ) )
244 # Everything is permitted.
245 $extensionsList = '';
248 return $extensionsList;
252 * Get the descriptor of the fieldset that contains the file description
253 * input. The section is 'description'
255 * @return array Descriptor array
257 protected function getDescriptionSection() {
258 $config = $this->getConfig();
259 if ( $this->mSessionKey
) {
260 $stash = RepoGroup
::singleton()->getLocalRepo()->getUploadStash( $this->getUser() );
262 $file = $stash->getFile( $this->mSessionKey
);
263 } catch ( Exception
$e ) {
267 $mto = $file->transform( [ 'width' => 120 ] );
269 $this->addHeaderText(
270 '<div class="thumb t' .
271 MediaWikiServices
::getInstance()->getContentLanguage()->alignEnd() . '">' .
272 Html
::element( 'img', [
273 'src' => $mto->getUrl(),
274 'class' => 'thumbimage',
275 ] ) . '</div>', 'description' );
283 'section' => 'description',
284 'id' => 'wpDestFile',
285 'label-message' => 'destfilename',
287 'default' => $this->mDestFile
,
288 # @todo FIXME: Hack to work around poor handling of the 'default' option in HTMLForm
289 'nodata' => strval( $this->mDestFile
) !== '',
291 'UploadDescription' => [
292 'type' => 'textarea',
293 'section' => 'description',
294 'id' => 'wpUploadDescription',
295 'label-message' => $this->mForReUpload
296 ?
'filereuploadsummary'
297 : 'fileuploadsummary',
298 'default' => $this->mComment
,
303 if ( $this->mTextAfterSummary
) {
304 $descriptor['UploadFormTextAfterSummary'] = [
306 'section' => 'description',
307 'default' => $this->mTextAfterSummary
,
314 'type' => 'edittools',
315 'section' => 'description',
316 'message' => 'edittools-upload',
320 if ( $this->mForReUpload
) {
321 $descriptor['DestFile']['readonly'] = true;
323 $descriptor['License'] = [
325 'class' => Licenses
::class,
326 'section' => 'description',
328 'label-message' => 'license',
332 if ( $config->get( 'UseCopyrightUpload' ) ) {
333 $descriptor['UploadCopyStatus'] = [
335 'section' => 'description',
336 'id' => 'wpUploadCopyStatus',
337 'label-message' => 'filestatus',
339 $descriptor['UploadSource'] = [
341 'section' => 'description',
342 'id' => 'wpUploadSource',
343 'label-message' => 'filesource',
351 * Get the descriptor of the fieldset that contains the upload options,
352 * such as "watch this file". The section is 'options'
354 * @return array Descriptor array
356 protected function getOptionsSection() {
357 $user = $this->getUser();
358 if ( $user->isLoggedIn() ) {
362 'id' => 'wpWatchthis',
363 'label-message' => 'watchthisupload',
364 'section' => 'options',
365 'default' => $this->mWatch
,
369 if ( !$this->mHideIgnoreWarning
) {
370 $descriptor['IgnoreWarning'] = [
372 'id' => 'wpIgnoreWarning',
373 'label-message' => 'ignorewarnings',
374 'section' => 'options',
378 $descriptor['DestFileWarningAck'] = [
380 'id' => 'wpDestFileWarningAck',
381 'default' => $this->mDestWarningAck ?
'1' : '',
384 if ( $this->mForReUpload
) {
385 $descriptor['ForReUpload'] = [
387 'id' => 'wpForReUpload',
396 * Add the upload JS and show the form.
398 public function show() {
399 $this->addUploadJS();
400 return parent
::show();
404 * Add upload JS to the OutputPage
406 protected function addUploadJS() {
407 $config = $this->getConfig();
409 $this->mMaxUploadSize
['*'] = UploadBase
::getMaxUploadSize();
412 'wgAjaxUploadDestCheck' => $config->get( 'AjaxUploadDestCheck' ),
413 'wgAjaxLicensePreview' => $config->get( 'AjaxLicensePreview' ),
414 'wgUploadAutoFill' => !$this->mForReUpload
&&
415 // If we received mDestFile from the request, don't autofill
416 // the wpDestFile textbox
417 $this->mDestFile
=== '',
418 'wgUploadSourceIds' => $this->mSourceIds
,
419 'wgCheckFileExtensions' => $config->get( 'CheckFileExtensions' ),
420 'wgStrictFileExtensions' => $config->get( 'StrictFileExtensions' ),
421 'wgFileExtensions' => array_values( array_unique( $config->get( 'FileExtensions' ) ) ),
422 'wgCapitalizeUploads' => MediaWikiServices
::getInstance()->getNamespaceInfo()->
423 isCapitalized( NS_FILE
),
424 'wgMaxUploadSize' => $this->mMaxUploadSize
,
425 'wgFileCanRotate' => SpecialUpload
::rotationEnabled(),
428 $out = $this->getOutput();
429 $out->addJsConfigVars( $scriptVars );
432 'mediawiki.special.upload', // Extras for thumbnail and license preview.
437 * Empty function; submission is handled elsewhere.
441 function trySubmit() {