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