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