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