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