config override

This commit is contained in:
Yuri Kuznetsov
2024-01-24 11:36:32 +02:00
parent e4af67aa68
commit 525397e64d
4 changed files with 161 additions and 29 deletions

2
.gitignore vendored
View File

@@ -5,6 +5,8 @@
/data/.backup/*
/data/config.php
/data/config-internal.php
/data/config-override.php
/data/config-internal-override.php
/data/tmp/*
/build
/node_modules

View File

@@ -41,9 +41,11 @@ use const E_USER_DEPRECATED;
*/
class Config
{
private string $systemConfigPath = 'application/Espo/Resources/defaults/systemConfig.php';
private string $configPath = 'data/config.php';
private string $internalConfigPath = 'data/config-internal.php';
private string $systemConfigPath = 'application/Espo/Resources/defaults/systemConfig.php';
private string $overrideConfigPath = 'data/config-override.php';
private string $internalOverrideConfigPath = 'data/config-internal-override.php';
private string $cacheTimestamp = 'cacheTimestamp';
/** @var string[] */
protected $associativeArrayAttributeList = [
@@ -52,6 +54,7 @@ class Config
'logger',
'defaultPermissions',
];
/** @var ?array<string, mixed> */
private $data = null;
/** @var array<string, mixed> */
@@ -227,6 +230,7 @@ class Config
$values = $this->changedData;
if (!isset($values[$this->cacheTimestamp])) {
/** @noinspection PhpDeprecationInspection */
$values = array_merge($this->updateCacheTimestamp(true) ?? [], $values);
}
@@ -235,7 +239,7 @@ class Config
$configPath = $this->getConfigPath();
if (!$this->fileManager->isFile($configPath)) {
throw new RuntimeException("Config file '{$configPath}' is not found.");
throw new RuntimeException("Config file '$configPath' is not found.");
}
$data = include($configPath);
@@ -274,7 +278,7 @@ class Config
private function isLoaded(): bool
{
return isset($this->data) && !empty($this->data);
return !empty($this->data);
}
/**
@@ -294,26 +298,65 @@ class Config
private function load(): void
{
$systemData = $this->fileManager->getPhpContents($this->systemConfigPath);
$data = $this->readFile($this->configPath);
$internalData = $this->readFile($this->internalConfigPath);
$overrideData = $this->readFile($this->overrideConfigPath);
$internalOverrideData = $this->readFile($this->internalOverrideConfigPath);
$data = $this->fileManager->isFile($this->configPath) ?
$this->fileManager->getPhpContents($this->configPath) : [];
$internalData = $this->fileManager->isFile($this->internalConfigPath) ?
$this->fileManager->getPhpContents($this->internalConfigPath) : [];
/** @var array<string, mixed> $mergedData */
$mergedData = Util::merge(
Util::merge($systemData, $data),
$internalData
$this->data = $this->mergeData(
$systemData,
$data,
$internalData,
$overrideData,
$internalOverrideData
);
$this->data = $mergedData;
$this->internalParamList = array_keys($internalData);
$this->internalParamList = array_values(array_merge(
array_keys($internalData),
array_keys($internalOverrideData)
));
$this->fileManager->setConfig($this);
}
/**
* @param array<string, mixed> $systemData
* @param array<string, mixed> $data
* @param array<string, mixed> $internalData
* @param array<string, mixed> $overrideData
* @param array<string, mixed> $internalOverrideData
* @return array<string, mixed>
*/
private function mergeData(
array $systemData,
array $data,
array $internalData,
array $overrideData,
array $internalOverrideData
): array {
/** @var array<string, mixed> $mergedData */
$mergedData = Util::merge($systemData, $data);
/** @var array<string, mixed> $mergedData */
$mergedData = Util::merge($mergedData, $internalData);
/** @var array<string, mixed> $mergedData */
$mergedData = Util::merge($mergedData, $overrideData);
/** @var array<string, mixed> */
return Util::merge($mergedData, $internalOverrideData);
}
/**
* @return array<string, mixed>
*/
private function readFile(string $path): array
{
return $this->fileManager->isFile($path) ?
$this->fileManager->getPhpContents($path) : [];
}
/**
* Get all parameters excluding those that are set in the internal config.
*/
@@ -348,9 +391,11 @@ class Config
public function setData($data)
{
if (is_object($data)) {
/** @noinspection PhpParamsInspection */
$data = get_object_vars($data);
}
/** @noinspection PhpDeprecationInspection */
$this->set($data);
}
@@ -368,6 +413,7 @@ class Config
return $timestamp;
}
/** @noinspection PhpDeprecationInspection */
$this->set($timestamp);
return null;

View File

