diff --git a/application/Espo/Core/Utils/Config.php b/application/Espo/Core/Utils/Config.php index ecf8654a8b..f57daf7781 100644 --- a/application/Espo/Core/Utils/Config.php +++ b/application/Espo/Core/Utils/Config.php @@ -122,7 +122,11 @@ class Config return $default; } - if (!isset($lastBranch[$key])) { + if (is_array($lastBranch) && !isset($lastBranch[$key])) { + return $default; + } + + if (is_object($lastBranch) && !property_exists($lastBranch, $key)) { return $default; } @@ -152,7 +156,11 @@ class Config return false; } - if (!isset($lastBranch[$key])) { + if (is_array($lastBranch) && !isset($lastBranch[$key])) { + return false; + } + + if (is_object($lastBranch) && !property_exists($lastBranch, $key)) { return false; } @@ -311,8 +319,13 @@ class Config $internalData = $this->fileManager->isFile($this->internalConfigPath) ? $this->fileManager->getPhpContents($this->internalConfigPath) : []; - $this->data = Util::merge($systemData, $data); - $this->data = Util::merge($this->data, $internalData); + /** @var array */ + $mergedData = Util::merge( + Util::merge($systemData, $data), + $internalData + ); + + $this->data = $mergedData; $this->internalParamList = array_keys($internalData); diff --git a/application/Espo/Core/Utils/Crypt.php b/application/Espo/Core/Utils/Crypt.php index 97f1e2159b..5717d481b8 100644 --- a/application/Espo/Core/Utils/Crypt.php +++ b/application/Espo/Core/Utils/Crypt.php @@ -64,7 +64,10 @@ class Crypt throw new RuntimeException("openssl extension is not loaded."); } - $this->iv = openssl_random_pseudo_bytes(16); + /** @var string */ + $iv = openssl_random_pseudo_bytes(16); + + $this->iv = $iv; } return $this->iv; @@ -93,9 +96,13 @@ class Crypt throw new RuntimeException("openssl extension is not loaded."); } - return trim( - openssl_decrypt($string, 'aes-256-cbc', $this->getKey(), OPENSSL_RAW_DATA, $iv) - ); + $value = openssl_decrypt($string, 'aes-256-cbc', $this->getKey(), OPENSSL_RAW_DATA, $iv); + + if ($value === false) { + throw new RuntimeException("OpenSSL decrypt failure."); + } + + return trim($value); } public function generateKey(): string diff --git a/application/Espo/Core/Utils/DataUtil.php b/application/Espo/Core/Utils/DataUtil.php index ce2b89c3ac..a02ec84b93 100644 --- a/application/Espo/Core/Utils/DataUtil.php +++ b/application/Espo/Core/Utils/DataUtil.php @@ -117,9 +117,9 @@ class DataUtil } /** - * @param array $data + * @param array|\stdClass $data * @param mixed $needle - * @return array + * @return array|\stdClass */ public static function unsetByValue(&$data, $needle) { @@ -156,7 +156,7 @@ class DataUtil * * @param array|\stdClass $data * @param array|\stdClass $overrideData - * @return array|\stdClass + * @return array|\stdClass */ public static function merge($data, $overrideData) { @@ -196,6 +196,8 @@ class DataUtil $data = []; } + /** @var array $data */ + if (in_array($appendIdentifier, $overrideData)) { foreach ($overrideData as $key => $item) { if ($item === $appendIdentifier) { diff --git a/tests/unit/Espo/Core/Utils/ConfigTest.php b/tests/unit/Espo/Core/Utils/ConfigTest.php index ce58f15d77..0c7db57fe0 100644 --- a/tests/unit/Espo/Core/Utils/ConfigTest.php +++ b/tests/unit/Espo/Core/Utils/ConfigTest.php @@ -36,6 +36,8 @@ use Espo\Core\Utils\Config\ConfigFileManager; class ConfigTest extends \PHPUnit\Framework\TestCase { + private ?Config $config = null; + private $defaultTestConfig = 'tests/unit/testData/Utils/Config/config.php'; private $configPath = 'tests/unit/testData/cache/config.php'; @@ -44,7 +46,7 @@ class ConfigTest extends \PHPUnit\Framework\TestCase private $internalConfigPath = 'tests/unit/testData/cache/config-internal.php'; - protected function setUp() : void + protected function setUp(): void { $this->fileManager = new ConfigFileManager; @@ -74,7 +76,7 @@ class ConfigTest extends \PHPUnit\Framework\TestCase $this->assertArrayHasKey('dateFormat', $this->reflection->invokeMethod('getData', [])); } - public function testGet() + public function testGet1(): void { $result = [ 'driver' => 'pdo_mysql', @@ -108,7 +110,7 @@ class ConfigTest extends \PHPUnit\Framework\TestCase $this->assertArrayHasKey('adminItems', $configData); } - public function testGet1(): void + public function testGet2(): void { $fileManager = $this->createMock(ConfigFileManager::class); @@ -157,4 +159,55 @@ class ConfigTest extends \PHPUnit\Framework\TestCase $config->getAllNonInternalData(), ); } + + public function testGet3(): void + { + $fileManager = $this->createMock(ConfigFileManager::class); + + $fileManager + ->method('isFile') + ->willReturn(true); + + $data = [ + 'a' => [ + '1' => 'a1', + ], + 'b' => (object) [ + '1' => 'b1', + ], + 'c' => 'c', + 'd' => ['d'], + ]; + + $dataInternal = [ + ]; + + $dataSystem = [ + ]; + + $fileManager + ->method('getPhpContents') + ->will( + $this->returnValueMap([ + ['data/config.php', $data], + ['data/config-internal.php', $dataInternal], + ['application/Espo/Resources/defaults/systemConfig.php', $dataSystem], + ]) + ); + + + $config = new Config($fileManager); + + $this->assertEquals(['1' => 'a1'], $config->get('a')); + $this->assertEquals('a1', $config->get('a.1')); + $this->assertEquals('b1', $config->get('b.1')); + $this->assertEquals('c', $config->get('c')); + $this->assertEquals(['d'], $config->get('d')); + + $this->assertFalse($config->has('a.2')); + $this->assertTrue($config->has('a.1')); + + $this->assertTrue($config->has('a')); + $this->assertFalse($config->has('0')); + } }