Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
30 / 30 |
|
100.00% |
3 / 3 |
CRAP | |
100.00% |
1 / 1 |
DynamicDefaultValues | |
100.00% |
30 / 30 |
|
100.00% |
3 / 3 |
9 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
applyDynamicDefaults | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
computeDefaultFor | |
100.00% |
25 / 25 |
|
100.00% |
1 / 1 |
6 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Settings; |
4 | |
5 | use LogicException; |
6 | use MediaWiki\Settings\Config\ConfigBuilder; |
7 | use MediaWiki\Settings\Config\ConfigSchema; |
8 | |
9 | class DynamicDefaultValues { |
10 | |
11 | private ConfigSchema $configSchema; |
12 | |
13 | /** |
14 | * @var array |
15 | */ |
16 | private $declarations; |
17 | |
18 | /** |
19 | * @param ConfigSchema $configSchema |
20 | */ |
21 | public function __construct( ConfigSchema $configSchema ) { |
22 | $this->configSchema = $configSchema; |
23 | $this->declarations = $this->configSchema->getDynamicDefaults(); |
24 | } |
25 | |
26 | /** |
27 | * Compute dynamic defaults for settings that have them defined. |
28 | * |
29 | * @param ConfigBuilder $configBuilder |
30 | * |
31 | * @return void |
32 | */ |
33 | public function applyDynamicDefaults( ConfigBuilder $configBuilder ): void { |
34 | $alreadyComputed = []; |
35 | |
36 | foreach ( $this->declarations as $key => $unused ) { |
37 | $this->computeDefaultFor( $key, $configBuilder, $alreadyComputed ); |
38 | } |
39 | } |
40 | |
41 | /** |
42 | * Compute dynamic default for a setting, recursively computing any dependencies. |
43 | * |
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. |
50 | */ |
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; |
59 | } |
60 | if ( isset( $currentlyComputing[ $key ] ) ) { |
61 | throw new LogicException( |
62 | 'Cyclic dependency when computing dynamic default: ' . |
63 | implode( ' -> ', array_keys( $currentlyComputing ) ) . " -> $key" |
64 | ); |
65 | } |
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; |
72 | |
73 | return; |
74 | } |
75 | |
76 | $currentlyComputing[ $key ] = true; |
77 | |
78 | $callback = $this->declarations[ $key ]['callback']; |
79 | $argNames = $this->declarations[ $key ]['use'] ?? []; |
80 | $args = []; |
81 | |
82 | foreach ( $argNames as $argName ) { |
83 | $this->computeDefaultFor( |
84 | $argName, |
85 | $configBuilder, |
86 | $alreadyComputed, |
87 | $currentlyComputing |
88 | ); |
89 | $args[] = $configBuilder->get( $argName ); |
90 | } |
91 | |
92 | $configBuilder->set( $key, $callback( ...$args ) ); |
93 | |
94 | $alreadyComputed[ $key ] = true; |
95 | } |
96 | } |