Merge ".mailmap: Correct two contributor names"
[mediawiki.git] / includes / Setup.php
blob41707fcb8f4f60c420c617faf977345aaa9590d6
1 <?php
2 /**
3 * The setup for all MediaWiki processes (both web-based and CLI).
5 * The entry point (such as WebStart.php and doMaintenance.php) has these responsibilities:
6 * - The entry point MUST:
7 * - define the 'MEDIAWIKI' constant.
8 * - The entry point SHOULD:
9 * - define the 'MW_ENTRY_POINT' constant.
10 * - display an error if MW_CONFIG_CALLBACK is not defined and the
11 * file specified in MW_CONFIG_FILE (or the LocalSettings.php default location)
12 * does not exist. The error should either be sent before and instead
13 * of the Setup.php inclusion, or (if it needs classes and dependencies
14 * from core) the error can be displayed via a MW_CONFIG_CALLBACK,
15 * which must then abort the process to prevent the rest of Setup.php
16 * from executing.
18 * This file does:
19 * - run-time environment checks,
20 * - define MW_INSTALL_PATH, and $IP,
21 * - load autoloaders, constants, default settings, and global functions,
22 * - load the site configuration (e.g. LocalSettings.php),
23 * - load the enabled extensions (via ExtensionRegistry),
24 * - trivial expansion of site configuration defaults and shortcuts
25 * (no calls to MediaWikiServices or other parts of MediaWiki),
26 * - initialization of:
27 * - PHP run-time (setlocale, memory limit, default date timezone)
28 * - the debug logger (MWDebug)
29 * - the service container (MediaWikiServices)
30 * - the exception handler (MWExceptionHandler)
31 * - the session manager (SessionManager)
32 * - complex expansion of site configuration defaults (those that require
33 * calling into MediaWikiServices, global functions, or other classes.).
35 * This program is free software; you can redistribute it and/or modify
36 * it under the terms of the GNU General Public License as published by
37 * the Free Software Foundation; either version 2 of the License, or
38 * (at your option) any later version.
40 * This program is distributed in the hope that it will be useful,
41 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 * GNU General Public License for more details.
45 * You should have received a copy of the GNU General Public License along
46 * with this program; if not, write to the Free Software Foundation, Inc.,
47 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
48 * http://www.gnu.org/copyleft/gpl.html
50 * @file
53 // phpcs:disable MediaWiki.Usage.DeprecatedGlobalVariables
54 use MediaWiki\Config\SiteConfiguration;
55 use MediaWiki\Context\RequestContext;
56 use MediaWiki\Debug\MWDebug;
57 use MediaWiki\Deferred\DeferredUpdates;
58 use MediaWiki\HookContainer\FauxGlobalHookArray;
59 use MediaWiki\HookContainer\HookRunner;
60 use MediaWiki\Language\Language;
61 use MediaWiki\Logger\LoggerFactory;
62 use MediaWiki\MainConfigNames;
63 use MediaWiki\MainConfigSchema;
64 use MediaWiki\MediaWikiServices;
65 use MediaWiki\Message\Message;
66 use MediaWiki\Registration\ExtensionRegistry;
67 use MediaWiki\Registration\MissingExtensionException;
68 use MediaWiki\Request\HeaderCallback;
69 use MediaWiki\Settings\DynamicDefaultValues;
70 use MediaWiki\Settings\LocalSettingsLoader;
71 use MediaWiki\Settings\SettingsBuilder;
72 use MediaWiki\Settings\Source\PhpSettingsSource;
73 use MediaWiki\Settings\Source\ReflectionSchemaSource;
74 use MediaWiki\Settings\WikiFarmSettingsLoader;
75 use MediaWiki\StubObject\StubGlobalUser;
76 use MediaWiki\StubObject\StubUserLang;
77 use MediaWiki\Title\Title;
78 use MediaWiki\User\User;
79 use Psr\Log\LoggerInterface;
80 use Wikimedia\RequestTimeout\RequestTimeout;
81 use Wikimedia\Telemetry\SpanInterface;
82 use Wikimedia\Telemetry\TracerState;
84 /**
85 * Environment checks
87 * These are inline checks done before we include any source files,
88 * and thus these conditions may be assumed by all source code.
91 // This file must be included from a valid entry point (e.g. WebStart.php, Maintenance.php)
92 if ( !defined( 'MEDIAWIKI' ) ) {
93 exit( 1 );
96 // PHP must not be configured to overload mbstring functions. (T5782, T122807)
97 // This was deprecated by upstream in PHP 7.2 and was removed in PHP 8.0.
98 if ( ini_get( 'mbstring.func_overload' ) ) {
99 die( 'MediaWiki does not support installations where mbstring.func_overload is non-zero.' );
102 // The MW_ENTRY_POINT constant must always exists, to make it safe to access.
103 // For compat, we do support older and custom MW entrypoints that don't set this,
104 // in which case we assign a default here.
105 if ( !defined( 'MW_ENTRY_POINT' ) ) {
107 * The entry point, which may be either the script filename without the
108 * file extension, or "cli" for maintenance scripts, or "unknown" for any
109 * entry point that does not set the constant.
111 define( 'MW_ENTRY_POINT', 'unknown' );
114 // The $IP variable is defined for use by LocalSettings.php.
115 // It is made available as a global variable for backwards compatibility.
117 // Source code should use the MW_INSTALL_PATH constant instead.
118 global $IP;
119 $IP = wfDetectInstallPath(); // ensures MW_INSTALL_PATH is defined
122 * Pre-config setup: Before loading LocalSettings.php
124 * These are changes and additions to runtime that don't vary on site configuration.
126 require_once MW_INSTALL_PATH . '/includes/AutoLoader.php';
127 require_once MW_INSTALL_PATH . '/includes/Defines.php';
129 // Assert that composer dependencies were successfully loaded
130 if ( !interface_exists( LoggerInterface::class ) ) {
131 $message = (
132 'MediaWiki requires the <a href="https://github.com/php-fig/log">PSR-3 logging ' .
133 "library</a> to be present. This library is not embedded directly in MediaWiki's " .
134 "git repository and must be installed separately by the end user.\n\n" .
135 'Please see the <a href="https://www.mediawiki.org/wiki/Download_from_Git' .
136 '#Fetch_external_libraries">instructions for installing libraries</a> on mediawiki.org ' .
137 'for help on installing the required components.'
139 echo $message;
140 trigger_error( $message, E_USER_ERROR );
143 // Deprecated global variable for backwards-compatibility.
144 // New code should check MW_ENTRY_POINT directly.
145 $wgCommandLineMode = MW_ENTRY_POINT === 'cli';
148 * $wgConf hold the site configuration.
149 * Not used for much in a default install.
150 * @since 1.5
152 $wgConf = new SiteConfiguration;
154 $wgAutoloadClasses ??= [];
156 $wgSettings = SettingsBuilder::getInstance();
158 if ( defined( 'MW_USE_CONFIG_SCHEMA_CLASS' ) ) {
159 // Load config schema from MainConfigSchema. Useful for running scripts that
160 // generate other representations of the config schema. This is slow, so it
161 // should not be used for serving web traffic.
162 $wgSettings->load( new ReflectionSchemaSource( MainConfigSchema::class ) );
163 } else {
164 $wgSettings->load( new PhpSettingsSource( MW_INSTALL_PATH . '/includes/config-schema.php' ) );
167 require_once MW_INSTALL_PATH . '/includes/GlobalFunctions.php';
169 HeaderCallback::register();
171 // Set the encoding used by PHP for reading HTTP input, and writing output.
172 // This is also the default for mbstring functions.
173 mb_internal_encoding( 'UTF-8' );
176 * Load LocalSettings.php
179 // Initialize some config settings with dynamic defaults, and
180 // make default settings available in globals for use in LocalSettings.php.
181 $wgSettings->putConfigValues( [
182 MainConfigNames::ExtensionDirectory => MW_INSTALL_PATH . '/extensions',
183 MainConfigNames::StyleDirectory => MW_INSTALL_PATH . '/skins',
184 MainConfigNames::UploadDirectory => MW_INSTALL_PATH . '/images',
185 MainConfigNames::ServiceWiringFiles => [ MW_INSTALL_PATH . '/includes/ServiceWiring.php' ],
186 'Version' => MW_VERSION,
187 ] );
188 $wgSettings->apply();
190 // $wgSettings->apply() puts all configuration into global variables.
191 // If we are not in global scope, make all relevant globals available
192 // in this file's scope as well.
193 $wgScopeTest = 'MediaWiki Setup.php scope test';
194 if ( !isset( $GLOBALS['wgScopeTest'] ) || $GLOBALS['wgScopeTest'] !== $wgScopeTest ) {
195 foreach ( $wgSettings->getConfigSchema()->getDefinedKeys() as $key ) {
196 $var = "wg$key";
197 // phpcs:ignore MediaWiki.NamingConventions.ValidGlobalName.allowedPrefix
198 global $$var;
200 unset( $key, $var );
202 unset( $wgScopeTest );
204 try {
205 if ( defined( 'MW_CONFIG_CALLBACK' ) ) {
206 call_user_func( MW_CONFIG_CALLBACK, $wgSettings );
207 } else {
208 wfDetectLocalSettingsFile( MW_INSTALL_PATH );
210 if ( getenv( 'MW_USE_LOCAL_SETTINGS_LOADER' ) ) {
211 // NOTE: This will not work for configuration variables that use a prefix
212 // other than "wg".
213 $localSettingsLoader = new LocalSettingsLoader( $wgSettings, MW_INSTALL_PATH );
214 $localSettingsLoader->loadLocalSettingsFile( MW_CONFIG_FILE );
215 unset( $localSettingsLoader );
216 } else {
217 if ( str_ends_with( MW_CONFIG_FILE, '.php' ) ) {
218 // make defaults available as globals
219 $wgSettings->apply();
220 require_once MW_CONFIG_FILE;
221 } else {
222 $wgSettings->loadFile( MW_CONFIG_FILE );
227 // Make settings loaded by LocalSettings.php available in globals for use here
228 $wgSettings->apply();
229 } catch ( MissingExtensionException $e ) {
230 // Make a common mistake give a friendly error
231 $e->render();
234 // If in a wiki-farm, load site-specific settings
235 if ( $wgSettings->getConfig()->get( MainConfigNames::WikiFarmSettingsDirectory ) ) {
236 $wikiFarmSettingsLoader = new WikiFarmSettingsLoader( $wgSettings );
237 $wikiFarmSettingsLoader->loadWikiFarmSettings();
238 unset( $wikiFarmSettingsLoader );
241 // All settings should be loaded now.
242 $wgSettings->enterRegistrationStage();
245 * Customization point after most things are loaded (constants, functions, classes,
246 * LocalSettings.
247 * Note that this runs before extensions are registered, and before most singletons become
248 * available, and before MediaWikiServices is initialized.
251 if ( defined( 'MW_SETUP_CALLBACK' ) ) {
252 call_user_func( MW_SETUP_CALLBACK, $wgSettings );
253 // Make any additional settings available in globals for use here
254 $wgSettings->apply();
257 // Apply dynamic defaults declared in config schema callbacks.
258 $dynamicDefaults = new DynamicDefaultValues( $wgSettings->getConfigSchema() );
259 $dynamicDefaults->applyDynamicDefaults( $wgSettings->getConfigBuilder() );
261 // Make updated config available in global scope.
262 $wgSettings->apply();
264 // Apply dynamic defaults implemented in SetupDynamicConfig.php.
265 // Ideally, all logic in SetupDynamicConfig would be converted to
266 // callbacks in the config schema.
267 require __DIR__ . '/SetupDynamicConfig.php';
269 if ( defined( 'MW_AUTOLOAD_TEST_CLASSES' ) ) {
270 require_once __DIR__ . '/../tests/common/TestsAutoLoader.php';
273 // Start time limit
274 if ( $wgRequestTimeLimit && MW_ENTRY_POINT !== 'cli' ) {
275 RequestTimeout::singleton()->setWallTimeLimit( $wgRequestTimeLimit );
279 * Load queued extensions
281 if ( defined( 'MW_AUTOLOAD_TEST_CLASSES' ) ) {
282 ExtensionRegistry::getInstance()->setLoadTestClassesAndNamespaces( true );
285 ExtensionRegistry::getInstance()->setSettingsBuilder( $wgSettings );
286 ExtensionRegistry::getInstance()->loadFromQueue();
287 // Don't let any other extensions load
288 ExtensionRegistry::getInstance()->finish();
291 * Customization point after ALL loading (constants, functions, classes,
292 * LocalSettings, extensions, dynamic defaults).
293 * Note that this runs before MediaWikiServices is initialized.
295 if ( defined( 'MW_FINAL_SETUP_CALLBACK' ) ) {
296 call_user_func( MW_FINAL_SETUP_CALLBACK, $wgSettings );
297 // Make any additional settings available in globals for use below
298 $wgSettings->apply();
301 // Config can no longer be changed.
302 $wgSettings->enterReadOnlyStage();
304 // Set an appropriate locale (T291234)
305 // setlocale() will return the locale name actually set.
306 // The putenv() is meant to propagate the choice of locale to shell commands
307 // so that they will interpret UTF-8 correctly. If you have a problem with a
308 // shell command and need to send a special locale, you can override the locale
309 // with Command::environment().
310 putenv( "LC_ALL=" . setlocale( LC_ALL, 'C.UTF-8', 'C' ) );
312 // Set PHP runtime to the desired timezone
313 date_default_timezone_set( $wgLocaltimezone );
315 MWDebug::setup();
317 // Enable the global service locator.
318 // Trivial expansion of site configuration should go before this point.
319 // Any non-trivial expansion that requires calling into MediaWikiServices or other parts of MW.
320 MediaWikiServices::allowGlobalInstance();
322 // Define a constant that indicates that the bootstrapping of the service locator
323 // is complete.
324 define( 'MW_SERVICE_BOOTSTRAP_COMPLETE', 1 );
326 MWExceptionRenderer::setShowExceptionDetails( $wgShowExceptionDetails );
327 if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
328 // Never install the handler in PHPUnit tests, otherwise PHPUnit's own handler will be unset and things
329 // like convertWarningsToExceptions won't work.
330 MWExceptionHandler::installHandler( $wgLogExceptionBacktrace, $wgPropagateErrors );
332 Profiler::init( $wgProfiler );
334 // Initialize the root span for distributed tracing if we're in a web request context (T340552).
335 // Do this here since subsequent setup code, e.g. session initialization or post-setup hooks,
336 // may themselves create spans, so the root span needs to have been initialized by then.
337 call_user_func( static function (): void {
338 if ( wfIsCLI() ) {
339 return;
342 $tracer = MediaWikiServices::getInstance()->getTracer();
343 $request = RequestContext::getMain()->getRequest();
344 // Backdate the start of the root span to the timestamp where PHP actually started working on this operation.
345 $startTimeNanos = (int)( 1e9 * $_SERVER['REQUEST_TIME_FLOAT'] );
346 // Avoid high cardinality URL path as root span name, instead safely use the HTTP method.
347 // Per OTEL Semantic Conventions, https://opentelemetry.io/docs/specs/semconv/http/http-spans/
348 $spanName = "EntryPoint " . MW_ENTRY_POINT . ".php HTTP {$request->getMethod()}";
349 global $wgAllowExternalReqID;
350 $rootSpan = $tracer->createRootSpanFromCarrier( $spanName, $wgAllowExternalReqID ? $request->getAllHeaders() : [] );
351 $rootSpan->setSpanKind( SpanInterface::SPAN_KIND_SERVER )
352 ->setAttributes( array_filter( [
353 'http.request.method' => $request->getMethod(),
354 'url.path' => $request->getRequestURL(),
355 'server.name' => $_SERVER['SERVER_NAME'] ?? null,
356 ] ) )
357 ->start( $startTimeNanos );
358 $rootSpan->activate();
360 TracerState::getInstance()->setRootSpan( $rootSpan );
361 } );
363 // Non-trivial validation of: $wgServer
364 // The FatalError page only renders cleanly after MWExceptionHandler is installed.
365 if ( $wgServer === false ) {
366 // T30798: $wgServer must be explicitly set
367 throw new FatalError(
368 '$wgServer must be set in LocalSettings.php. ' .
369 'See <a href="https://www.mediawiki.org/wiki/Manual:$wgServer">' .
370 'https://www.mediawiki.org/wiki/Manual:$wgServer</a>.'
374 // Set up a fake $wgHooks array.
375 // XXX: It would be nice if we could still get the originally configured hook handlers
376 // using the MainConfigNames::Hooks setting, but it's not really needed,
377 // since we need the HookContainer to be initialized first anyway.
379 global $wgHooks;
380 $wgHooks = new FauxGlobalHookArray(
381 MediaWikiServices::getInstance()->getHookContainer(),
382 $wgHooks
385 // Non-trivial expansion of: $wgCanonicalServer, $wgServerName.
386 // These require calling global functions.
387 // Also here are other settings that further depend on these two.
388 if ( $wgCanonicalServer === false ) {
389 $wgCanonicalServer = MediaWikiServices::getInstance()->getUrlUtils()->getCanonicalServer();
391 $wgVirtualRestConfig['global']['domain'] = $wgCanonicalServer;
393 if ( $wgServerName !== false ) {
394 wfWarn( '$wgServerName should be derived from $wgCanonicalServer, '
395 . 'not customized. Overwriting $wgServerName.' );
397 $wgServerName = parse_url( $wgCanonicalServer, PHP_URL_HOST );
399 // $wgEmergencyContact and $wgPasswordSender may be false or empty string (T104142)
400 if ( !$wgEmergencyContact ) {
401 $wgEmergencyContact = 'wikiadmin@' . $wgServerName;
403 if ( !$wgPasswordSender ) {
404 $wgPasswordSender = 'apache@' . $wgServerName;
406 if ( !$wgNoReplyAddress ) {
407 $wgNoReplyAddress = $wgPasswordSender;
410 // Non-trivial expansion of: $wgSecureLogin
411 // (due to calling wfWarn).
412 if ( $wgSecureLogin && substr( $wgServer, 0, 2 ) !== '//' ) {
413 $wgSecureLogin = false;
414 wfWarn( 'Secure login was enabled on a server that only supports '
415 . 'HTTP or HTTPS. Disabling secure login.' );
418 // Now that GlobalFunctions is loaded, set defaults that depend on it.
419 if ( $wgTmpDirectory === false ) {
420 $wgTmpDirectory = wfTempDir();
423 if ( $wgSharedDB && $wgSharedTables ) {
424 // Apply $wgSharedDB table aliases for the local LB (all non-foreign DB connections)
425 MediaWikiServices::getInstance()->getDBLoadBalancer()->setTableAliases(
426 array_fill_keys(
427 $wgSharedTables,
429 'dbname' => $wgSharedDB,
430 'schema' => $wgSharedSchema,
431 'prefix' => $wgSharedPrefix
437 // Raise the memory limit if it's too low
438 // NOTE: This use wfDebug, and must remain after the MWDebug::setup() call.
439 wfMemoryLimit( $wgMemoryLimit );
441 // Explicit globals, so this works with bootstrap.php
442 global $wgRequest, $wgInitialSessionId;
444 // Initialize the request object in $wgRequest
445 $wgRequest = RequestContext::getMain()->getRequest(); // BackCompat
447 // Make sure that object caching does not undermine the ChronologyProtector improvements
448 if ( $wgRequest->getCookie( 'UseDC', '' ) === 'master' ) {
449 // The user is pinned to the primary DC, meaning that they made recent changes which should
450 // be reflected in their subsequent web requests. Avoid the use of interim cache keys because
451 // they use a blind TTL and could be stale if an object changes twice in a short time span.
452 MediaWikiServices::getInstance()->getMainWANObjectCache()->useInterimHoldOffCaching( false );
455 // Useful debug output
456 ( static function () {
457 global $wgRequest;
459 $logger = LoggerFactory::getInstance( 'wfDebug' );
460 if ( MW_ENTRY_POINT === 'cli' ) {
461 $self = $_SERVER['PHP_SELF'] ?? '';
462 $logger->debug( "\n\nStart command line script $self" );
463 } else {
464 $debug = "\n\nStart request {$wgRequest->getMethod()} {$wgRequest->getRequestURL()}\n";
465 $debug .= "IP: " . $wgRequest->getIP() . "\n";
466 $debug .= "HTTP HEADERS:\n";
467 foreach ( $wgRequest->getAllHeaders() as $name => $value ) {
468 $debug .= "$name: $value\n";
470 $debug .= "(end headers)";
471 $logger->debug( $debug );
473 } )();
475 // Most of the config is out, some might want to run hooks here.
476 ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )->onSetupAfterCache();
478 // Now that variant lists may be available, parse any action paths and article paths
479 // as query parameters.
481 // Skip title interpolation on API queries where it is useless and sometimes harmful (T18019).
483 // Optimization: Skip on load.php and all other entrypoints besides index.php to save time.
485 // TODO: Figure out if this can be safely done after everything else in Setup.php (e.g. any
486 // hooks or other state that would miss this?). If so, move to wfIndexMain or MediaWiki::run.
487 if ( MW_ENTRY_POINT === 'index' ) {
488 $wgRequest->interpolateTitle();
492 * @var MediaWiki\Session\SessionId|null $wgInitialSessionId The persistent session ID (if any) loaded at startup
494 $wgInitialSessionId = null;
495 if ( !defined( 'MW_NO_SESSION' ) && MW_ENTRY_POINT !== 'cli' ) {
496 // If session.auto_start is there, we can't touch session name
497 if ( $wgPHPSessionHandling !== 'disable' && !wfIniGetBool( 'session.auto_start' ) ) {
498 HeaderCallback::warnIfHeadersSent();
499 session_name( $wgSessionName ?: $wgCookiePrefix . '_session' );
502 // Create the SessionManager singleton and set up our session handler,
503 // unless we're specifically asked not to.
504 if ( !defined( 'MW_NO_SESSION_HANDLER' ) ) {
505 MediaWiki\Session\PHPSessionHandler::install(
506 MediaWiki\Session\SessionManager::singleton()
510 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
512 // Initialize the session
513 try {
514 $session = MediaWiki\Session\SessionManager::getGlobalSession();
515 } catch ( MediaWiki\Session\SessionOverflowException $ex ) {
516 // The exception is because the request had multiple possible
517 // sessions tied for top priority. Report this to the user.
518 $list = [];
519 foreach ( $ex->getSessionInfos() as $info ) {
520 $list[] = $info->getProvider()->describe( $contLang );
522 $list = $contLang->listToText( $list );
523 throw new HttpError( 400,
524 Message::newFromKey( 'sessionmanager-tie', $list )->inLanguage( $contLang )
528 unset( $contLang );
530 if ( $session->isPersistent() ) {
531 $wgInitialSessionId = $session->getSessionId();
534 $session->renew();
535 if ( MediaWiki\Session\PHPSessionHandler::isEnabled() &&
536 ( $session->isPersistent() || $session->shouldRememberUser() ) &&
537 session_id() !== $session->getId()
539 // Start the PHP-session for backwards compatibility
540 if ( session_id() !== '' ) {
541 wfDebugLog( 'session', 'PHP session {old_id} was already started, changing to {new_id}', 'all', [
542 'old_id' => session_id(),
543 'new_id' => $session->getId(),
544 ] );
545 session_write_close();
547 session_id( $session->getId() );
548 session_start();
551 unset( $session );
552 } else {
553 // Even if we didn't set up a global Session, still install our session
554 // handler unless specifically requested not to.
555 if ( !defined( 'MW_NO_SESSION_HANDLER' ) ) {
556 MediaWiki\Session\PHPSessionHandler::install(
557 MediaWiki\Session\SessionManager::singleton()
562 // Explicit globals, so this works with bootstrap.php
563 global $wgUser, $wgLang, $wgOut, $wgTitle;
566 * @var User $wgUser
567 * @deprecated since 1.35, use an available context source when possible, or, as a backup,
568 * RequestContext::getMain()
570 $wgUser = new StubGlobalUser( RequestContext::getMain()->getUser() ); // BackCompat
571 register_shutdown_function( static function () {
572 StubGlobalUser::$destructorDeprecationDisarmed = true;
573 } );
576 * @var Language|StubUserLang $wgLang
578 $wgLang = new StubUserLang;
581 * @var MediaWiki\Output\OutputPage $wgOut
583 $wgOut = RequestContext::getMain()->getOutput(); // BackCompat
586 * @var Title|null $wgTitle
588 $wgTitle = null;
590 // Explicit globals, so this works with bootstrap.php
591 global $wgFullyInitialised, $wgExtensionFunctions;
593 // Extension setup functions
594 // Entries should be added to this variable during the inclusion
595 // of the extension file. This allows the extension to perform
596 // any necessary initialisation in the fully initialised environment
597 foreach ( $wgExtensionFunctions as $func ) {
598 call_user_func( $func );
600 unset( $func ); // no global pollution; destroy reference
602 // If the session user has a 0 id but a valid name, that means we need to
603 // autocreate it.
604 if ( !defined( 'MW_NO_SESSION' ) && MW_ENTRY_POINT !== 'cli' ) {
605 $sessionUser = MediaWiki\Session\SessionManager::getGlobalSession()->getUser();
606 if ( $sessionUser->getId() === 0 &&
607 MediaWikiServices::getInstance()->getUserNameUtils()->isValid( $sessionUser->getName() )
609 MediaWikiServices::getInstance()->getAuthManager()->autoCreateUser(
610 $sessionUser,
611 MediaWiki\Auth\AuthManager::AUTOCREATE_SOURCE_SESSION,
612 true,
613 true,
614 $sessionUser
617 unset( $sessionUser );
620 // Optimization: Avoid overhead from DeferredUpdates and Pingback deps when turned off.
621 if ( MW_ENTRY_POINT !== 'cli' && $wgPingback ) {
622 // NOTE: Do not refactor to inject Config or otherwise make unconditional service call.
624 // On a plain install of MediaWiki, Pingback is likely the *only* feature
625 // involving DeferredUpdates or DB_PRIMARY on a regular page view.
626 // To allow for error recovery and fault isolation, let admins turn this
627 // off completely. (T269516)
628 DeferredUpdates::addCallableUpdate( static function () {
629 MediaWikiServices::getInstance()->getPingback()->run();
630 } );
633 $settingsWarnings = $wgSettings->getWarnings();
634 if ( $settingsWarnings ) {
635 $logger = LoggerFactory::getInstance( 'Settings' );
636 foreach ( $settingsWarnings as $msg ) {
637 $logger->warning( $msg );
639 unset( $logger );
642 unset( $settingsWarnings );
644 // Explicit globals, so this works with bootstrap.php
645 global $wgFullyInitialised;
646 $wgFullyInitialised = true;
648 // T264370
649 if ( !defined( 'MW_NO_SESSION' ) && MW_ENTRY_POINT !== 'cli' ) {
650 MediaWiki\Session\SessionManager::singleton()->logPotentialSessionLeakage();