From 0014c2d9f6b5bfd08da31978709ae6a602faad19 Mon Sep 17 00:00:00 2001 From: Abel Hoogeveen Date: Tue, 30 Nov 2021 00:09:53 +0100 Subject: [PATCH] Added config layers. Configs are now layered on top of each other. If a config file is found in multiple directories, they are merged together. Higher fields will override lower fields. This way, if one field is missing in a higher priority file, the lower priority can still be used. --- src/FuzeWorks/Config.php | 45 +++++-------- src/FuzeWorks/ConfigORM/ConfigORM.php | 67 +++++++++++++------ src/FuzeWorks/Configurator.php | 4 ++ .../HighPriorityFolder/config.cumulative.php | 37 ++++++++++ .../LowPriorityFolder/config.cumulative.php | 36 ++++++++++ test/core/core_configTest.php | 23 +++++++ 6 files changed, 162 insertions(+), 50 deletions(-) create mode 100644 test/config/TestCumulativeConfigFile/HighPriorityFolder/config.cumulative.php create mode 100644 test/config/TestCumulativeConfigFile/LowPriorityFolder/config.cumulative.php diff --git a/src/FuzeWorks/Config.php b/src/FuzeWorks/Config.php index cd5c611..65dc210 100644 --- a/src/FuzeWorks/Config.php +++ b/src/FuzeWorks/Config.php @@ -52,6 +52,10 @@ class Config { use ComponentPathsTrait; + public function __construct() { + $this->addComponentPath(Core::$coreDir . DS . 'Config', Priority::LOWEST); + } + /** * Array where all config files are saved while FuzeWorks runs * @@ -150,6 +154,7 @@ class Config return new ConfigORM(); // Cycle through all priorities if they exist + $configORM = new ConfigORM(); for ($i=Priority::getHighestPriority(); $i<=Priority::getLowestPriority(); $i++) { if (!isset($event->configPaths[$i])) @@ -161,41 +166,23 @@ class Config // If file exists, load it and break the loop $file = $configPath . DS . 'config.'.strtolower($event->configName).'.php'; if (file_exists($file)) - { - // Load object - $configORM = (new ConfigORM())->load($file); - - // Override config values if they exist - if (isset(self::$configOverrides[$event->configName])) - { - foreach (self::$configOverrides[$event->configName] as $configKey => $configValue) - $configORM->{$configKey} = $configValue; - } - - // Return object - return $configORM; - } + $configORM->addFile($i, $file); } } - // Try fallback - $file = Core::$coreDir . DS . 'Config' . DS . 'config.' . $event->configName . '.php'; - if (file_exists($file)) + // And initialize the ORM + $configORM->init(); + + // Override config values if they exist + if (isset(self::$configOverrides[$event->configName])) { - // Load object - $configORM = (new ConfigORM())->load($file); - - // Override config values if they exist - if (isset(self::$configOverrides[$event->configName])) - { - foreach (self::$configOverrides[$event->configName] as $configKey => $configValue) - $configORM->{$configKey} = $configValue; - } - - // Return object - return $configORM; + foreach (self::$configOverrides[$event->configName] as $configKey => $configValue) + $configORM->{$configKey} = $configValue; } + if ($configORM->loaded) + return $configORM; + throw new ConfigException("Could not load config. File $event->configName not found", 1); } diff --git a/src/FuzeWorks/ConfigORM/ConfigORM.php b/src/FuzeWorks/ConfigORM/ConfigORM.php index f9568fd..57c5f02 100644 --- a/src/FuzeWorks/ConfigORM/ConfigORM.php +++ b/src/FuzeWorks/ConfigORM/ConfigORM.php @@ -36,6 +36,7 @@ namespace FuzeWorks\ConfigORM; use FuzeWorks\Exception\ConfigException; +use FuzeWorks\Priority; /** * ORM class for config files in PHP files. @@ -48,37 +49,61 @@ use FuzeWorks\Exception\ConfigException; class ConfigORM extends ConfigORMAbstract { /** - * The current filename. + * The path to the highest priority filename. * * @var string filename */ - private string $file; + protected string $file; /** - * Load the ConfigORM file. + * Files the ConfigORM is built on * - * @param string $file - * @return ConfigORM - * @throws ConfigException + * @var array files */ - public function load(string $file = ''): ConfigORM + protected array $files = []; + + /** + * Whether the ConfigORM is loaded or not. + * + * @var bool + */ + public bool $loaded = false; + + public function addFile(int $priority, string $file) { - if (empty($file)) - { - throw new ConfigException('Could not load config file. No file provided', 1); - } - elseif (file_exists($file)) - { - $this->file = $file; - $this->cfg = (array) include $file; - $this->originalCfg = $this->cfg; - } - else - { - throw new ConfigException('Could not load config file. Config file does not exist', 1); + if (!isset($this->files[$priority])) + $this->files[$priority] = []; + + $this->files[$priority][] = $file; + } + + public function init() + { + // Set cfg + $this->cfg = []; + + for ($i = Priority::getLowestPriority(); $i >= Priority::getHighestPriority(); $i--) { + + // If priority does not exist for this file, skip it + if (!isset($this->files[$i])) + continue; + + // Pass over each file in this priority + foreach ($this->files[$i] as $file) { + // Read the contents + $contents = (array) include $file; + + // Merge them with the config as we know it + $this->cfg = array_replace_recursive($this->cfg, $contents); + + // And save the last file that we found (with the highest priority) + $this->file = $file; + $this->loaded = true; + } } - return $this; + // When done, save originalCfg + $this->originalCfg = $this->cfg; } /** diff --git a/src/FuzeWorks/Configurator.php b/src/FuzeWorks/Configurator.php index 13a7825..d0b47c1 100644 --- a/src/FuzeWorks/Configurator.php +++ b/src/FuzeWorks/Configurator.php @@ -404,6 +404,10 @@ class Configurator $container->{$component}->setDirectories($priorityArray); } + // And add the fallback directory + $container->config->addComponentPath(Core::$coreDir . DS . 'Config', Priority::LOWEST); + + // Initialize and return the container $container->initFactory(); Logger::stopLevel(); return $container; diff --git a/test/config/TestCumulativeConfigFile/HighPriorityFolder/config.cumulative.php b/test/config/TestCumulativeConfigFile/HighPriorityFolder/config.cumulative.php new file mode 100644 index 0000000..d90134c --- /dev/null +++ b/test/config/TestCumulativeConfigFile/HighPriorityFolder/config.cumulative.php @@ -0,0 +1,37 @@ + 'world', + 'onlyInHigh' => 'highValue', + 'override' => 'firstValue' +); \ No newline at end of file diff --git a/test/config/TestCumulativeConfigFile/LowPriorityFolder/config.cumulative.php b/test/config/TestCumulativeConfigFile/LowPriorityFolder/config.cumulative.php new file mode 100644 index 0000000..742bc1d --- /dev/null +++ b/test/config/TestCumulativeConfigFile/LowPriorityFolder/config.cumulative.php @@ -0,0 +1,36 @@ + 'hello', + 'onlyInLow' => 'lowValue' +); \ No newline at end of file diff --git a/test/core/core_configTest.php b/test/core/core_configTest.php index 04ec2fc..33cc997 100644 --- a/test/core/core_configTest.php +++ b/test/core/core_configTest.php @@ -207,4 +207,27 @@ class configTest extends CoreTestAbstract $this->assertEquals('somethingDefault', $config->get('otherKey')); } + /** + * @covers ::loadConfigFile + * @depends testLoadConfigCoreOverride + */ + public function testCumulativeConfigFile() + { + // Add folders + $this->config->addComponentPath('test'.DS.'config'.DS.'TestCumulativeConfigFile'.DS.'HighPriorityFolder', Priority::HIGH); + $this->config->addComponentPath('test'.DS.'config'.DS.'TestCumulativeConfigFile'.DS.'LowPriorityFolder', Priority::LOW); + + // And override a value + Config::overrideConfig('cumulative', 'override', 'secondValue'); + + // Load the config + $config = $this->config->get('cumulative'); + + // Check values + $this->assertEquals("world", $config->get('first')); + $this->assertEquals("highValue", $config->get('onlyInHigh')); + $this->assertEquals("lowValue", $config->get('onlyInLow')); + $this->assertEquals("secondValue", $config->get('override')); + } + }