[JsonCodec] Use wikimedia/json-codec to implement JsonCodec
[mediawiki.git] / includes / Settings / DynamicDefaultValues.php
blob50b87317f7eff88642c6de10b75264c1ddd97816
1 <?php
3 namespace MediaWiki\Settings;
5 use LogicException;
6 use MediaWiki\Settings\Config\ConfigBuilder;
7 use MediaWiki\Settings\Config\ConfigSchema;
9 class DynamicDefaultValues {
11 private ConfigSchema $configSchema;
13 /**
14 * @var array
16 private $declarations;
18 /**
19 * @param ConfigSchema $configSchema
21 public function __construct( ConfigSchema $configSchema ) {
22 $this->configSchema = $configSchema;
23 $this->declarations = $this->configSchema->getDynamicDefaults();
26 /**
27 * Compute dynamic defaults for settings that have them defined.
29 * @param ConfigBuilder $configBuilder
31 * @return void
33 public function applyDynamicDefaults( ConfigBuilder $configBuilder ): void {
34 $alreadyComputed = [];
36 foreach ( $this->declarations as $key => $unused ) {
37 $this->computeDefaultFor( $key, $configBuilder, $alreadyComputed );
41 /**
42 * Compute dynamic default for a setting, recursively computing any dependencies.
44 * @param string $key Name of setting
45 * @param ConfigBuilder $configBuilder
46 * @param array &$alreadyComputed Map whose keys are the names of settings whose dynamic
47 * defaults have already been computed
48 * @param array $currentlyComputing Ordered map whose keys are the names of settings whose
49 * dynamic defaults are currently being computed, for cycle detection.
51 private function computeDefaultFor(
52 string $key,
53 ConfigBuilder $configBuilder,
54 array &$alreadyComputed = [],
55 array $currentlyComputing = []
56 ): void {
57 if ( !isset( $this->declarations[ $key ] ) || isset( $alreadyComputed[ $key ] ) ) {
58 return;
60 if ( isset( $currentlyComputing[ $key ] ) ) {
61 throw new LogicException(
62 'Cyclic dependency when computing dynamic default: ' .
63 implode( ' -> ', array_keys( $currentlyComputing ) ) . " -> $key"
66 if (
67 $configBuilder->get( $key ) !==
68 $this->configSchema->getDefaultFor( $key )
69 ) {
70 // Default was already overridden, nothing more to do
71 $alreadyComputed[ $key ] = true;
73 return;
76 $currentlyComputing[ $key ] = true;
78 $callback = $this->declarations[ $key ]['callback'];
79 $argNames = $this->declarations[ $key ]['use'] ?? [];
80 $args = [];
82 foreach ( $argNames as $argName ) {
83 $this->computeDefaultFor(
84 $argName,
85 $configBuilder,
86 $alreadyComputed,
87 $currentlyComputing
89 $args[] = $configBuilder->get( $argName );
92 $configBuilder->set( $key, $callback( ...$args ) );
94 $alreadyComputed[ $key ] = true;