diff options
author | daniel <dkinzler@wikimedia.org> | 2022-01-14 17:40:52 +0100 |
---|---|---|
committer | Daniel Kinzler <dkinzler@wikimedia.org> | 2022-01-26 12:02:56 +0000 |
commit | a652f306a542c0efdfa0bef33cd68c8f6587e0bc (patch) | |
tree | 2cc2e01ea43e614d44a33ce150756247ef1f567b /includes/Settings | |
parent | f2915281696a4c60f9aa606bab3bff1abb9b29a3 (diff) | |
download | mediawikicore-a652f306a542c0efdfa0bef33cd68c8f6587e0bc.tar.gz mediawikicore-a652f306a542c0efdfa0bef33cd68c8f6587e0bc.zip |
SettingsBuilder: allow maintenance scripts to manipulate config
Maintenance scripts often need to manipulate configuration settings.
This introduces a way to do this cleanly via SettingsBuilder,
removing the need to rely on global variables.
Bug: T294739
Bug: T294742
Bug: T300128
Change-Id: Ibf443fd564bbbf388cce8ab4dabba55ebca0dfa4
Diffstat (limited to 'includes/Settings')
-rw-r--r-- | includes/Settings/SettingsBuilder.php | 91 |
1 files changed, 86 insertions, 5 deletions
diff --git a/includes/Settings/SettingsBuilder.php b/includes/Settings/SettingsBuilder.php index dfdd230312ba..a55eb6e9e4ae 100644 --- a/includes/Settings/SettingsBuilder.php +++ b/includes/Settings/SettingsBuilder.php @@ -37,6 +37,9 @@ class SettingsBuilder { /** @var ConfigBuilder */ private $configSink; + /** @var Config */ + private $config; + /** @var SettingsSource[] */ private $currentBatch; @@ -47,6 +50,16 @@ class SettingsBuilder { private $phpIniSink; /** + * Configuration that applies to SettingsBuilder itself. + * Initialized by the constructor, may be overwritten by regular + * config values. Merge strategies are currently not implemented + * but can be added if needed. + * + * @var array + */ + private $settingsConfig; + + /** * When we're done applying all settings. * * @var bool @@ -76,6 +89,10 @@ class SettingsBuilder { $this->configSink = $configSink; $this->configSchema = new ConfigSchemaAggregator(); $this->phpIniSink = $phpIniSink; + $this->settingsConfig = [ + 'ExtensionDirectory' => "$baseDir/extensions", + 'StyleDirectory' => "$baseDir/skins", + ]; $this->reset(); } @@ -153,7 +170,7 @@ class SettingsBuilder { * @return StatusValue */ public function validate(): StatusValue { - $config = $this->configSink->build(); + $config = $this->getConfig(); $validator = new Validator(); $result = StatusValue::newGood(); @@ -183,9 +200,12 @@ class SettingsBuilder { /** * Return a Config object with all the default settings loaded so far. * + * @note This will implicitly call apply() + * * @return Config */ public function getDefaultConfig(): Config { + $this->apply(); return new HashConfig( $this->configSchema->getDefaults() ); } @@ -201,7 +221,12 @@ class SettingsBuilder { * @throws SettingsBuilderException */ public function apply(): self { + if ( !$this->currentBatch ) { + return $this; + } + $this->assertNotFinished(); + $this->config = null; $allSettings = $this->loadRecursive( $this->currentBatch ); @@ -267,6 +292,16 @@ class SettingsBuilder { * @param array $settings */ private function applySettings( array $settings ) { + // First extract config variables that change the behavior of SettingsBuilder. + // No merge strategies are applied, defaults are set in the constructor. + if ( isset( $settings['config'] ) ) { + foreach ( $this->settingsConfig as $key => $dummy ) { + if ( array_key_exists( $key, $settings['config'] ) ) { + $this->settingsConfig[$key] = $settings['config'][$key]; + } + } + } + foreach ( $settings['config'] ?? [] as $key => $value ) { $this->configSink->set( $key, @@ -298,10 +333,8 @@ class SettingsBuilder { // not just queued. We can't do this right now, because we need to preserve // interoperability with wfLoadExtension() being called from LocalSettings.php. - $config = $this->configSink->build(); - if ( isset( $settings['extensions'] ) ) { - $extDir = $config->get( 'ExtensionDirectory' ); + $extDir = $this->settingsConfig['ExtensionDirectory']; foreach ( $settings['extensions'] ?? [] as $ext ) { $path = "$extDir/$ext/extension.json"; // see wfLoadExtension $this->extensionRegistry->queue( $path ); @@ -309,7 +342,7 @@ class SettingsBuilder { } if ( isset( $settings['skins'] ) ) { - $skinDir = $config->get( 'StyleDirectory' ); + $skinDir = $this->settingsConfig['StyleDirectory']; foreach ( $settings['skins'] ?? [] as $skin ) { $path = "$skinDir/$skin/skin.json"; // see wfLoadSkin $this->extensionRegistry->queue( $path ); @@ -317,6 +350,54 @@ class SettingsBuilder { } } + /** + * Sets the value of a config variable. + * This is a shorthand for loadArray(). + * @unstable + * + * @param string $key the name of the config setting + * @param mixed $value The value to set + * + * @return $this + */ + public function setConfigValue( string $key, $value ): self { + $this->loadArray( [ 'config' => [ $key => $value ] ] ); + return $this; + } + + /** + * Sets the value of multiple config variables. + * This is a shorthand for loadArray(). + * @unstable + * + * @param array $values An associative array mapping names to values. + * + * @return $this + */ + public function setConfigValues( array $values ): self { + $this->loadArray( [ 'config' => $values ] ); + return $this; + } + + /** + * Returns the config loaded so far. Implicitly triggers apply() when needed. + * + * @note This will implicitly call apply() + * + * @unstable + * @return Config + */ + public function getConfig(): Config { + if ( $this->config && !$this->currentBatch ) { + return $this->config; + } + + $this->apply(); + $this->config = $this->configSink->build(); + + return $this->config; + } + private function reset() { $this->currentBatch = []; } |