41use Psr\Log\LoggerInterface;
42use UnexpectedValueException;
59 private LoggerInterface $log;
67 parent::__construct(
'Upload',
'upload' );
70 $this->jobQueueGroup = $services->getJobQueueGroup();
71 $repoGroup ??= $services->getRepoGroup();
72 $this->localRepo = $repoGroup->getLocalRepo();
73 $this->userOptionsLookup = $userOptionsLookup ?? $services->getUserOptionsLookup();
74 $this->nsInfo = $nsInfo ?? $services->getNamespaceInfo();
75 $this->watchlistManager = $watchlistManager ?? $services->getWatchlistManager();
76 $this->log = LoggerFactory::getInstance(
'SpecialUpload' );
79 private function addMessageBoxStyling() {
80 $this->
getOutput()->addModuleStyles(
'mediawiki.codex.messagebox.styles' );
140 public $mUploadSuccessful =
false;
151 $this->mRequest = $request = $this->
getRequest();
152 $this->mSourceType = $request->getVal(
'wpSourceType',
'file' );
153 $this->mUpload = UploadBase::createFromRequest( $request );
154 $this->mUploadClicked = $request->wasPosted()
155 && ( $request->getCheck(
'wpUpload' )
156 || $request->getCheck(
'wpUploadIgnoreWarning' ) );
159 $this->mDesiredDestName = $request->getText(
'wpDestFile' );
160 if ( !$this->mDesiredDestName && $request->getFileName(
'wpUploadFile' ) !== null ) {
161 $this->mDesiredDestName = $request->getFileName(
'wpUploadFile' );
163 $this->mLicense = $request->getText(
'wpLicense' );
165 $this->mDestWarningAck = $request->getText(
'wpDestFileWarningAck' );
166 $this->mIgnoreWarning = $request->getCheck(
'wpIgnoreWarning' )
167 || $request->getCheck(
'wpUploadIgnoreWarning' );
168 $this->mWatchthis = $request->getBool(
'wpWatchthis' ) && $this->
getUser()->isRegistered();
169 $this->mCopyrightStatus = $request->getText(
'wpUploadCopyStatus' );
170 $this->mCopyrightSource = $request->getText(
'wpUploadSource' );
172 $this->mForReUpload = $request->getBool(
'wpForReUpload' );
174 $commentDefault =
'';
175 $commentMsg = $this->
msg(
'upload-default-description' )->inContentLanguage();
176 if ( !$this->mForReUpload && !$commentMsg->isDisabled() ) {
177 $commentDefault = $commentMsg->plain();
179 $this->mComment = $request->getText(
'wpUploadDescription', $commentDefault );
181 $this->mCancelUpload = $request->getCheck(
'wpCancelUpload' )
182 || $request->getCheck(
'wpReUpload' );
185 $token = $request->getVal(
'wpEditToken' );
186 $this->mTokenOk = $this->
getUser()->matchEditToken( $token );
191 $this->mCacheKey = \MediaWiki\Upload\UploadFromUrl::getCacheKeyFromRequest( $request );
193 $this->mCacheKey =
'';
196 $this->uploadFormTextTop =
'';
197 $this->uploadFormTextAfterSummary =
'';
206 return $this->mSourceType ===
'url'
220 return UploadBase::isEnabled() && parent::userCanExecute( $user );
232 # Check uploading enabled
233 if ( !UploadBase::isEnabled() ) {
234 throw new ErrorPageError(
'uploaddisabled',
'uploaddisabledtext' );
241 $permissionRequired = UploadBase::isAllowed( $user );
242 if ( $permissionRequired !==
true ) {
247 if ( $user->isBlockedFromUpload() ) {
252 $this->getLanguage(),
253 $this->getRequest()->getIP()
257 # Check whether we actually want to allow changing stuff
262 }
catch ( UploadStashException $e ) {
267 # Unsave the temporary file in case this was a cancelled upload
269 # Something went wrong, so unsaveUploadedFile showed a warning
273 # If we have a cache key, show the upload status.
274 if ( $this->mTokenOk && $this->mCacheKey !==
'' ) {
275 if ( $this->mUpload && $this->mUploadClicked && !$this->mCancelUpload ) {
276 # If the user clicked the upload button, we need to process the upload
279 # Show the upload status
283 # Process upload or show a form
284 $this->mTokenOk && !$this->mCancelUpload &&
285 ( $this->mUpload && $this->mUploadClicked )
289 # Backwards compatibility hook
290 if ( !$this->
getHookRunner()->onUploadForm_initial( $this ) ) {
291 wfDebug(
"Hook 'UploadForm:initial' broke output of the upload form" );
299 if ( $this->mUpload ) {
300 $this->mUpload->cleanupTempFile();
311 $progress = UploadBase::getSessionStatus( $user, $this->mCacheKey );
313 $progress = [
'status' => Status::newFatal(
'invalid-cache-key' ) ];
315 $this->log->debug(
'Upload status: stage {stage}, result {result}', $progress );
317 $status = $progress[
'status'] ?? Status::newFatal(
'invalid-cache-key' );
318 $stage = $progress[
'stage'] ??
'unknown';
319 $result = $progress[
'result'] ??
'unknown';
327 $this->mUploadSuccessful =
true;
331 $title = Title::makeTitleSafe(
NS_FILE, $this->mRequest->getText(
'wpDestFile' ) );
333 $this->log->debug(
'Purging page', [
'title' => $title->getText() ] );
337 $this->
getOutput()->redirect( $this->mRequest->getText(
'wpDestUrl' ) );
340 $this->
showUploadWarning( UploadBase::unserializeWarnings( $progress[
'warnings'] ) );
343 $details = $status->getValue();
345 if ( is_array( $details ) && isset( $details[
'verification'] ) ) {
349 $status->getWikiText(
false,
false, $this->getLanguage() ) )
354 $this->showUploadProgress(
355 [
'active' =>
true,
'msg' =>
'upload-progress-processing' ]
361 $status->getWikiText(
false,
false, $this->getLanguage() ) )
368 $this->showUploadProgress( [
'active' =>
false,
'msg' =>
'upload-progress-queued' ] );
375 $this->showUploadProgress( [
'active' =>
true,
'msg' =>
'upload-progress-downloading' ] );
380 $status->getWikiText(
false,
false, $this->getLanguage() ) )
386 $status->getWikiText(
false,
false, $this->getLanguage() ) )
393 if ( $status->isOK() ) {
394 $status = Status::newFatal(
'upload-progress-unknown' );
396 $statusmsg = $this->
getOutput()->parseAsInterface(
397 $status->getWikiText(
false,
false, $this->getLanguage() )
399 $message =
'<h2>' . $this->
msg(
'uploaderror' )->escaped() .
'</h2>' . Html::errorBox( $statusmsg );
400 $this->addMessageBoxStyling();
416 private function showUploadProgress( $options ) {
419 $message = $this->
msg( $options[
'msg'] )->escaped();
420 $destUrl = $this->mRequest->getText(
'wpDestUrl',
'' );
421 if ( !$destUrl && $this->mUpload ) {
422 if ( !$this->mLocalFile ) {
423 $this->mLocalFile = $this->mUpload->getLocalFile();
427 if ( $this->mLocalFile ===
null ) {
430 $destUrl = $this->mLocalFile->getTitle()->getFullURL();
436 $destName = $this->mRequest->getText(
'wpDestFile' );
440 $sourceURL = $this->mRequest->getText(
'wpUploadFileURL' );
442 $form =
new HTMLForm( [
445 'default' => $this->mCacheKey,
449 'default' => $this->mSourceType,
453 'default' => $destUrl,
457 'default' => $destName,
461 'default' => $sourceURL,
464 $form->setSubmitText( $this->
msg(
'upload-refresh' )->escaped() );
467 $preHtml =
"<div id='upload-progress-message'>$message</div>";
468 $form->addPreHtml( $preHtml );
469 $form->setSubmitCallback(
470 static function ( $formData ) {
474 $form->prepareForm();
475 $this->
getOutput()->addHTML( $form->getHTML(
false ) );
499 protected function getUploadForm( $message =
'', $sessionKey =
'', $hideIgnoreWarning =
false ) {
504 'forreupload' => $this->mForReUpload,
505 'sessionkey' => $sessionKey,
506 'hideignorewarning' => $hideIgnoreWarning,
507 'destwarningack' => (
bool)$this->mDestWarningAck,
509 'description' => $this->mComment,
510 'texttop' => $this->uploadFormTextTop,
511 'textaftersummary' => $this->uploadFormTextAfterSummary,
512 'destfile' => $this->mDesiredDestName,
523 # Check the token, but only if necessary
525 !$this->mTokenOk && !$this->mCancelUpload &&
526 ( $this->mUpload && $this->mUploadClicked )
528 $form->addPreHtml( $this->
msg(
'session_fail_preview' )->parse() );
531 # Give a notice if the user is uploading a file that has been deleted or moved
532 # Note that this is independent from the message 'filewasdeleted'
533 $desiredTitleObj = Title::makeTitleSafe(
NS_FILE, $this->mDesiredDestName );
535 if ( $desiredTitleObj instanceof
Title && !$desiredTitleObj->
exists() ) {
536 LogEventsList::showLogExtract( $delNotice, [
'delete',
'move' ],
539 'conds' => [ $this->localRepo->getReplicaDB()->expr(
'log_action',
'!=',
'revision' ) ],
540 'showIfEmpty' =>
false,
541 'msgKey' => [
'upload-recreate-warning' ] ]
544 $form->addPreHtml( $delNotice );
547 $form->addPreHtml(
'<div id="uploadtext">' .
548 $this->
msg(
'uploadtext', [ $this->mDesiredDestName ] )->parseAsBlock() .
550 # Add upload error message
551 $form->addPreHtml( $message );
554 $uploadFooter = $this->
msg(
'uploadfooter' );
555 if ( !$uploadFooter->isDisabled() ) {
556 $form->addPostHtml(
'<div id="mw-upload-footer-message">'
557 . $uploadFooter->parseAsBlock() .
"</div>\n" );
575 $stashFile = $this->mUpload->getStashFile();
577 $stashStatus = $this->mUpload->tryStashFile( $this->
getUser() );
578 if ( $stashStatus->isGood() ) {
579 $stashFile = $stashStatus->getValue();
583 $sessionKey = $stashFile->getFileKey();
584 $uploadWarning =
'upload-tryagain';
587 $uploadWarning =
'upload-tryagain-nostash';
589 $message =
'<h2>' . $this->
msg(
'uploaderror' )->escaped() .
'</h2>' .
590 Html::errorBox( $message );
592 $this->addMessageBoxStyling();
594 $form->setSubmitText( $this->
msg( $uploadWarning )->escaped() );
607 # If there are no warnings, or warnings we can ignore, return early.
608 # mDestWarningAck is set when some javascript has shown the warning
609 # to the user. mForReUpload is set when the user clicks the "upload a
611 if ( !$warnings || ( count( $warnings ) == 1
612 && isset( $warnings[
'exists'] )
613 && ( $this->mDestWarningAck || $this->mForReUpload ) )
618 if ( $this->mUpload ) {
619 $stashFile = $this->mUpload->getStashFile();
621 $stashStatus = $this->mUpload->tryStashFile( $this->
getUser() );
622 if ( $stashStatus->isGood() ) {
623 $stashFile = $stashStatus->getValue();
627 $sessionKey = $stashFile->getFileKey();
628 $uploadWarning =
'uploadwarning-text';
631 $uploadWarning =
'uploadwarning-text-nostash';
635 $uploadWarning =
'uploadwarning-text-nostash';
639 $this->
getOutput()->addModuleStyles(
'mediawiki.special' );
642 $warningHtml =
'<h2>' . $this->
msg(
'uploadwarning' )->escaped() .
"</h2>\n"
643 .
'<div class="mw-destfile-warning"><ul>';
644 foreach ( $warnings as $warning => $args ) {
645 if ( $warning ==
'badfilename' ) {
648 if ( $warning ==
'exists' ) {
650 } elseif ( $warning ==
'no-change' ) {
652 $filename = $file->getTitle()->getPrefixedText();
653 $msg =
"\t<li>" . $this->
msg(
'fileexists-no-change', $filename )->parse() .
"</li>\n";
654 } elseif ( $warning ==
'duplicate-version' ) {
656 $count = count( $args );
657 $filename = $file->getTitle()->getPrefixedText();
658 $message = $this->
msg(
'fileexists-duplicate-version' )
659 ->params( $filename )
660 ->numParams( $count );
661 $msg =
"\t<li>" . $message->parse() .
"</li>\n";
662 } elseif ( $warning ==
'was-deleted' ) {
663 # If the file existed before and was deleted, warn the user of this
665 $llink = $linkRenderer->makeKnownLink(
667 $this->
msg(
'deletionlog' )->text(),
674 $msg =
"\t<li>" . $this->
msg(
'filewasdeleted' )->rawParams( $llink )->parse() .
"</li>\n";
675 } elseif ( $warning ==
'duplicate' ) {
677 } elseif ( $warning ==
'duplicate-archive' ) {
678 if ( $args ===
'' ) {
679 $msg =
"\t<li>" . $this->
msg(
'file-deleted-duplicate-notitle' )->parse()
682 $msg =
"\t<li>" . $this->
msg(
'file-deleted-duplicate',
687 if ( $args ===
true ) {
689 } elseif ( !is_array( $args ) ) {
692 $msg =
"\t<li>" . $this->
msg( $warning, $args )->parse() .
"</li>\n";
694 $warningHtml .= $msg;
696 $warningHtml .=
"</ul></div>\n";
697 $warningHtml .= $this->
msg( $uploadWarning )->parseAsBlock();
699 $form = $this->
getUploadForm( $warningHtml, $sessionKey,
true );
700 $form->setSubmitTextMsg(
'upload-tryagain' );
702 'name' =>
'wpUploadIgnoreWarning',
703 'value' => $this->
msg(
'ignorewarning' )->text()
706 'name' =>
'wpCancelUpload',
707 'value' => $this->
msg(
'reuploaddesc' )->text()
712 # Indicate that we showed a form
722 $message =
'<h2>' . $this->
msg(
'uploadwarning' )->escaped() .
'</h2>' .
723 Html::errorBox( $message );
725 $this->addMessageBoxStyling();
735 if ( !$fetchFileStatus->isOK() ) {
737 $fetchFileStatus->getWikiText(
false,
false, $this->getLanguage() )
742 if ( !$this->
getHookRunner()->onUploadForm_BeforeProcessing( $this ) ) {
743 wfDebug(
"Hook 'UploadForm:BeforeProcessing' broke processing the file." );
757 $details = $this->mUpload->verifyUpload();
758 if ( $details[
'status'] != UploadBase::OK ) {
766 $status = $this->mUpload->authorizeUpload( $user );
767 if ( !$status->isGood() ) {
770 Status::wrap( $status )->getWikiText(
false,
false, $this->
getLanguage() )
777 $this->mLocalFile = $this->mUpload->getLocalFile();
780 if ( !$this->mIgnoreWarning ) {
781 $warnings = $this->mUpload->checkWarnings( $user );
797 if ( !$this->mForReUpload ) {
798 $pageText = self::getInitialPageText( $this->mComment, $this->mLicense,
799 $this->mCopyrightStatus, $this->mCopyrightSource,
800 $this->getConfig() );
804 $changeTags = $this->getRequest()->getVal(
'wpChangeTags' );
805 if ( $changeTags ===
null || $changeTags ===
'' ) {
808 $changeTags = array_filter( array_map(
'trim', explode(
',', $changeTags ) ) );
811 $changeTagsStatus = ChangeTags::canAddTagsAccompanyingChange(
812 $changeTags, $this->getUser() );
813 if ( !$changeTagsStatus->isOK() ) {
814 $this->showUploadError( $this->getOutput()->parseAsInterface(
815 $changeTagsStatus->getWikiText(
false,
false, $this->getLanguage() )
821 return [ $pageText, $changeTags ];
830 $status = $this->mUpload->fetchFile();
831 if ( !$this->performUploadChecks( $status ) ) {
834 $user = $this->getUser();
835 $pageAndTags = $this->getPageTextAndTags();
836 if ( $pageAndTags ===
null ) {
839 [ $pageText, $changeTags ] = $pageAndTags;
841 $status = $this->mUpload->performUpload(
849 if ( !$status->isGood() ) {
850 $this->showRecoverableUploadError(
851 $this->getOutput()->parseAsInterface(
852 $status->getWikiText(
false,
false, $this->getLanguage() )
860 $this->mUploadSuccessful =
true;
861 $this->getHookRunner()->onSpecialUploadComplete( $this );
862 $this->getOutput()->redirect( $this->mLocalFile->getTitle()->getFullURL() );
870 if ( !$this->mUpload instanceof \
MediaWiki\Upload\UploadFromUrl ) {
871 $this->showUploadError( $this->msg(
'uploaderror' )->escaped() );
876 $status = $this->mUpload->canFetchFile();
877 if ( !$this->performUploadChecks( $status ) ) {
878 $this->log->debug(
'Upload failed verification: {error}', [
'error' => $status ] );
882 $pageAndTags = $this->getPageTextAndTags();
883 if ( $pageAndTags ===
null ) {
886 [ $pageText, $changeTags ] = $pageAndTags;
891 'filename' => $this->mUpload->getDesiredDestName(),
892 'url' => $this->mUpload->getUrl(),
893 'comment' => $this->mComment,
894 'tags' => $changeTags,
896 'watch' => $this->mWatchthis,
897 'watchlistexpiry' =>
null,
898 'session' => $this->getContext()->exportSession(),
899 'reupload' => $this->mForReUpload,
900 'ignorewarnings' => $this->mIgnoreWarning,
904 $cacheKey =
$job->getCacheKey();
905 UploadBase::setSessionStatus( $this->getUser(), $cacheKey, [
906 'status' => Status::newGood(),
910 $this->log->info(
"Submitting UploadFromUrlJob for {filename}",
911 [
'filename' => $this->mUpload->getDesiredDestName() ]
914 $this->jobQueueGroup->push(
$job );
916 $this->showUploadStatus( $this->getUser() );
931 if ( $config ===
null ) {
932 wfDebug( __METHOD__ .
' called without a Config instance passed to it' );
942 foreach ( [
'license-header',
'filedesc',
'filestatus',
'filesource' ] as $msgName ) {
943 if ( in_array( $msgName, $forceUIMsgAsContentMsg ) ) {
944 $msg[$msgName] =
"{{int:$msgName}}";
946 $msg[$msgName] =
wfMessage( $msgName )->inContentLanguage()->text();
951 if ( $license !==
'' ) {
952 $licenseText =
'== ' . $msg[
'license-header'] .
" ==\n{{" . $license .
"}}\n";
955 $pageText = $comment .
"\n";
956 $headerText =
'== ' . $msg[
'filedesc'] .
' ==';
957 if ( $comment !==
'' && !str_contains( $comment, $headerText ) ) {
959 $pageText = $headerText .
"\n" . $pageText;
963 $pageText .=
'== ' . $msg[
'filestatus'] .
" ==\n" . $copyStatus .
"\n";
964 $pageText .= $licenseText;
965 $pageText .=
'== ' . $msg[
'filesource'] .
" ==\n" .
$source;
967 $pageText .= $licenseText;
972 ->onUploadForm_getInitialPageText( $pageText, $msg, $config );
990 $user = $this->getUser();
991 if ( $this->userOptionsLookup->getBoolOption( $user,
'watchdefault' ) ) {
996 $desiredTitleObj = Title::makeTitleSafe(
NS_FILE, $this->mDesiredDestName );
997 if ( $desiredTitleObj instanceof
Title &&
998 $this->watchlistManager->isWatched( $user, $desiredTitleObj ) ) {
1003 $local = $this->localRepo->newFile( $this->mDesiredDestName );
1004 if ( $local && $local->exists() ) {
1010 return $this->userOptionsLookup->getBoolOption( $user,
'watchcreations' ) ||
1011 $this->userOptionsLookup->getBoolOption( $user,
'watchuploads' );
1021 switch ( $details[
'status'] ) {
1023 case UploadBase::MIN_LENGTH_PARTNAME:
1024 $this->showRecoverableUploadError( $this->msg(
'minlength1' )->escaped() );
1026 case UploadBase::ILLEGAL_FILENAME:
1027 $this->showRecoverableUploadError( $this->msg(
'illegalfilename',
1028 $details[
'filtered'] )->parse() );
1030 case UploadBase::FILENAME_TOO_LONG:
1031 $this->showRecoverableUploadError( $this->msg(
'filename-toolong' )->escaped() );
1033 case UploadBase::FILETYPE_MISSING:
1034 $this->showRecoverableUploadError( $this->msg(
'filetype-missing' )->parse() );
1036 case UploadBase::WINDOWS_NONASCII_FILENAME:
1037 $this->showRecoverableUploadError( $this->msg(
'windows-nonascii-filename' )->parse() );
1041 case UploadBase::EMPTY_FILE:
1042 $this->showUploadError( $this->msg(
'emptyfile' )->escaped() );
1044 case UploadBase::FILE_TOO_LARGE:
1045 $this->showUploadError( $this->msg(
'largefileserver' )->escaped() );
1047 case UploadBase::FILETYPE_BADTYPE:
1048 $msg = $this->msg(
'filetype-banned-type' );
1049 if ( isset( $details[
'blacklistedExt'] ) ) {
1050 $msg->params( $this->getLanguage()->commaList( $details[
'blacklistedExt'] ) );
1052 $msg->params( $details[
'finalExt'] );
1056 $msg->params( $this->getLanguage()->commaList( $extensions ),
1057 count( $extensions ) );
1062 if ( isset( $details[
'blacklistedExt'] ) ) {
1063 $msg->params( count( $details[
'blacklistedExt'] ) );
1068 $this->showUploadError( $msg->parse() );
1070 case UploadBase::VERIFICATION_ERROR:
1071 unset( $details[
'status'] );
1072 $code = array_shift( $details[
'details'] );
1073 $this->showUploadError( $this->msg( $code, $details[
'details'] )->parse() );
1076 throw new UnexpectedValueException( __METHOD__ .
": Unknown value `{$details['status']}`" );
1089 $success = $this->mUpload->unsaveUploadedFile();
1091 $this->getOutput()->showErrorPage(
1094 [ $this->mUpload->getTempPath() ]
1117 $file = $exists[
'file'];
1118 if ( !$file instanceof
File ) {
1124 $filename = $file->getTitle()->getPrefixedText();
1127 if ( $exists[
'warning'] ==
'exists' ) {
1129 $warnMsg =
wfMessage(
'fileexists', $filename );
1130 } elseif ( $exists[
'warning'] ==
'page-exists' ) {
1132 $warnMsg =
wfMessage(
'filepageexists', $filename );
1133 } elseif ( $exists[
'warning'] ==
'exists-normalized' ) {
1134 $warnMsg =
wfMessage(
'fileexists-extension', $filename,
1135 $exists[
'normalizedFile']->getTitle()->getPrefixedText() );
1136 } elseif ( $exists[
'warning'] ==
'thumb' ) {
1138 $warnMsg =
wfMessage(
'fileexists-thumbnail-yes',
1139 $exists[
'thumbFile']->getTitle()->getPrefixedText(), $filename );
1140 } elseif ( $exists[
'warning'] ==
'thumb-name' ) {
1142 $name = $file->getName();
1143 $badPart = substr( $name, 0, strpos( $name,
'-' ) + 1 );
1144 $warnMsg =
wfMessage(
'file-thumbnail-no', $badPart );
1145 } elseif ( $exists[
'warning'] ==
'bad-prefix' ) {
1146 $warnMsg =
wfMessage(
'filename-bad-prefix', $exists[
'prefix'] );
1149 return $warnMsg ? $warnMsg->page( $file->getTitle() )->parse() :
'';
1162 $gallery = ImageGalleryBase::factory(
false, $this->getContext() );
1163 $gallery->setShowBytes(
false );
1164 $gallery->setShowDimensions(
false );
1165 foreach ( $dupes as $file ) {
1166 $gallery->add( $file->getTitle() );
1170 $this->msg(
'file-exists-duplicate' )->numParams( count( $dupes ) )->parse() .
1171 $gallery->toHTML() .
"</li>\n";
1189 return $bitmapHandler->autoRotateEnabled();
1197class_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.
getMessageObject()
Return a Message object for this exception.Message
if(count( $args)< 1) $job