@@ -174,7 +174,7 @@ class ConfigWriter
try {
$this->fileManager->putPhpContents($path, $data);
}
catch (Exception $e) {
catch (Exception) {
throw new RuntimeException("Could not save config.");
}
@@ -190,7 +190,7 @@ class ConfigWriter
try {
$this->fileManager->putPhpContentsNoRenaming($path, $data);
}
catch (Exception $e) {
catch (Exception) {
throw new RuntimeException("Could not save config.");
}
}

View File

@@ -29,21 +29,19 @@
namespace tests\unit\Espo\Core\Utils;
use PHPUnit\Framework\TestCase;
use tests\unit\ReflectionHelper;
use Espo\Core\Utils\Config;
use Espo\Core\Utils\Config\ConfigFileManager;
class ConfigTest extends \PHPUnit\Framework\TestCase
class ConfigTest extends TestCase
{
private ?Config $config = null;
private $defaultTestConfig = 'tests/unit/testData/Utils/Config/config.php';
private $configPath = 'tests/unit/testData/cache/config.php';
private $systemConfigPath = 'tests/unit/testData/Utils/Config/systemConfig.php';
private $internalConfigPath = 'tests/unit/testData/cache/config-internal.php';
protected function setUp(): void
@@ -64,7 +62,7 @@ class ConfigTest extends \PHPUnit\Framework\TestCase
$this->reflection->setProperty('internalConfigPath', $this->internalConfigPath);
}
protected function tearDown() : void
protected function tearDown(): void
{
$this->config = NULL;
}
@@ -116,7 +114,15 @@ class ConfigTest extends \PHPUnit\Framework\TestCase
$fileManager
->method('isFile')
->willReturn(true);
->will(
$this->returnValueMap([
['data/config.php', true],
['data/config-internal.php', true],
['application/Espo/Resources/defaults/systemConfig.php', true],
['data/config-override.php', false],
['data/config-internal-override.php', false],
])
);
$data = [
'test1' => '1',
@@ -147,9 +153,9 @@ class ConfigTest extends \PHPUnit\Framework\TestCase
$this->assertEquals('2', $config->get('test2'));
$this->assertEquals('3', $config->get('test3'));
$this->assertEquals(false, $config->isInternal('test1'));
$this->assertEquals(true, $config->isInternal('test2'));
$this->assertEquals(false, $config->isInternal('test3'));
$this->assertFalse($config->isInternal('test1'));
$this->assertTrue($config->isInternal('test2'));
$this->assertFalse($config->isInternal('test3'));
$this->assertEquals(
(object) [
@@ -166,7 +172,15 @@ class ConfigTest extends \PHPUnit\Framework\TestCase
$fileManager
->method('isFile')
->willReturn(true);
->will(
$this->returnValueMap([
['data/config.php', true],
['data/config-internal.php', true],
['application/Espo/Resources/defaults/systemConfig.php', true],
['data/config-override.php', false],
['data/config-internal-override.php', false],
])
);
$data = [
'a' => [
@@ -195,7 +209,6 @@ class ConfigTest extends \PHPUnit\Framework\TestCase
])
);
$config = new Config($fileManager);
$this->assertEquals(['1' => 'a1'], $config->get('a'));
@@ -210,4 +223,75 @@ class ConfigTest extends \PHPUnit\Framework\TestCase
$this->assertTrue($config->has('a'));
$this->assertFalse($config->has('0'));
}
public function testGetWithOverride(): void
{
$fileManager = $this->createMock(ConfigFileManager::class);
$fileManager
->method('isFile')
->will(
$this->returnValueMap([
['application/Espo/Resources/defaults/systemConfig.php', true],
['data/config.php', true],
['data/config-internal.php', true],
['data/config-override.php', true],
['data/config-internal-override.php', true],
])
);
$dataSystem = [];
$data = [
'a' => 'a',
'c' => 'c',
'b' => 'b0',
];
$dataInternal = [
'b' => 'b0',
'e' => 'e0',
];
$dataOverride = [
'c' => 'c1',
];
$dataInternalOverride = [
'e' => 'e1',
'h' => 'h1',
];
$fileManager
->method('getPhpContents')
->will(
$this->returnValueMap([
['application/Espo/Resources/defaults/systemConfig.php', $dataSystem],
['data/config.php', $data],
['data/config-internal.php', $dataInternal],
['data/config-override.php', $dataOverride],
['data/config-internal-override.php', $dataInternalOverride],
])
);
$config = new Config($fileManager);
$this->assertEquals('a', $config->get('a'));
$this->assertEquals('c1', $config->get('c'));
$this->assertEquals('e1', $config->get('e'));
$this->assertEquals('h1', $config->get('h'));
$this->assertFalse($config->isInternal('c'));
$this->assertTrue($config->isInternal('e'));
$this->assertTrue($config->isInternal('h'));
$this->assertTrue($config->isInternal('b'));
$nonInternalData = $config->getAllNonInternalData();
$this->assertTrue(isset($nonInternalData->a));
$this->assertTrue(isset($nonInternalData->c));
$this->assertFalse(isset($nonInternalData->e));
$this->assertFalse(isset($nonInternalData->h));
}
}