Localisation updates from https://translatewiki.net.
[mediawiki.git] / includes / Setup.php
blob68000f6abdd6b782b45bf996493131a759266dcb
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, $IP, and $wgBaseDirectory,
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\Logger\LoggerFactory;
61 use MediaWiki\MainConfigNames;
62 use MediaWiki\MainConfigSchema;
63 use MediaWiki\MediaWikiServices;
64 use MediaWiki\Message\Message;
65 use MediaWiki\Registration\ExtensionRegistry;
66 use MediaWiki\Registration\MissingExtensionException;
67 use MediaWiki\Request\HeaderCallback;
68 use MediaWiki\Settings\DynamicDefaultValues;
69 use MediaWiki\Settings\LocalSettingsLoader;
70 use MediaWiki\Settings\SettingsBuilder;
71 use MediaWiki\Settings\Source\PhpSettingsSource;
72 use MediaWiki\Settings\Source\ReflectionSchemaSource;
73 use MediaWiki\Settings\WikiFarmSettingsLoader;
74 use MediaWiki\StubObject\StubGlobalUser;
75 use MediaWiki\StubObject\StubUserLang;
76 use MediaWiki\Title\Title;
77 use MediaWiki\User\User;
78 use Psr\Log\LoggerInterface;
79 use Wikimedia\RequestTimeout\RequestTimeout;
81 /**
82 * Environment checks
84 * These are inline checks done before we include any source files,
85 * and thus these conditions may be assumed by all source code.
88 // This file must be included from a valid entry point (e.g. WebStart.php, Maintenance.php)
89 if ( !defined( 'MEDIAWIKI' ) ) {
90 exit( 1 );
93 // PHP must not be configured to overload mbstring functions. (T5782, T122807)
94 // This was deprecated by upstream in PHP 7.2 and was removed in PHP 8.0.
95 if ( ini_get( 'mbstring.func_overload' ) ) {
96 die( 'MediaWiki does not support installations where mbstring.func_overload is non-zero.' );
99 // The MW_ENTRY_POINT constant must always exists, to make it safe to access.
100 // For compat, we do support older and custom MW entrypoints that don't set this,
101 // in which case we assign a default here.
102 if ( !defined( 'MW_ENTRY_POINT' ) ) {
104 * The entry point, which may be either the script filename without the
105 * file extension, or "cli" for maintenance scripts, or "unknown" for any
106 * entry point that does not set the constant.
108 define( 'MW_ENTRY_POINT', 'unknown' );
111 // The $IP variable is defined for use by LocalSettings.php.
112 // It is made available as a global variable for backwards compatibility.
114 // Source code should instead use the MW_INSTALL_PATH constant, or the
115 // MainConfigNames::BaseDirectory setting. The BaseDirectory setting is set further
116 // down in Setup.php to the value of MW_INSTALL_PATH.
117 global $IP;
118 $IP = wfDetectInstallPath(); // ensure MW_INSTALL_PATH is defined
121 * Pre-config setup: Before loading LocalSettings.php
123 * These are changes and additions to runtime that don't vary on site configuration.
125 require_once MW_INSTALL_PATH . '/includes/AutoLoader.php';
126 require_once MW_INSTALL_PATH . '/includes/Defines.php';
128 // Assert that composer dependencies were successfully loaded
129 if ( !interface_exists( LoggerInterface::class ) ) {
130 $message = (
131 'MediaWiki requires the <a href="https://github.com/php-fig/log">PSR-3 logging ' .
132 "library</a> to be present. This library is not embedded directly in MediaWiki's " .
133 "git repository and must be installed separately by the end user.\n\n" .
134 'Please see the <a href="https://www.mediawiki.org/wiki/Download_from_Git' .
135 '#Fetch_external_libraries">instructions for installing libraries</a> on mediawiki.org ' .
136 'for help on installing the required components.'
138 echo $message;
139 trigger_error( $message, E_USER_ERROR );
142 // Deprecated global variable for backwards-compatibility.
143 // New code should check MW_ENTRY_POINT directly.
144 $wgCommandLineMode = MW_ENTRY_POINT === 'cli';
147 * $wgConf hold the site configuration.
148 * Not used for much in a default install.
149 * @since 1.5
151 $wgConf = new SiteConfiguration;
153 $wgAutoloadClasses ??= [];
155 $wgSettings = SettingsBuilder::getInstance();
157 if ( defined( 'MW_USE_CONFIG_SCHEMA_CLASS' ) ) {
158 // Load config schema from MainConfigSchema. Useful for running scripts that
159 // generate other representations of the config schema. This is slow, so it
160 // should not be used for serving web traffic.
161 $wgSettings->load( new ReflectionSchemaSource( MainConfigSchema::class ) );
162 } else {
163 $wgSettings->load( new PhpSettingsSource( MW_INSTALL_PATH . '/includes/config-schema.php' ) );
166 require_once MW_INSTALL_PATH . '/includes/GlobalFunctions.php';
168 HeaderCallback::register();
170 // Set the encoding used by PHP for reading HTTP input, and writing output.
171 // This is also the default for mbstring functions.
172 mb_internal_encoding( 'UTF-8' );
175 * Load LocalSettings.php
178 // Initialize some config settings with dynamic defaults, and
179 // make default settings available in globals for use in LocalSettings.php.
180 $wgSettings->putConfigValues( [
181 MainConfigNames::BaseDirectory => MW_INSTALL_PATH,
182 MainConfigNames::ExtensionDirectory => MW_INSTALL_PATH . '/extensions',
183 MainConfigNames::StyleDirectory => MW_INSTALL_PATH . '/skins',
184 MainConfigNames::ServiceWiringFiles => [ MW_INSTALL_PATH . '/includes/ServiceWiring.php' ],
185 'Version' => MW_VERSION,
186 ] );
187 $wgSettings->apply();
189 // $wgSettings->apply() puts all configuration into global variables.
190 // If we are not in global scope, make all relevant globals available
191 // in this file's scope as well.
192 $wgScopeTest = 'MediaWiki Setup.php scope test';
193 if ( !isset( $GLOBALS['wgScopeTest'] ) || $GLOBALS['wgScopeTest'] !== $wgScopeTest ) {
194 foreach ( $wgSettings->getConfigSchema()->getDefinedKeys() as $key ) {
195 $var = "wg$key";
196 // phpcs:ignore MediaWiki.NamingConventions.ValidGlobalName.allowedPrefix
197 global $$var;
199 unset( $key, $var );
201 unset( $wgScopeTest );
203 try {
204 if ( defined( 'MW_CONFIG_CALLBACK' ) ) {
205 call_user_func( MW_CONFIG_CALLBACK, $wgSettings );
206 } else {
207 wfDetectLocalSettingsFile( MW_INSTALL_PATH );
209 if ( getenv( 'MW_USE_LOCAL_SETTINGS_LOADER' ) ) {
210 // NOTE: This will not work for configuration variables that use a prefix
211 // other than "wg".
212 $localSettingsLoader = new LocalSettingsLoader( $wgSettings, MW_INSTALL_PATH );
213 $localSettingsLoader->loadLocalSettingsFile( MW_CONFIG_FILE );
214 unset( $localSettingsLoader );
215 } else {
216 if ( str_ends_with( MW_CONFIG_FILE, '.php' ) ) {
217 // make defaults available as globals
218 $wgSettings->apply();
219 require_once MW_CONFIG_FILE;
220 } else {
221 $wgSettings->loadFile( MW_CONFIG_FILE );
226 // Make settings loaded by LocalSettings.php available in globals for use here
227 $wgSettings->apply();
228 } catch ( MissingExtensionException $e ) {
229 // Make a common mistake give a friendly error
230 $e->render();
233 // If in a wiki-farm, load site-specific settings
234 if ( $wgSettings->getConfig()->get( MainConfigNames::WikiFarmSettingsDirectory ) ) {
235 $wikiFarmSettingsLoader = new WikiFarmSettingsLoader( $wgSettings );
236 $wikiFarmSettingsLoader->loadWikiFarmSettings();
237 unset( $wikiFarmSettingsLoader );
240 // All settings should be loaded now.
241 $wgSettings->enterRegistrationStage();
244 * Customization point after most things are loaded (constants, functions, classes,
245 * LocalSettings.
246 * Note that this runs before extensions are registered, and before most singletons become
247 * available, and before MediaWikiServices is initialized.
250 if ( defined( 'MW_SETUP_CALLBACK' ) ) {
251 call_user_func( MW_SETUP_CALLBACK, $wgSettings );
252 // Make any additional settings available in globals for use here
253 $wgSettings->apply();
256 // Apply dynamic defaults declared in config schema callbacks.
257 $dynamicDefaults = new DynamicDefaultValues( $wgSettings->getConfigSchema() );
258 $dynamicDefaults->applyDynamicDefaults( $wgSettings->getConfigBuilder() );
260 // Make updated config available in global scope.
261 $wgSettings->apply();
263 // Apply dynamic defaults implemented in SetupDynamicConfig.php.
264 // Ideally, all logic in SetupDynamicConfig would be converted to
265 // callbacks in the config schema.
266 require __DIR__ . '/SetupDynamicConfig.php';
268 if ( defined( 'MW_AUTOLOAD_TEST_CLASSES' ) ) {
269 require_once __DIR__ . '/../tests/common/TestsAutoLoader.php';
272 if ( $wgBaseDirectory !== MW_INSTALL_PATH ) {
273 throw new FatalError(
274 '$wgBaseDirectory must not be modified in settings files! ' .
275 'Use the MW_INSTALL_PATH environment variable to override the installation root directory.'
279 // Start time limit
280 if ( $wgRequestTimeLimit && MW_ENTRY_POINT !== 'cli' ) {
281 RequestTimeout::singleton()->setWallTimeLimit( $wgRequestTimeLimit );
285 * Load queued extensions
287 if ( defined( 'MW_AUTOLOAD_TEST_CLASSES' ) ) {
288 ExtensionRegistry::getInstance()->setLoadTestClassesAndNamespaces( true );
291 ExtensionRegistry::getInstance()->setSettingsBuilder( $wgSettings );
292 ExtensionRegistry::getInstance()->loadFromQueue();
293 // Don't let any other extensions load
294 ExtensionRegistry::getInstance()->finish();
297 * Customization point after ALL loading (constants, functions, classes,
298 * LocalSettings, extensions, dynamic defaults).
299 * Note that this runs before MediaWikiServices is initialized.
301 if ( defined( 'MW_FINAL_SETUP_CALLBACK' ) ) {
302 call_user_func( MW_FINAL_SETUP_CALLBACK, $wgSettings );
303 // Make any additional settings available in globals for use below
304 $wgSettings->apply();
307 // Config can no longer be changed.
308 $wgSettings->enterReadOnlyStage();
310 // Set an appropriate locale (T291234)
311 // setlocale() will return the locale name actually set.
312 // The putenv() is meant to propagate the choice of locale to shell commands
313 // so that they will interpret UTF-8 correctly. If you have a problem with a
314 // shell command and need to send a special locale, you can override the locale
315 // with Command::environment().
316 putenv( "LC_ALL=" . setlocale( LC_ALL, 'C.UTF-8', 'C' ) );
318 // Set PHP runtime to the desired timezone
319 date_default_timezone_set( $wgLocaltimezone );
321 MWDebug::setup();
323 // Enable the global service locator.
324 // Trivial expansion of site configuration should go before this point.
325 // Any non-trivial expansion that requires calling into MediaWikiServices or other parts of MW.
326 MediaWikiServices::allowGlobalInstance();
328 // Define a constant that indicates that the bootstrapping of the service locator
329 // is complete.
330 define( 'MW_SERVICE_BOOTSTRAP_COMPLETE', 1 );
332 MWExceptionRenderer::setShowExceptionDetails( $wgShowExceptionDetails );
333 if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
334 // Never install the handler in PHPUnit tests, otherwise PHPUnit's own handler will be unset and things
335 // like convertWarningsToExceptions won't work.
336 MWExceptionHandler::installHandler( $wgLogExceptionBacktrace, $wgPropagateErrors );
338 Profiler::init( $wgProfiler );
340 // Non-trivial validation of: $wgServer
341 // The FatalError page only renders cleanly after MWExceptionHandler is installed.
342 if ( $wgServer === false ) {
343 // T30798: $wgServer must be explicitly set
344 throw new FatalError(
345 '$wgServer must be set in LocalSettings.php. ' .
346 'See <a href="https://www.mediawiki.org/wiki/Manual:$wgServer">' .
347 'https://www.mediawiki.org/wiki/Manual:$wgServer</a>.'
351 // Set up a fake $wgHooks array.
352 // XXX: It would be nice if we could still get the originally configured hook handlers
353 // using the MainConfigNames::Hooks setting, but it's not really needed,
354 // since we need the HookContainer to be initialized first anyway.
356 global $wgHooks;
357 $wgHooks = new FauxGlobalHookArray(
358 MediaWikiServices::getInstance()->getHookContainer(),
359 $wgHooks
362 // Non-trivial expansion of: $wgCanonicalServer, $wgServerName.
363 // These require calling global functions.
364 // Also here are other settings that further depend on these two.
365 if ( $wgCanonicalServer === false ) {
366 $wgCanonicalServer = MediaWikiServices::getInstance()->getUrlUtils()->getCanonicalServer();
368 $wgVirtualRestConfig['global']['domain'] = $wgCanonicalServer;
370 if ( $wgServerName !== false ) {
371 wfWarn( '$wgServerName should be derived from $wgCanonicalServer, '
372 . 'not customized. Overwriting $wgServerName.' );
374 $wgServerName = parse_url( $wgCanonicalServer, PHP_URL_HOST );
376 // $wgEmergencyContact and $wgPasswordSender may be false or empty string (T104142)
377 if ( !$wgEmergencyContact ) {
378 $wgEmergencyContact = 'wikiadmin@' . $wgServerName;
380 if ( !$wgPasswordSender ) {
381 $wgPasswordSender = 'apache@' . $wgServerName;
383 if ( !$wgNoReplyAddress ) {
384 $wgNoReplyAddress = $wgPasswordSender;
387 // Non-trivial expansion of: $wgSecureLogin
388 // (due to calling wfWarn).
389 if ( $wgSecureLogin && substr( $wgServer, 0, 2 ) !== '//' ) {
390 $wgSecureLogin = false;
391 wfWarn( 'Secure login was enabled on a server that only supports '
392 . 'HTTP or HTTPS. Disabling secure login.' );
395 // Now that GlobalFunctions is loaded, set defaults that depend on it.
396 if ( $wgTmpDirectory === false ) {
397 $wgTmpDirectory = wfTempDir();
400 if ( $wgSharedDB && $wgSharedTables ) {
401 // Apply $wgSharedDB table aliases for the local LB (all non-foreign DB connections)
402 MediaWikiServices::getInstance()->getDBLoadBalancer()->setTableAliases(
403 array_fill_keys(
404 $wgSharedTables,
406 'dbname' => $wgSharedDB,
407 'schema' => $wgSharedSchema,
408 'prefix' => $wgSharedPrefix
414 // Raise the memory limit if it's too low
415 // NOTE: This use wfDebug, and must remain after the MWDebug::setup() call.
416 wfMemoryLimit( $wgMemoryLimit );
418 // Explicit globals, so this works with bootstrap.php
419 global $wgRequest, $wgInitialSessionId;
421 // Initialize the request object in $wgRequest
422 $wgRequest = RequestContext::getMain()->getRequest(); // BackCompat
424 // Make sure that object caching does not undermine the ChronologyProtector improvements
425 if ( $wgRequest->getCookie( 'UseDC', '' ) === 'master' ) {
426 // The user is pinned to the primary DC, meaning that they made recent changes which should
427 // be reflected in their subsequent web requests. Avoid the use of interim cache keys because
428 // they use a blind TTL and could be stale if an object changes twice in a short time span.
429 MediaWikiServices::getInstance()->getMainWANObjectCache()->useInterimHoldOffCaching( false );
432 // Useful debug output
433 ( static function () {
434 global $wgRequest;
436 $logger = LoggerFactory::getInstance( 'wfDebug' );
437 if ( MW_ENTRY_POINT === 'cli' ) {
438 $self = $_SERVER['PHP_SELF'] ?? '';
439 $logger->debug( "\n\nStart command line script $self" );
440 } else {
441 $debug = "\n\nStart request {$wgRequest->getMethod()} {$wgRequest->getRequestURL()}\n";
442 $debug .= "IP: " . $wgRequest->getIP() . "\n";
443 $debug .= "HTTP HEADERS:\n";
444 foreach ( $wgRequest->getAllHeaders() as $name => $value ) {
445 $debug .= "$name: $value\n";
447 $debug .= "(end headers)";
448 $logger->debug( $debug );
450 } )();
452 // Most of the config is out, some might want to run hooks here.
453 ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )->onSetupAfterCache();
455 // Now that variant lists may be available, parse any action paths and article paths
456 // as query parameters.
458 // Skip title interpolation on API queries where it is useless and sometimes harmful (T18019).
460 // Optimization: Skip on load.php and all other entrypoints besides index.php to save time.
462 // TODO: Figure out if this can be safely done after everything else in Setup.php (e.g. any
463 // hooks or other state that would miss this?). If so, move to wfIndexMain or MediaWiki::run.
464 if ( MW_ENTRY_POINT === 'index' ) {
465 $wgRequest->interpolateTitle();
469 * @var MediaWiki\Session\SessionId|null $wgInitialSessionId The persistent session ID (if any) loaded at startup
471 $wgInitialSessionId = null;
472 if ( !defined( 'MW_NO_SESSION' ) && MW_ENTRY_POINT !== 'cli' ) {
473 // If session.auto_start is there, we can't touch session name
474 if ( $wgPHPSessionHandling !== 'disable' && !wfIniGetBool( 'session.auto_start' ) ) {
475 HeaderCallback::warnIfHeadersSent();
476 session_name( $wgSessionName ?: $wgCookiePrefix . '_session' );
479 // Create the SessionManager singleton and set up our session handler,
480 // unless we're specifically asked not to.
481 if ( !defined( 'MW_NO_SESSION_HANDLER' ) ) {
482 MediaWiki\Session\PHPSessionHandler::install(
483 MediaWiki\Session\SessionManager::singleton()
487 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
489 // Initialize the session
490 try {
491 $session = MediaWiki\Session\SessionManager::getGlobalSession();
492 } catch ( MediaWiki\Session\SessionOverflowException $ex ) {
493 // The exception is because the request had multiple possible
494 // sessions tied for top priority. Report this to the user.
495 $list = [];
496 foreach ( $ex->getSessionInfos() as $info ) {
497 $list[] = $info->getProvider()->describe( $contLang );
499 $list = $contLang->listToText( $list );
500 throw new HttpError( 400,
501 Message::newFromKey( 'sessionmanager-tie', $list )->inLanguage( $contLang )
505 unset( $contLang );
507 if ( $session->isPersistent() ) {
508 $wgInitialSessionId = $session->getSessionId();
511 $session->renew();
512 if ( MediaWiki\Session\PHPSessionHandler::isEnabled() &&
513 ( $session->isPersistent() || $session->shouldRememberUser() ) &&
514 session_id() !== $session->getId()
516 // Start the PHP-session for backwards compatibility
517 if ( session_id() !== '' ) {
518 wfDebugLog( 'session', 'PHP session {old_id} was already started, changing to {new_id}', 'all', [
519 'old_id' => session_id(),
520 'new_id' => $session->getId(),
521 ] );
522 session_write_close();
524 session_id( $session->getId() );
525 session_start();
528 unset( $session );
529 } else {
530 // Even if we didn't set up a global Session, still install our session
531 // handler unless specifically requested not to.
532 if ( !defined( 'MW_NO_SESSION_HANDLER' ) ) {
533 MediaWiki\Session\PHPSessionHandler::install(
534 MediaWiki\Session\SessionManager::singleton()
539 // Explicit globals, so this works with bootstrap.php
540 global $wgUser, $wgLang, $wgOut, $wgTitle;
543 * @var User $wgUser
544 * @deprecated since 1.35, use an available context source when possible, or, as a backup,
545 * RequestContext::getMain()
547 $wgUser = new StubGlobalUser( RequestContext::getMain()->getUser() ); // BackCompat
548 register_shutdown_function( static function () {
549 StubGlobalUser::$destructorDeprecationDisarmed = true;
550 } );
553 * @var Language|StubUserLang $wgLang
555 $wgLang = new StubUserLang;
558 * @var MediaWiki\Output\OutputPage $wgOut
560 $wgOut = RequestContext::getMain()->getOutput(); // BackCompat
563 * @var Title|null $wgTitle
565 $wgTitle = null;
567 // Explicit globals, so this works with bootstrap.php
568 global $wgFullyInitialised, $wgExtensionFunctions;
570 // Extension setup functions
571 // Entries should be added to this variable during the inclusion
572 // of the extension file. This allows the extension to perform
573 // any necessary initialisation in the fully initialised environment
574 foreach ( $wgExtensionFunctions as $func ) {
575 call_user_func( $func );
577 unset( $func ); // no global pollution; destroy reference
579 // If the session user has a 0 id but a valid name, that means we need to
580 // autocreate it.
581 if ( !defined( 'MW_NO_SESSION' ) && MW_ENTRY_POINT !== 'cli' ) {
582 $sessionUser = MediaWiki\Session\SessionManager::getGlobalSession()->getUser();
583 if ( $sessionUser->getId() === 0 &&
584 MediaWikiServices::getInstance()->getUserNameUtils()->isValid( $sessionUser->getName() )
586 $res = MediaWikiServices::getInstance()->getAuthManager()->autoCreateUser(
587 $sessionUser,
588 MediaWiki\Auth\AuthManager::AUTOCREATE_SOURCE_SESSION,
589 true,
590 true,
591 $sessionUser
593 $firstMessage = $res->getMessages( 'error' )[0] ?? $res->getMessages( 'warning' )[0] ?? null;
594 \MediaWiki\Logger\LoggerFactory::getInstance( 'authevents' )->info( 'Autocreation attempt', [
595 'event' => 'autocreate',
596 'successful' => $res->isGood(),
597 'status' => $firstMessage ? $firstMessage->getKey() : '-',
598 ] );
599 unset( $res );
600 unset( $firstMessage );
602 unset( $sessionUser );
605 // Optimization: Avoid overhead from DeferredUpdates and Pingback deps when turned off.
606 if ( MW_ENTRY_POINT !== 'cli' && $wgPingback ) {
607 // NOTE: Do not refactor to inject Config or otherwise make unconditional service call.
609 // On a plain install of MediaWiki, Pingback is likely the *only* feature
610 // involving DeferredUpdates or DB_PRIMARY on a regular page view.
611 // To allow for error recovery and fault isolation, let admins turn this
612 // off completely. (T269516)
613 DeferredUpdates::addCallableUpdate( static function () {
614 MediaWikiServices::getInstance()->getPingback()->run();
615 } );
618 $settingsWarnings = $wgSettings->getWarnings();
619 if ( $settingsWarnings ) {
620 $logger = LoggerFactory::getInstance( 'Settings' );
621 foreach ( $settingsWarnings as $msg ) {
622 $logger->warning( $msg );
624 unset( $logger );
627 unset( $settingsWarnings );
629 // Explicit globals, so this works with bootstrap.php
630 global $wgFullyInitialised;
631 $wgFullyInitialised = true;
633 // T264370
634 if ( !defined( 'MW_NO_SESSION' ) && MW_ENTRY_POINT !== 'cli' ) {
635 MediaWiki\Session\SessionManager::singleton()->logPotentialSessionLeakage();