diff --git a/core/config.class.inc.php b/core/config.class.inc.php index 66545f161..922adb163 100644 --- a/core/config.class.inc.php +++ b/core/config.class.inc.php @@ -20,6 +20,8 @@ */ +use Combodo\iTop\Core\Configuration\ConfigLoader; + define('ITOP_APPLICATION', 'iTop'); define('ITOP_APPLICATION_SHORT', 'iTop'); @@ -2096,62 +2098,7 @@ class Config { $this->CheckFile('configuration', $sConfigFile); - $sConfigCode = trim(file_get_contents($sConfigFile)); - - // Variables created when doing an eval() on the config file - /** @var array $MySettings */ - $MySettings = null; - /** @var array $MyModuleSettings */ - $MyModuleSettings = null; - /** @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 (!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'; - } + [$MySettings, $MyModuleSettings, $MyModules] = ConfigLoader::GetInstance()->Load($sConfigFile); $this->m_aAddons = $MyModules['addons']; diff --git a/core/log.class.inc.php b/core/log.class.inc.php index a1688afdc..9b209437a 100644 --- a/core/log.class.inc.php +++ b/core/log.class.inc.php @@ -745,6 +745,17 @@ abstract class LogAPI static::Log(self::LEVEL_TRACE, $sMessage, $sChannel, $aContext); } + public static function Exception(string $sMessage, throwable $previous): void + { + if (is_null($previous)) { + $previous = new Exception(''); + } + + $aContext['error'] = $previous->getMessage(); + $aContext['stack'] = $previous->getTraceAsString(); + static::Error($sMessage, static::CHANNEL_DEFAULT, $aContext); + } + /** * @throws \ConfigException if log wrongly configured */ diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index d98cfc88e..4357552bf 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -414,6 +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\\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 4b1fc5b95..ce0b41773 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -779,6 +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\\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 new file mode 100644 index 000000000..23d00c1b3 --- /dev/null +++ b/sources/Core/Configuration/ConfigLoader.php @@ -0,0 +1,115 @@ +$/', $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