19 'AuthManagerAutoConfig',
21 'CentralIdLookupProviders',
22 'ChangeCredentialsBlacklist',
26 'ExtensionEntryPointListFiles',
31 'GrantPermissionGroups',
35 'GroupsRemoveFromSelf',
51 'RemoveCredentialsBlacklist',
53 'ResourceLoaderSources',
79 'wgAuthManagerAutoConfig' =>
'array_plus_2d',
80 'wgCapitalLinkOverrides' =>
'array_plus',
81 'wgExtensionCredits' =>
'array_merge_recursive',
82 'wgExtraGenderNamespaces' =>
'array_plus',
83 'wgGrantPermissions' =>
'array_plus_2d',
84 'wgGroupPermissions' =>
'array_plus_2d',
85 'wgHooks' =>
'array_merge_recursive',
86 'wgNamespaceContentModels' =>
'array_plus',
87 'wgNamespaceProtection' =>
'array_plus',
88 'wgNamespacesWithSubpages' =>
'array_plus',
89 'wgPasswordPolicy' =>
'array_merge_recursive',
90 'wgRateLimits' =>
'array_plus_2d',
91 'wgRevokePermissions' =>
'array_plus_2d',
120 'ResourceFileModulePaths',
122 'ResourceModuleSkinStyles',
125 'ExtensionMessagesFiles',
130 'ServiceWiringFiles',
134 'load_composer_autoloader',
145 'wgExtensionMessagesFiles' => [],
146 'wgMessagesDirs' => [],
196 $dir = dirname(
$path );
202 if ( isset( $info[
'ServiceWiringFiles'] ) ) {
204 'wgServiceWiringFiles',
206 $info[
'ServiceWiringFiles']
209 if ( isset( $info[
'ParserTestFiles'] ) ) {
213 $info[
'ParserTestFiles']
217 if ( isset( $info[
'callback'] ) ) {
218 $this->callbacks[$name] = $info[
'callback'];
223 if ( $version === 2 ) {
230 if ( $version === 2 ) {
234 foreach ( $info as $key => $val ) {
236 if ( in_array( $key, self::$globalSettings ) ) {
241 if ( $key[0] ===
'@' ) {
245 if ( $version === 2 ) {
247 if ( in_array( $key, self::$coreAttributes ) ) {
252 if ( !in_array( $key, self::$notAttributes )
253 && !in_array( $key, self::$creditsAttributes )
268 if ( isset( $info[
'attributes'] ) ) {
269 foreach ( $info[
'attributes'] as $extName => $value ) {
277 foreach ( $this->globals as $key => $val ) {
278 if ( isset( self::$mergeStrategies[$key] ) ) {
284 foreach ( $this->extAttributes as $extName => $value ) {
286 if ( isset( $this->credits[$extName] ) ) {
287 foreach ( $value as $attrName => $attrValue ) {
290 $extName . $attrName,
295 unset( $this->extAttributes[$extName] );
311 if ( !$includeDev || !isset( $info[
'dev-requires'] ) ) {
312 return $info[
'requires'] ?? [];
315 if ( !isset( $info[
'requires'] ) ) {
316 return $info[
'dev-requires'] ?? [];
326 $pick =
function ( $a, $b ) {
329 } elseif ( $b ===
null ) {
336 $req = $info[
'requires'];
337 $dev = $info[
'dev-requires'];
338 if ( isset( $req[
'MediaWiki'] ) || isset( $dev[
'MediaWiki'] ) ) {
339 $merged[
'MediaWiki'] = $pick(
340 $req[
'MediaWiki'] ??
null,
341 $dev[
'MediaWiki'] ??
null
345 $platform = array_merge(
346 array_keys( $req[
'platform'] ?? [] ),
347 array_keys( $dev[
'platform'] ?? [] )
350 foreach ( $platform as $pkey ) {
351 if ( $pkey ===
'php' ) {
353 $req[
'platform'][
'php'] ??
null,
354 $dev[
'platform'][
'php'] ??
null
359 $value = $dev[
'platform'][$pkey] ?? $req[
'platform'][$pkey];
361 $merged[
'platform'][$pkey] = $value;
365 foreach ( [
'extensions',
'skins' ] as $thing ) {
366 $things = array_merge(
367 array_keys( $req[$thing] ?? [] ),
368 array_keys( $dev[$thing] ?? [] )
370 foreach ( $things as $name ) {
371 $merged[$thing][$name] = $pick(
372 $req[$thing][$name] ??
null,
373 $dev[$thing][$name] ??
null
382 if ( isset( $info[
'Hooks'] ) ) {
383 foreach ( $info[
'Hooks'] as $name => $value ) {
384 if ( is_array( $value ) ) {
385 foreach ( $value as $callback ) {
386 $this->globals[
'wgHooks'][$name][] = $callback;
389 $this->globals[
'wgHooks'][$name][] = $value;
401 if ( isset( $info[
'namespaces'] ) ) {
402 foreach ( $info[
'namespaces'] as $ns ) {
403 if ( defined( $ns[
'constant'] ) ) {
406 $id = constant( $ns[
'constant'] );
409 $this->defines[ $ns[
'constant'] ] = $id;
412 if ( !( isset( $ns[
'conditional'] ) && $ns[
'conditional'] ) ) {
414 $this->attributes[
'ExtensionNamespaces'][$id] = $ns[
'name'];
416 if ( isset( $ns[
'gender'] ) ) {
417 $this->globals[
'wgExtraGenderNamespaces'][$id] = $ns[
'gender'];
419 if ( isset( $ns[
'subpages'] ) && $ns[
'subpages'] ) {
420 $this->globals[
'wgNamespacesWithSubpages'][$id] =
true;
422 if ( isset( $ns[
'content'] ) && $ns[
'content'] ) {
423 $this->globals[
'wgContentNamespaces'][] = $id;
425 if ( isset( $ns[
'defaultcontentmodel'] ) ) {
426 $this->globals[
'wgNamespaceContentModels'][$id] = $ns[
'defaultcontentmodel'];
428 if ( isset( $ns[
'protection'] ) ) {
429 $this->globals[
'wgNamespaceProtection'][$id] = $ns[
'protection'];
431 if ( isset( $ns[
'capitallinkoverride'] ) ) {
432 $this->globals[
'wgCapitalLinkOverrides'][$id] = $ns[
'capitallinkoverride'];
439 $defaultPaths = $info[
'ResourceFileModulePaths'] ??
false;
440 if ( isset( $defaultPaths[
'localBasePath'] ) ) {
441 if ( $defaultPaths[
'localBasePath'] ===
'' ) {
443 $defaultPaths[
'localBasePath'] = $dir;
445 $defaultPaths[
'localBasePath'] =
"$dir/{$defaultPaths['localBasePath']}";
449 foreach ( [
'ResourceModules',
'ResourceModuleSkinStyles',
'OOUIThemePaths' ] as $setting ) {
450 if ( isset( $info[$setting] ) ) {
451 foreach ( $info[$setting] as $name => $data ) {
452 if ( isset( $data[
'localBasePath'] ) ) {
453 if ( $data[
'localBasePath'] ===
'' ) {
455 $data[
'localBasePath'] = $dir;
457 $data[
'localBasePath'] =
"$dir/{$data['localBasePath']}";
460 if ( $defaultPaths ) {
461 $data += $defaultPaths;
463 if ( $setting ===
'OOUIThemePaths' ) {
464 $this->attributes[$setting][$name] = $data;
466 $this->globals[
"wg$setting"][$name] = $data;
472 if ( isset( $info[
'QUnitTestModule'] ) ) {
473 $data = $info[
'QUnitTestModule'];
474 if ( isset( $data[
'localBasePath'] ) ) {
475 if ( $data[
'localBasePath'] ===
'' ) {
477 $data[
'localBasePath'] = $dir;
479 $data[
'localBasePath'] =
"$dir/{$data['localBasePath']}";
482 $this->attributes[
'QUnitTestModules'][
"test.{$info['name']}"] = $data;
487 if ( isset( $info[
'ExtensionMessagesFiles'] ) ) {
488 foreach ( $info[
'ExtensionMessagesFiles'] as &
$file ) {
489 $file =
"$dir/$file";
491 $this->globals[
"wgExtensionMessagesFiles"] += $info[
'ExtensionMessagesFiles'];
503 if ( isset( $info[
'MessagesDirs'] ) ) {
504 foreach ( $info[
'MessagesDirs'] as $name => $files ) {
505 foreach ( (array)$files as
$file ) {
506 $this->globals[
"wgMessagesDirs"][$name][] =
"$dir/$file";
521 'type' => $info[
'type'] ??
'other',
523 foreach ( self::$creditsAttributes as $attr ) {
524 if ( isset( $info[$attr] ) ) {
533 if ( isset( $this->credits[$name] ) ) {
534 $firstPath = $this->credits[$name][
'path'];
536 throw new Exception(
"It was attempted to load $name twice, from $firstPath and $secondPath." );
552 if ( isset( $info[
'config'] ) ) {
553 if ( isset( $info[
'config'][
'_prefix'] ) ) {
554 $prefix = $info[
'config'][
'_prefix'];
555 unset( $info[
'config'][
'_prefix'] );
559 foreach ( $info[
'config'] as $key => $val ) {
560 if ( $key[0] !==
'@' ) {
575 $prefix = $info[
'config_prefix'] ??
'wg';
576 if ( isset( $info[
'config'] ) ) {
577 foreach ( $info[
'config'] as $key => $data ) {
578 $value = $data[
'value'];
579 if ( isset( $data[
'merge_strategy'] ) ) {
582 if ( isset( $data[
'path'] ) && $data[
'path'] ) {
583 $value =
"$dir/$value";
586 $data[
'providedby'] = $info[
'name'];
587 if ( isset( $info[
'ConfigRegistry'][0] ) ) {
588 $data[
'configregistry'] = array_keys( $info[
'ConfigRegistry'] )[0];
590 $this->config[$key] = $data;
603 if ( array_key_exists( $key, $this->globals ) ) {
604 throw new RuntimeException(
605 "The configuration setting '$key' was already set by MediaWiki core or"
606 .
" another extension, and cannot be set again by $extName." );
608 $this->globals[$key] = $value;
612 foreach ( $paths as
$path ) {
613 $this->globals[$global][] =
"$dir/$path";
625 if ( !is_array( $value ) ) {
626 throw new InvalidArgumentException(
"The value for '$name' should be an array (from $path)" );
628 if ( isset( $array[$name] ) ) {
629 $array[$name] = array_merge_recursive( $array[$name], $value );
631 $array[$name] = $value;
637 if ( isset( $info[
'load_composer_autoloader'] ) && $info[
'load_composer_autoloader'] ===
true ) {
638 $paths[] =
"$dir/vendor/autoload.php";