MediaWiki REL1_40
UploadForm.php
Go to the documentation of this file.
1<?php
27use Wikimedia\RequestTimeout\TimeoutException;
28
32class UploadForm extends HTMLForm {
33 protected $mWatch;
34 protected $mForReUpload;
35 protected $mSessionKey;
38 protected $mDestFile;
39
40 protected $mComment;
42 protected $mTextTop;
45
46 protected $mSourceIds;
47
48 protected $mMaxFileSize = [];
49
51 protected $mMaxUploadSize = [];
52
54 private $localRepo;
55
57 private $contentLanguage;
58
60 private $nsInfo;
61
63 private $hookRunner;
64
74 public function __construct(
75 array $options = [],
76 IContextSource $context = null,
77 LinkRenderer $linkRenderer = null,
78 LocalRepo $localRepo = null,
79 Language $contentLanguage = null,
80 NamespaceInfo $nsInfo = null,
81 HookContainer $hookContainer = null
82 ) {
83 if ( $context instanceof IContextSource ) {
84 $this->setContext( $context );
85 }
86
87 $services = MediaWikiServices::getInstance();
88 if ( !$linkRenderer ) {
89 $linkRenderer = $services->getLinkRenderer();
90 }
91 if ( !$localRepo ) {
92 $localRepo = $services->getRepoGroup()->getLocalRepo();
93 }
94 if ( !$contentLanguage ) {
95 $contentLanguage = $services->getContentLanguage();
96 }
97 if ( !$nsInfo ) {
98 $nsInfo = $services->getNamespaceInfo();
99 }
100 $this->localRepo = $localRepo;
101 $this->contentLanguage = $contentLanguage;
102 $this->nsInfo = $nsInfo;
103 $this->hookRunner = new HookRunner( $hookContainer ?? $services->getHookContainer() );
104
105 $this->mWatch = !empty( $options['watch'] );
106 $this->mForReUpload = !empty( $options['forreupload'] );
107 $this->mSessionKey = $options['sessionkey'] ?? '';
108 $this->mHideIgnoreWarning = !empty( $options['hideignorewarning'] );
109 $this->mDestWarningAck = !empty( $options['destwarningack'] );
110 $this->mDestFile = $options['destfile'] ?? '';
111
112 $this->mComment = $options['description'] ?? '';
113
114 $this->mTextTop = $options['texttop'] ?? '';
115
116 $this->mTextAfterSummary = $options['textaftersummary'] ?? '';
117
118 $sourceDescriptor = $this->getSourceSection();
119 $descriptor = $sourceDescriptor
120 + $this->getDescriptionSection()
121 + $this->getOptionsSection();
122
123 $this->hookRunner->onUploadFormInitDescriptor( $descriptor );
124 parent::__construct( $descriptor, $this->getContext(), 'upload' );
125
126 # Add a link to edit MediaWiki:Licenses
127 if ( $this->getAuthority()->isAllowed( 'editinterface' ) ) {
128 $this->getOutput()->addModuleStyles( 'mediawiki.special' );
129 $licensesLink = $linkRenderer->makeKnownLink(
130 $this->msg( 'licenses' )->inContentLanguage()->getTitle(),
131 $this->msg( 'licenses-edit' )->text(),
132 [],
133 [ 'action' => 'edit' ]
134 );
135 $editLicenses = '<p class="mw-upload-editlicenses">' . $licensesLink . '</p>';
136 $this->addFooterText( $editLicenses, 'description' );
137 }
138
139 # Set some form properties
140 $this->setSubmitTextMsg( 'uploadbtn' );
141 $this->setSubmitName( 'wpUpload' );
142 # Used message keys: 'accesskey-upload', 'tooltip-upload'
143 $this->setSubmitTooltip( 'upload' );
144 $this->setId( 'mw-upload-form' );
145
146 # Build a list of IDs for javascript insertion
147 $this->mSourceIds = [];
148 foreach ( $sourceDescriptor as $field ) {
149 if ( !empty( $field['id'] ) ) {
150 $this->mSourceIds[] = $field['id'];
151 }
152 }
153 }
154
161 protected function getSourceSection() {
162 if ( $this->mSessionKey ) {
163 return [
164 'SessionKey' => [
165 'type' => 'hidden',
166 'default' => $this->mSessionKey,
167 ],
168 'SourceType' => [
169 'type' => 'hidden',
170 'default' => 'Stash',
171 ],
172 ];
173 }
174
175 $canUploadByUrl = UploadFromUrl::isEnabled()
176 && ( UploadFromUrl::isAllowed( $this->getAuthority() ) === true )
177 && $this->getConfig()->get( MainConfigNames::CopyUploadsFromSpecialUpload );
178 $radio = $canUploadByUrl;
179 $selectedSourceType = strtolower( $this->getRequest()->getText( 'wpSourceType', 'File' ) );
180
181 $descriptor = [];
182 if ( $this->mTextTop ) {
183 $descriptor['UploadFormTextTop'] = [
184 'type' => 'info',
185 'section' => 'source',
186 'default' => $this->mTextTop,
187 'raw' => true,
188 ];
189 }
190
191 $this->mMaxUploadSize['file'] = min(
192 UploadBase::getMaxUploadSize( 'file' ),
193 UploadBase::getMaxPhpUploadSize()
194 );
195
196 $help = $this->msg( 'upload-maxfilesize' )->sizeParams( $this->mMaxUploadSize['file'] )->parse();
197
198 // If the user can also upload by URL, there are 2 different file size limits.
199 // This extra message helps stress which limit corresponds to what.
200 if ( $canUploadByUrl ) {
201 $help .= $this->msg( 'word-separator' )->escaped();
202 $help .= $this->msg( 'upload_source_file' )->parse();
203 }
204
205 $descriptor['UploadFile'] = [
206 'class' => UploadSourceField::class,
207 'section' => 'source',
208 'type' => 'file',
209 'id' => 'wpUploadFile',
210 'radio-id' => 'wpSourceTypeFile',
211 'label-message' => 'sourcefilename',
212 'upload-type' => 'File',
213 'radio' => &$radio,
214 'help' => $help,
215 'checked' => $selectedSourceType == 'file',
216 ];
217
218 if ( $canUploadByUrl ) {
219 $this->mMaxUploadSize['url'] = UploadBase::getMaxUploadSize( 'url' );
220 $descriptor['UploadFileURL'] = [
221 'class' => UploadSourceField::class,
222 'section' => 'source',
223 'id' => 'wpUploadFileURL',
224 'radio-id' => 'wpSourceTypeurl',
225 'label-message' => 'sourceurl',
226 'upload-type' => 'url',
227 'radio' => &$radio,
228 'help' => $this->msg( 'upload-maxfilesize' )->sizeParams( $this->mMaxUploadSize['url'] )->parse() .
229 $this->msg( 'word-separator' )->escaped() .
230 $this->msg( 'upload_source_url' )->parse(),
231 'checked' => $selectedSourceType == 'url',
232 ];
233 }
234 $this->hookRunner->onUploadFormSourceDescriptors(
235 $descriptor, $radio, $selectedSourceType );
236
237 $descriptor['Extensions'] = [
238 'type' => 'info',
239 'section' => 'source',
240 'default' => $this->getExtensionsMessage(),
241 'raw' => true,
242 ];
243
244 return $descriptor;
245 }
246
252 protected function getExtensionsMessage() {
253 # Print a list of allowed file extensions, if so configured. We ignore
254 # MIME type here, it's incomprehensible to most people and too long.
255 $config = $this->getConfig();
256
257 if ( $config->get( MainConfigNames::CheckFileExtensions ) ) {
258 $fileExtensions = array_unique( $config->get( MainConfigNames::FileExtensions ) );
259 if ( $config->get( MainConfigNames::StrictFileExtensions ) ) {
260 # Everything not permitted is banned
261 $extensionsList =
262 '<div id="mw-upload-permitted">' .
263 $this->msg( 'upload-permitted' )
264 ->params( $this->getLanguage()->commaList( $fileExtensions ) )
265 ->numParams( count( $fileExtensions ) )
266 ->parseAsBlock() .
267 "</div>\n";
268 } else {
269 # We have to list both preferred and prohibited
270 $prohibitedExtensions =
271 array_unique( $config->get( MainConfigNames::ProhibitedFileExtensions ) );
272 $extensionsList =
273 '<div id="mw-upload-preferred">' .
274 $this->msg( 'upload-preferred' )
275 ->params( $this->getLanguage()->commaList( $fileExtensions ) )
276 ->numParams( count( $fileExtensions ) )
277 ->parseAsBlock() .
278 "</div>\n" .
279 '<div id="mw-upload-prohibited">' .
280 $this->msg( 'upload-prohibited' )
281 ->params( $this->getLanguage()->commaList( $prohibitedExtensions ) )
282 ->numParams( count( $prohibitedExtensions ) )
283 ->parseAsBlock() .
284 "</div>\n";
285 }
286 } else {
287 # Everything is permitted.
288 $extensionsList = '';
289 }
290
291 return $extensionsList;
292 }
293
300 protected function getDescriptionSection() {
301 $config = $this->getConfig();
302 if ( $this->mSessionKey ) {
303 $stash = $this->localRepo->getUploadStash( $this->getUser() );
304 try {
305 $file = $stash->getFile( $this->mSessionKey );
306 } catch ( TimeoutException $e ) {
307 throw $e;
308 } catch ( Exception $e ) {
309 $file = null;
310 }
311 if ( $file ) {
312 $mto = $file->transform( [ 'width' => 120 ] );
313 if ( $mto ) {
314 $this->addHeaderText(
315 '<div class="thumb t' .
316 $this->contentLanguage->alignEnd() . '">' .
317 Html::element( 'img', [
318 'src' => $mto->getUrl(),
319 'class' => 'thumbimage',
320 ] ) . '</div>', 'description' );
321 }
322 }
323 }
324
325 $descriptor = [
326 'DestFile' => [
327 'type' => 'text',
328 'section' => 'description',
329 'id' => 'wpDestFile',
330 'label-message' => 'destfilename',
331 'size' => 60,
332 'default' => $this->mDestFile,
333 # @todo FIXME: Hack to work around poor handling of the 'default' option in HTMLForm
334 'nodata' => strval( $this->mDestFile ) !== '',
335 ],
336 'UploadDescription' => [
337 'type' => $this->mForReUpload
338 ? 'text'
339 : 'textarea',
340 'section' => 'description',
341 'id' => 'wpUploadDescription',
342 'label-message' => $this->mForReUpload
343 ? 'filereuploadsummary'
344 : 'fileuploadsummary',
345 'default' => $this->mComment,
346 ]
347 ];
348 if ( $this->mTextAfterSummary ) {
349 $descriptor['UploadFormTextAfterSummary'] = [
350 'type' => 'info',
351 'section' => 'description',
352 'default' => $this->mTextAfterSummary,
353 'raw' => true,
354 ];
355 }
356
357 $descriptor += [
358 'EditTools' => [
359 'type' => 'edittools',
360 'section' => 'description',
361 'message' => 'edittools-upload',
362 ]
363 ];
364
365 if ( $this->mForReUpload ) {
366 $descriptor['DestFile']['readonly'] = true;
367 $descriptor['UploadDescription']['size'] = 60;
368 } else {
369 $descriptor['License'] = [
370 'type' => 'select',
371 'class' => Licenses::class,
372 'section' => 'description',
373 'id' => 'wpLicense',
374 'label-message' => 'license',
375 ];
376 $descriptor['UploadDescription']['rows'] = 8;
377 }
378
379 if ( $config->get( MainConfigNames::UseCopyrightUpload ) ) {
380 $descriptor['UploadCopyStatus'] = [
381 'type' => 'text',
382 'section' => 'description',
383 'id' => 'wpUploadCopyStatus',
384 'label-message' => 'filestatus',
385 ];
386 $descriptor['UploadSource'] = [
387 'type' => 'text',
388 'section' => 'description',
389 'id' => 'wpUploadSource',
390 'label-message' => 'filesource',
391 ];
392 }
393
394 return $descriptor;
395 }
396
403 protected function getOptionsSection() {
404 $user = $this->getUser();
405 if ( $user->isRegistered() ) {
406 $descriptor = [
407 'Watchthis' => [
408 'type' => 'check',
409 'id' => 'wpWatchthis',
410 'label-message' => 'watchthisupload',
411 'section' => 'options',
412 'default' => $this->mWatch,
413 ]
414 ];
415 }
416 if ( !$this->mHideIgnoreWarning ) {
417 $descriptor['IgnoreWarning'] = [
418 'type' => 'check',
419 'id' => 'wpIgnoreWarning',
420 'label-message' => 'ignorewarnings',
421 'section' => 'options',
422 ];
423 }
424
425 $descriptor['DestFileWarningAck'] = [
426 'type' => 'hidden',
427 'id' => 'wpDestFileWarningAck',
428 'default' => $this->mDestWarningAck ? '1' : '',
429 ];
430
431 if ( $this->mForReUpload ) {
432 $descriptor['ForReUpload'] = [
433 'type' => 'hidden',
434 'id' => 'wpForReUpload',
435 'default' => '1',
436 ];
437 }
438
439 return $descriptor;
440 }
441
446 public function show() {
447 $this->addUploadJS();
448 return parent::show();
449 }
450
454 protected function addUploadJS() {
455 $config = $this->getConfig();
456
457 $this->mMaxUploadSize['*'] = UploadBase::getMaxUploadSize();
458
459 $scriptVars = [
460 'wgAjaxLicensePreview' => $config->get( MainConfigNames::AjaxLicensePreview ),
461 'wgUploadAutoFill' => !$this->mForReUpload &&
462 // If we received mDestFile from the request, don't autofill
463 // the wpDestFile textbox
464 $this->mDestFile === '',
465 'wgUploadSourceIds' => $this->mSourceIds,
466 'wgCheckFileExtensions' => $config->get( MainConfigNames::CheckFileExtensions ),
467 'wgStrictFileExtensions' => $config->get( MainConfigNames::StrictFileExtensions ),
468 'wgFileExtensions' =>
469 array_values( array_unique( $config->get( MainConfigNames::FileExtensions ) ) ),
470 'wgMaxUploadSize' => $this->mMaxUploadSize,
471 'wgFileCanRotate' => SpecialUpload::rotationEnabled(),
472 ];
473
474 $out = $this->getOutput();
475 $out->addJsConfigVars( $scriptVars );
476
477 $out->addModules( [
478 'mediawiki.special.upload', // Extras for thumbnail and license preview.
479 ] );
480 }
481
487 public function trySubmit() {
488 return false;
489 }
490}
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
getContext()
Get the base IContextSource object.
setContext(IContextSource $context)
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition HTMLForm.php:153
setSubmitName( $name)
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
setId( $id)
addFooterText( $msg, $section=null)
Add footer text, inside the form.
addHeaderText( $msg, $section=null)
Add HTML to the header, inside the form.
Definition HTMLForm.php:952
setSubmitTooltip( $name)
Base class for language-specific code.
Definition Language.php:56
Local repository that stores files in the local filesystem and registers them in the wiki's own datab...
Definition LocalRepo.php:41
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
This class is a collection of static functions that serve two purposes:
Definition Html.php:55
Class that generates HTML for internal links.
A class containing constants representing the names of configuration variables.
Service locator for MediaWiki core services.
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
Sub class of HTMLForm that provides the form section of SpecialUpload.
string $mTextAfterSummary
raw html
show()
Add the upload JS and show the form.
trySubmit()
Empty function; submission is handled elsewhere.
getDescriptionSection()
Get the descriptor of the fieldset that contains the file description input.
getOptionsSection()
Get the descriptor of the fieldset that contains the upload options, such as "watch this file".
addUploadJS()
Add upload JS to the OutputPage.
__construct(array $options=[], IContextSource $context=null, LinkRenderer $linkRenderer=null, LocalRepo $localRepo=null, Language $contentLanguage=null, NamespaceInfo $nsInfo=null, HookContainer $hookContainer=null)
getSourceSection()
Get the descriptor of the fieldset that contains the file source selection.
string $mTextTop
raw html
getExtensionsMessage()
Get the messages indicating which extensions are preferred and prohibited.
array $mMaxUploadSize
static isAllowed(Authority $performer)
Checks if the user is allowed to use the upload-by-URL feature.
static isEnabled()
Checks if the upload from URL feature is enabled.
Interface for objects which can provide a MediaWiki context on request.
return true
Definition router.php:92
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition router.php:42