23 use Liuggio\StatsdClient\Sender\SocketSender;
24 use MediaWiki\HookContainer\ProtectedHookAccessorTrait;
29 use Psr\Log\LoggerInterface;
30 use Wikimedia\AtEase\AtEase;
33 use Wikimedia\ScopedCallback;
39 use ProtectedHookAccessorTrait;
63 $this->config = $this->context->getConfig();
65 if ( $GLOBALS[
'wgCommandLineMode'] ) {
67 } elseif ( function_exists(
'fastcgi_finish_request' ) ) {
81 $request = $this->context->getRequest();
82 $curid = $request->getInt(
'curid' );
83 $title = $request->getText(
'title' );
84 $action = $request->getRawVal(
'action' );
91 if ( $ret !==
null ) {
94 if ( $ret->getNamespace() ===
NS_MEDIA ) {
100 $languageConverter = $services
101 ->getLanguageConverterFactory()
102 ->getLanguageConverter( $services->getContentLanguage() );
103 if ( $languageConverter->hasVariants() && !$ret->exists() ) {
104 $languageConverter->findVariantLink(
$title, $ret );
113 if ( $ret ===
null || !$ret->isSpecialPage() ) {
115 $oldid = $request->getInt(
'oldid' );
116 $oldid = $oldid ?: $request->getInt(
'diff' );
120 ->getRevisionLookup()
121 ->getRevisionById( $oldid );
124 $revRecord->getPageAsLinkTarget()
130 if ( $ret ===
null && $request->getCheck(
'search' ) ) {
139 && strval(
$title ) ===
''
140 && !$request->getCheck(
'curid' )
146 if ( $ret ===
null || ( $ret->getDBkey() ==
'' && !$ret->isExternal() ) ) {
161 if ( !$this->context->hasTitle() ) {
163 $this->context->setTitle( $this->
parseTitle() );
168 return $this->context->getTitle();
177 if ( $this->action === null ) {
178 $this->action = $this->context->getActionName();
199 $request = $this->context->getRequest();
200 $requestTitle =
$title = $this->context->getTitle();
201 $output = $this->context->getOutput();
202 $user = $this->context->getUser();
204 if ( $request->getRawVal(
'printable' ) ===
'yes' ) {
205 $output->setPrintable();
208 $this->getHookRunner()->onBeforeInitialize(
$title,
null, $output, $user, $request, $this );
212 ||
$title->isSpecial(
'Badtitle' )
226 $permissionStatus = PermissionStatus::newEmpty();
227 if ( !$this->context->getAuthority()->authorizeRead(
'read',
$title, $permissionStatus ) ) {
238 $this->context->setTitle( $badTitle );
245 if (
$title->isExternal() ) {
246 $rdfrom = $request->getVal(
'rdfrom' );
248 $url =
$title->getFullURL( [
'rdfrom' => $rdfrom ] );
250 $query = $request->getValues();
251 unset( $query[
'title'] );
252 $url =
$title->getFullURL( $query );
255 if ( !preg_match(
'/^' . preg_quote( $this->config->get( MainConfigNames::Server ),
'/' ) .
'/', $url )
259 $output->redirect( $url, 301 );
271 } elseif ( !$this->tryNormaliseRedirect(
$title ) ) {
273 $spFactory = MediaWikiServices::getInstance()->getSpecialPageFactory();
274 if (
$title->isSpecialPage() ) {
275 $specialPage = $spFactory->getPage(
$title->getDBkey() );
277 $specialPage->setContext( $this->context );
278 if ( $this->config->get( MainConfigNames::HideIdentifiableRedirects )
279 && $specialPage->personallyIdentifiableTarget()
281 [ , $subpage ] = $spFactory->resolveAlias(
$title->getDBkey() );
282 $target = $specialPage->getRedirect( $subpage );
284 if ( $target instanceof
Title ) {
285 if ( $target->isExternal() ) {
289 'force/' . $target->getPrefixedDBkey()
293 $query = $specialPage->getRedirectQuery( $subpage ) ?: [];
295 $request->setRequestURL( $this->context->getRequest()->getRequestURL() );
296 $this->context->setRequest( $request );
298 $this->context->getOutput()->lowerCdnMaxage( 0 );
299 $this->context->setTitle( $target );
302 $this->action =
null;
304 $output->addJsConfigVars( [
305 'wgInternalRedirectTargetUrl' => $target->getLinkURL( $query ),
307 $output->addModules(
'mediawiki.action.view.redirect' );
314 if (
$title->isSpecialPage() ) {
316 $spFactory->executePath(
$title, $this->context );
320 $article = $this->initializeArticle();
321 if ( is_object( $article ) ) {
322 $this->performAction( $article, $requestTitle );
323 } elseif ( is_string( $article ) ) {
324 $output->redirect( $article );
326 throw new MWException(
"Shouldn't happen: MediaWiki::initializeArticle()"
327 .
" returned neither an object nor a URL" );
330 $output->considerCacheSettingsFinal();
357 $request = $this->context->getRequest();
358 $output = $this->context->getOutput();
360 if ( $request->getRawVal(
'action',
'view' ) !=
'view'
361 || $request->wasPosted()
362 || ( $request->getCheck(
'title' )
363 &&
$title->getPrefixedDBkey() == $request->getText(
'title' ) )
364 || count( $request->getValueNames( [
'action',
'title' ] ) )
365 || !$this->getHookRunner()->onTestCanonicalRedirect( $request,
$title, $output )
370 if ( $this->config->get( MainConfigNames::MainPageIsDomainRoot ) && $request->getRequestURL() ===
'/' ) {
374 if (
$title->isSpecialPage() ) {
375 [ $name, $subpage ] = MediaWikiServices::getInstance()->getSpecialPageFactory()->
376 resolveAlias(
$title->getDBkey() );
383 if ( $targetUrl == $request->getFullRequestURL() ) {
384 $message =
"Redirect loop detected!\n\n" .
385 "This means the wiki got confused about what page was " .
386 "requested; this sometimes happens when moving a wiki " .
387 "to a new server or changing the server configuration.\n\n";
389 if ( $this->config->get( MainConfigNames::UsePathInfo ) ) {
390 $message .=
"The wiki is trying to interpret the page " .
391 "title from the URL path portion (PATH_INFO), which " .
392 "sometimes fails depending on the web server. Try " .
393 "setting \"\$wgUsePathInfo = false;\" in your " .
394 "LocalSettings.php, or check that \$wgArticlePath " .
397 $message .=
"Your web server was detected as possibly not " .
398 "supporting URL path components (PATH_INFO) correctly; " .
399 "check your LocalSettings.php for a customized " .
400 "\$wgArticlePath setting and/or toggle \$wgUsePathInfo " .
405 $output->setCdnMaxage( 1200 );
406 $output->redirect( $targetUrl,
'301' );
417 $title = $this->context->getTitle();
418 $services = MediaWikiServices::getInstance();
419 if ( $this->context->canUseWikiPage() ) {
422 $page = $this->context->getWikiPage();
426 $page = $services->getWikiPageFactory()->newFromTitle(
$title );
427 $this->context->setWikiPage( $page );
428 wfWarn(
"RequestContext::canUseWikiPage() returned false" );
435 if ( !$services->getContentHandlerFactory()
436 ->getContentHandler(
$title->getContentModel() )
437 ->supportsRedirects()
442 $request = $this->context->getRequest();
446 $action = $request->getRawVal(
'action',
'view' );
448 if ( ( $action ==
'view' || $action ==
'render' )
449 && !$request->getCheck(
'oldid' )
450 && !$request->getCheck(
'diff' )
451 && $request->getRawVal(
'redirect' ) !==
'no'
453 && !( is_object(
$file ) &&
$file->exists() && !
$file->getRedirected() )
456 $ignoreRedirect = $target =
false;
458 $this->getHookRunner()->onInitializeArticleMaybeRedirect(
$title, $request,
460 $ignoreRedirect, $target, $article );
461 $page = $article->getPage();
465 if ( !$ignoreRedirect && ( $target || $page->isRedirect() ) ) {
467 $target = $target ?: $page->followRedirect();
468 if ( is_string( $target ) && !$this->config->get( MainConfigNames::DisableHardRedirects ) ) {
472 if ( is_object( $target ) ) {
474 $rpage = $services->getWikiPageFactory()->newFromTitle( $target );
475 $rpage->loadPageData();
476 if ( $rpage->exists() || ( is_object(
$file ) && !
$file->isLocal() ) ) {
478 $rarticle->setRedirectedFrom(
$title );
480 $article = $rarticle;
481 $this->context->setTitle( $target );
482 $this->context->setWikiPage( $article->getPage() );
487 $this->context->setTitle( $article->getTitle() );
488 $this->context->setWikiPage( $article->getPage() );
502 $request = $this->context->getRequest();
503 $output = $this->context->getOutput();
504 $title = $this->context->getTitle();
505 $user = $this->context->getUser();
506 $services = MediaWikiServices::getInstance();
508 if ( !$this->getHookRunner()->onMediaWikiPerformAction(
509 $output, $article,
$title, $user, $request, $this )
514 $t = microtime(
true );
515 $actionName = $this->getAction();
516 $action = $services->getActionFactory()->getAction( $actionName, $article, $this->context );
518 if ( $action instanceof
Action ) {
520 if ( $action->needsReadRights() && !$user->isAllowed(
'read' ) ) {
525 $trxLimits = $this->config->get( MainConfigNames::TrxProfilerLimits );
527 if ( $request->wasPosted() && !$action->doesWrites() ) {
528 $trxProfiler->setExpectations( $trxLimits[
'POST-nonwrite'], __METHOD__ );
529 $request->markAsSafeRequest();
534 if ( $this->config->get( MainConfigNames::UseCdn ) ) {
535 $htmlCacheUpdater = $services->getHtmlCacheUpdater();
540 $htmlCacheUpdater->getUrls( $requestTitle )
543 $output->setCdnMaxage( $this->config->get( MainConfigNames::CdnMaxAge ) );
545 $output->setCdnMaxage( 3600 );
551 $runTime = microtime(
true ) -
$t;
552 $services->getStatsdDataFactory()->timing(
553 'action.' . strtr( $actionName,
'.',
'_' ) .
'.executeTiming',
560 $output->setStatusCode( 404 );
561 $output->showErrorPage(
'nosuchaction',
'nosuchactiontext' );
570 }
catch ( Exception $e ) {
571 $context = $this->context;
572 $action = $context->getRequest()->getRawVal(
'action',
'view' );
575 $context->hasTitle() &&
576 $context->getTitle()->canExist() &&
577 in_array( $action, [
'view',
'history' ],
true ) &&
582 if (
$cache->isCached() ) {
589 }
catch ( Throwable $e ) {
594 $this->doPostOutputShutdown();
601 $jobRunRate = $this->config->get( MainConfigNames::JobRunRate );
604 $this->
getTitle()->isSpecial(
'RunJobs' ) ||
607 MediaWikiServices::getInstance()->getReadOnlyMode()->isReadOnly() ||
609 $this->context->getRequest()->getMethod() ===
'HEAD' ||
610 $this->context->getRequest()->getHeader(
'If-Modified-Since' )
615 if ( $jobRunRate < 1 ) {
616 $max = mt_getrandmax();
617 if ( mt_rand( 0, $max ) > $max * $jobRunRate ) {
622 $n = intval( $jobRunRate );
627 $logger = LoggerFactory::getInstance(
'runJobs' );
628 if ( $this->config->get( MainConfigNames::RunJobsAsync ) ) {
630 $invokedWithSuccess = $this->triggerAsyncJobs( $n, $logger );
631 if ( !$invokedWithSuccess ) {
633 $logger->warning(
"Jobs switched to blocking; Special:RunJobs disabled" );
634 $this->triggerSyncJobs( $n );
637 $this->triggerSyncJobs( $n );
648 self::preOutputCommit( $this->context, $postCommitWork );
668 $services = MediaWikiServices::getInstance();
669 $lbFactory = $services->getDBLoadBalancerFactory();
672 ignore_user_abort(
true );
675 $lbFactory->commitPrimaryChanges(
678 [
'maxWriteDuration' => $config->get( MainConfigNames::MaxUserDBWriteDuration ) ]
680 wfDebug( __METHOD__ .
': primary transaction round committed' );
685 $config->get( MainConfigNames::ForceDeferredUpdatesPreSend )
686 ? DeferredUpdates::ALL
687 : DeferredUpdates::PRESEND
690 wfDebug( __METHOD__ .
': pre-send deferred updates completed' );
693 $request->getSession()->save();
694 wfDebug( __METHOD__ .
': session changes committed' );
700 $isCrossWikiRedirect = (
701 $output->getRedirect() &&
702 $lbFactory->hasOrMadeRecentPrimaryChanges( INF ) &&
703 self::getUrlDomainDistance( $output->getRedirect() ) ===
'remote'
710 $lbFactory->shutdown(
711 $lbFactory::SHUTDOWN_NORMAL,
718 $allowHeaders = !( $output->isDisabled() || headers_sent() );
720 if ( $cpIndex > 0 ) {
721 if ( $allowHeaders ) {
722 $expires = $now + ChronologyProtector::POSITION_COOKIE_TTL;
723 $options = [
'prefix' =>
'' ];
724 $value = $lbFactory::makeCookieValueFromCPIndex( $cpIndex, $now, $cpClientId );
725 $request->response()->setCookie(
'cpPosIndex', $value, $expires, $options );
728 if ( $isCrossWikiRedirect ) {
729 if ( $output->getRedirect() ) {
730 $safeUrl = $lbFactory->appendShutdownCPIndexAsQuery(
731 $output->getRedirect(),
734 $output->redirect( $safeUrl );
737 new LogicException(
"No redirect; cannot append cpPosIndex parameter." ),
738 MWExceptionHandler::CAUGHT_BY_ENTRYPOINT
744 if ( $allowHeaders ) {
748 if ( $request->wasPosted() && $lbFactory->hasOrMadeRecentPrimaryChanges() ) {
749 $expires = $now + max(
750 ChronologyProtector::POSITION_COOKIE_TTL,
751 $config->get( MainConfigNames::DataCenterUpdateStickTTL )
753 $options = [
'prefix' =>
'' ];
754 $request->response()->setCookie(
'UseDC',
'master', $expires, $options );
755 $request->response()->setCookie(
'UseCDNCache',
'false', $expires, $options );
760 if ( $lbFactory->laggedReplicaUsed() ) {
761 $maxAge = $config->get( MainConfigNames::CdnMaxageLagged );
762 $output->lowerCdnMaxage( $maxAge );
763 $request->response()->header(
"X-Database-Lagged: true" );
765 "Lagged DB used; CDN cache TTL limited to $maxAge seconds" );
769 if ( $services->getMessageCache()->isDisabled() ) {
770 $maxAge = $config->get( MainConfigNames::CdnMaxageSubstitute );
771 $output->lowerCdnMaxage( $maxAge );
772 $request->response()->header(
"X-Response-Substitute: true" );
775 if ( !$output->couldBePublicCached() || $output->haveCacheVaryCookies() ) {
787 $services->getBlockManager()
788 ->trackBlockWithCookie( $user, $request->response() );
802 if ( $clusterWiki !==
false ) {
820 $timing = $this->context->getTiming();
821 $timing->mark(
'requestShutdown' );
824 if ( $this->postSendStrategy === self::DEFER_FASTCGI_FINISH_REQUEST ) {
826 fastcgi_finish_request();
827 } elseif ( $this->postSendStrategy === self::DEFER_SET_LENGTH_AND_FLUSH ) {
829 if ( ob_get_level() ) {
842 ob_start(
static function () {
846 $this->restInPeace();
847 }
catch ( Throwable $e ) {
850 MWExceptionHandler::CAUGHT_BY_ENTRYPOINT
853 $length = ob_get_length();
855 trigger_error( __METHOD__ .
": suppressed $length byte(s)", E_USER_NOTICE );
866 $output = $this->context->getOutput();
867 $request = $this->context->getRequest();
875 $trxLimits = $this->config->get( MainConfigNames::TrxProfilerLimits );
877 $trxProfiler->setLogger( LoggerFactory::getInstance(
'DBPerformance' ) );
878 if ( $request->hasSafeMethod() ) {
879 $trxProfiler->setExpectations( $trxLimits[
'GET'], __METHOD__ );
881 $trxProfiler->setExpectations( $trxLimits[
'POST'], __METHOD__ );
884 if ( $this->maybeDoHttpsRedirect() ) {
892 $action = $this->getAction();
895 if (
$cache->isCacheGood( ) ) {
897 $timestamp =
$cache->cacheTimestamp();
898 if ( !$output->checkLastModified( $timestamp ) ) {
899 $cache->loadFromFileCache( $this->context );
903 $this->context->getWikiPage()->doViewUpdates( $this->context->getAuthority() );
913 $this->performRequest();
917 $output->considerCacheSettingsFinal();
925 $outputWork =
static function () use ( $output, &$buffer ) {
926 if ( $buffer ===
null ) {
927 $buffer = $output->output(
true );
936 $this->doPreOutputCommit( $outputWork );
938 $this->schedulePostSendJobs();
940 $this->outputResponsePayload( $outputWork() );
950 $request = $this->context->getRequest();
953 if ( $request->getProtocol() !==
'http' ) {
957 $force = $this->config->get( MainConfigNames::ForceHTTPS );
963 throw new RuntimeException(
'$wgForceHTTPS is true but the server is not HTTPS' );
974 return $request->getSession()->shouldForceHTTPS() ||
976 $request->getCookie(
'forceHTTPS',
'' ) ||
979 $this->context->getUser()->isRegistered()
980 && $this->context->getUser()->requiresHTTPS()
994 if ( !$this->shouldDoHttpRedirect() ) {
998 $request = $this->context->getRequest();
999 $oldUrl = $request->getFullRequestURL();
1000 $redirUrl = preg_replace(
'#^http://#',
'https://', $oldUrl );
1002 if ( $request->wasPosted() ) {
1011 wfDebugLog(
'RedirectedPosts',
"Redirected from HTTP to HTTPS: $oldUrl" );
1015 $this->context->setTitle(
$title );
1017 $output = $this->context->getOutput();
1018 $output->addVaryHeader(
'X-Forwarded-Proto' );
1019 $output->redirect( $redirUrl );
1053 if ( function_exists(
'apache_setenv' ) ) {
1055 @apache_setenv(
'no-gzip',
'1' );
1060 $this->postSendStrategy === self::DEFER_SET_LENGTH_AND_FLUSH &&
1062 in_array( http_response_code(), [ 200, 404 ],
true ) &&
1066 ob_get_level() <= 1 &&
1070 $response = $this->context->getRequest()->response();
1072 $obStatus = ob_get_status();
1073 if ( !isset( $obStatus[
'name'] ) ) {
1075 $response->header(
'Content-Length: ' . strlen(
$content ) );
1076 } elseif ( $obStatus[
'name'] ===
'default output handler' ) {
1079 $response->header(
'Content-Length: ' . ( ob_get_length() + strlen(
$content ) ) );
1091 if ( ( $_SERVER[
'SERVER_PROTOCOL'] ??
'' ) ===
'HTTP/1.1' ) {
1092 $response->header(
'Connection: close' );
1108 ignore_user_abort(
true );
1110 $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
1112 $lbFactory->commitPrimaryChanges( __METHOD__ );
1116 $trxProfiler->redefineExpectations(
1117 $this->context->getRequest()->hasSafeMethod()
1118 ? $this->config->get( MainConfigNames::TrxProfilerLimits )[
'PostSend-GET']
1119 : $this->config->get( MainConfigNames::TrxProfilerLimits )[
'PostSend-POST'],
1129 $profiler->logData();
1131 self::emitBufferedStatsdData(
1132 MediaWikiServices::getInstance()->getStatsdDataFactory(),
1137 MediaWikiServices::getInstance()->getMetricsFactory()->flush();
1140 $lbFactory->commitPrimaryChanges( __METHOD__ );
1141 $lbFactory->shutdown( $lbFactory::SHUTDOWN_NO_CHRONPROT );
1143 wfDebug(
"Request ended normally" );
1176 if ( $config->
get( MainConfigNames::StatsdServer ) && $stats->
hasData() ) {
1178 $statsdServer = explode(
':', $config->
get( MainConfigNames::StatsdServer ), 2 );
1179 $statsdHost = $statsdServer[0];
1180 $statsdPort = $statsdServer[1] ?? 8125;
1181 $statsdSender =
new SocketSender( $statsdHost, $statsdPort );
1183 $statsdClient->setSamplingRates( $config->
get( MainConfigNames::StatsdSamplingRates ) );
1184 $statsdClient->send( $stats->
getData() );
1187 }
catch ( Exception $e ) {
1198 $runner = MediaWikiServices::getInstance()->getJobRunner();
1199 $runner->run( [
'maxJobs' => $n ] );
1200 ScopedCallback::consume( $scope );
1209 $services = MediaWikiServices::getInstance();
1211 $group = $services->getJobQueueGroupFactory()->makeJobQueueGroup();
1216 $query = [
'title' =>
'Special:RunJobs',
1217 'tasks' =>
'jobs',
'maxjobs' => $n,
'sigexpiry' => time() + 5 ];
1219 $query, $this->config->get( MainConfigNames::SecretKey ) );
1221 $errno = $errstr =
null;
1222 $info =
wfParseUrl( $this->config->get( MainConfigNames::CanonicalServer ) );
1223 $host = $info ? $info[
'host'] :
null;
1225 if ( isset( $info[
'scheme'] ) && $info[
'scheme'] ==
'https' ) {
1226 $host =
"tls://" . $host;
1229 if ( isset( $info[
'port'] ) ) {
1230 $port = $info[
'port'];
1233 AtEase::suppressWarnings();
1234 $sock = $host ? fsockopen(
1242 AtEase::restoreWarnings();
1244 $invokedWithSuccess =
true;
1246 $special = $services->getSpecialPageFactory()->getPage(
'RunJobs' );
1247 $url = $special->getPageTitle()->getCanonicalURL( $query );
1249 "POST $url HTTP/1.1\r\n" .
1250 "Host: {$info['host']}\r\n" .
1251 "Connection: Close\r\n" .
1252 "Content-Length: 0\r\n\r\n"
1255 $runJobsLogger->info(
"Running $n job(s) via '$url'" );
1258 stream_set_timeout( $sock, 2 );
1259 $bytes = fwrite( $sock, $req );
1260 if ( $bytes !== strlen( $req ) ) {
1261 $invokedWithSuccess =
false;
1262 $runJobsLogger->error(
"Failed to start cron API (socket write error)" );
1266 $start = microtime(
true );
1267 $status = fgets( $sock );
1268 $sec = microtime(
true ) - $start;
1269 if ( !preg_match(
'#^HTTP/\d\.\d 202 #', $status ) ) {
1270 $invokedWithSuccess =
false;
1271 $runJobsLogger->error(
"Failed to start cron API: received '$status' ($sec)" );
1276 $invokedWithSuccess =
false;
1277 $runJobsLogger->error(
"Failed to start cron API (socket error $errno): $errstr" );
1280 return $invokedWithSuccess;
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfParseUrl( $url)
parse_url() work-alike, but non-broken.
wfWarn( $msg, $callerOffset=1, $level=E_USER_NOTICE)
Send a warning either to the debug log or in a PHP error depending on $wgDevelopmentWarnings.
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
if(!defined( 'MW_NO_SESSION') &&! $wgCommandLineMode) $wgTitle
if(!defined('MW_SETUP_CALLBACK'))
The persistent session ID (if any) loaded at startup.
Actions are things which can be done to pages (edit, delete, rollback, etc).
Legacy class representing an editable page and handling UI for some page actions.
static newFromWikiPage(WikiPage $page, IContextSource $context)
Create an Article object of the appropriate class for the given page.
Show an error page on a badtitle.
static addUpdate(DeferrableUpdate $update, $stage=self::POSTSEND)
Add an update to the pending update queue for execution at the appropriate time.
static pendingUpdatesCount()
Get the number of pending updates for the current execution context.
static doUpdates( $unused=null, $stage=self::ALL)
Consume and execute all pending updates.
Similar to FauxRequest, but only fakes URL parameters and method (POST or GET) and use the base reque...
An error page which can definitely be safely rendered using the OutputPage.
report( $action=self::SEND_OUTPUT)
Page view caching in the file system.
static useFileCache(IContextSource $context, $mode=self::MODE_NORMAL)
Check if pages can be cached for this request/user.
Show an error that looks like an HTTP server error.
static rollbackPrimaryChangesAndLog(Throwable $e, $catcher=self::CAUGHT_BY_OTHER)
Roll back any open database transactions and log the stack trace of the throwable.
static logException(Throwable $e, $catcher=self::CAUGHT_BY_OTHER, $extraData=[])
Log a throwable to the exception log (if enabled).
static handleException(Throwable $e, $catcher=self::CAUGHT_BY_OTHER)
Exception handler which simulates the appropriate catch() handling:
static getHTML(Throwable $e)
Format an HTML message for the given exception object.
A class containing constants representing the names of configuration variables.
Show an error when a user tries to do something they do not have the necessary permissions for.
static instance()
Singleton.
Shortcut to construct a special page alias.
static getMain()
Get the RequestContext object associated with the main request.
A statsd client that applies the sampling rate to the data items before sending them.
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,...
static getQuerySignature(array $query, $secretKey)
Represents a title within MediaWiki.
static newFromID( $id, $flags=0)
Create a new Title from an article ID.
static newFromLinkTarget(LinkTarget $linkTarget, $forceClone='')
Returns a Title given a LinkTarget.
static newFromURL( $url)
THIS IS NOT THE FUNCTION YOU WANT.
static newFromTextThrow( $text, $defaultNamespace=NS_MAIN)
Like Title::newFromText(), but throws MalformedTitleException when the title is invalid,...
static newMainPage(MessageLocalizer $localizer=null)
Create a new Title for the Main Page.
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Deferrable update that must run outside of any explicit LBFactory transaction round.
An action that views article content.
static disableForPostSend()
Disable setters for post-send processing.
Special handling for representing file pages.
static isCurrentWikiId( $wikiId)
static getWikiFromUrl( $url)
Interface for configuration instances.
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
MediaWiki adaptation of StatsdDataFactory that provides buffering functionality.
hasData()
Check whether this data factory has any buffered data.
clearData()
Clear all buffered data from the factory.
getData()
Return the buffered data from the factory.
Interface for objects which can provide a MediaWiki context on request.
getConfig()
Get the site configuration.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.