eesyphp/src/Config.php
2024-01-23 19:23:10 +01:00

259 lines
8.5 KiB
PHP

<?php
Namespace EesyPHP;
Class Config {
/**
* Configuration file path
* @var string|null
*/
private static $filepath = null;
/**
* Loaded configuration data
* @var array|null
*/
private static $config = null;
/**
* Extra registered variables usable in configuration file
* @var array
*/
private static $extra_variables = array();
/**
* Load configuration file
* @param string $filepath The configuration file path
* @param bool $extra Load as an extra configuration file (default: false)
* @return bool
*/
public static function load($filepath, $extra=false) {
if (!file_exists($filepath)) {
Log :: error("Configuration file not found ($filepath)");
return false;
}
$config = yaml_parse_file($filepath);
if (!is_array($config) || empty($config)) {
Log :: error("Fail to load %sconfiguration file (%s)", $extra?'extra ':'', $filepath);
return false;
}
if (!$extra || !is_array(self :: $config))
self :: $config = $config;
else
self :: $config = array_replace_recursive(self :: $config, $config);
if (!$extra)
self :: $filepath = $filepath;
return true;
}
/**
* Check if configuration is loaded
* @return bool
*/
public static function loaded() {
return is_array(self :: $config);
}
/**
* Save configuration
* @param string|null $filepath The configuration file path
* @param bool $overwrite Overwrite existing file (optional, default: true)
* @return bool
*/
public static function save($filepath=null, $overwrite=true) {
if (!self :: loaded()) {
Log :: error("Configuration not loaded, can't save it.");
return false;
}
if (!$filepath) $filepath = self :: $filepath;
if (!$filepath) {
Log :: error("No configuration file set or pass as parameter");
return false;
}
if (file_exists($filepath)) {
if (!$overwrite) {
Log :: error("Configuration file already exist (%s)", $filepath);
return false;
}
if (!is_writable($filepath)) {
Log :: error(
"Configuration file already exist and is not writable (%s)",
$filepath);
return false;
}
}
if (!yaml_emit_file($filepath, self :: $config)) {
Log :: error("Fail to save configuration in '%s'", $filepath);
return false;
}
Log :: info("Configuration saved in '%s'", $filepath);
return true;
}
/**
* Register extra variable usable in configuration file
* @param string $key The variable key
* @param mixed $value The variable value
*/
public static function register_extra_variable($key, $value) {
self :: $extra_variables[$key] = $value;
}
/**
* Check if a specific configuration variable is set
*
* @param string $key The configuration variable key
* @param array|null $config Optional configuration to use instead of current loaded configuration
* @return bool
**/
public static function isset($key, &$config=null) {
if (array_key_exists($key, self :: $extra_variables))
return true;
if (!is_array($config) && !self :: loaded())
Log :: fatal('Configuration not loaded (on checking if %s is set)', $key);
$exploded_key = explode('.', $key);
if (!is_array($exploded_key)) return false;
$value = is_array($config)?$config:self :: $config;
foreach ($exploded_key as $k) {
if (!is_array($value) || !isset($value[$k]))
return false;
$value = $value[$k];
}
return true;
}
/**
* Get a specific configuration variable value
*
* @param string $key The configuration variable key
* @param mixed $default The default value to return if configuration variable
* is not set (Default : null)
* @param string $cast The type of expected value. The configuration variable
* value will be cast as this type. Could be : bool, int,
* float or string. (Optional, default : raw value)
* @param bool $split If true, $cast=='array' and $value is a string, split
* the value by comma (optional, default: false)
* @param array|null $config Optional configuration to use instead of current loaded configuration
* @param callable|null $get Optional callable to get another value that will be used to replace
* variables references found in retrieved value.
* @return mixed The configuration variable value
**/
public static function get($key, $default=null, $cast=null, $split=false, &$config=null, $get=null) {
if (array_key_exists($key, self :: $extra_variables)) {
$value = self :: $extra_variables[$key];
}
else if (!is_array($config) && !self :: loaded()) {
Log :: fatal(
"Configuration not loaded (on getting %s):\n%s",
$key, Log :: get_debug_backtrace_context()
);
}
else {
$exploded_key = explode('.', $key);
if (!is_array($exploded_key)) return self :: replace_variables($default, $get?$get:$config);
$value = is_array($config)?$config:self :: $config;
foreach ($exploded_key as $k) {
if (!is_array($value) || !isset($value[$k]))
return self :: replace_variables($default, $get?$get:$config);
$value = $value[$k];
}
}
return self :: replace_variables(cast($value, $cast, $split), $get?$get:$config);
}
/**
* Replace variable in specified value
* @param mixed $value
* @param array|callable|null $config Optional configuration to use to retrieve variable reference
* value instead of current loaded configuration. Could be an
* array of configuration data or a callable that could be used
* as Config::get() to retrieve the desired variable reference.
* @return mixed
*/
public static function replace_variables($value, $config=null) {
if (is_array($value)) {
foreach(array_keys($value) as $key) {
if (is_string($value[$key]) || is_array($value[$key]))
$value[$key] = self :: replace_variables($value[$key], $config);
}
}
else if (is_string($value)) {
$config = is_null($config)?self :: $config:$config;
$iteration = 0;
while (preg_match('/\$\{([^\}]+)\}/', $value, $m)) {
if ($iteration > 20)
Log::fatal('Config::replace_variables(%s): max iteration reached');
if (is_callable($config))
$replace_by = call_user_func($config, $m[1], '', 'string', false);
else
$replace_by = self :: get($m[1], '', 'string', false, $config);
$value = str_replace($m[0], $replace_by, $value);
$iteration++;
}
}
return $value;
}
/**
* Get list of keys of a specific configuration variable
*
* @param string $key The configuration variable key
*
* @return array An array of the keys of a specific configuration variable
**/
public static function keys($key) {
$value = self :: get($key);
return (is_array($value)?array_keys($value):array());
}
/**
* Set a configuration variable
*
* @param string $key The configuration variable key
* @param mixed $value The configuration variable value
* @param array|null &$config Optional configuration to use instead of current loaded configuration
*
* @return boolean
**/
public static function set($key, $value, &$config=null) {
$exploded_key = explode('.', $key);
if (!is_array($exploded_key)) return false;
if (is_array($config)) {
$parent = &$config;
}
else {
if (!is_array(self :: $config))
self :: $config = array();
$parent = &self :: $config;
}
for ($i=0; $i < count($exploded_key) - 1; $i++) {
$k = $exploded_key[$i];
if (!array_key_exists($k, $parent))
$parent[$k] = array();
$parent = &$parent[$k];
}
$parent[array_pop($exploded_key)] = $value;
return true;
}
/**
* Helper to set PHP INI option and log error
* @param string $option
* @param string|int|float|bool|null $value
* @return void
*/
public static function ini_set($option, $value) {
Log :: trace('Set PHP INI option "%s" to "%s"', $option, $value);
if (ini_set($option, $value) === false)
Log::warning('Fail to set PHP INI option "%s" to "%s"', $option, $value);
Log :: trace(
'PHP INI option "%s" after setting it to "%s": "%s"',
$option, $value, vardump(ini_get($option)));
}
}
# vim: tabstop=4 shiftwidth=4 softtabstop=4 expandtab