52use Psr\Log\LoggerInterface;
53use UnexpectedValueException;
73 private LoggerInterface $log;
81 parent::__construct(
'Upload',
'upload' );
84 $this->jobQueueGroup = $services->getJobQueueGroup();
85 $repoGroup ??= $services->getRepoGroup();
86 $this->localRepo = $repoGroup->getLocalRepo();
87 $this->userOptionsLookup = $userOptionsLookup ?? $services->getUserOptionsLookup();
88 $this->nsInfo = $nsInfo ?? $services->getNamespaceInfo();
89 $this->watchlistManager = $watchlistManager ?? $services->getWatchlistManager();
94 $this->log = LoggerFactory::getInstance(
'SpecialUpload' );
97 private function addMessageBoxStyling() {
98 $this->
getOutput()->addModuleStyles(
'mediawiki.codex.messagebox.styles' );
157 public $mUploadSuccessful =
false;
168 $this->mRequest = $request = $this->
getRequest();
169 $this->mSourceType = $request->getVal(
'wpSourceType',
'file' );
170 $this->mUpload = UploadBase::createFromRequest( $request );
171 $this->mUploadClicked = $request->wasPosted()
172 && ( $request->getCheck(
'wpUpload' )
173 || $request->getCheck(
'wpUploadIgnoreWarning' ) );
176 $this->mDesiredDestName = $request->getText(
'wpDestFile' );
177 if ( !$this->mDesiredDestName && $request->getFileName(
'wpUploadFile' ) !== null ) {
178 $this->mDesiredDestName = $request->getFileName(
'wpUploadFile' );
180 $this->mLicense = $request->getText(
'wpLicense' );
182 $this->mDestWarningAck = $request->getText(
'wpDestFileWarningAck' );
183 $this->mIgnoreWarning = $request->getCheck(
'wpIgnoreWarning' )
184 || $request->getCheck(
'wpUploadIgnoreWarning' );
185 $this->mWatchthis = $request->getBool(
'wpWatchthis' ) && $this->
getUser()->isRegistered();
186 $this->mCopyrightStatus = $request->getText(
'wpUploadCopyStatus' );
187 $this->mCopyrightSource = $request->getText(
'wpUploadSource' );
189 $this->mForReUpload = $request->getBool(
'wpForReUpload' );
191 $commentDefault =
'';
192 $commentMsg = $this->
msg(
'upload-default-description' )->inContentLanguage();
193 if ( !$this->mForReUpload && !$commentMsg->isDisabled() ) {
194 $commentDefault = $commentMsg->plain();
196 $this->mComment = $request->getText(
'wpUploadDescription', $commentDefault );
198 $this->mCancelUpload = $request->getCheck(
'wpCancelUpload' )
199 || $request->getCheck(
'wpReUpload' );
202 $token = $request->getVal(
'wpEditToken' );
203 $this->mTokenOk = $this->
getUser()->matchEditToken( $token );
208 $this->mCacheKey = \UploadFromUrl::getCacheKeyFromRequest( $request );
210 $this->mCacheKey =
'';
213 $this->uploadFormTextTop =
'';
214 $this->uploadFormTextAfterSummary =
'';
223 return ( $this->mSourceType ===
'url' && $this->allowAsync );
235 return UploadBase::isEnabled() && parent::userCanExecute( $user );
247 # Check uploading enabled
248 if ( !UploadBase::isEnabled() ) {
249 throw new ErrorPageError(
'uploaddisabled',
'uploaddisabledtext' );
256 $permissionRequired = UploadBase::isAllowed( $user );
257 if ( $permissionRequired !==
true ) {
262 if ( $user->isBlockedFromUpload() ) {
267 $this->getLanguage(),
268 $this->getRequest()->getIP()
272 # Check whether we actually want to allow changing stuff
277 # Unsave the temporary file in case this was a cancelled upload
279 # Something went wrong, so unsaveUploadedFile showed a warning
283 # If we have a cache key, show the upload status.
284 if ( $this->mTokenOk && $this->mCacheKey !==
'' ) {
285 if ( $this->mUpload && $this->mUploadClicked && !$this->mCancelUpload ) {
286 # If the user clicked the upload button, we need to process the upload
289 # Show the upload status
293 # Process upload or show a form
294 $this->mTokenOk && !$this->mCancelUpload &&
295 ( $this->mUpload && $this->mUploadClicked )
299 # Backwards compatibility hook
300 if ( !$this->
getHookRunner()->onUploadForm_initial( $this ) ) {
301 wfDebug(
"Hook 'UploadForm:initial' broke output of the upload form" );
309 if ( $this->mUpload ) {
310 $this->mUpload->cleanupTempFile();
321 $progress = UploadBase::getSessionStatus( $user, $this->mCacheKey );
323 $progress = [
'status' => Status::newFatal(
'invalid-cache-key' ) ];
325 $this->log->debug(
'Upload status: stage {stage}, result {result}', $progress );
327 $status = $progress[
'status'] ?? Status::newFatal(
'invalid-cache-key' );
328 $stage = $progress[
'stage'] ??
'unknown';
329 $result = $progress[
'result'] ??
'unknown';
337 $this->mUploadSuccessful =
true;
341 $title = Title::makeTitleSafe(
NS_FILE, $this->mRequest->getText(
'wpDestFile' ) );
343 $this->log->debug(
'Purging page', [
'title' => $title->getText() ] );
347 $this->
getOutput()->redirect( $this->mRequest->getText(
'wpDestUrl' ) );
350 $this->
showUploadWarning( UploadBase::unserializeWarnings( $progress[
'warnings'] ) );
353 $details = $status->getValue();
355 if ( is_array( $details ) && isset( $details[
'verification'] ) ) {
359 $status->getWikiText(
false,
false, $this->getLanguage() ) )
364 $this->showUploadProgress(
365 [
'active' =>
true,
'msg' =>
'upload-progress-processing' ]
371 $status->getWikiText(
false,
false, $this->getLanguage() ) )
378 $this->showUploadProgress( [
'active' =>
false,
'msg' =>
'upload-progress-queued' ] );
385 $this->showUploadProgress( [
'active' =>
true,
'msg' =>
'upload-progress-downloading' ] );
390 $status->getWikiText(
false,
false, $this->getLanguage() ) )
396 $status->getWikiText(
false,
false, $this->getLanguage() ) )
403 if ( $status->isOK() ) {
404 $status = Status::newFatal(
'upload-progress-unknown' );
406 $statusmsg = $this->
getOutput()->parseAsInterface(
407 $status->getWikiText(
false,
false, $this->getLanguage() )
409 $message =
'<h2>' . $this->
msg(
'uploaderror' )->escaped() .
'</h2>' . HTML::errorBox( $statusmsg );
410 $this->addMessageBoxStyling();
426 private function showUploadProgress( $options ) {
429 $message = $this->
msg( $options[
'msg'] )->escaped();
430 $destUrl = $this->mRequest->getText(
'wpDestUrl',
'' );
431 if ( !$destUrl && $this->mUpload ) {
432 if ( !$this->mLocalFile ) {
433 $this->mLocalFile = $this->mUpload->getLocalFile();
437 if ( $this->mLocalFile ===
null ) {
440 $destUrl = $this->mLocalFile->getTitle()->getFullURL();
446 $destName = $this->mRequest->getText(
'wpDestFile' );
450 $sourceURL = $this->mRequest->getText(
'wpUploadFileURL' );
452 $form =
new HTMLForm( [
455 'default' => $this->mCacheKey,
459 'default' => $this->mSourceType,
463 'default' => $destUrl,
467 'default' => $destName,
471 'default' => $sourceURL,
474 $form->setSubmitText( $this->
msg(
'upload-refresh' )->escaped() );
477 $preHtml =
"<div id='upload-progress-message'>$message</div>";
478 $form->addPreHtml( $preHtml );
479 $form->setSubmitCallback(
480 static function ( $formData ) {
484 $form->prepareForm();
485 $this->
getOutput()->addHTML( $form->getHTML(
false ) );
509 protected function getUploadForm( $message =
'', $sessionKey =
'', $hideIgnoreWarning =
false ) {
514 'forreupload' => $this->mForReUpload,
515 'sessionkey' => $sessionKey,
516 'hideignorewarning' => $hideIgnoreWarning,
517 'destwarningack' => (
bool)$this->mDestWarningAck,
519 'description' => $this->mComment,
520 'texttop' => $this->uploadFormTextTop,
521 'textaftersummary' => $this->uploadFormTextAfterSummary,
522 'destfile' => $this->mDesiredDestName,
533 # Check the token, but only if necessary
535 !$this->mTokenOk && !$this->mCancelUpload &&
536 ( $this->mUpload && $this->mUploadClicked )
538 $form->addPreHtml( $this->
msg(
'session_fail_preview' )->parse() );
541 # Give a notice if the user is uploading a file that has been deleted or moved
542 # Note that this is independent from the message 'filewasdeleted'
543 $desiredTitleObj = Title::makeTitleSafe(
NS_FILE, $this->mDesiredDestName );
545 if ( $desiredTitleObj instanceof
Title && !$desiredTitleObj->
exists() ) {
546 LogEventsList::showLogExtract( $delNotice, [
'delete',
'move' ],
549 'conds' => [ $this->localRepo->getReplicaDB()->expr(
'log_action',
'!=',
'revision' ) ],
550 'showIfEmpty' =>
false,
551 'msgKey' => [
'upload-recreate-warning' ] ]
554 $form->addPreHtml( $delNotice );
557 $form->addPreHtml(
'<div id="uploadtext">' .
558 $this->
msg(
'uploadtext', [ $this->mDesiredDestName ] )->parseAsBlock() .
560 # Add upload error message
561 $form->addPreHtml( $message );
564 $uploadFooter = $this->
msg(
'uploadfooter' );
565 if ( !$uploadFooter->isDisabled() ) {
566 $form->addPostHtml(
'<div id="mw-upload-footer-message">'
567 . $uploadFooter->parseAsBlock() .
"</div>\n" );
585 $stashStatus = $this->mUpload->tryStashFile( $this->
getUser() );
586 if ( $stashStatus->isGood() ) {
587 $sessionKey = $stashStatus->getValue()->getFileKey();
588 $uploadWarning =
'upload-tryagain';
591 $uploadWarning =
'upload-tryagain-nostash';
593 $message =
'<h2>' . $this->
msg(
'uploaderror' )->escaped() .
'</h2>' .
594 Html::errorBox( $message );
596 $this->addMessageBoxStyling();
598 $form->setSubmitText( $this->
msg( $uploadWarning )->escaped() );
611 # If there are no warnings, or warnings we can ignore, return early.
612 # mDestWarningAck is set when some javascript has shown the warning
613 # to the user. mForReUpload is set when the user clicks the "upload a
615 if ( !$warnings || ( count( $warnings ) == 1
616 && isset( $warnings[
'exists'] )
617 && ( $this->mDestWarningAck || $this->mForReUpload ) )
622 if ( $this->mUpload ) {
623 $stashStatus = $this->mUpload->tryStashFile( $this->
getUser() );
624 if ( $stashStatus->isGood() ) {
625 $sessionKey = $stashStatus->getValue()->getFileKey();
626 $uploadWarning =
'uploadwarning-text';
629 $uploadWarning =
'uploadwarning-text-nostash';
633 $uploadWarning =
'uploadwarning-text-nostash';
637 $this->
getOutput()->addModuleStyles(
'mediawiki.special' );
640 $warningHtml =
'<h2>' . $this->
msg(
'uploadwarning' )->escaped() .
"</h2>\n"
641 .
'<div class="mw-destfile-warning"><ul>';
642 foreach ( $warnings as $warning => $args ) {
643 if ( $warning ==
'badfilename' ) {
644 $this->mDesiredDestName = Title::makeTitle(
NS_FILE, $args )->getText();
646 if ( $warning ==
'exists' ) {
648 } elseif ( $warning ==
'no-change' ) {
650 $filename = $file->getTitle()->getPrefixedText();
651 $msg =
"\t<li>" . $this->
msg(
'fileexists-no-change', $filename )->parse() .
"</li>\n";
652 } elseif ( $warning ==
'duplicate-version' ) {
654 $count = count( $args );
655 $filename = $file->getTitle()->getPrefixedText();
656 $message = $this->
msg(
'fileexists-duplicate-version' )
657 ->params( $filename )
658 ->numParams( $count );
659 $msg =
"\t<li>" . $message->parse() .
"</li>\n";
660 } elseif ( $warning ==
'was-deleted' ) {
661 # If the file existed before and was deleted, warn the user of this
663 $llink = $linkRenderer->makeKnownLink(
665 $this->
msg(
'deletionlog' )->text(),
669 'page' => Title::makeTitle(
NS_FILE, $args )->getPrefixedText(),
672 $msg =
"\t<li>" . $this->
msg(
'filewasdeleted' )->rawParams( $llink )->parse() .
"</li>\n";
673 } elseif ( $warning ==
'duplicate' ) {
675 } elseif ( $warning ==
'duplicate-archive' ) {
676 if ( $args ===
'' ) {
677 $msg =
"\t<li>" . $this->
msg(
'file-deleted-duplicate-notitle' )->parse()
680 $msg =
"\t<li>" . $this->
msg(
'file-deleted-duplicate',
681 Title::makeTitle(
NS_FILE, $args )->getPrefixedText() )->parse()
685 if ( $args ===
true ) {
687 } elseif ( !is_array( $args ) ) {
690 $msg =
"\t<li>" . $this->
msg( $warning, $args )->parse() .
"</li>\n";
692 $warningHtml .= $msg;
694 $warningHtml .=
"</ul></div>\n";
695 $warningHtml .= $this->
msg( $uploadWarning )->parseAsBlock();
697 $form = $this->
getUploadForm( $warningHtml, $sessionKey,
true );
698 $form->setSubmitTextMsg(
'upload-tryagain' );
700 'name' =>
'wpUploadIgnoreWarning',
701 'value' => $this->
msg(
'ignorewarning' )->text()
704 'name' =>
'wpCancelUpload',
705 'value' => $this->
msg(
'reuploaddesc' )->text()
710 # Indicate that we showed a form
720 $message =
'<h2>' . $this->
msg(
'uploadwarning' )->escaped() .
'</h2>' .
721 Html::errorBox( $message );
723 $this->addMessageBoxStyling();
733 if ( !$fetchFileStatus->isOK() ) {
735 $fetchFileStatus->getWikiText(
false,
false, $this->getLanguage() )
740 if ( !$this->
getHookRunner()->onUploadForm_BeforeProcessing( $this ) ) {
741 wfDebug(
"Hook 'UploadForm:BeforeProcessing' broke processing the file." );
755 $details = $this->mUpload->verifyUpload();
756 if ( $details[
'status'] != UploadBase::OK ) {
764 $status = $this->mUpload->authorizeUpload( $user );
765 if ( !$status->isGood() ) {
768 Status::wrap( $status )->getWikiText(
false,
false, $this->
getLanguage() )
775 $this->mLocalFile = $this->mUpload->getLocalFile();
778 if ( !$this->mIgnoreWarning ) {
779 $warnings = $this->mUpload->checkWarnings( $user );
795 if ( !$this->mForReUpload ) {
796 $pageText = self::getInitialPageText( $this->mComment, $this->mLicense,
797 $this->mCopyrightStatus, $this->mCopyrightSource,
798 $this->getConfig() );
802 $changeTags = $this->getRequest()->getVal(
'wpChangeTags' );
803 if ( $changeTags ===
null || $changeTags ===
'' ) {
806 $changeTags = array_filter( array_map(
'trim', explode(
',', $changeTags ) ) );
809 $changeTagsStatus = ChangeTags::canAddTagsAccompanyingChange(
810 $changeTags, $this->getUser() );
811 if ( !$changeTagsStatus->isOK() ) {
812 $this->showUploadError( $this->getOutput()->parseAsInterface(
813 $changeTagsStatus->getWikiText(
false,
false, $this->getLanguage() )
819 return [ $pageText, $changeTags ];
828 $status = $this->mUpload->fetchFile();
829 if ( !$this->performUploadChecks( $status ) ) {
832 $user = $this->getUser();
833 $pageAndTags = $this->getPageTextAndTags();
834 if ( $pageAndTags ===
null ) {
837 [ $pageText, $changeTags ] = $pageAndTags;
839 $status = $this->mUpload->performUpload(
847 if ( !$status->isGood() ) {
848 $this->showRecoverableUploadError(
849 $this->getOutput()->parseAsInterface(
850 $status->getWikiText(
false,
false, $this->getLanguage() )
858 $this->mUploadSuccessful =
true;
859 $this->getHookRunner()->onSpecialUploadComplete( $this );
860 $this->getOutput()->redirect( $this->mLocalFile->getTitle()->getFullURL() );
869 $this->showUploadError( $this->msg(
'uploaderror' )->escaped() );
874 $status = $this->mUpload->canFetchFile();
875 if ( !$this->performUploadChecks( $status ) ) {
876 $this->log->debug(
'Upload failed verification: {error}', [
'error' => $status ] );
880 $pageAndTags = $this->getPageTextAndTags();
881 if ( $pageAndTags ===
null ) {
884 [ $pageText, $changeTags ] = $pageAndTags;
889 'filename' => $this->mUpload->getDesiredDestName(),
890 'url' => $this->mUpload->getUrl(),
891 'comment' => $this->mComment,
892 'tags' => $changeTags,
894 'watch' => $this->mWatchthis,
895 'watchlistexpiry' =>
null,
896 'session' => $this->getContext()->exportSession(),
897 'reupload' => $this->mForReUpload,
898 'ignorewarnings' => $this->mIgnoreWarning,
902 $cacheKey =
$job->getCacheKey();
903 UploadBase::setSessionStatus( $this->getUser(), $cacheKey, [
904 'status' => Status::newGood(),
908 $this->log->info(
"Submitting UploadFromUrlJob for {filename}",
909 [
'filename' => $this->mUpload->getDesiredDestName() ]
912 $this->jobQueueGroup->push(
$job );
914 $this->showUploadStatus( $this->getUser() );
929 if ( $config ===
null ) {
930 wfDebug( __METHOD__ .
' called without a Config instance passed to it' );
940 foreach ( [
'license-header',
'filedesc',
'filestatus',
'filesource' ] as $msgName ) {
941 if ( in_array( $msgName, $forceUIMsgAsContentMsg ) ) {
942 $msg[$msgName] =
"{{int:$msgName}}";
944 $msg[$msgName] =
wfMessage( $msgName )->inContentLanguage()->text();
949 if ( $license !==
'' ) {
950 $licenseText =
'== ' . $msg[
'license-header'] .
" ==\n{{" . $license .
"}}\n";
953 $pageText = $comment .
"\n";
954 $headerText =
'== ' . $msg[
'filedesc'] .
' ==';
955 if ( $comment !==
'' && !str_contains( $comment, $headerText ) ) {
957 $pageText = $headerText .
"\n" . $pageText;
961 $pageText .=
'== ' . $msg[
'filestatus'] .
" ==\n" . $copyStatus .
"\n";
962 $pageText .= $licenseText;
963 $pageText .=
'== ' . $msg[
'filesource'] .
" ==\n" .
$source;
965 $pageText .= $licenseText;
970 ->onUploadForm_getInitialPageText( $pageText, $msg, $config );
988 $user = $this->getUser();
989 if ( $this->userOptionsLookup->getBoolOption( $user,
'watchdefault' ) ) {
994 $desiredTitleObj = Title::makeTitleSafe(
NS_FILE, $this->mDesiredDestName );
995 if ( $desiredTitleObj instanceof
Title &&
996 $this->watchlistManager->isWatched( $user, $desiredTitleObj ) ) {
1001 $local = $this->localRepo->newFile( $this->mDesiredDestName );
1002 if ( $local && $local->exists() ) {
1008 return $this->userOptionsLookup->getBoolOption( $user,
'watchcreations' ) ||
1009 $this->userOptionsLookup->getBoolOption( $user,
'watchuploads' );
1019 switch ( $details[
'status'] ) {
1021 case UploadBase::MIN_LENGTH_PARTNAME:
1022 $this->showRecoverableUploadError( $this->msg(
'minlength1' )->escaped() );
1024 case UploadBase::ILLEGAL_FILENAME:
1025 $this->showRecoverableUploadError( $this->msg(
'illegalfilename',
1026 $details[
'filtered'] )->parse() );
1028 case UploadBase::FILENAME_TOO_LONG:
1029 $this->showRecoverableUploadError( $this->msg(
'filename-toolong' )->escaped() );
1031 case UploadBase::FILETYPE_MISSING:
1032 $this->showRecoverableUploadError( $this->msg(
'filetype-missing' )->parse() );
1034 case UploadBase::WINDOWS_NONASCII_FILENAME:
1035 $this->showRecoverableUploadError( $this->msg(
'windows-nonascii-filename' )->parse() );
1039 case UploadBase::EMPTY_FILE:
1040 $this->showUploadError( $this->msg(
'emptyfile' )->escaped() );
1042 case UploadBase::FILE_TOO_LARGE:
1043 $this->showUploadError( $this->msg(
'largefileserver' )->escaped() );
1045 case UploadBase::FILETYPE_BADTYPE:
1046 $msg = $this->msg(
'filetype-banned-type' );
1047 if ( isset( $details[
'blacklistedExt'] ) ) {
1048 $msg->params( $this->getLanguage()->commaList( $details[
'blacklistedExt'] ) );
1050 $msg->params( $details[
'finalExt'] );
1054 $msg->params( $this->getLanguage()->commaList( $extensions ),
1055 count( $extensions ) );
1060 if ( isset( $details[
'blacklistedExt'] ) ) {
1061 $msg->params( count( $details[
'blacklistedExt'] ) );
1066 $this->showUploadError( $msg->parse() );
1068 case UploadBase::VERIFICATION_ERROR:
1069 unset( $details[
'status'] );
1070 $code = array_shift( $details[
'details'] );
1071 $this->showUploadError( $this->msg( $code, $details[
'details'] )->parse() );
1074 throw new UnexpectedValueException( __METHOD__ .
": Unknown value `{$details['status']}`" );
1087 $success = $this->mUpload->unsaveUploadedFile();
1089 $this->getOutput()->showErrorPage(
1092 [ $this->mUpload->getTempPath() ]
1115 $file = $exists[
'file'];
1116 $filename = $file->getTitle()->getPrefixedText();
1119 if ( $exists[
'warning'] ==
'exists' ) {
1121 $warnMsg =
wfMessage(
'fileexists', $filename );
1122 } elseif ( $exists[
'warning'] ==
'page-exists' ) {
1124 $warnMsg =
wfMessage(
'filepageexists', $filename );
1125 } elseif ( $exists[
'warning'] ==
'exists-normalized' ) {
1126 $warnMsg =
wfMessage(
'fileexists-extension', $filename,
1127 $exists[
'normalizedFile']->
getTitle()->getPrefixedText() );
1128 } elseif ( $exists[
'warning'] ==
'thumb' ) {
1130 $warnMsg =
wfMessage(
'fileexists-thumbnail-yes',
1131 $exists[
'thumbFile']->
getTitle()->getPrefixedText(), $filename );
1132 } elseif ( $exists[
'warning'] ==
'thumb-name' ) {
1134 $name = $file->getName();
1135 $badPart = substr( $name, 0, strpos( $name,
'-' ) + 1 );
1136 $warnMsg =
wfMessage(
'file-thumbnail-no', $badPart );
1137 } elseif ( $exists[
'warning'] ==
'bad-prefix' ) {
1138 $warnMsg =
wfMessage(
'filename-bad-prefix', $exists[
'prefix'] );
1141 return $warnMsg ? $warnMsg->page( $file->getTitle() )->parse() :
'';
1154 $gallery = ImageGalleryBase::factory(
false, $this->getContext() );
1155 $gallery->setShowBytes(
false );
1156 $gallery->setShowDimensions(
false );
1157 foreach ( $dupes as $file ) {
1158 $gallery->add( $file->getTitle() );
1162 $this->msg(
'file-exists-duplicate' )->numParams( count( $dupes ) )->parse() .
1163 $gallery->toHTML() .
"</li>\n";
1180 return $bitmapHandler->autoRotateEnabled();
1188class_alias( SpecialUpload::class,
'SpecialUpload' );
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.
if(!defined('MW_SETUP_CALLBACK'))
Generic handler for bitmap images.
An error page which can definitely be safely rendered using the OutputPage.
A class containing constants representing the names of configuration variables.
const EnableAsyncUploads
Name constant for the EnableAsyncUploads setting, for use with Config::get()
const ForceUIMsgAsContentMsg
Name constant for the ForceUIMsgAsContentMsg setting, for use with Config::get()
const UseCopyrightUpload
Name constant for the UseCopyrightUpload setting, for use with Config::get()
const FileExtensions
Name constant for the FileExtensions setting, for use with Config::get()
const EnableAsyncUploadsByURL
Name constant for the EnableAsyncUploadsByURL setting, for use with Config::get()
Special handling for representing file pages.
Parent class for all special pages.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
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,...
getUser()
Shortcut to get the User executing this instance.
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
getPageTitle( $subpage=false)
Get a self-referential title object.
checkReadOnly()
If the wiki is currently in readonly mode, throws a ReadOnlyError.
getConfig()
Shortcut to get main config object.
getContext()
Gets the context this SpecialPage is executed in.
getRequest()
Get the WebRequest being used for this instance.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getOutput()
Get the OutputPage being used for this instance.
getContentLanguage()
Shortcut to get content language.
getLanguage()
Shortcut to get user's language.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages By default the message key is the canonical name of...
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
UploadBase and subclasses are the backend of MediaWiki's file uploads.
Implements uploading from previously stored file.
Implements uploading from a HTTP resource.
if(count( $args)< 1) $job