Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 226
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2/**
3 * This is included by Setup.php to adjust the values of globals before services are initialized.
4 * It's split into a separate file so it can be tested.
5 */
6
7use MediaWiki\Language\LanguageCode;
8use MediaWiki\MainConfigSchema;
9use MediaWiki\Title\NamespaceInfo;
10use Wikimedia\AtEase\AtEase;
11
12// For backwards compatibility, the value of wgLogos is copied to wgLogo.
13// This is because some extensions/skins may be using $config->get('Logo')
14// to access the value.
15if ( $wgLogos !== false && isset( $wgLogos['1x'] ) ) {
16    $wgLogo = $wgLogos['1x'];
17}
18
19// Back-compat
20if ( isset( $wgFileBlacklist ) ) {
21    $wgProhibitedFileExtensions = array_merge( $wgProhibitedFileExtensions, $wgFileBlacklist );
22} else {
23    $wgFileBlacklist = $wgProhibitedFileExtensions;
24}
25if ( isset( $wgMimeTypeBlacklist ) ) {
26    $wgMimeTypeExclusions = array_merge( $wgMimeTypeExclusions, $wgMimeTypeBlacklist );
27} else {
28    $wgMimeTypeBlacklist = $wgMimeTypeExclusions;
29}
30if ( isset( $wgEnableUserEmailBlacklist ) ) {
31    $wgEnableUserEmailMuteList = $wgEnableUserEmailBlacklist;
32} else {
33    $wgEnableUserEmailBlacklist = $wgEnableUserEmailMuteList;
34}
35if ( isset( $wgShortPagesNamespaceBlacklist ) ) {
36    $wgShortPagesNamespaceExclusions = $wgShortPagesNamespaceBlacklist;
37} else {
38    $wgShortPagesNamespaceBlacklist = $wgShortPagesNamespaceExclusions;
39}
40
41// Rate limits should have the same name as the corresponding permission
42if ( isset( $wgRateLimits['emailuser'] ) ) {
43    // If the deprecated field is set, use it.
44    // Note that we can't know whether the new field has been set explicitly, since it has a default value.
45    $wgSettings->warning(
46        'RateLimit: The "emailuser" limit is deprecated, use "sendemail" instead.'
47    );
48    $wgRateLimits['sendemail'] = $wgRateLimits['emailuser'];
49}
50
51// Rate limits should have the same name as the corresponding permission
52if ( isset( $wgRateLimits['changetag'] ) ) {
53    // If the deprecated field is set, use it.
54    // Note that we can't know whether the new field has been set explicitly, since it has a default value.
55    $wgSettings->warning(
56        'RateLimit: The "changetag" limit is deprecated, use "changetags" instead.'
57    );
58    $wgRateLimits['changetags'] = $wgRateLimits['changetag'];
59}
60
61// Prohibited file extensions shouldn't appear on the "allowed" list
62// @phan-suppress-next-line PhanTypeMismatchArgumentNullableInternal False positive
63$wgFileExtensions = array_values( array_diff( $wgFileExtensions, $wgProhibitedFileExtensions ) );
64
65// Fix path to icon images after they were moved in 1.24
66if ( $wgRightsIcon ) {
67    $wgRightsIcon = str_replace(
68        "{$wgStylePath}/common/images/",
69        "{$wgResourceBasePath}/resources/assets/licenses/",
70        $wgRightsIcon
71    );
72}
73
74if ( isset( $wgFooterIcons['copyright']['copyright'] )
75    && $wgFooterIcons['copyright']['copyright'] === []
76) {
77    if ( $wgRightsIcon || $wgRightsText ) {
78        $wgFooterIcons['copyright']['copyright'] = [
79            'url' => $wgRightsUrl,
80            'src' => $wgRightsIcon,
81            'alt' => $wgRightsText,
82        ];
83    }
84}
85
86if ( isset( $wgFooterIcons['poweredby'] )
87    && isset( $wgFooterIcons['poweredby']['mediawiki'] )
88    && is_array( $wgFooterIcons['poweredby']['mediawiki'] )
89    && $wgFooterIcons['poweredby']['mediawiki']['src'] === null
90) {
91    $compactLogo = "$wgResourceBasePath/resources/assets/mediawiki_compact.svg";
92    $wgFooterIcons['poweredby']['mediawiki']['sources'] = [
93        [
94            "media" => "(min-width: 500px)",
95            "srcset" => "$wgResourceBasePath/resources/assets/poweredby_mediawiki.svg",
96            "width" => 88,
97            "height" => 31,
98        ]
99    ];
100    $wgFooterIcons['poweredby']['mediawiki']['src'] = $compactLogo;
101    $wgFooterIcons['poweredby']['mediawiki']['width'] = 25;
102    $wgFooterIcons['poweredby']['mediawiki']['height'] = 25;
103}
104
105// Unconditional protection for NS_MEDIAWIKI since otherwise it's too easy for a
106// sysadmin to set $wgNamespaceProtection incorrectly and leave the wiki insecure.
107//
108// Note that this is the definition of editinterface and it can be granted to
109// all users if desired.
110$wgNamespaceProtection[NS_MEDIAWIKI] = 'editinterface';
111
112// Initialise $wgLockManagers to include basic FS version
113$wgLockManagers[] = [
114    'name' => 'fsLockManager',
115    'class' => FSLockManager::class,
116    'lockDirectory' => "{$wgUploadDirectory}/lockdir",
117];
118$wgLockManagers[] = [
119    'name' => 'nullLockManager',
120    'class' => NullLockManager::class,
121];
122
123// Default parameters for the "<gallery>" tag.
124// See \MediaWiki\MainConfigSchema::GalleryOptions
125$wgGalleryOptions += [
126    'imagesPerRow' => 0,
127    'imageWidth' => 120,
128    'imageHeight' => 120,
129    'captionLength' => true,
130    'showBytes' => true,
131    'showDimensions' => true,
132    'mode' => 'traditional',
133];
134
135if ( isset( $wgLocalFileRepo['name'] ) && !isset( $wgLocalFileRepo['backend'] ) ) {
136    // Create a default FileBackend name.
137    // FileBackendGroup will register a default, if absent from $wgFileBackends.
138    $wgLocalFileRepo['backend'] = $wgLocalFileRepo['name'] . '-backend';
139}
140
141/**
142 * Shortcuts for $wgForeignFileRepos
143 */
144if ( $wgUseSharedUploads ) {
145    if ( $wgSharedUploadDBname ) {
146        $wgForeignFileRepos[] = [
147            'class' => ForeignDBRepo::class,
148            'name' => 'shared',
149            'directory' => $wgSharedUploadDirectory,
150            'url' => $wgSharedUploadPath,
151            'hashLevels' => $wgHashedSharedUploadDirectory ? 2 : 0,
152            'thumbScriptUrl' => $wgSharedThumbnailScriptPath,
153            'transformVia404' => !$wgGenerateThumbnailOnParse,
154            'dbType' => $wgDBtype,
155            'dbServer' => $wgDBserver,
156            'dbUser' => $wgDBuser,
157            'dbPassword' => $wgDBpassword,
158            'dbName' => $wgSharedUploadDBname,
159            'dbFlags' => ( $wgDebugDumpSql ? DBO_DEBUG : 0 ) | DBO_DEFAULT,
160            'tablePrefix' => $wgSharedUploadDBprefix,
161            'hasSharedCache' => $wgCacheSharedUploads,
162            'descBaseUrl' => $wgRepositoryBaseUrl,
163            'fetchDescription' => $wgFetchCommonsDescriptions,
164        ];
165    } else {
166        $wgForeignFileRepos[] = [
167            'class' => FileRepo::class,
168            'name' => 'shared',
169            'directory' => $wgSharedUploadDirectory,
170            'url' => $wgSharedUploadPath,
171            'hashLevels' => $wgHashedSharedUploadDirectory ? 2 : 0,
172            'thumbScriptUrl' => $wgSharedThumbnailScriptPath,
173            'transformVia404' => !$wgGenerateThumbnailOnParse,
174            'descBaseUrl' => $wgRepositoryBaseUrl,
175            'fetchDescription' => $wgFetchCommonsDescriptions,
176        ];
177    }
178}
179if ( $wgUseInstantCommons ) {
180    $wgForeignFileRepos[] = [
181        'class' => ForeignAPIRepo::class,
182        'name' => 'wikimediacommons',
183        'apibase' => 'https://commons.wikimedia.org/w/api.php',
184        'url' => 'https://upload.wikimedia.org/wikipedia/commons',
185        'thumbUrl' => 'https://upload.wikimedia.org/wikipedia/commons/thumb',
186        'hashLevels' => 2,
187        'transformVia404' => true,
188        'fetchDescription' => true,
189        'descriptionCacheExpiry' => 43200,
190        'apiThumbCacheExpiry' => 0,
191    ];
192}
193foreach ( $wgForeignFileRepos as &$repo ) {
194    if ( !isset( $repo['directory'] ) && $repo['class'] === ForeignAPIRepo::class ) {
195        $repo['directory'] = $wgUploadDirectory; // b/c
196    }
197    if ( !isset( $repo['backend'] ) ) {
198        $repo['backend'] = $repo['name'] . '-backend';
199    }
200}
201unset( $repo ); // no global pollution; destroy reference
202
203$rcMaxAgeDays = $wgRCMaxAge / ( 3600 * 24 );
204// Ensure that default user options are not invalid, since that breaks Special:Preferences
205$wgDefaultUserOptions['rcdays'] = min(
206    $wgDefaultUserOptions['rcdays'],
207    ceil( $rcMaxAgeDays )
208);
209$wgDefaultUserOptions['watchlistdays'] = min(
210    $wgDefaultUserOptions['watchlistdays'],
211    ceil( $rcMaxAgeDays )
212);
213unset( $rcMaxAgeDays );
214
215$wgCookiePrefix = strtr( $wgCookiePrefix, '=,; +."\'\\[', '__________' );
216
217if ( !$wgEnableEmail ) {
218    // Disable all other email settings automatically if $wgEnableEmail
219    // is set to false. - T65678
220    $wgAllowHTMLEmail = false;
221    $wgEmailAuthentication = false; // do not require auth if you're not sending email anyway
222    $wgEnableUserEmail = false;
223    $wgEnotifFromEditor = false;
224    $wgEnotifImpersonal = false;
225    $wgEnotifMaxRecips = 0;
226    $wgEnotifMinorEdits = false;
227    $wgEnotifRevealEditorAddress = false;
228    $wgEnotifUseRealName = false;
229    $wgEnotifUserTalk = false;
230    $wgEnotifWatchlist = false;
231    unset( $wgGroupPermissions['user']['sendemail'] );
232    $wgUserEmailUseReplyTo = false;
233    $wgUsersNotifiedOnAllChanges = [];
234}
235
236if ( !$wgLocaltimezone ) {
237    // NOTE: The automatic dynamic default only kicks in if $wgLocaltimezone is null,
238    //       but the installer writes $wgLocaltimezone into LocalSettings, and may
239    //       produce (or may have produced historically) an empty string for some
240    //       reason. To be compatible with existing LocalSettings.php files, we need
241    //       to gracefully handle the case of $wgLocaltimezone being the empty string.
242    //       See T305093#8063451.
243    $wgLocaltimezone = MainConfigSchema::getDefaultLocaltimezone();
244    $wgSettings->warning(
245        'The Localtimezone setting must a valid timezone string or null. '
246        . 'It must not be an empty string or false.'
247    );
248}
249
250// The part after the System| is ignored, but rest of MW fills it out as the local offset.
251$wgDefaultUserOptions['timecorrection'] = "System|$wgLocalTZoffset";
252
253/**
254 * Definitions of the NS_ constants are in Defines.php
255 * @internal
256 */
257$wgCanonicalNamespaceNames = NamespaceInfo::CANONICAL_NAMES;
258
259// Hard-deprecate setting $wgDummyLanguageCodes in LocalSettings.php
260if ( count( $wgDummyLanguageCodes ) !== 0 ) {
261    $wgSettings->warning(
262        'Do not add to DummyLanguageCodes directly, ' .
263        'add to ExtraLanguageCodes instead.'
264    );
265}
266// Merge in the legacy language codes, incorporating overrides from the config
267$wgDummyLanguageCodes += [
268    // Internal language codes of the private-use area which get mapped to
269    // themselves.
270    'qqq' => 'qqq', // Used for message documentation
271    'qqx' => 'qqx', // Used for viewing message keys
272] + $wgExtraLanguageCodes + LanguageCode::getDeprecatedCodeMapping();
273// Merge in (inverted) BCP 47 mappings
274foreach ( LanguageCode::getNonstandardLanguageCodeMapping() as $code => $bcp47 ) {
275    $bcp47 = strtolower( $bcp47 ); // force case-insensitivity
276    if ( !isset( $wgDummyLanguageCodes[$bcp47] ) ) {
277        $wgDummyLanguageCodes[$bcp47] = $wgDummyLanguageCodes[$code] ?? $code;
278    }
279}
280unset( $code ); // no global pollution; destroy reference
281unset( $bcp47 ); // no global pollution; destroy reference
282if ( $wgUseXssLanguage ) {
283    $wgDummyLanguageCodes['x-xss'] = 'x-xss'; // Used for testing
284}
285
286// Temporary backwards-compatibility reading of old replica lag settings as of MediaWiki 1.36,
287// to support sysadmins who fail to update their settings immediately:
288
289if ( isset( $wgSlaveLagWarning ) ) {
290    // If the old value is set to something other than the default, use it.
291    if ( $wgDatabaseReplicaLagWarning === 10 && $wgSlaveLagWarning !== 10 ) {
292        $wgDatabaseReplicaLagWarning = $wgSlaveLagWarning;
293        $wgSettings->warning( 'SlaveLagWarning is no longer supported, ' .
294            'use DatabaseReplicaLagWarning instead!' );
295    }
296} else {
297    // Backwards-compatibility for extensions that read this value.
298    $wgSlaveLagWarning = $wgDatabaseReplicaLagWarning;
299}
300
301if ( isset( $wgSlaveLagCritical ) ) {
302    // If the old value is set to something other than the default, use it.
303    if ( $wgDatabaseReplicaLagCritical === 30 && $wgSlaveLagCritical !== 30 ) {
304        $wgDatabaseReplicaLagCritical = $wgSlaveLagCritical;
305        $wgSettings->warning( 'SlaveLagCritical is no longer supported, ' .
306            'use DatabaseReplicaLagCritical instead!' );
307    }
308} else {
309    // Backwards-compatibility for extensions that read this value.
310    $wgSlaveLagCritical = $wgDatabaseReplicaLagCritical;
311}
312
313if ( $wgInvalidateCacheOnLocalSettingsChange && defined( 'MW_CONFIG_FILE' ) ) {
314    AtEase::suppressWarnings();
315    $wgCacheEpoch = max( $wgCacheEpoch, gmdate( 'YmdHis', filemtime( MW_CONFIG_FILE ) ) );
316    AtEase::restoreWarnings();
317}
318
319if ( $wgNewUserLog ) {
320    // Add new user log type
321    $wgLogTypes[] = 'newusers';
322    $wgLogNames['newusers'] = 'newuserlogpage';
323    $wgLogHeaders['newusers'] = 'newuserlogpagetext';
324    $wgLogActionsHandlers['newusers/newusers'] = NewUsersLogFormatter::class;
325    $wgLogActionsHandlers['newusers/create'] = NewUsersLogFormatter::class;
326    $wgLogActionsHandlers['newusers/create2'] = NewUsersLogFormatter::class;
327    $wgLogActionsHandlers['newusers/byemail'] = NewUsersLogFormatter::class;
328    $wgLogActionsHandlers['newusers/autocreate'] = NewUsersLogFormatter::class;
329}
330
331if ( $wgPageCreationLog ) {
332    // Add page creation log type
333    $wgLogTypes[] = 'create';
334    $wgLogActionsHandlers['create/create'] = LogFormatter::class;
335}
336
337if ( $wgPageLanguageUseDB ) {
338    $wgLogTypes[] = 'pagelang';
339    $wgLogActionsHandlers['pagelang/pagelang'] = [
340        'class' => PageLangLogFormatter::class,
341        'services' => [
342            'LanguageNameUtils',
343        ]
344    ];
345}
346
347if ( $wgPHPSessionHandling !== 'enable' &&
348    $wgPHPSessionHandling !== 'warn' &&
349    $wgPHPSessionHandling !== 'disable'
350) {
351    $wgPHPSessionHandling = 'warn';
352}
353if ( defined( 'MW_NO_SESSION' ) ) {
354    // If the entry point wants no session, force 'disable' here unless they
355    // specifically set it to the (undocumented) 'warn'.
356    $wgPHPSessionHandling = MW_NO_SESSION === 'warn' ? 'warn' : 'disable';
357}
358
359// Backwards compatibility with old bot passwords storage configs
360if ( !$wgVirtualDomainsMapping ) {
361    $wgVirtualDomainsMapping = [];
362}
363if ( $wgBotPasswordsCluster ) {
364    $wgVirtualDomainsMapping['virtual-botpasswords']['cluster'] = $wgBotPasswordsCluster;
365}
366
367if ( $wgBotPasswordsDatabase ) {
368    $wgVirtualDomainsMapping['virtual-botpasswords']['db'] = $wgBotPasswordsDatabase;
369}