MediaWiki REL1_37
SpecialUpload.php
Go to the documentation of this file.
1<?php
28
36
38 private $localRepo;
39
42
44 private $nsInfo;
45
48
55 public function __construct(
56 RepoGroup $repoGroup = null,
58 NamespaceInfo $nsInfo = null,
60 ) {
61 parent::__construct( 'Upload', 'upload' );
62 // This class is extended and therefor fallback to global state - T265300
63 $services = MediaWikiServices::getInstance();
64 $repoGroup = $repoGroup ?? $services->getRepoGroup();
65 $this->localRepo = $repoGroup->getLocalRepo();
66 $this->userOptionsLookup = $userOptionsLookup ?? $services->getUserOptionsLookup();
67 $this->nsInfo = $nsInfo ?? $services->getNamespaceInfo();
68 $this->watchlistManager = $watchlistManager ?? $services->getWatchlistManager();
69 }
70
71 public function doesWrites() {
72 return true;
73 }
74
78 public $mRequest;
80
82 public $mUpload;
83
87
92 public $mComment;
93 public $mLicense;
94
101
105
108
111 public $mTokenOk;
112
114 public $mUploadSuccessful = false;
115
120
124 protected function loadRequest() {
125 $this->mRequest = $request = $this->getRequest();
126 $this->mSourceType = $request->getVal( 'wpSourceType', 'file' );
127 $this->mUpload = UploadBase::createFromRequest( $request );
128 $this->mUploadClicked = $request->wasPosted()
129 && ( $request->getCheck( 'wpUpload' )
130 || $request->getCheck( 'wpUploadIgnoreWarning' ) );
131
132 // Guess the desired name from the filename if not provided
133 $this->mDesiredDestName = $request->getText( 'wpDestFile' );
134 if ( !$this->mDesiredDestName && $request->getFileName( 'wpUploadFile' ) !== null ) {
135 $this->mDesiredDestName = $request->getFileName( 'wpUploadFile' );
136 }
137 $this->mLicense = $request->getText( 'wpLicense' );
138
139 $this->mDestWarningAck = $request->getText( 'wpDestFileWarningAck' );
140 $this->mIgnoreWarning = $request->getCheck( 'wpIgnoreWarning' )
141 || $request->getCheck( 'wpUploadIgnoreWarning' );
142 $this->mWatchthis = $request->getBool( 'wpWatchthis' ) && $this->getUser()->isRegistered();
143 $this->mCopyrightStatus = $request->getText( 'wpUploadCopyStatus' );
144 $this->mCopyrightSource = $request->getText( 'wpUploadSource' );
145
146 $this->mForReUpload = $request->getBool( 'wpForReUpload' ); // updating a file
147
148 $commentDefault = '';
149 $commentMsg = $this->msg( 'upload-default-description' )->inContentLanguage();
150 if ( !$this->mForReUpload && !$commentMsg->isDisabled() ) {
151 $commentDefault = $commentMsg->plain();
152 }
153 $this->mComment = $request->getText( 'wpUploadDescription', $commentDefault );
154
155 $this->mCancelUpload = $request->getCheck( 'wpCancelUpload' )
156 || $request->getCheck( 'wpReUpload' ); // b/w compat
157
158 // If it was posted check for the token (no remote POST'ing with user credentials)
159 $token = $request->getVal( 'wpEditToken' );
160 $this->mTokenOk = $this->getUser()->matchEditToken( $token );
161
162 $this->uploadFormTextTop = '';
163 $this->uploadFormTextAfterSummary = '';
164 }
165
174 public function userCanExecute( User $user ) {
175 return UploadBase::isEnabled() && parent::userCanExecute( $user );
176 }
177
188 public function execute( $par ) {
190
191 $this->setHeaders();
192 $this->outputHeader();
193
194 # Check uploading enabled
195 if ( !UploadBase::isEnabled() ) {
196 throw new ErrorPageError( 'uploaddisabled', 'uploaddisabledtext' );
197 }
198
199 $this->addHelpLink( 'Help:Managing files' );
200
201 # Check permissions
202 $user = $this->getUser();
203 $permissionRequired = UploadBase::isAllowed( $user );
204 if ( $permissionRequired !== true ) {
205 throw new PermissionsError( $permissionRequired );
206 }
207
208 # Check blocks
209 if ( $user->isBlockedFromUpload() ) {
210 throw new UserBlockedError(
211 $user->getBlock(),
212 $user,
213 $this->getLanguage(),
214 $this->getRequest()->getIP()
215 );
216 }
217
218 // Global blocks
219 if ( $user->isBlockedGlobally() ) {
220 throw new UserBlockedError(
221 $user->getGlobalBlock(),
222 $user,
223 $this->getLanguage(),
224 $this->getRequest()->getIP()
225 );
226 }
227
228 # Check whether we actually want to allow changing stuff
229 $this->checkReadOnly();
230
231 $this->loadRequest();
232
233 # Unsave the temporary file in case this was a cancelled upload
234 if ( $this->mCancelUpload && !$this->unsaveUploadedFile() ) {
235 # Something went wrong, so unsaveUploadedFile showed a warning
236 return;
237 }
238
239 # Process upload or show a form
240 if (
241 $this->mTokenOk && !$this->mCancelUpload &&
242 ( $this->mUpload && $this->mUploadClicked )
243 ) {
244 $this->processUpload();
245 } else {
246 # Backwards compatibility hook
247 if ( !$this->getHookRunner()->onUploadForm_initial( $this ) ) {
248 wfDebug( "Hook 'UploadForm:initial' broke output of the upload form" );
249
250 return;
251 }
252 $this->showUploadForm( $this->getUploadForm() );
253 }
254
255 # Cleanup
256 if ( $this->mUpload ) {
257 $this->mUpload->cleanupTempFile();
258 }
259 }
260
266 protected function showUploadForm( $form ) {
267 # Add links if file was previously deleted
268 if ( $this->mDesiredDestName ) {
269 $this->showViewDeletedLinks();
270 }
271
272 if ( $form instanceof HTMLForm ) {
273 $form->show();
274 } else {
275 $this->getOutput()->addHTML( $form );
276 }
277 }
278
287 protected function getUploadForm( $message = '', $sessionKey = '', $hideIgnoreWarning = false ) {
288 # Initialize form
289 $context = new DerivativeContext( $this->getContext() );
290 $context->setTitle( $this->getPageTitle() ); // Remove subpage
291 $form = new UploadForm(
292 [
293 'watch' => $this->getWatchCheck(),
294 'forreupload' => $this->mForReUpload,
295 'sessionkey' => $sessionKey,
296 'hideignorewarning' => $hideIgnoreWarning,
297 'destwarningack' => (bool)$this->mDestWarningAck,
298
299 'description' => $this->mComment,
300 'texttop' => $this->uploadFormTextTop,
301 'textaftersummary' => $this->uploadFormTextAfterSummary,
302 'destfile' => $this->mDesiredDestName,
303 ],
304 $context,
305 $this->getLinkRenderer(),
306 $this->localRepo,
307 $this->getContentLanguage(),
308 $this->nsInfo
309 );
310
311 # Check the token, but only if necessary
312 if (
313 !$this->mTokenOk && !$this->mCancelUpload &&
314 ( $this->mUpload && $this->mUploadClicked )
315 ) {
316 $form->addPreText( $this->msg( 'session_fail_preview' )->parse() );
317 }
318
319 # Give a notice if the user is uploading a file that has been deleted or moved
320 # Note that this is independent from the message 'filewasdeleted'
321 $desiredTitleObj = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
322 $delNotice = ''; // empty by default
323 if ( $desiredTitleObj instanceof Title && !$desiredTitleObj->exists() ) {
324 LogEventsList::showLogExtract( $delNotice, [ 'delete', 'move' ],
325 $desiredTitleObj,
326 '', [ 'lim' => 10,
327 'conds' => [ 'log_action != ' . $this->localRepo->getReplicaDB()->addQuotes( 'revision' ) ],
328 'showIfEmpty' => false,
329 'msgKey' => [ 'upload-recreate-warning' ] ]
330 );
331 }
332 $form->addPreText( $delNotice );
333
334 # Add text to form
335 $form->addPreText( '<div id="uploadtext">' .
336 $this->msg( 'uploadtext', [ $this->mDesiredDestName ] )->parseAsBlock() .
337 '</div>' );
338 # Add upload error message
339 $form->addPreText( $message );
340
341 # Add footer to form
342 $uploadFooter = $this->msg( 'uploadfooter' );
343 if ( !$uploadFooter->isDisabled() ) {
344 $form->addPostText( '<div id="mw-upload-footer-message">'
345 . $uploadFooter->parseAsBlock() . "</div>\n" );
346 }
347
348 return $form;
349 }
350
354 protected function showViewDeletedLinks() {
355 $title = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
356 $user = $this->getUser();
357 // Show a subtitle link to deleted revisions (to sysops et al only)
358 if ( $title instanceof Title ) {
359 $count = $title->getDeletedEditsCount();
360 if ( $count > 0 && $this->getAuthority()->isAllowed( 'deletedhistory' ) ) {
361 $restorelink = $this->getLinkRenderer()->makeKnownLink(
362 SpecialPage::getTitleFor( 'Undelete', $title->getPrefixedText() ),
363 $this->msg( 'restorelink' )->numParams( $count )->text()
364 );
365 $link = $this->msg(
366 $this->getAuthority()->isAllowed( 'delete' ) ? 'thisisdeleted' : 'viewdeleted'
367 )->rawParams( $restorelink )->parseAsBlock();
368 $this->getOutput()->addHTML(
369 Html::rawElement(
370 'div',
371 [ 'id' => 'contentSub2' ],
372 $link
373 )
374 );
375 }
376 }
377 }
378
390 protected function showRecoverableUploadError( $message ) {
391 $stashStatus = $this->mUpload->tryStashFile( $this->getUser() );
392 if ( $stashStatus->isGood() ) {
393 $sessionKey = $stashStatus->getValue()->getFileKey();
394 $uploadWarning = 'upload-tryagain';
395 } else {
396 $sessionKey = null;
397 $uploadWarning = 'upload-tryagain-nostash';
398 }
399 $message = '<h2>' . $this->msg( 'uploaderror' )->escaped() . '</h2>' .
400 Html::errorBox( $message );
401
402 $form = $this->getUploadForm( $message, $sessionKey );
403 $form->setSubmitText( $this->msg( $uploadWarning )->escaped() );
404 $this->showUploadForm( $form );
405 }
406
415 protected function showUploadWarning( $warnings ) {
416 # If there are no warnings, or warnings we can ignore, return early.
417 # mDestWarningAck is set when some javascript has shown the warning
418 # to the user. mForReUpload is set when the user clicks the "upload a
419 # new version" link.
420 if ( !$warnings || ( count( $warnings ) == 1
421 && isset( $warnings['exists'] )
422 && ( $this->mDestWarningAck || $this->mForReUpload ) )
423 ) {
424 return false;
425 }
426
427 $stashStatus = $this->mUpload->tryStashFile( $this->getUser() );
428 if ( $stashStatus->isGood() ) {
429 $sessionKey = $stashStatus->getValue()->getFileKey();
430 $uploadWarning = 'uploadwarning-text';
431 } else {
432 $sessionKey = null;
433 $uploadWarning = 'uploadwarning-text-nostash';
434 }
435
436 // Add styles for the warning, reused from the live preview
437 $this->getOutput()->addModuleStyles( 'mediawiki.special' );
438
440 $warningHtml = '<h2>' . $this->msg( 'uploadwarning' )->escaped() . "</h2>\n"
441 . '<div class="mw-destfile-warning"><ul>';
442 foreach ( $warnings as $warning => $args ) {
443 if ( $warning == 'badfilename' ) {
444 $this->mDesiredDestName = Title::makeTitle( NS_FILE, $args )->getText();
445 }
446 if ( $warning == 'exists' ) {
447 $msg = "\t<li>" . self::getExistsWarning( $args ) . "</li>\n";
448 } elseif ( $warning == 'no-change' ) {
449 $file = $args;
450 $filename = $file->getTitle()->getPrefixedText();
451 $msg = "\t<li>" . $this->msg( 'fileexists-no-change', $filename )->parse() . "</li>\n";
452 } elseif ( $warning == 'duplicate-version' ) {
453 $file = $args[0];
454 $count = count( $args );
455 $filename = $file->getTitle()->getPrefixedText();
456 $message = $this->msg( 'fileexists-duplicate-version' )
457 ->params( $filename )
458 ->numParams( $count );
459 $msg = "\t<li>" . $message->parse() . "</li>\n";
460 } elseif ( $warning == 'was-deleted' ) {
461 # If the file existed before and was deleted, warn the user of this
462 $ltitle = SpecialPage::getTitleFor( 'Log' );
464 $ltitle,
465 $this->msg( 'deletionlog' )->text(),
466 [],
467 [
468 'type' => 'delete',
469 'page' => Title::makeTitle( NS_FILE, $args )->getPrefixedText(),
470 ]
471 );
472 $msg = "\t<li>" . $this->msg( 'filewasdeleted' )->rawParams( $llink )->parse() . "</li>\n";
473 } elseif ( $warning == 'duplicate' ) {
474 $msg = $this->getDupeWarning( $args );
475 } elseif ( $warning == 'duplicate-archive' ) {
476 if ( $args === '' ) {
477 $msg = "\t<li>" . $this->msg( 'file-deleted-duplicate-notitle' )->parse()
478 . "</li>\n";
479 } else {
480 $msg = "\t<li>" . $this->msg( 'file-deleted-duplicate',
481 Title::makeTitle( NS_FILE, $args )->getPrefixedText() )->parse()
482 . "</li>\n";
483 }
484 } else {
485 if ( $args === true ) {
486 $args = [];
487 } elseif ( !is_array( $args ) ) {
488 $args = [ $args ];
489 }
490 $msg = "\t<li>" . $this->msg( $warning, $args )->parse() . "</li>\n";
491 }
492 $warningHtml .= $msg;
493 }
494 $warningHtml .= "</ul></div>\n";
495 $warningHtml .= $this->msg( $uploadWarning )->parseAsBlock();
496
497 $form = $this->getUploadForm( $warningHtml, $sessionKey, /* $hideIgnoreWarning */ true );
498 $form->setSubmitTextMsg( 'upload-tryagain' );
499 $form->addButton( [
500 'name' => 'wpUploadIgnoreWarning',
501 'value' => $this->msg( 'ignorewarning' )->text()
502 ] );
503 $form->addButton( [
504 'name' => 'wpCancelUpload',
505 'value' => $this->msg( 'reuploaddesc' )->text()
506 ] );
507
508 $this->showUploadForm( $form );
509
510 # Indicate that we showed a form
511 return true;
512 }
513
519 protected function showUploadError( $message ) {
520 $message = '<h2>' . $this->msg( 'uploadwarning' )->escaped() . '</h2>' .
521 Html::errorBox( $message );
522 $this->showUploadForm( $this->getUploadForm( $message ) );
523 }
524
529 protected function processUpload() {
530 // Fetch the file if required
531 $status = $this->mUpload->fetchFile();
532 if ( !$status->isOK() ) {
533 $this->showUploadError( $this->getOutput()->parseAsInterface(
534 $status->getWikiText( false, false, $this->getLanguage() )
535 ) );
536
537 return;
538 }
539 if ( !$this->getHookRunner()->onUploadForm_BeforeProcessing( $this ) ) {
540 wfDebug( "Hook 'UploadForm:BeforeProcessing' broke processing the file." );
541 // This code path is deprecated. If you want to break upload processing
542 // do so by hooking into the appropriate hooks in UploadBase::verifyUpload
543 // and UploadBase::verifyFile.
544 // If you use this hook to break uploading, the user will be returned
545 // an empty form with no error message whatsoever.
546 return;
547 }
548
549 // Upload verification
550 $details = $this->mUpload->verifyUpload();
551 if ( $details['status'] != UploadBase::OK ) {
552 $this->processVerificationError( $details );
553
554 return;
555 }
556
557 // Verify permissions for this title
558 $user = $this->getUser();
559 $permErrors = $this->mUpload->verifyTitlePermissions( $user );
560 if ( $permErrors !== true ) {
561 $code = array_shift( $permErrors[0] );
562 $this->showRecoverableUploadError( $this->msg( $code, $permErrors[0] )->parse() );
563
564 return;
565 }
566
567 $this->mLocalFile = $this->mUpload->getLocalFile();
568
569 // Check warnings if necessary
570 if ( !$this->mIgnoreWarning ) {
571 $warnings = $this->mUpload->checkWarnings( $user );
572 if ( $this->showUploadWarning( $warnings ) ) {
573 return;
574 }
575 }
576
577 // This is as late as we can throttle, after expected issues have been handled
578 if ( UploadBase::isThrottled( $user ) ) {
580 $this->msg( 'actionthrottledtext' )->escaped()
581 );
582 return;
583 }
584
585 // Get the page text if this is not a reupload
586 if ( !$this->mForReUpload ) {
587 $pageText = self::getInitialPageText( $this->mComment, $this->mLicense,
588 $this->mCopyrightStatus, $this->mCopyrightSource, $this->getConfig() );
589 } else {
590 $pageText = false;
591 }
592
593 $changeTags = $this->getRequest()->getVal( 'wpChangeTags' );
594 if ( $changeTags === null || $changeTags === '' ) {
595 $changeTags = [];
596 } else {
597 $changeTags = array_filter( array_map( 'trim', explode( ',', $changeTags ) ) );
598 }
599
600 if ( $changeTags ) {
602 $changeTags, $user );
603 if ( !$changeTagsStatus->isOK() ) {
604 $this->showUploadError( $this->getOutput()->parseAsInterface(
605 $changeTagsStatus->getWikiText( false, false, $this->getLanguage() )
606 ) );
607
608 return;
609 }
610 }
611
612 $status = $this->mUpload->performUpload(
613 $this->mComment,
614 $pageText,
615 $this->mWatchthis,
616 $user,
617 $changeTags
618 );
619
620 if ( !$status->isGood() ) {
622 $this->getOutput()->parseAsInterface(
623 $status->getWikiText( false, false, $this->getLanguage() )
624 )
625 );
626
627 return;
628 }
629
630 // Success, redirect to description page
631 $this->mUploadSuccessful = true;
632 $this->getHookRunner()->onSpecialUploadComplete( $this );
633 $this->getOutput()->redirect( $this->mLocalFile->getTitle()->getFullURL() );
634 }
635
645 public static function getInitialPageText( $comment = '', $license = '',
646 $copyStatus = '', $source = '', Config $config = null
647 ) {
648 if ( $config === null ) {
649 wfDebug( __METHOD__ . ' called without a Config instance passed to it' );
650 $config = MediaWikiServices::getInstance()->getMainConfig();
651 }
652
653 $msg = [];
654 $forceUIMsgAsContentMsg = (array)$config->get( 'ForceUIMsgAsContentMsg' );
655 /* These messages are transcluded into the actual text of the description page.
656 * Thus, forcing them as content messages makes the upload to produce an int: template
657 * instead of hardcoding it there in the uploader language.
658 */
659 foreach ( [ 'license-header', 'filedesc', 'filestatus', 'filesource' ] as $msgName ) {
660 if ( in_array( $msgName, $forceUIMsgAsContentMsg ) ) {
661 $msg[$msgName] = "{{int:$msgName}}";
662 } else {
663 $msg[$msgName] = wfMessage( $msgName )->inContentLanguage()->text();
664 }
665 }
666
667 $licenseText = '';
668 if ( $license !== '' ) {
669 $licenseText = '== ' . $msg['license-header'] . " ==\n{{" . $license . "}}\n";
670 }
671
672 $pageText = $comment . "\n";
673 $headerText = '== ' . $msg['filedesc'] . ' ==';
674 if ( $comment !== '' && strpos( $comment, $headerText ) === false ) {
675 // prepend header to page text unless it's already there (or there is no content)
676 $pageText = $headerText . "\n" . $pageText;
677 }
678
679 if ( $config->get( 'UseCopyrightUpload' ) ) {
680 $pageText .= '== ' . $msg['filestatus'] . " ==\n" . $copyStatus . "\n";
681 $pageText .= $licenseText;
682 $pageText .= '== ' . $msg['filesource'] . " ==\n" . $source;
683 } else {
684 $pageText .= $licenseText;
685 }
686
687 // allow extensions to modify the content
688 Hooks::runner()->onUploadForm_getInitialPageText( $pageText, $msg, $config );
689
690 return $pageText;
691 }
692
705 protected function getWatchCheck() {
706 $user = $this->getUser();
707 if ( $this->userOptionsLookup->getBoolOption( $user, 'watchdefault' ) ) {
708 // Watch all edits!
709 return true;
710 }
711
712 $desiredTitleObj = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
713 if ( $desiredTitleObj instanceof Title &&
714 $this->watchlistManager->isWatched( $user, $desiredTitleObj ) ) {
715 // Already watched, don't change that
716 return true;
717 }
718
719 $local = $this->localRepo->newFile( $this->mDesiredDestName );
720 if ( $local && $local->exists() ) {
721 // We're uploading a new version of an existing file.
722 // No creation, so don't watch it if we're not already.
723 return false;
724 } else {
725 // New page should get watched if that's our option.
726 return $this->userOptionsLookup->getBoolOption( $user, 'watchcreations' ) ||
727 $this->userOptionsLookup->getBoolOption( $user, 'watchuploads' );
728 }
729 }
730
737 protected function processVerificationError( $details ) {
738 switch ( $details['status'] ) {
740 case UploadBase::MIN_LENGTH_PARTNAME:
741 $this->showRecoverableUploadError( $this->msg( 'minlength1' )->escaped() );
742 break;
743 case UploadBase::ILLEGAL_FILENAME:
744 $this->showRecoverableUploadError( $this->msg( 'illegalfilename',
745 $details['filtered'] )->parse() );
746 break;
747 case UploadBase::FILENAME_TOO_LONG:
748 $this->showRecoverableUploadError( $this->msg( 'filename-toolong' )->escaped() );
749 break;
750 case UploadBase::FILETYPE_MISSING:
751 $this->showRecoverableUploadError( $this->msg( 'filetype-missing' )->parse() );
752 break;
753 case UploadBase::WINDOWS_NONASCII_FILENAME:
754 $this->showRecoverableUploadError( $this->msg( 'windows-nonascii-filename' )->parse() );
755 break;
756
758 case UploadBase::EMPTY_FILE:
759 $this->showUploadError( $this->msg( 'emptyfile' )->escaped() );
760 break;
761 case UploadBase::FILE_TOO_LARGE:
762 $this->showUploadError( $this->msg( 'largefileserver' )->escaped() );
763 break;
764 case UploadBase::FILETYPE_BADTYPE:
765 $msg = $this->msg( 'filetype-banned-type' );
766 if ( isset( $details['blacklistedExt'] ) ) {
767 $msg->params( $this->getLanguage()->commaList( $details['blacklistedExt'] ) );
768 } else {
769 $msg->params( $details['finalExt'] );
770 }
771 $extensions = array_unique( $this->getConfig()->get( 'FileExtensions' ) );
772 $msg->params( $this->getLanguage()->commaList( $extensions ),
773 count( $extensions ) );
774
775 // Add PLURAL support for the first parameter. This results
776 // in a bit unlogical parameter sequence, but does not break
777 // old translations
778 if ( isset( $details['blacklistedExt'] ) ) {
779 $msg->params( count( $details['blacklistedExt'] ) );
780 } else {
781 $msg->params( 1 );
782 }
783
784 $this->showUploadError( $msg->parse() );
785 break;
786 case UploadBase::VERIFICATION_ERROR:
787 unset( $details['status'] );
788 $code = array_shift( $details['details'] );
789 $this->showUploadError( $this->msg( $code, $details['details'] )->parse() );
790 break;
791 case UploadBase::HOOK_ABORTED:
792 if ( is_array( $details['error'] ) ) { # allow hooks to return error details in an array
793 $args = $details['error'];
794 $error = array_shift( $args );
795 } else {
796 $error = $details['error'];
797 $args = null;
798 }
799
800 $this->showUploadError( $this->msg( $error, $args )->parse() );
801 break;
802 default:
803 throw new MWException( __METHOD__ . ": Unknown value `{$details['status']}`" );
804 }
805 }
806
812 protected function unsaveUploadedFile() {
813 if ( !( $this->mUpload instanceof UploadFromStash ) ) {
814 return true;
815 }
816 $success = $this->mUpload->unsaveUploadedFile();
817 if ( !$success ) {
818 $this->getOutput()->showFatalError(
819 $this->msg( 'filedeleteerror' )
820 ->params( $this->mUpload->getTempPath() )
821 ->escaped()
822 );
823
824 return false;
825 } else {
826 return true;
827 }
828 }
829
839 public static function getExistsWarning( $exists ) {
840 if ( !$exists ) {
841 return '';
842 }
843
844 $file = $exists['file'];
845 $filename = $file->getTitle()->getPrefixedText();
846 $warnMsg = null;
847
848 if ( $exists['warning'] == 'exists' ) {
849 // Exact match
850 $warnMsg = wfMessage( 'fileexists', $filename );
851 } elseif ( $exists['warning'] == 'page-exists' ) {
852 // Page exists but file does not
853 $warnMsg = wfMessage( 'filepageexists', $filename );
854 } elseif ( $exists['warning'] == 'exists-normalized' ) {
855 $warnMsg = wfMessage( 'fileexists-extension', $filename,
856 $exists['normalizedFile']->getTitle()->getPrefixedText() );
857 } elseif ( $exists['warning'] == 'thumb' ) {
858 // Swapped argument order compared with other messages for backwards compatibility
859 $warnMsg = wfMessage( 'fileexists-thumbnail-yes',
860 $exists['thumbFile']->getTitle()->getPrefixedText(), $filename );
861 } elseif ( $exists['warning'] == 'thumb-name' ) {
862 // Image w/o '180px-' does not exists, but we do not like these filenames
863 $name = $file->getName();
864 $badPart = substr( $name, 0, strpos( $name, '-' ) + 1 );
865 $warnMsg = wfMessage( 'file-thumbnail-no', $badPart );
866 } elseif ( $exists['warning'] == 'bad-prefix' ) {
867 $warnMsg = wfMessage( 'filename-bad-prefix', $exists['prefix'] );
868 }
869
870 return $warnMsg ? $warnMsg->page( $file->getTitle() )->parse() : '';
871 }
872
878 public function getDupeWarning( $dupes ) {
879 if ( !$dupes ) {
880 return '';
881 }
882
883 $gallery = ImageGalleryBase::factory( false, $this->getContext() );
884 $gallery->setShowBytes( false );
885 $gallery->setShowDimensions( false );
886 foreach ( $dupes as $file ) {
887 $gallery->add( $file->getTitle() );
888 }
889
890 return '<li>' .
891 $this->msg( 'file-exists-duplicate' )->numParams( count( $dupes ) )->parse() .
892 $gallery->toHTML() . "</li>\n";
893 }
894
895 protected function getGroupName() {
896 return 'media';
897 }
898
907 public static function rotationEnabled() {
908 $bitmapHandler = new BitmapHandler();
909 return $bitmapHandler->autoRotateEnabled();
910 }
911}
getAuthority()
WatchlistManager $watchlistManager
UserOptionsLookup $userOptionsLookup
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)
Is it OK to allow the user to apply all the specified tags at the same time as they edit/make the cha...
An IContextSource implementation which will inherit context from another source but allow individual ...
An error page which can definitely be safely rendered using the OutputPage.
WebRequest clone which takes values from a provided array.
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition HTMLForm.php:143
Class to represent a local file in the wiki's own database.
Definition LocalFile.php:63
A repository that stores files in the local filesystem and registers them in the wiki's own database.
Definition LocalRepo.php:41
MediaWiki exception.
makeKnownLink( $target, $text=null, array $extraAttribs=[], array $query=[])
MediaWikiServices is the service locator for the application scope of MediaWiki.
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:33
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.
getUser()
Shortcut to get the User executing 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,...
LinkRenderer null $linkRenderer
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
showViewDeletedLinks()
Shows the "view X deleted revivions link"".
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.
LocalRepo $localRepo
string $uploadFormTextAfterSummary
Raw html injection point for hooks not using HTMLForm.
$mDestWarningAck
Hidden variables.
UserOptionsLookup $userOptionsLookup
getDupeWarning( $dupes)
Construct a warning and a gallery from an array of duplicate files.
showUploadForm( $form)
Show the main upload form.
WatchlistManager $watchlistManager
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.
NamespaceInfo $nsInfo
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)
Represents a title within MediaWiki.
Definition Title.php:48
exists( $flags=0)
Check if page exists.
Definition Title.php:3572
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.
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition User.php:69
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
if( $line===false) $args
Definition mcc.php:124
$source
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition router.php:42