23use Liuggio\StatsdClient\Sender\SocketSender;
24use MediaWiki\HookContainer\ProtectedHookAccessorTrait;
27use Psr\Log\LoggerInterface;
37 use ProtectedHookAccessorTrait;
50 private const DEFER_FASTCGI_FINISH_REQUEST = 1;
52 private const DEFER_SET_LENGTH_AND_FLUSH = 2;
58 $this->context =
$context ?: RequestContext::getMain();
59 $this->config = $this->context->getConfig();
60 if ( function_exists(
'fastcgi_finish_request' ) ) {
61 $this->postSendStrategy = self::DEFER_FASTCGI_FINISH_REQUEST;
63 $this->postSendStrategy = self::DEFER_SET_LENGTH_AND_FLUSH;
74 $request = $this->context->getRequest();
75 $curid = $request->getInt(
'curid' );
76 $title = $request->getVal(
'title' );
77 $action = $request->getVal(
'action' );
79 if ( $request->getCheck(
'search' ) ) {
86 $ret = Title::newFromID( $curid );
88 $ret = Title::newFromURL(
$title );
91 if ( $ret !==
null && $ret->getNamespace() ==
NS_MEDIA ) {
92 $ret = Title::makeTitle(
NS_FILE, $ret->getDBkey() );
98 $contLang->hasVariants() && $ret !==
null && $ret->getArticleID() == 0
100 $contLang->findVariantLink(
$title, $ret );
108 if ( $ret ===
null || !$ret->isSpecialPage() ) {
110 $oldid = $request->getInt(
'oldid' );
111 $oldid = $oldid ?: $request->getInt(
'diff' );
115 ->getRevisionLookup()
116 ->getRevisionById( $oldid );
118 $ret = Title::newFromLinkTarget(
119 $revRecord->getPageAsLinkTarget()
127 && strval(
$title ) ===
''
128 && !$request->getCheck(
'curid' )
131 $ret = Title::newMainPage();
134 if ( $ret ===
null || ( $ret->getDBkey() ==
'' && !$ret->isExternal() ) ) {
137 Title::newFromTextThrow(
$title );
149 if ( !$this->context->hasTitle() ) {
151 $this->context->setTitle( $this->
parseTitle() );
156 return $this->context->getTitle();
165 if ( $this->action === null ) {
166 $this->action = Action::getActionName( $this->context );
169 return $this->action;
187 $request = $this->context->getRequest();
188 $requestTitle =
$title = $this->context->getTitle();
189 $output = $this->context->getOutput();
190 $user = $this->context->getUser();
192 if ( $request->getVal(
'printable' ) ===
'yes' ) {
193 $output->setPrintable();
196 $this->getHookRunner()->onBeforeInitialize(
$title,
null, $output, $user, $request, $this );
200 ||
$title->isSpecial(
'Badtitle' )
214 $permErrors =
$title->isSpecial(
'RunJobs' )
216 : MediaWikiServices::getInstance()->getPermissionManager()
217 ->getPermissionErrors(
'read', $user,
$title );
218 if ( count( $permErrors ) ) {
229 $this->context->setTitle( $badTitle );
236 if (
$title->isExternal() ) {
237 $rdfrom = $request->getVal(
'rdfrom' );
239 $url =
$title->getFullURL( [
'rdfrom' => $rdfrom ] );
241 $query = $request->getValues();
242 unset( $query[
'title'] );
243 $url =
$title->getFullURL( $query );
246 if ( !preg_match(
'/^' . preg_quote( $this->config->get(
'Server' ),
'/' ) .
'/', $url )
250 $output->redirect( $url, 301 );
262 } elseif ( !$this->tryNormaliseRedirect(
$title ) ) {
264 $spFactory = MediaWikiServices::getInstance()->getSpecialPageFactory();
265 if (
$title->isSpecialPage() ) {
266 $specialPage = $spFactory->getPage(
$title->getDBkey() );
268 $specialPage->setContext( $this->context );
269 if ( $this->config->get(
'HideIdentifiableRedirects' )
270 && $specialPage->personallyIdentifiableTarget()
272 list( , $subpage ) = $spFactory->resolveAlias(
$title->getDBkey() );
273 $target = $specialPage->getRedirect( $subpage );
275 if ( $target instanceof
Title ) {
276 if ( $target->isExternal() ) {
280 'force/' . $target->getPrefixedDBkey()
284 $query = $specialPage->getRedirectQuery( $subpage ) ?: [];
286 $request->setRequestURL( $this->context->getRequest()->getRequestURL() );
287 $this->context->setRequest( $request );
289 $this->context->getOutput()->lowerCdnMaxage( 0 );
290 $this->context->setTitle( $target );
293 $this->action =
null;
295 $output->addJsConfigVars( [
296 'wgInternalRedirectTargetUrl' => $target->getLinkURL( $query ),
298 $output->addModules(
'mediawiki.action.view.redirect' );
305 if (
$title->isSpecialPage() ) {
307 $spFactory->executePath(
$title, $this->context );
311 $article = $this->initializeArticle();
312 if ( is_object( $article ) ) {
313 $this->performAction( $article, $requestTitle );
314 } elseif ( is_string( $article ) ) {
315 $output->redirect( $article );
317 throw new MWException(
"Shouldn't happen: MediaWiki::initializeArticle()"
318 .
" returned neither an object nor a URL" );
321 $output->considerCacheSettingsFinal();
348 $request = $this->context->getRequest();
349 $output = $this->context->getOutput();
351 if ( $request->getVal(
'action',
'view' ) !=
'view'
352 || $request->wasPosted()
353 || ( $request->getCheck(
'title' )
354 &&
$title->getPrefixedDBkey() == $request->getVal(
'title' ) )
355 || count( $request->getValueNames( [
'action',
'title' ] ) )
356 || !$this->getHookRunner()->onTestCanonicalRedirect( $request,
$title, $output )
361 if ( $this->config->get(
'MainPageIsDomainRoot' ) && $request->getRequestURL() ===
'/' ) {
365 if (
$title->isSpecialPage() ) {
366 list( $name, $subpage ) = MediaWikiServices::getInstance()->getSpecialPageFactory()->
367 resolveAlias(
$title->getDBkey() );
374 if ( $targetUrl == $request->getFullRequestURL() ) {
375 $message =
"Redirect loop detected!\n\n" .
376 "This means the wiki got confused about what page was " .
377 "requested; this sometimes happens when moving a wiki " .
378 "to a new server or changing the server configuration.\n\n";
380 if ( $this->config->get(
'UsePathInfo' ) ) {
381 $message .=
"The wiki is trying to interpret the page " .
382 "title from the URL path portion (PATH_INFO), which " .
383 "sometimes fails depending on the web server. Try " .
384 "setting \"\$wgUsePathInfo = false;\" in your " .
385 "LocalSettings.php, or check that \$wgArticlePath " .
388 $message .=
"Your web server was detected as possibly not " .
389 "supporting URL path components (PATH_INFO) correctly; " .
390 "check your LocalSettings.php for a customized " .
391 "\$wgArticlePath setting and/or toggle \$wgUsePathInfo " .
396 $output->setCdnMaxage( 1200 );
397 $output->redirect( $targetUrl,
'301' );
408 $title = $this->context->getTitle();
409 if ( $this->context->canUseWikiPage() ) {
412 $page = $this->context->getWikiPage();
416 $page = WikiPage::factory(
$title );
417 $this->context->setWikiPage( $page );
418 wfWarn(
"RequestContext::canUseWikiPage() returned false" );
422 $article = Article::newFromWikiPage( $page, $this->context );
425 if ( !MediaWikiServices::getInstance()
426 ->getContentHandlerFactory()
427 ->getContentHandler(
$title->getContentModel() )
428 ->supportsRedirects()
433 $request = $this->context->getRequest();
437 $action = $request->getVal(
'action',
'view' );
439 if ( ( $action ==
'view' || $action ==
'render' )
440 && !$request->getVal(
'oldid' )
441 && !$request->getVal(
'diff' )
442 && $request->getVal(
'redirect' ) !=
'no'
444 && !( is_object(
$file ) &&
$file->exists() && !
$file->getRedirected() )
447 $ignoreRedirect = $target =
false;
449 $this->getHookRunner()->onInitializeArticleMaybeRedirect(
$title, $request,
450 $ignoreRedirect, $target, $article );
451 $page = $article->getPage();
455 if ( !$ignoreRedirect && ( $target || $page->isRedirect() ) ) {
457 $target = $target ?: $page->followRedirect();
458 if ( is_string( $target ) && !$this->config->get(
'DisableHardRedirects' ) ) {
462 if ( is_object( $target ) ) {
464 $rpage = WikiPage::factory( $target );
465 $rpage->loadPageData();
466 if ( $rpage->exists() || ( is_object(
$file ) && !
$file->isLocal() ) ) {
467 $rarticle = Article::newFromWikiPage( $rpage, $this->context );
468 $rarticle->setRedirectedFrom(
$title );
470 $article = $rarticle;
471 $this->context->setTitle( $target );
472 $this->context->setWikiPage( $article->getPage() );
477 $this->context->setTitle( $article->getTitle() );
478 $this->context->setWikiPage( $article->getPage() );
492 $request = $this->context->getRequest();
493 $output = $this->context->getOutput();
494 $title = $this->context->getTitle();
495 $user = $this->context->getUser();
497 if ( !$this->getHookRunner()->onMediaWikiPerformAction(
498 $output, $article,
$title, $user, $request, $this )
503 $act = $this->getAction();
504 $action = Action::factory( $act, $article, $this->context );
506 if ( $action instanceof
Action ) {
508 if ( $action->needsReadRights() && !$user->isAllowed(
'read' ) ) {
513 $trxLimits = $this->config->get(
'TrxProfilerLimits' );
514 $trxProfiler = Profiler::instance()->getTransactionProfiler();
515 if ( $request->wasPosted() && !$action->doesWrites() ) {
516 $trxProfiler->setExpectations( $trxLimits[
'POST-nonwrite'], __METHOD__ );
517 $request->markAsSafeRequest();
520 # Let CDN cache things if we can purge them.
521 if ( $this->config->get(
'UseCdn' ) &&
528 $output->setCdnMaxage( $this->config->get(
'CdnMaxAge' ) );
536 $output->setStatusCode( 404 );
537 $output->showErrorPage(
'nosuchaction',
'nosuchactiontext' );
545 $this->setDBProfilingAgent();
549 $out = $this->context->getOutput();
552 $out->considerCacheSettingsFinal();
557 $this->doPreOutputCommit();
560 }
catch ( Exception $e ) {
561 $context = $this->context;
562 $action = $context->getRequest()->getVal(
'action',
'view' );
565 $context->hasTitle() &&
566 $context->getTitle()->canExist() &&
567 in_array( $action, [
'view',
'history' ],
true ) &&
572 if (
$cache->isCached() ) {
580 MWExceptionHandler::handleException( $e, MWExceptionHandler::CAUGHT_BY_ENTRYPOINT );
581 }
catch ( Throwable $e ) {
583 MWExceptionHandler::handleException( $e, MWExceptionHandler::CAUGHT_BY_ENTRYPOINT );
586 $this->doPostOutputShutdown();
593 $services = MediaWikiServices::getInstance();
594 $name = $this->context->getUser()->getName();
595 $services->getDBLoadBalancerFactory()->setAgentName(
596 mb_strlen( $name ) > 15 ? mb_substr( $name, 0, 15 ) .
'...' : $name
604 $jobRunRate = $this->config->get(
'JobRunRate' );
607 $this->
getTitle()->isSpecial(
'RunJobs' ) ||
612 $this->context->getRequest()->getMethod() ===
'HEAD' ||
613 $this->context->getRequest()->getHeader(
'If-Modified-Since' )
619 if ( $jobRunRate < 1 ) {
620 $max = mt_getrandmax();
621 if ( mt_rand( 0, $max ) > $max * $jobRunRate ) {
626 $n = intval( $jobRunRate );
631 $logger = LoggerFactory::getInstance(
'runJobs' );
632 if ( $this->config->get(
'RunJobsAsync' ) ) {
634 $invokedWithSuccess = $this->triggerAsyncJobs( $n, $logger );
635 if ( !$invokedWithSuccess ) {
637 $logger->warning(
"Jobs switched to blocking; Special:RunJobs disabled" );
638 $this->triggerSyncJobs( $n );
641 $this->triggerSyncJobs( $n );
652 self::preOutputCommit( $this->context, $postCommitWork );
672 $services = MediaWikiServices::getInstance();
673 $lbFactory = $services->getDBLoadBalancerFactory();
676 ignore_user_abort(
true );
679 $lbFactory->commitMasterChanges(
682 [
'maxWriteDuration' => $config->get(
'MaxUserDBWriteDuration' ) ]
684 wfDebug( __METHOD__ .
': primary transaction round committed' );
687 DeferredUpdates::doUpdates(
'run', DeferredUpdates::PRESEND );
688 wfDebug( __METHOD__ .
': pre-send deferred updates completed' );
690 $request->getSession()->save();
691 wfDebug( __METHOD__ .
': session changes committed' );
697 list( $flags, $strategy ) = self::getChronProtStrategy( $lbFactory, $output );
701 $lbFactory->shutdown( $flags, $postCommitWork, $cpIndex, $cpClientId );
702 wfDebug( __METHOD__ .
': LBFactory shutdown completed' );
704 $allowHeaders = !( $output->isDisabled() || headers_sent() );
705 if ( $cpIndex > 0 ) {
706 if ( $allowHeaders ) {
708 $expires = $now + ChronologyProtector::POSITION_COOKIE_TTL;
709 $options = [
'prefix' =>
'' ];
710 $value = $lbFactory::makeCookieValueFromCPIndex( $cpIndex, $now, $cpClientId );
711 $request->response()->setCookie(
'cpPosIndex', $value, $expires, $options );
714 if ( $strategy ===
'cookie+url' ) {
715 if ( $output->getRedirect() ) {
716 $safeUrl = $lbFactory->appendShutdownCPIndexAsQuery(
717 $output->getRedirect(),
720 $output->redirect( $safeUrl );
722 MWExceptionHandler::logException(
723 new LogicException(
"No redirect; cannot append cpPosIndex parameter." ),
724 MWExceptionHandler::CAUGHT_BY_ENTRYPOINT
730 if ( $allowHeaders ) {
734 if ( $request->wasPosted() && $lbFactory->hasOrMadeRecentMasterChanges() ) {
735 $expires = time() + $config->get(
'DataCenterUpdateStickTTL' );
736 $options = [
'prefix' =>
'' ];
737 $request->response()->setCookie(
'UseDC',
'master', $expires, $options );
738 $request->response()->setCookie(
'UseCDNCache',
'false', $expires, $options );
743 if ( $lbFactory->laggedReplicaUsed() ) {
744 $maxAge = $config->get(
'CdnMaxageLagged' );
745 $output->lowerCdnMaxage( $maxAge );
746 $request->response()->header(
"X-Database-Lagged: true" );
748 "Lagged DB used; CDN cache TTL limited to $maxAge seconds" );
752 if ( $services->getMessageCache()->isDisabled() ) {
753 $maxAge = $config->get(
'CdnMaxageSubstitute' );
754 $output->lowerCdnMaxage( $maxAge );
755 $request->response()->header(
"X-Response-Substitute: true" );
758 if ( !$output->couldBePublicCached() || $output->haveCacheVaryCookies() ) {
770 $services->getBlockManager()
771 ->trackBlockWithCookie( $user, $request->response() );
787 $flags = $lbFactory::SHUTDOWN_CHRONPROT_SYNC;
788 $strategy =
'cookie+sync';
790 $allowHeaders = !( $output->
isDisabled() || headers_sent() );
795 $domainDistance = self::getUrlDomainDistance( $output->
getRedirect() );
796 if ( $domainDistance ===
'local' && $allowHeaders ) {
797 $flags = $lbFactory::SHUTDOWN_CHRONPROT_ASYNC;
798 $strategy =
'cookie';
799 } elseif ( $domainDistance ===
'remote' ) {
800 $flags = $lbFactory::SHUTDOWN_CHRONPROT_ASYNC;
801 $strategy =
'cookie+url';
805 return [ $flags, $strategy ];
813 $clusterWiki = WikiMap::getWikiFromUrl( $url );
814 if ( WikiMap::isCurrentWikiId( $clusterWiki ) ) {
817 if ( $clusterWiki !==
false ) {
835 $timing = $this->context->getTiming();
836 $timing->mark(
'requestShutdown' );
841 Profiler::instance()->logDataPageOutputOnly();
842 }
catch ( Throwable $e ) {
844 MWExceptionHandler::logException( $e, MWExceptionHandler::CAUGHT_BY_ENTRYPOINT );
848 WebResponse::disableForPostSend();
851 $callback =
function () {
853 $this->restInPeace();
854 }
catch ( Throwable $e ) {
856 MWExceptionHandler::rollbackMasterChangesAndLog(
858 MWExceptionHandler::CAUGHT_BY_ENTRYPOINT
863 if ( $this->postSendStrategy === self::DEFER_FASTCGI_FINISH_REQUEST ) {
864 fastcgi_finish_request();
868 if ( !$this->config->get(
'CommandLineMode' ) ) {
869 AtEase\AtEase::suppressWarnings();
870 if ( ob_get_status() ) {
874 AtEase\AtEase::restoreWarnings();
886 $output = $this->context->getOutput();
887 $request = $this->context->getRequest();
890 if ( $request->getVal(
'action' ) ===
'ajax' ) {
892 $title = Title::makeTitle(
NS_SPECIAL,
'Badtitle/performing an AJAX call in '
895 $this->context->setTitle(
$title );
899 $dispatcher->performAction( $this->context->getUser() );
910 $trxLimits = $this->config->get(
'TrxProfilerLimits' );
911 $trxProfiler = Profiler::instance()->getTransactionProfiler();
912 $trxProfiler->setLogger( LoggerFactory::getInstance(
'DBPerformance' ) );
913 if ( $request->hasSafeMethod() ) {
914 $trxProfiler->setExpectations( $trxLimits[
'GET'], __METHOD__ );
916 $trxProfiler->setExpectations( $trxLimits[
'POST'], __METHOD__ );
919 if ( $this->maybeDoHttpsRedirect() ) {
927 $action = $this->getAction();
930 if (
$cache->isCacheGood( ) ) {
932 $timestamp =
$cache->cacheTimestamp();
933 if ( !$output->checkLastModified( $timestamp ) ) {
934 $cache->loadFromFileCache( $this->context );
938 $this->context->getWikiPage()->doViewUpdates( $this->context->getUser() );
947 $this->performRequest();
952 $outputWork =
function () use ( $output, &$buffer ) {
953 if ( $buffer ===
null ) {
954 $buffer = $output->output(
true );
963 $this->doPreOutputCommit( $outputWork );
965 $this->schedulePostSendJobs();
967 $this->outputResponsePayload( $outputWork() );
977 $request = $this->context->getRequest();
980 if ( $request->getProtocol() !==
'http' ) {
984 $force = $this->config->get(
'ForceHTTPS' );
990 throw new RuntimeException(
'$wgForceHTTPS is true but the server is not HTTPS' );
1001 return $request->getSession()->shouldForceHTTPS() ||
1003 $request->getCookie(
'forceHTTPS',
'' ) ||
1006 $this->context->getUser()->isLoggedIn()
1007 && $this->context->getUser()->requiresHTTPS()
1021 if ( !$this->shouldDoHttpRedirect() ) {
1025 $request = $this->context->getRequest();
1026 $oldUrl = $request->getFullRequestURL();
1027 $redirUrl = preg_replace(
'#^http://#',
'https://', $oldUrl );
1030 if ( !$this->getHookRunner()->onBeforeHttpsRedirect( $this->context, $redirUrl ) ) {
1034 if ( $request->wasPosted() ) {
1043 wfDebugLog(
'RedirectedPosts',
"Redirected from HTTP to HTTPS: $oldUrl" );
1047 $this->context->setTitle(
$title );
1049 $output = $this->context->getOutput();
1050 $output->addVaryHeader(
'X-Forwarded-Proto' );
1051 $output->redirect( $redirUrl );
1073 ignore_user_abort(
true );
1075 $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
1077 $lbFactory->commitMasterChanges( __METHOD__ );
1080 $trxProfiler = Profiler::instance()->getTransactionProfiler();
1081 $trxProfiler->redefineExpectations(
1082 $this->context->getRequest()->hasSafeMethod()
1083 ? $this->config->get(
'TrxProfilerLimits' )[
'PostSend-GET']
1084 : $this->config->get(
'TrxProfilerLimits' )[
'PostSend-POST'],
1089 DeferredUpdates::doUpdates(
'run' );
1095 $lbFactory->commitMasterChanges( __METHOD__ );
1096 $lbFactory->shutdown( $lbFactory::SHUTDOWN_NO_CHRONPROT );
1098 wfDebug(
"Request ended normally" );
1112 if ( $config->
get(
'StatsdServer' ) && $stats->
hasData() ) {
1114 $statsdServer = explode(
':', $config->
get(
'StatsdServer' ), 2 );
1115 $statsdHost = $statsdServer[0];
1116 $statsdPort = $statsdServer[1] ?? 8125;
1117 $statsdSender =
new SocketSender( $statsdHost, $statsdPort );
1119 $statsdClient->setSamplingRates( $config->
get(
'StatsdSamplingRates' ) );
1120 $statsdClient->send( $stats->
getData() );
1123 }
catch ( Exception $e ) {
1124 MWExceptionHandler::logException( $e, MWExceptionHandler::CAUGHT_BY_ENTRYPOINT );
1136 $jobRunRate = $this->config->get(
'JobRunRate' );
1137 if ( $this->
getTitle()->isSpecial(
'RunJobs' ) ) {
1139 } elseif ( $jobRunRate <= 0 ||
wfReadOnly() ) {
1143 if ( $jobRunRate < 1 ) {
1144 $max = mt_getrandmax();
1145 if ( mt_rand( 0, $max ) > $max * $jobRunRate ) {
1150 $n = intval( $jobRunRate );
1153 $logger = LoggerFactory::getInstance(
'runJobs' );
1156 if ( $this->config->get(
'RunJobsAsync' ) ) {
1158 $invokedWithSuccess = $this->triggerAsyncJobs( $n, $logger );
1159 if ( !$invokedWithSuccess ) {
1161 $logger->warning(
"Jobs switched to blocking; Special:RunJobs disabled" );
1162 $this->triggerSyncJobs( $n );
1165 $this->triggerSyncJobs( $n );
1169 MWExceptionHandler::logException( $e, MWExceptionHandler::CAUGHT_BY_ENTRYPOINT );
1177 $trxProfiler = Profiler::instance()->getTransactionProfiler();
1178 $old = $trxProfiler->setSilenced(
true );
1180 $runner = MediaWikiServices::getInstance()->getJobRunner();
1181 $runner->run( [
'maxJobs' => $n ] );
1183 $trxProfiler->setSilenced( $old );
1194 $group = JobQueueGroup::singleton();
1195 if ( !$group->queuesHaveJobs( JobQueueGroup::TYPE_DEFAULT ) ) {
1199 $query = [
'title' =>
'Special:RunJobs',
1200 'tasks' =>
'jobs',
'maxjobs' => $n,
'sigexpiry' => time() + 5 ];
1202 $query, $this->config->get(
'SecretKey' ) );
1204 $errno = $errstr =
null;
1205 $info =
wfParseUrl( $this->config->get(
'CanonicalServer' ) );
1206 $host = $info ? $info[
'host'] :
null;
1208 if ( isset( $info[
'scheme'] ) && $info[
'scheme'] ==
'https' ) {
1209 $host =
"tls://" . $host;
1212 if ( isset( $info[
'port'] ) ) {
1213 $port = $info[
'port'];
1216 Wikimedia\suppressWarnings();
1217 $sock = $host ? fsockopen(
1225 Wikimedia\restoreWarnings();
1227 $invokedWithSuccess =
true;
1229 $special = MediaWikiServices::getInstance()->getSpecialPageFactory()->
1230 getPage(
'RunJobs' );
1231 $url = $special->getPageTitle()->getCanonicalURL( $query );
1233 "POST $url HTTP/1.1\r\n" .
1234 "Host: {$info['host']}\r\n" .
1235 "Connection: Close\r\n" .
1236 "Content-Length: 0\r\n\r\n"
1239 $runJobsLogger->info(
"Running $n job(s) via '$url'" );
1242 stream_set_timeout( $sock, 2 );
1243 $bytes = fwrite( $sock, $req );
1244 if ( $bytes !== strlen( $req ) ) {
1245 $invokedWithSuccess =
false;
1246 $runJobsLogger->error(
"Failed to start cron API (socket write error)" );
1250 $start = microtime(
true );
1251 $status = fgets( $sock );
1252 $sec = microtime(
true ) - $start;
1253 if ( !preg_match(
'#^HTTP/\d\.\d 202 #', $status ) ) {
1254 $invokedWithSuccess =
false;
1255 $runJobsLogger->error(
"Failed to start cron API: received '$status' ($sec)" );
1260 $invokedWithSuccess =
false;
1261 $runJobsLogger->error(
"Failed to start cron API (socket error $errno): $errstr" );
1264 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.
wfReadOnly()
Check whether the wiki is in read-only mode.
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.
Actions are things which can be done to pages (edit, delete, rollback, etc).
Object-Oriented Ajax functions.
Class for viewing MediaWiki article and history.
Show an error page on a badtitle.
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)
Stable to override.
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 getHTML(Throwable $e)
If $wgShowExceptionDetails is true, return a HTML message with a backtrace to the error,...
This is one of the Core classes and should be read at least once by any new developers.
getRedirect()
Get the URL to redirect to, or an empty string if not redirect URL set.
isDisabled()
Return whether the output will be completely disabled.
Show an error when a user tries to do something they do not have the necessary permissions for.
Shortcut to construct a special page alias.
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.
getCdnUrls()
Get a list of URLs to purge from the CDN cache when this page changes.
Deferrable update that must run outside of any explicit LBFactory transaction round.
Special handling for file pages.
while(( $__line=Maintenance::readconsole()) !==false) print
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.