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