aboutsummaryrefslogtreecommitdiffstats
path: root/includes/Settings
diff options
context:
space:
mode:
authordaniel <dkinzler@wikimedia.org>2022-01-14 17:40:52 +0100
committerDaniel Kinzler <dkinzler@wikimedia.org>2022-01-26 12:02:56 +0000
commita652f306a542c0efdfa0bef33cd68c8f6587e0bc (patch)
tree2cc2e01ea43e614d44a33ce150756247ef1f567b /includes/Settings
parentf2915281696a4c60f9aa606bab3bff1abb9b29a3 (diff)
downloadmediawikicore-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.php91
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 = [];
}