MediaWiki REL1_40
SpecialUpload.php
Go to the documentation of this file.
1<?php
32
40
42 private $localRepo;
43
45 private $userOptionsLookup;
46
48 private $nsInfo;
49
51 private $watchlistManager;
52
59 public function __construct(
60 RepoGroup $repoGroup = null,
61 UserOptionsLookup $userOptionsLookup = null,
62 NamespaceInfo $nsInfo = null,
63 WatchlistManager $watchlistManager = null
64 ) {
65 parent::__construct( 'Upload', 'upload' );
66 // This class is extended and therefor fallback to global state - T265300
67 $services = MediaWikiServices::getInstance();
68 $repoGroup ??= $services->getRepoGroup();
69 $this->localRepo = $repoGroup->getLocalRepo();
70 $this->userOptionsLookup = $userOptionsLookup ?? $services->getUserOptionsLookup();
71 $this->nsInfo = $nsInfo ?? $services->getNamespaceInfo();
72 $this->watchlistManager = $watchlistManager ?? $services->getWatchlistManager();
73 }
74
75 public function doesWrites() {
76 return true;
77 }
78
82 public $mRequest;
84
86 public $mUpload;
87
91
96 public $mComment;
97 public $mLicense;
98
105
109
112
115 public $mTokenOk;
116
118 public $mUploadSuccessful = false;
119
124
128 protected function loadRequest() {
129 $this->mRequest = $request = $this->getRequest();
130 $this->mSourceType = $request->getVal( 'wpSourceType', 'file' );
131 $this->mUpload = UploadBase::createFromRequest( $request );
132 $this->mUploadClicked = $request->wasPosted()
133 && ( $request->getCheck( 'wpUpload' )
134 || $request->getCheck( 'wpUploadIgnoreWarning' ) );
135
136 // Guess the desired name from the filename if not provided
137 $this->mDesiredDestName = $request->getText( 'wpDestFile' );
138 if ( !$this->mDesiredDestName && $request->getFileName( 'wpUploadFile' ) !== null ) {
139 $this->mDesiredDestName = $request->getFileName( 'wpUploadFile' );
140 }
141 $this->mLicense = $request->getText( 'wpLicense' );
142
143 $this->mDestWarningAck = $request->getText( 'wpDestFileWarningAck' );
144 $this->mIgnoreWarning = $request->getCheck( 'wpIgnoreWarning' )
145 || $request->getCheck( 'wpUploadIgnoreWarning' );
146 $this->mWatchthis = $request->getBool( 'wpWatchthis' ) && $this->getUser()->isRegistered();
147 $this->mCopyrightStatus = $request->getText( 'wpUploadCopyStatus' );
148 $this->mCopyrightSource = $request->getText( 'wpUploadSource' );
149
150 $this->mForReUpload = $request->getBool( 'wpForReUpload' ); // updating a file
151
152 $commentDefault = '';
153 $commentMsg = $this->msg( 'upload-default-description' )->inContentLanguage();
154 if ( !$this->mForReUpload && !$commentMsg->isDisabled() ) {
155 $commentDefault = $commentMsg->plain();
156 }
157 $this->mComment = $request->getText( 'wpUploadDescription', $commentDefault );
158
159 $this->mCancelUpload = $request->getCheck( 'wpCancelUpload' )
160 || $request->getCheck( 'wpReUpload' ); // b/w compat
161
162 // If it was posted check for the token (no remote POST'ing with user credentials)
163 $token = $request->getVal( 'wpEditToken' );
164 $this->mTokenOk = $this->getUser()->matchEditToken( $token );
165
166 $this->uploadFormTextTop = '';
167 $this->uploadFormTextAfterSummary = '';
168 }
169
178 public function userCanExecute( User $user ) {
179 return UploadBase::isEnabled() && parent::userCanExecute( $user );
180 }
181
185 public function execute( $par ) {
187
188 $this->setHeaders();
189 $this->outputHeader();
190
191 # Check uploading enabled
192 if ( !UploadBase::isEnabled() ) {
193 throw new ErrorPageError( 'uploaddisabled', 'uploaddisabledtext' );
194 }
195
196 $this->addHelpLink( 'Help:Managing files' );
197
198 # Check permissions
199 $user = $this->getUser();
200 $permissionRequired = UploadBase::isAllowed( $user );
201 if ( $permissionRequired !== true ) {
202 throw new PermissionsError( $permissionRequired );
203 }
204
205 # Check blocks
206 if ( $user->isBlockedFromUpload() ) {
207 throw new UserBlockedError(
208 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable Block is checked and not null
209 $user->getBlock(),
210 $user,
211 $this->getLanguage(),
212 $this->getRequest()->getIP()
213 );
214 }
215
216 # Check whether we actually want to allow changing stuff
217 $this->checkReadOnly();
218
219 $this->loadRequest();
220
221 # Unsave the temporary file in case this was a cancelled upload
222 if ( $this->mCancelUpload && !$this->unsaveUploadedFile() ) {
223 # Something went wrong, so unsaveUploadedFile showed a warning
224 return;
225 }
226
227 # Process upload or show a form
228 if (
229 $this->mTokenOk && !$this->mCancelUpload &&
230 ( $this->mUpload && $this->mUploadClicked )
231 ) {
232 $this->processUpload();
233 } else {
234 # Backwards compatibility hook
235 if ( !$this->getHookRunner()->onUploadForm_initial( $this ) ) {
236 wfDebug( "Hook 'UploadForm:initial' broke output of the upload form" );
237
238 return;
239 }
240 $this->showUploadForm( $this->getUploadForm() );
241 }
242
243 # Cleanup
244 if ( $this->mUpload ) {
245 $this->mUpload->cleanupTempFile();
246 }
247 }
248
254 protected function showUploadForm( $form ) {
255 if ( $form instanceof HTMLForm ) {
256 $form->show();
257 } else {
258 $this->getOutput()->addHTML( $form );
259 }
260 }
261
270 protected function getUploadForm( $message = '', $sessionKey = '', $hideIgnoreWarning = false ) {
271 # Initialize form
272 $form = new UploadForm(
273 [
274 'watch' => $this->getWatchCheck(),
275 'forreupload' => $this->mForReUpload,
276 'sessionkey' => $sessionKey,
277 'hideignorewarning' => $hideIgnoreWarning,
278 'destwarningack' => (bool)$this->mDestWarningAck,
279
280 'description' => $this->mComment,
281 'texttop' => $this->uploadFormTextTop,
282 'textaftersummary' => $this->uploadFormTextAfterSummary,
283 'destfile' => $this->mDesiredDestName,
284 ],
285 $this->getContext(),
286 $this->getLinkRenderer(),
287 $this->localRepo,
288 $this->getContentLanguage(),
289 $this->nsInfo,
290 $this->getHookContainer()
291 );
292 $form->setTitle( $this->getPageTitle() ); // Remove subpage
293
294 # Check the token, but only if necessary
295 if (
296 !$this->mTokenOk && !$this->mCancelUpload &&
297 ( $this->mUpload && $this->mUploadClicked )
298 ) {
299 $form->addPreText( $this->msg( 'session_fail_preview' )->parse() );
300 }
301
302 # Give a notice if the user is uploading a file that has been deleted or moved
303 # Note that this is independent from the message 'filewasdeleted'
304 $desiredTitleObj = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
305 $delNotice = ''; // empty by default
306 if ( $desiredTitleObj instanceof Title && !$desiredTitleObj->exists() ) {
307 LogEventsList::showLogExtract( $delNotice, [ 'delete', 'move' ],
308 $desiredTitleObj,
309 '', [ 'lim' => 10,
310 'conds' => [ 'log_action != ' . $this->localRepo->getReplicaDB()->addQuotes( 'revision' ) ],
311 'showIfEmpty' => false,
312 'msgKey' => [ 'upload-recreate-warning' ] ]
313 );
314 }
315 $form->addPreText( $delNotice );
316
317 # Add text to form
318 $form->addPreText( '<div id="uploadtext">' .
319 $this->msg( 'uploadtext', [ $this->mDesiredDestName ] )->parseAsBlock() .
320 '</div>' );
321 # Add upload error message
322 $form->addPreText( $message );
323
324 # Add footer to form
325 $uploadFooter = $this->msg( 'uploadfooter' );
326 if ( !$uploadFooter->isDisabled() ) {
327 $form->addPostText( '<div id="mw-upload-footer-message">'
328 . $uploadFooter->parseAsBlock() . "</div>\n" );
329 }
330
331 return $form;
332 }
333
345 protected function showRecoverableUploadError( $message ) {
346 $stashStatus = $this->mUpload->tryStashFile( $this->getUser() );
347 if ( $stashStatus->isGood() ) {
348 $sessionKey = $stashStatus->getValue()->getFileKey();
349 $uploadWarning = 'upload-tryagain';
350 } else {
351 $sessionKey = null;
352 $uploadWarning = 'upload-tryagain-nostash';
353 }
354 $message = '<h2>' . $this->msg( 'uploaderror' )->escaped() . '</h2>' .
355 Html::errorBox( $message );
356
357 $form = $this->getUploadForm( $message, $sessionKey );
358 $form->setSubmitText( $this->msg( $uploadWarning )->escaped() );
359 $this->showUploadForm( $form );
360 }
361
370 protected function showUploadWarning( $warnings ) {
371 # If there are no warnings, or warnings we can ignore, return early.
372 # mDestWarningAck is set when some javascript has shown the warning
373 # to the user. mForReUpload is set when the user clicks the "upload a
374 # new version" link.
375 if ( !$warnings || ( count( $warnings ) == 1
376 && isset( $warnings['exists'] )
377 && ( $this->mDestWarningAck || $this->mForReUpload ) )
378 ) {
379 return false;
380 }
381
382 $stashStatus = $this->mUpload->tryStashFile( $this->getUser() );
383 if ( $stashStatus->isGood() ) {
384 $sessionKey = $stashStatus->getValue()->getFileKey();
385 $uploadWarning = 'uploadwarning-text';
386 } else {
387 $sessionKey = null;
388 $uploadWarning = 'uploadwarning-text-nostash';
389 }
390
391 // Add styles for the warning, reused from the live preview
392 $this->getOutput()->addModuleStyles( 'mediawiki.special' );
393
394 $linkRenderer = $this->getLinkRenderer();
395 $warningHtml = '<h2>' . $this->msg( 'uploadwarning' )->escaped() . "</h2>\n"
396 . '<div class="mw-destfile-warning"><ul>';
397 foreach ( $warnings as $warning => $args ) {
398 if ( $warning == 'badfilename' ) {
399 $this->mDesiredDestName = Title::makeTitle( NS_FILE, $args )->getText();
400 }
401 if ( $warning == 'exists' ) {
402 $msg = "\t<li>" . self::getExistsWarning( $args ) . "</li>\n";
403 } elseif ( $warning == 'no-change' ) {
404 $file = $args;
405 $filename = $file->getTitle()->getPrefixedText();
406 $msg = "\t<li>" . $this->msg( 'fileexists-no-change', $filename )->parse() . "</li>\n";
407 } elseif ( $warning == 'duplicate-version' ) {
408 $file = $args[0];
409 $count = count( $args );
410 $filename = $file->getTitle()->getPrefixedText();
411 $message = $this->msg( 'fileexists-duplicate-version' )
412 ->params( $filename )
413 ->numParams( $count );
414 $msg = "\t<li>" . $message->parse() . "</li>\n";
415 } elseif ( $warning == 'was-deleted' ) {
416 # If the file existed before and was deleted, warn the user of this
417 $ltitle = SpecialPage::getTitleFor( 'Log' );
418 $llink = $linkRenderer->makeKnownLink(
419 $ltitle,
420 $this->msg( 'deletionlog' )->text(),
421 [],
422 [
423 'type' => 'delete',
424 'page' => Title::makeTitle( NS_FILE, $args )->getPrefixedText(),
425 ]
426 );
427 $msg = "\t<li>" . $this->msg( 'filewasdeleted' )->rawParams( $llink )->parse() . "</li>\n";
428 } elseif ( $warning == 'duplicate' ) {
429 $msg = $this->getDupeWarning( $args );
430 } elseif ( $warning == 'duplicate-archive' ) {
431 if ( $args === '' ) {
432 $msg = "\t<li>" . $this->msg( 'file-deleted-duplicate-notitle' )->parse()
433 . "</li>\n";
434 } else {
435 $msg = "\t<li>" . $this->msg( 'file-deleted-duplicate',
436 Title::makeTitle( NS_FILE, $args )->getPrefixedText() )->parse()
437 . "</li>\n";
438 }
439 } else {
440 if ( $args === true ) {
441 $args = [];
442 } elseif ( !is_array( $args ) ) {
443 $args = [ $args ];
444 }
445 $msg = "\t<li>" . $this->msg( $warning, $args )->parse() . "</li>\n";
446 }
447 $warningHtml .= $msg;
448 }
449 $warningHtml .= "</ul></div>\n";
450 $warningHtml .= $this->msg( $uploadWarning )->parseAsBlock();
451
452 $form = $this->getUploadForm( $warningHtml, $sessionKey, /* $hideIgnoreWarning */ true );
453 $form->setSubmitTextMsg( 'upload-tryagain' );
454 $form->addButton( [
455 'name' => 'wpUploadIgnoreWarning',
456 'value' => $this->msg( 'ignorewarning' )->text()
457 ] );
458 $form->addButton( [
459 'name' => 'wpCancelUpload',
460 'value' => $this->msg( 'reuploaddesc' )->text()
461 ] );
462
463 $this->showUploadForm( $form );
464
465 # Indicate that we showed a form
466 return true;
467 }
468
474 protected function showUploadError( $message ) {
475 $message = '<h2>' . $this->msg( 'uploadwarning' )->escaped() . '</h2>' .
476 Html::errorBox( $message );
477 $this->showUploadForm( $this->getUploadForm( $message ) );
478 }
479
484 protected function processUpload() {
485 // Fetch the file if required
486 $status = $this->mUpload->fetchFile();
487 if ( !$status->isOK() ) {
488 $this->showUploadError( $this->getOutput()->parseAsInterface(
489 $status->getWikiText( false, false, $this->getLanguage() )
490 ) );
491
492 return;
493 }
494 if ( !$this->getHookRunner()->onUploadForm_BeforeProcessing( $this ) ) {
495 wfDebug( "Hook 'UploadForm:BeforeProcessing' broke processing the file." );
496 // This code path is deprecated. If you want to break upload processing
497 // do so by hooking into the appropriate hooks in UploadBase::verifyUpload
498 // and UploadBase::verifyFile.
499 // If you use this hook to break uploading, the user will be returned
500 // an empty form with no error message whatsoever.
501 return;
502 }
503
504 // Upload verification
505 $details = $this->mUpload->verifyUpload();
506 if ( $details['status'] != UploadBase::OK ) {
507 $this->processVerificationError( $details );
508
509 return;
510 }
511
512 // Verify permissions for this title
513 $user = $this->getUser();
514 $permErrors = $this->mUpload->verifyTitlePermissions( $user );
515 if ( $permErrors !== true ) {
516 $code = array_shift( $permErrors[0] );
517 $this->showRecoverableUploadError( $this->msg( $code, $permErrors[0] )->parse() );
518
519 return;
520 }
521
522 $this->mLocalFile = $this->mUpload->getLocalFile();
523
524 // Check warnings if necessary
525 if ( !$this->mIgnoreWarning ) {
526 $warnings = $this->mUpload->checkWarnings( $user );
527 if ( $this->showUploadWarning( $warnings ) ) {
528 return;
529 }
530 }
531
532 // This is as late as we can throttle, after expected issues have been handled
533 if ( UploadBase::isThrottled( $user ) ) {
535 $this->msg( 'actionthrottledtext' )->escaped()
536 );
537 return;
538 }
539
540 // Get the page text if this is not a reupload
541 if ( !$this->mForReUpload ) {
542 $pageText = self::getInitialPageText( $this->mComment, $this->mLicense,
543 $this->mCopyrightStatus, $this->mCopyrightSource, $this->getConfig() );
544 } else {
545 $pageText = false;
546 }
547
548 $changeTags = $this->getRequest()->getVal( 'wpChangeTags' );
549 if ( $changeTags === null || $changeTags === '' ) {
550 $changeTags = [];
551 } else {
552 $changeTags = array_filter( array_map( 'trim', explode( ',', $changeTags ) ) );
553 }
554
555 if ( $changeTags ) {
557 $changeTags, $user );
558 if ( !$changeTagsStatus->isOK() ) {
559 $this->showUploadError( $this->getOutput()->parseAsInterface(
560 $changeTagsStatus->getWikiText( false, false, $this->getLanguage() )
561 ) );
562
563 return;
564 }
565 }
566
567 $status = $this->mUpload->performUpload(
568 $this->mComment,
569 $pageText,
570 $this->mWatchthis,
571 $user,
572 $changeTags
573 );
574
575 if ( !$status->isGood() ) {
577 $this->getOutput()->parseAsInterface(
578 $status->getWikiText( false, false, $this->getLanguage() )
579 )
580 );
581
582 return;
583 }
584
585 // Success, redirect to description page
586 $this->mUploadSuccessful = true;
587 $this->getHookRunner()->onSpecialUploadComplete( $this );
588 $this->getOutput()->redirect( $this->mLocalFile->getTitle()->getFullURL() );
589 }
590
600 public static function getInitialPageText( $comment = '', $license = '',
601 $copyStatus = '', $source = '', Config $config = null
602 ) {
603 if ( $config === null ) {
604 wfDebug( __METHOD__ . ' called without a Config instance passed to it' );
605 $config = MediaWikiServices::getInstance()->getMainConfig();
606 }
607
608 $msg = [];
609 $forceUIMsgAsContentMsg = (array)$config->get( MainConfigNames::ForceUIMsgAsContentMsg );
610 /* These messages are transcluded into the actual text of the description page.
611 * Thus, forcing them as content messages makes the upload to produce an int: template
612 * instead of hardcoding it there in the uploader language.
613 */
614 foreach ( [ 'license-header', 'filedesc', 'filestatus', 'filesource' ] as $msgName ) {
615 if ( in_array( $msgName, $forceUIMsgAsContentMsg ) ) {
616 $msg[$msgName] = "{{int:$msgName}}";
617 } else {
618 $msg[$msgName] = wfMessage( $msgName )->inContentLanguage()->text();
619 }
620 }
621
622 $licenseText = '';
623 if ( $license !== '' ) {
624 $licenseText = '== ' . $msg['license-header'] . " ==\n{{" . $license . "}}\n";
625 }
626
627 $pageText = $comment . "\n";
628 $headerText = '== ' . $msg['filedesc'] . ' ==';
629 if ( $comment !== '' && !str_contains( $comment, $headerText ) ) {
630 // prepend header to page text unless it's already there (or there is no content)
631 $pageText = $headerText . "\n" . $pageText;
632 }
633
634 if ( $config->get( MainConfigNames::UseCopyrightUpload ) ) {
635 $pageText .= '== ' . $msg['filestatus'] . " ==\n" . $copyStatus . "\n";
636 $pageText .= $licenseText;
637 $pageText .= '== ' . $msg['filesource'] . " ==\n" . $source;
638 } else {
639 $pageText .= $licenseText;
640 }
641
642 // allow extensions to modify the content
643 Hooks::runner()->onUploadForm_getInitialPageText( $pageText, $msg, $config );
644
645 return $pageText;
646 }
647
660 protected function getWatchCheck() {
661 $user = $this->getUser();
662 if ( $this->userOptionsLookup->getBoolOption( $user, 'watchdefault' ) ) {
663 // Watch all edits!
664 return true;
665 }
666
667 $desiredTitleObj = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
668 if ( $desiredTitleObj instanceof Title &&
669 $this->watchlistManager->isWatched( $user, $desiredTitleObj ) ) {
670 // Already watched, don't change that
671 return true;
672 }
673
674 $local = $this->localRepo->newFile( $this->mDesiredDestName );
675 if ( $local && $local->exists() ) {
676 // We're uploading a new version of an existing file.
677 // No creation, so don't watch it if we're not already.
678 return false;
679 } else {
680 // New page should get watched if that's our option.
681 return $this->userOptionsLookup->getBoolOption( $user, 'watchcreations' ) ||
682 $this->userOptionsLookup->getBoolOption( $user, 'watchuploads' );
683 }
684 }
685
691 protected function processVerificationError( $details ) {
692 switch ( $details['status'] ) {
694 case UploadBase::MIN_LENGTH_PARTNAME:
695 $this->showRecoverableUploadError( $this->msg( 'minlength1' )->escaped() );
696 break;
697 case UploadBase::ILLEGAL_FILENAME:
698 $this->showRecoverableUploadError( $this->msg( 'illegalfilename',
699 $details['filtered'] )->parse() );
700 break;
701 case UploadBase::FILENAME_TOO_LONG:
702 $this->showRecoverableUploadError( $this->msg( 'filename-toolong' )->escaped() );
703 break;
704 case UploadBase::FILETYPE_MISSING:
705 $this->showRecoverableUploadError( $this->msg( 'filetype-missing' )->parse() );
706 break;
707 case UploadBase::WINDOWS_NONASCII_FILENAME:
708 $this->showRecoverableUploadError( $this->msg( 'windows-nonascii-filename' )->parse() );
709 break;
710
712 case UploadBase::EMPTY_FILE:
713 $this->showUploadError( $this->msg( 'emptyfile' )->escaped() );
714 break;
715 case UploadBase::FILE_TOO_LARGE:
716 $this->showUploadError( $this->msg( 'largefileserver' )->escaped() );
717 break;
718 case UploadBase::FILETYPE_BADTYPE:
719 $msg = $this->msg( 'filetype-banned-type' );
720 if ( isset( $details['blacklistedExt'] ) ) {
721 $msg->params( $this->getLanguage()->commaList( $details['blacklistedExt'] ) );
722 } else {
723 $msg->params( $details['finalExt'] );
724 }
725 $extensions =
726 array_unique( $this->getConfig()->get( MainConfigNames::FileExtensions ) );
727 $msg->params( $this->getLanguage()->commaList( $extensions ),
728 count( $extensions ) );
729
730 // Add PLURAL support for the first parameter. This results
731 // in a bit unlogical parameter sequence, but does not break
732 // old translations
733 if ( isset( $details['blacklistedExt'] ) ) {
734 $msg->params( count( $details['blacklistedExt'] ) );
735 } else {
736 $msg->params( 1 );
737 }
738
739 $this->showUploadError( $msg->parse() );
740 break;
741 case UploadBase::VERIFICATION_ERROR:
742 unset( $details['status'] );
743 $code = array_shift( $details['details'] );
744 $this->showUploadError( $this->msg( $code, $details['details'] )->parse() );
745 break;
746 case UploadBase::HOOK_ABORTED:
747 if ( is_array( $details['error'] ) ) { # allow hooks to return error details in an array
748 $args = $details['error'];
749 $error = array_shift( $args );
750 } else {
751 $error = $details['error'];
752 $args = null;
753 }
754
755 $this->showUploadError( $this->msg( $error, $args )->parse() );
756 break;
757 default:
758 throw new UnexpectedValueException( __METHOD__ . ": Unknown value `{$details['status']}`" );
759 }
760 }
761
767 protected function unsaveUploadedFile() {
768 if ( !( $this->mUpload instanceof UploadFromStash ) ) {
769 return true;
770 }
771 $success = $this->mUpload->unsaveUploadedFile();
772 if ( !$success ) {
773 $this->getOutput()->showFatalError(
774 $this->msg( 'filedeleteerror' )
775 ->params( $this->mUpload->getTempPath() )
776 ->escaped()
777 );
778
779 return false;
780 } else {
781 return true;
782 }
783 }
784
794 public static function getExistsWarning( $exists ) {
795 if ( !$exists ) {
796 return '';
797 }
798
799 $file = $exists['file'];
800 $filename = $file->getTitle()->getPrefixedText();
801 $warnMsg = null;
802
803 if ( $exists['warning'] == 'exists' ) {
804 // Exact match
805 $warnMsg = wfMessage( 'fileexists', $filename );
806 } elseif ( $exists['warning'] == 'page-exists' ) {
807 // Page exists but file does not
808 $warnMsg = wfMessage( 'filepageexists', $filename );
809 } elseif ( $exists['warning'] == 'exists-normalized' ) {
810 $warnMsg = wfMessage( 'fileexists-extension', $filename,
811 $exists['normalizedFile']->getTitle()->getPrefixedText() );
812 } elseif ( $exists['warning'] == 'thumb' ) {
813 // Swapped argument order compared with other messages for backwards compatibility
814 $warnMsg = wfMessage( 'fileexists-thumbnail-yes',
815 $exists['thumbFile']->getTitle()->getPrefixedText(), $filename );
816 } elseif ( $exists['warning'] == 'thumb-name' ) {
817 // Image w/o '180px-' does not exists, but we do not like these filenames
818 $name = $file->getName();
819 $badPart = substr( $name, 0, strpos( $name, '-' ) + 1 );
820 $warnMsg = wfMessage( 'file-thumbnail-no', $badPart );
821 } elseif ( $exists['warning'] == 'bad-prefix' ) {
822 $warnMsg = wfMessage( 'filename-bad-prefix', $exists['prefix'] );
823 }
824
825 return $warnMsg ? $warnMsg->page( $file->getTitle() )->parse() : '';
826 }
827
833 public function getDupeWarning( $dupes ) {
834 if ( !$dupes ) {
835 return '';
836 }
837
838 $gallery = ImageGalleryBase::factory( false, $this->getContext() );
839 $gallery->setShowBytes( false );
840 $gallery->setShowDimensions( false );
841 foreach ( $dupes as $file ) {
842 $gallery->add( $file->getTitle() );
843 }
844
845 return '<li>' .
846 $this->msg( 'file-exists-duplicate' )->numParams( count( $dupes ) )->parse() .
847 $gallery->toHTML() . "</li>\n";
848 }
849
850 protected function getGroupName() {
851 return 'media';
852 }
853
862 public static function rotationEnabled() {
863 $bitmapHandler = new BitmapHandler();
864 return $bitmapHandler->autoRotateEnabled();
865 }
866}
getUser()
const NS_FILE
Definition Defines.php:70
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
getContext()
Generic handler for bitmap images.
static canAddTagsAccompanyingChange(array $tags, Authority $performer=null, $checkBlock=true)
Is it OK to allow the user to apply all the specified tags at the same time as they edit/make the cha...
An error page which can definitely be safely rendered using the OutputPage.
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition HTMLForm.php:153
Local file in the wiki's own database.
Definition LocalFile.php:61
Local repository that stores files in the local filesystem and registers them in the wiki's own datab...
Definition LocalRepo.php:41
This class is a collection of static functions that serve two purposes:
Definition Html.php:55
A class containing constants representing the names of configuration variables.
Service locator for MediaWiki core services.
WebRequest clone which takes values from a provided array.
Represents a title within MediaWiki.
Definition Title.php:82
exists( $flags=0)
Check if page exists.
Definition Title.php:3523
Provides access to user options.
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
Show an error when a user tries to do something they do not have the necessary permissions for.
Prioritized list of file repositories.
Definition RepoGroup.php:30
Parent class for all special pages.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getOutput()
Get the OutputPage being used for this instance.
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getConfig()
Shortcut to get main config object.
getRequest()
Get the WebRequest being used for this instance.
checkReadOnly()
If the wiki is currently in readonly mode, throws a ReadOnlyError.
getPageTitle( $subpage=false)
Get a self-referential title object.
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
getLanguage()
Shortcut to get user's language.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
getContentLanguage()
Shortcut to get content language.
Form for handling uploads and special page.
processVerificationError( $details)
Provides output to the user for a result of UploadBase::verifyUpload.
UploadBase $mUpload
getWatchCheck()
See if we should check the 'watch this page' checkbox on the form based on the user's preferences and...
loadRequest()
Initialize instance variables from request and create an Upload handler.
static getInitialPageText( $comment='', $license='', $copyStatus='', $source='', Config $config=null)
Get the initial image page text based on a comment and optional file status information.
showUploadWarning( $warnings)
Stashes the upload, shows the main form, but adds a "continue anyway button".
bool $mCancelUpload
The user clicked "Cancel and return to upload form" button.
unsaveUploadedFile()
Remove a temporarily kept file stashed by saveTempUploadedFile().
userCanExecute(User $user)
This page can be shown if uploading is enabled.
static getExistsWarning( $exists)
Functions for formatting warnings.
string $mDesiredDestName
User input variables from the "description" section.
showRecoverableUploadError( $message)
Stashes the upload and shows the main upload form.
string $uploadFormTextAfterSummary
Raw html injection point for hooks not using HTMLForm.
$mDestWarningAck
Hidden variables.
getDupeWarning( $dupes)
Construct a warning and a gallery from an array of duplicate files.
showUploadForm( $form)
Show the main upload form.
WebRequest FauxRequest $mRequest
Misc variables.
processUpload()
Do the upload.
bool $mUploadSuccessful
Subclasses can use this to determine whether a file was uploaded.
LocalFile $mLocalFile
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
getUploadForm( $message='', $sessionKey='', $hideIgnoreWarning=false)
Get an UploadForm instance with title and text properly set.
doesWrites()
Indicates whether this special page may perform database writes.
string $uploadFormTextTop
Raw html injection point for hooks not using HTMLForm.
bool $mForReUpload
The user followed an "overwrite this file" link.
$mIgnoreWarning
User input variables from the root section.
showUploadError( $message)
Show the upload form with error message, but do not stash the file.
static rotationEnabled()
Should we rotate images in the preview on Special:Upload.
__construct(RepoGroup $repoGroup=null, UserOptionsLookup $userOptionsLookup=null, NamespaceInfo $nsInfo=null, WatchlistManager $watchlistManager=null)
UploadBase and subclasses are the backend of MediaWiki's file uploads.
Sub class of HTMLForm that provides the form section of SpecialUpload.
Implements uploading from previously stored file.
Show an error when the user tries to do something whilst blocked.
internal since 1.36
Definition User.php:71
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
Interface for configuration instances.
Definition Config.php:30
$source
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition router.php:42