wiki.techinc.nl/includes/Settings/DynamicDefaultValues.php
Aryeh Gregor b72b9a8c43 Move dynamic defaults into MainConfigSchema
The goal is to keep the actual default values for settings in the same
place as the setting is declared, and applied using the regular means
for loading the settings -- not in a separate piece of code that needs
to be loaded through some entirely different mechanism.

SetupDynamicConfig.php now contains a few categories of things:

* Post-processing of configuration settings, where already-set settings
  are altered. This could be moved to MainConfigSchema too as a separate
  set of methods.
* Processing of old aliases of settings (blacklist, slave) that are not
  registered as settings anymore and therefore are not available to
  MainConfigSchema. This could perhaps be moved to LocalSettings
  processing somehow?
* Setting $wgUseEnotif, which is also not registered as a setting.
  Easiest would be just to declare it as a setting and have it set
  unconditionally.
* Setting the actual timezone to $wgLocaltimezone. This is not related
  to configuration and should just be in Setup.php.

Bug: T305093
Change-Id: Ia5c23b52dbbfcb3d07ffcf5d3b7f2d7befba2a26
2022-07-07 09:55:48 +10:00

99 lines
2.4 KiB
PHP

<?php
namespace MediaWiki\Settings;
use LogicException;
use MediaWiki\Settings\Config\ConfigBuilder;
use MediaWiki\Settings\Config\ConfigSchema;
class DynamicDefaultValues {
/**
* @var ConfigSchema
*/
private $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;
}
}