From 9e2090fed3a19f1f5d9a7111f41824ca10dc240f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20M=C3=B6ller?= Date: Fri, 22 May 2020 19:02:14 +0200 Subject: [PATCH 1/5] add possibility to set options on transformation object instance --- Classes/ExternalConfigurationManager.php | 5 +++++ Classes/Transformation/JsonTransformation.php | 3 +++ Classes/Transformation/TransformationInterface.php | 7 +++++++ 3 files changed, 15 insertions(+) diff --git a/Classes/ExternalConfigurationManager.php b/Classes/ExternalConfigurationManager.php index ef5729f..9e18002 100644 --- a/Classes/ExternalConfigurationManager.php +++ b/Classes/ExternalConfigurationManager.php @@ -64,8 +64,13 @@ protected function loadExternalConfiguration(array $externalConfigurationConfig) throw new Exception(sprintf("The class %s does not exist or does not implement TransformationInterface.", $transformationClass)); } + $transformationOptions = array_key_exists('transformationOptions', $externalConfigElement) ? $externalConfigElement['transformationOptions'] : null; + /** @var TransformationInterface $transformation */ $transformation = new $transformationClass(); + if (is_array($transformationOptions)) { + $transformation->setOptions($transformationOptions); + } $configuration = $transformation->transform($configuration); } diff --git a/Classes/Transformation/JsonTransformation.php b/Classes/Transformation/JsonTransformation.php index 5e42aaa..2fa707a 100644 --- a/Classes/Transformation/JsonTransformation.php +++ b/Classes/Transformation/JsonTransformation.php @@ -13,4 +13,7 @@ public function transform($rawConfiguration) return json_decode($rawConfiguration, true); } + public function setOptions(array $options): void + { + } } diff --git a/Classes/Transformation/TransformationInterface.php b/Classes/Transformation/TransformationInterface.php index a2db768..12d7b22 100644 --- a/Classes/Transformation/TransformationInterface.php +++ b/Classes/Transformation/TransformationInterface.php @@ -13,4 +13,11 @@ interface TransformationInterface * @return mixed */ public function transform($rawConfiguration); + + /** + * Set transformation options + * + * @param array $options + */ + public function setOptions(array $options): void; } From a52b5c61b454456888758c646cceee36c57412d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20M=C3=B6ller?= Date: Wed, 27 May 2020 21:39:23 +0200 Subject: [PATCH 2/5] fix applying external configuration The env var notation was overwritten. This is fixed by loading unprocessed configuration before applying external configuration. --- Classes/ExternalConfigurationManager.php | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Classes/ExternalConfigurationManager.php b/Classes/ExternalConfigurationManager.php index 9e18002..e0d99ab 100644 --- a/Classes/ExternalConfigurationManager.php +++ b/Classes/ExternalConfigurationManager.php @@ -87,9 +87,21 @@ protected function loadExternalConfiguration(array $externalConfigurationConfig) */ protected function applyExternalConfiguration(ConfigurationManager $configurationManager): void { - $configurations = ObjectAccess::getProperty($configurationManager, 'configurations', true); - $configurations[ConfigurationManager::CONFIGURATION_TYPE_SETTINGS] = $this->processConfigurationLevel($configurations[ConfigurationManager::CONFIGURATION_TYPE_SETTINGS]); - ObjectAccess::setProperty($configurationManager, 'unprocessedConfiguration', $configurations, true); + // clear config cache to be able to load unprocessed configuration values such as env vars '%env:MY_ENV_VAR%%' + $configurationManager->flushConfigurationCache(); + + // load all available configuration (unprocessed) + $configurationManager->warmup(); + + // get unprocessed settings from configuration + $unprocessedSettings = $configurationManager->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS); + + // replace external configuration values + $rawConfigurations = ObjectAccess::getProperty($configurationManager, 'configurations', true); + $rawConfigurations[ConfigurationManager::CONFIGURATION_TYPE_SETTINGS] = $this->processConfigurationLevel($unprocessedSettings); + + // process configuration by ConfigurationManager + ObjectAccess::setProperty($configurationManager, 'unprocessedConfiguration', $rawConfigurations, true); $configurationManager->refreshConfiguration(); } From 93d45dae27117d90774caa6c3c49fc9ce9e6c656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20M=C3=B6ller?= Date: Thu, 28 May 2020 10:28:14 +0200 Subject: [PATCH 3/5] Apply external configuration only of needed --- Classes/ExternalConfigurationManager.php | 43 ++++++++++++++++++++---- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/Classes/ExternalConfigurationManager.php b/Classes/ExternalConfigurationManager.php index e0d99ab..0ffa557 100644 --- a/Classes/ExternalConfigurationManager.php +++ b/Classes/ExternalConfigurationManager.php @@ -9,6 +9,8 @@ class ExternalConfigurationManager { + const EXTERNAL_CONFIGURATION_PATTERN = '/%EXT:(.*)%/i'; + protected $externalConfiguration = []; /** @@ -19,8 +21,6 @@ class ExternalConfigurationManager */ public function process(ConfigurationManager $configurationManager) { - // TODO: Make sure this runs only once on boot - $externalConfigurationConfig = $configurationManager->getConfiguration( ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, 'Sandstorm.ConfigLoader.externalConfig'); @@ -30,8 +30,12 @@ public function process(ConfigurationManager $configurationManager) return; } - $this->loadExternalConfiguration($externalConfigurationConfig); - $this->applyExternalConfiguration($configurationManager); + // only load and process external configuration if directive existent + $settings = $configurationManager->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS); + if ($this->hasExternalConfigurationDirective($settings)) { + $this->loadExternalConfiguration($externalConfigurationConfig); + $this->applyExternalConfiguration($configurationManager); + } } /** @@ -111,7 +115,7 @@ protected function applyExternalConfiguration(ConfigurationManager $configuratio * @param array $config * @return array */ - protected function processConfigurationLevel(array $config) + protected function processConfigurationLevel(array $config): array { foreach ($config as $key => $value) { if (is_array($value)) { @@ -119,7 +123,7 @@ protected function processConfigurationLevel(array $config) } if (is_string($value)) { $externalConfig = $this->externalConfiguration; - $config[$key] = preg_replace_callback('/%EXT:(.*)%/i', function ($matches) use ($externalConfig) { + $config[$key] = preg_replace_callback(self::EXTERNAL_CONFIGURATION_PATTERN, function ($matches) use ($externalConfig) { return Arrays::getValueByPath($externalConfig, $matches[1]); }, $value); } @@ -127,4 +131,31 @@ protected function processConfigurationLevel(array $config) return $config; } + + /** + * Recursively parses the config and check for configuration directive + * + * @param array $config + * @return bool + */ + protected function hasExternalConfigurationDirective(array $config): bool + { + $hasDirective = false; + foreach ($config as $key => $value) { + if (is_array($value)) { + $hasDirective = $this->hasExternalConfigurationDirective($value); + if ($hasDirective) { + break; + } + } + if (is_string($value)) { + $result = preg_match(self::EXTERNAL_CONFIGURATION_PATTERN, $value); + if ($result === 1) { + break; + } + } + } + + return $hasDirective; + } } From b97e206a416544971957dd1bdbceb27019ce477b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20M=C3=B6ller?= Date: Thu, 28 May 2020 20:08:35 +0200 Subject: [PATCH 4/5] fix hasExternalConfigurationDirective() --- Classes/ExternalConfigurationManager.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Classes/ExternalConfigurationManager.php b/Classes/ExternalConfigurationManager.php index 0ffa557..b4462a7 100644 --- a/Classes/ExternalConfigurationManager.php +++ b/Classes/ExternalConfigurationManager.php @@ -150,7 +150,8 @@ protected function hasExternalConfigurationDirective(array $config): bool } if (is_string($value)) { $result = preg_match(self::EXTERNAL_CONFIGURATION_PATTERN, $value); - if ($result === 1) { + $hasDirective = $result === 1; + if ($hasDirective) { break; } } From 94e8ce18aad213f2726e4c9ecf3fa15c4b75947e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20M=C3=B6ller?= Date: Fri, 29 May 2020 12:04:40 +0200 Subject: [PATCH 5/5] add getExternalConfiguration mehtod --- Classes/ExternalConfigurationManager.php | 29 ++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/Classes/ExternalConfigurationManager.php b/Classes/ExternalConfigurationManager.php index b4462a7..e0b2c5e 100644 --- a/Classes/ExternalConfigurationManager.php +++ b/Classes/ExternalConfigurationManager.php @@ -15,11 +15,12 @@ class ExternalConfigurationManager /** * @param ConfigurationManager $configurationManager + * @param bool $force Force applying and refresh configuration * @return void * @throws \Neos\Flow\Configuration\Exception\InvalidConfigurationTypeException * @throws Exception */ - public function process(ConfigurationManager $configurationManager) + public function process(ConfigurationManager $configurationManager, $force = false) { $externalConfigurationConfig = $configurationManager->getConfiguration( ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, @@ -32,12 +33,36 @@ public function process(ConfigurationManager $configurationManager) // only load and process external configuration if directive existent $settings = $configurationManager->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS); - if ($this->hasExternalConfigurationDirective($settings)) { + if ($this->hasExternalConfigurationDirective($settings) || $force) { $this->loadExternalConfiguration($externalConfigurationConfig); $this->applyExternalConfiguration($configurationManager); } } + /** + * @param ConfigurationManager $configurationManager + * @param string|null $configurationPath + * @return array|mixed|null + * @throws Exception + */ + public function getExternalConfiguration(ConfigurationManager $configurationManager, string $configurationPath = null) + { + if (empty($this->externalConfiguration)) { + $externalConfigurationConfig = $configurationManager->getConfiguration( + ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, + 'Sandstorm.ConfigLoader.externalConfig'); + + $this->loadExternalConfiguration($externalConfigurationConfig); + } + + $configuration = $this->externalConfiguration; + if ($configurationPath === null) { + return $configuration; + } + + return (Arrays::getValueByPath($configuration, $configurationPath)); + } + /** * Iterates through all external config Sources, triggers their load methods, * applys Transformations and stores the results.