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