From a82aa3c66692cd0eb764d52c41698a6f5640fda7 Mon Sep 17 00:00:00 2001 From: Eric Espie Date: Tue, 30 Sep 2025 12:25:50 +0200 Subject: [PATCH] Configuration in json files by module --- core/config.class.inc.php | 12 +- lib/composer/autoload_classmap.php | 2 +- lib/composer/autoload_static.php | 2 +- sources/Core/Configuration/ConfigLoader.php | 115 ------------- sources/Core/Configuration/ConfigManager.php | 167 +++++++++++++++++++ 5 files changed, 175 insertions(+), 123 deletions(-) delete mode 100644 sources/Core/Configuration/ConfigLoader.php create mode 100644 sources/Core/Configuration/ConfigManager.php diff --git a/core/config.class.inc.php b/core/config.class.inc.php index 922adb163..41f7eb553 100644 --- a/core/config.class.inc.php +++ b/core/config.class.inc.php @@ -20,7 +20,7 @@ */ -use Combodo\iTop\Core\Configuration\ConfigLoader; +use Combodo\iTop\Core\Configuration\ConfigManager; define('ITOP_APPLICATION', 'iTop'); define('ITOP_APPLICATION_SHORT', 'iTop'); @@ -2098,21 +2098,21 @@ class Config { $this->CheckFile('configuration', $sConfigFile); - [$MySettings, $MyModuleSettings, $MyModules] = ConfigLoader::GetInstance()->Load($sConfigFile); + [$MySettings, $MyModuleSettings, $MyModules] = ConfigManager::GetInstance()->Load($sConfigFile); $this->m_aAddons = $MyModules['addons']; - foreach ($MySettings as $sPropCode => $rawvalue) + foreach ($MySettings as $sPropCode => $rawValue) { if ($this->IsProperty($sPropCode)) { - if (is_string($rawvalue)) + if (is_string($rawValue)) { - $value = trim($rawvalue); + $value = trim($rawValue); } else { - $value = $rawvalue; + $value = $rawValue; } $this->Set($sPropCode, $value, $sConfigFile, true); } diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index 4357552bf..37018b082 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -414,7 +414,7 @@ return array( 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderFactory' => $baseDir . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderFactory.php', 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderGoogle' => $baseDir . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderGoogle.php', 'Combodo\\iTop\\Core\\CMDBChange\\CMDBChangeOrigin' => $baseDir . '/sources/Core/CMDBChange/CMDBChangeOrigin.php', - 'Combodo\\iTop\\Core\\Configuration\\ConfigLoader' => $baseDir . '/sources/Core/Configuration/ConfigLoader.php', + 'Combodo\\iTop\\Core\\Configuration\\ConfigManager' => $baseDir . '/sources/Core/Configuration/ConfigManager.php', 'Combodo\\iTop\\Core\\DbConnectionWrapper' => $baseDir . '/core/DbConnectionWrapper.php', 'Combodo\\iTop\\Core\\Email\\EMailSymfony' => $baseDir . '/sources/Core/Email/EmailSymfony.php', 'Combodo\\iTop\\Core\\Email\\EmailFactory' => $baseDir . '/sources/Core/Email/EmailFactory.php', diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index ce0b41773..822fd779a 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -779,7 +779,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderFactory' => __DIR__ . '/../..' . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderFactory.php', 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderGoogle' => __DIR__ . '/../..' . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderGoogle.php', 'Combodo\\iTop\\Core\\CMDBChange\\CMDBChangeOrigin' => __DIR__ . '/../..' . '/sources/Core/CMDBChange/CMDBChangeOrigin.php', - 'Combodo\\iTop\\Core\\Configuration\\ConfigLoader' => __DIR__ . '/../..' . '/sources/Core/Configuration/ConfigLoader.php', + 'Combodo\\iTop\\Core\\Configuration\\ConfigManager' => __DIR__ . '/../..' . '/sources/Core/Configuration/ConfigManager.php', 'Combodo\\iTop\\Core\\DbConnectionWrapper' => __DIR__ . '/../..' . '/core/DbConnectionWrapper.php', 'Combodo\\iTop\\Core\\Email\\EMailSymfony' => __DIR__ . '/../..' . '/sources/Core/Email/EmailSymfony.php', 'Combodo\\iTop\\Core\\Email\\EmailFactory' => __DIR__ . '/../..' . '/sources/Core/Email/EmailFactory.php', diff --git a/sources/Core/Configuration/ConfigLoader.php b/sources/Core/Configuration/ConfigLoader.php deleted file mode 100644 index 23d00c1b3..000000000 --- a/sources/Core/Configuration/ConfigLoader.php +++ /dev/null @@ -1,115 +0,0 @@ -$/', $sConfigCode, $aMatches)... - // So, I've implemented a solution suggested in the PHP doc (search for phpWrapper) - try - { - ob_start(); - eval('?'.'>'.trim($sConfigCode)); - $sNoise = trim(ob_get_contents()); - ob_end_clean(); - } - catch (Error $e) - { - // PHP 7 - throw new ConfigException('Error in configuration file', - array('file' => $sConfigFile, 'error' => $e->getMessage().' at line '.$e->getLine())); - } - catch (Exception $e) - { - // well, never reach in case of parsing error :-( - // will be improved in PHP 6 ? - throw new ConfigException('Error in configuration file', - array('file' => $sConfigFile, 'error' => $e->getMessage())); - } - if (strlen($sNoise) > 0) - { - // Note: sNoise is an html output, but so far it was ok for me (e.g. showing the entire call stack) - throw new ConfigException('Syntax error in configuration file', - array('file' => $sConfigFile, 'error' => ''.utils::EscapeHtml($sNoise, ENT_QUOTES).'')); - } - - if (!isset($MySettings) || !is_array($MySettings)) - { - throw new ConfigException('Missing array in configuration file', - array('file' => $sConfigFile, 'expected' => '$MySettings')); - } - - if (!array_key_exists('addons', $MyModules)) - { - throw new ConfigException('Missing item in configuration file', - array('file' => $sConfigFile, 'expected' => '$MyModules[\'addons\']')); - } - if (!array_key_exists('user rights', $MyModules['addons'])) - { - // Add one, by default - $MyModules['addons']['user rights'] = '/addons/userrights/userrightsnull.class.inc.php'; - } - - $this->LoadModulesConfig(dirname($sConfigFile), $MySettings, $MyModuleSettings, $MyModules); - - return [$MySettings, $MyModuleSettings, $MyModules]; - } - - private function LoadModulesConfig(string $sConfigDir, array &$MySettings, array &$MyModuleSettings, array &$MyModules) - { - foreach (glob($sConfigDir.'/modules/*/*.json') as $sJSONModuleFiles) { - $aConf = json_decode(file_get_contents($sJSONModuleFiles), true); - if (is_null($aConf)) { - IssueLog::Exception('Error reading configuration file: '.$sJSONModuleFiles, new Exception()); - continue; - } - // TODO ajouter les confs dans les tableaux - if (is_array($aConf['MySettings'])) { - $MySettings = array_merge($MySettings, $aConf['MySettings']); - } - if (is_array($aConf['MyModuleSettings'])) { - $MyModuleSettings = array_merge($MyModuleSettings, $aConf['MyModuleSettings']); - } - if (is_array($aConf['MyModules'])) { - $MyModules = array_merge($MyModules, $aConf['MyModules']); - } - } - } -} \ No newline at end of file diff --git a/sources/Core/Configuration/ConfigManager.php b/sources/Core/Configuration/ConfigManager.php new file mode 100644 index 000000000..6901f0ae9 --- /dev/null +++ b/sources/Core/Configuration/ConfigManager.php @@ -0,0 +1,167 @@ +aMySettings)) { + return [$this->aMySettings, $this->aMyModuleSettings, $this->aMyModules]; + } + + // Variables created when doing an eval() on the config file + /** @var array $MySettings */ + $MySettings = null; + /** @var array $MyModuleSettings */ + $MyModuleSettings = []; + /** @var array $MyModules */ + $MyModules = null; + + // This does not work on several lines + // preg_match('/^<\\?php(.*)\\?'.'>$/', $sConfigCode, $aMatches)... + // So, I've implemented a solution suggested in the PHP doc (search for phpWrapper) + try + { + ob_start(); + eval('?'.'>'.trim($sConfigCode)); + $sNoise = trim(ob_get_contents()); + ob_end_clean(); + } + catch (Error $e) + { + // PHP 7 + throw new ConfigException('Error in configuration file', + array('file' => $sConfigFile, 'error' => $e->getMessage().' at line '.$e->getLine())); + } + catch (Exception $e) + { + // well, never reach in case of parsing error :-( + // will be improved in PHP 6 ? + throw new ConfigException('Error in configuration file', + array('file' => $sConfigFile, 'error' => $e->getMessage())); + } + if (strlen($sNoise) > 0) + { + // Note: sNoise is an html output, but so far it was ok for me (e.g. showing the entire call stack) + throw new ConfigException('Syntax error in configuration file', + array('file' => $sConfigFile, 'error' => ''.utils::EscapeHtml($sNoise, ENT_QUOTES).'')); + } + + if (!is_array($MySettings)) + { + throw new ConfigException('Missing array in configuration file', + array('file' => $sConfigFile, 'expected' => '$MySettings')); + } + + if (!array_key_exists('addons', $MyModules)) + { + throw new ConfigException('Missing item in configuration file', + array('file' => $sConfigFile, 'expected' => '$MyModules[\'addons\']')); + } + if (!array_key_exists('user rights', $MyModules['addons'])) + { + // Add one, by default + $MyModules['addons']['user rights'] = '/addons/userrights/userrightsnull.class.inc.php'; + } + + $this->aMySettings = $MySettings; + $this->aMyModuleSettings = $MyModuleSettings; + $this->aMyModules = $MyModules; + + $this->LoadModulesConfig(dirname($sConfigFile)); + + return [$this->aMySettings, $this->aMyModuleSettings, $this->aMyModules]; + } + + private function LoadModulesConfig(string $sConfigDir): void + { + foreach ($this->ListConfigFiles($sConfigDir) as $sJSONModuleFiles) { + $aConf = json_decode(file_get_contents($sJSONModuleFiles), true); + if (is_null($aConf)) { + IssueLog::Exception('Error reading configuration file: '.$sJSONModuleFiles, new Exception()); + continue; + } + if (is_array($aConf['MySettings'] ?? null)) { + $this->aMySettings = array_merge($this->aMySettings, $aConf['MySettings']); + } + if (is_array($aConf['MyModuleSettings'] ?? null)) { + $this->aMyModuleSettings = array_merge($this->aMyModuleSettings, $aConf['MyModuleSettings']); + } + if (is_array($aConf['MyModules'] ?? null)) { + $this->aMyModules = array_merge($this->aMyModules, $aConf['MyModules']); + } + } + } + + /** + * Find all json files under $sRootDir + * @param string $sRootDir + * + * @return array + */ + private function ListConfigFiles(string $sRootDir): array + { + $aConfigFiles = []; + while($aDirs = glob($sRootDir . '/*', GLOB_ONLYDIR)) { + $sRootDir .= '/*'; + foreach ($aDirs as $sConfDir) { + $aConfigFiles = array_merge($aConfigFiles, glob($sConfDir.'/*.json')); + } + } + + return $aConfigFiles; + } + + public function SaveModuleConfig(string $sModule, array $MyModuleSettings, array $MySettings = null, array $MyModules = null): void + { + $sConfigFile = dirname(utils::GetConfigFilePath()).'/modules/'.$sModule.'/'.$sModule.'.json'; + SetupUtils::builddir(dirname($sConfigFile)); + $aConf = ['MyModuleSettings' => $MyModuleSettings]; + if (is_array($MySettings)) { + $aConf['MySettings'] = $MySettings; + } + if (is_array($MyModules)) { + $aConf['MyModules'] = $MyModules; + } + file_put_contents($sConfigFile, json_encode($aConf, JSON_PRETTY_PRINT)); + } +} \ No newline at end of file