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.
This commit is contained in:
Abel Hoogeveen 2021-11-30 00:09:53 +01:00
parent 44ae26404c
commit 0014c2d9f6
Signed by: abelhooge
GPG Key ID: C540221690CBFFBA
6 changed files with 162 additions and 50 deletions

View File

@ -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);
}

View File

@ -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;
}
/**

View File

@ -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;

View File

@ -0,0 +1,37 @@
<?php
/**
* FuzeWorksCore
*
* Copyright (C) 2013-2021 i15
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @author i15
* @copyright Copyright (c) 2013 - 2021, i15. (https://i15.nl)
* @license https://opensource.org/licenses/MIT MIT License
*
* @since Version 1.0.0
*
* @version Version 1.3.2
*/
return array(
'first' => 'world',
'onlyInHigh' => 'highValue',
'override' => 'firstValue'
);

View File

@ -0,0 +1,36 @@
<?php
/**
* FuzeWorksCore
*
* Copyright (C) 2013-2021 i15
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @author i15
* @copyright Copyright (c) 2013 - 2021, i15. (https://i15.nl)
* @license https://opensource.org/licenses/MIT MIT License
*
* @since Version 1.0.0
*
* @version Version 1.3.2
*/
return array(
'first' => 'hello',
'onlyInLow' => 'lowValue'
);

View File

@ -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'));
}
}