Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
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 | |
7 | use MediaWiki\Language\LanguageCode; |
8 | use MediaWiki\MainConfigSchema; |
9 | use MediaWiki\Title\NamespaceInfo; |
10 | use 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. |
15 | if ( $wgLogos !== false && isset( $wgLogos['1x'] ) ) { |
16 | $wgLogo = $wgLogos['1x']; |
17 | } |
18 | |
19 | // Back-compat |
20 | if ( isset( $wgFileBlacklist ) ) { |
21 | $wgProhibitedFileExtensions = array_merge( $wgProhibitedFileExtensions, $wgFileBlacklist ); |
22 | } else { |
23 | $wgFileBlacklist = $wgProhibitedFileExtensions; |
24 | } |
25 | if ( isset( $wgMimeTypeBlacklist ) ) { |
26 | $wgMimeTypeExclusions = array_merge( $wgMimeTypeExclusions, $wgMimeTypeBlacklist ); |
27 | } else { |
28 | $wgMimeTypeBlacklist = $wgMimeTypeExclusions; |
29 | } |
30 | if ( isset( $wgEnableUserEmailBlacklist ) ) { |
31 | $wgEnableUserEmailMuteList = $wgEnableUserEmailBlacklist; |
32 | } else { |
33 | $wgEnableUserEmailBlacklist = $wgEnableUserEmailMuteList; |
34 | } |
35 | if ( isset( $wgShortPagesNamespaceBlacklist ) ) { |
36 | $wgShortPagesNamespaceExclusions = $wgShortPagesNamespaceBlacklist; |
37 | } else { |
38 | $wgShortPagesNamespaceBlacklist = $wgShortPagesNamespaceExclusions; |
39 | } |
40 | |
41 | // Rate limits should have the same name as the corresponding permission |
42 | if ( 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 |
52 | if ( 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 |
66 | if ( $wgRightsIcon ) { |
67 | $wgRightsIcon = str_replace( |
68 | "{$wgStylePath}/common/images/", |
69 | "{$wgResourceBasePath}/resources/assets/licenses/", |
70 | $wgRightsIcon |
71 | ); |
72 | } |
73 | |
74 | if ( 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 | |
86 | if ( 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 | |
135 | if ( 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 | */ |
144 | if ( $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 | } |
179 | if ( $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 | } |
193 | foreach ( $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 | } |
201 | unset( $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 | ); |
213 | unset( $rcMaxAgeDays ); |
214 | |
215 | $wgCookiePrefix = strtr( $wgCookiePrefix, '=,; +."\'\\[', '__________' ); |
216 | |
217 | if ( !$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 | |
236 | if ( !$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 |
260 | if ( 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 |
274 | foreach ( 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 | } |
280 | unset( $code ); // no global pollution; destroy reference |
281 | unset( $bcp47 ); // no global pollution; destroy reference |
282 | if ( $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 | |
289 | if ( 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 | |
301 | if ( 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 | |
313 | if ( $wgInvalidateCacheOnLocalSettingsChange && defined( 'MW_CONFIG_FILE' ) ) { |
314 | AtEase::suppressWarnings(); |
315 | $wgCacheEpoch = max( $wgCacheEpoch, gmdate( 'YmdHis', filemtime( MW_CONFIG_FILE ) ) ); |
316 | AtEase::restoreWarnings(); |
317 | } |
318 | |
319 | if ( $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 | |
331 | if ( $wgPageCreationLog ) { |
332 | // Add page creation log type |
333 | $wgLogTypes[] = 'create'; |
334 | $wgLogActionsHandlers['create/create'] = LogFormatter::class; |
335 | } |
336 | |
337 | if ( $wgPageLanguageUseDB ) { |
338 | $wgLogTypes[] = 'pagelang'; |
339 | $wgLogActionsHandlers['pagelang/pagelang'] = [ |
340 | 'class' => PageLangLogFormatter::class, |
341 | 'services' => [ |
342 | 'LanguageNameUtils', |
343 | ] |
344 | ]; |
345 | } |
346 | |
347 | if ( $wgPHPSessionHandling !== 'enable' && |
348 | $wgPHPSessionHandling !== 'warn' && |
349 | $wgPHPSessionHandling !== 'disable' |
350 | ) { |
351 | $wgPHPSessionHandling = 'warn'; |
352 | } |
353 | if ( 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 |
360 | if ( !$wgVirtualDomainsMapping ) { |
361 | $wgVirtualDomainsMapping = []; |
362 | } |
363 | if ( $wgBotPasswordsCluster ) { |
364 | $wgVirtualDomainsMapping['virtual-botpasswords']['cluster'] = $wgBotPasswordsCluster; |
365 | } |
366 | |
367 | if ( $wgBotPasswordsDatabase ) { |
368 | $wgVirtualDomainsMapping['virtual-botpasswords']['db'] = $wgBotPasswordsDatabase; |
369 | } |