79 lines
2.3 KiB
PHP
79 lines
2.3 KiB
PHP
<?php
|
|
namespace Hanyuu\Config;
|
|
|
|
use InvalidArgumentException;
|
|
|
|
class ArrayConfig implements IConfig {
|
|
private const SCOPE_CHAR = ':';
|
|
private const SCANNER_MODE = INI_SCANNER_TYPED;
|
|
private const TEST_VALUE = 'X-Config-Test';
|
|
|
|
private array $cache = [];
|
|
private array $exists = [];
|
|
|
|
public function __construct(
|
|
private array $config
|
|
) {}
|
|
|
|
public function scopeTo(string $prefix): IConfig {
|
|
return new ScopedConfig($this, $prefix);
|
|
}
|
|
|
|
private function getRaw(string $name): mixed {
|
|
$parts = array_reverse(explode(self::SCOPE_CHAR, $name));
|
|
$value = $this->config;
|
|
|
|
while(count($parts) > 1) {
|
|
$part = array_pop($parts);
|
|
if(!array_key_exists($part, $value))
|
|
break;
|
|
$value = $value[$part];
|
|
}
|
|
|
|
if($parts[0] === '')
|
|
return $value;
|
|
|
|
return $value[$parts[0]] ?? null;
|
|
}
|
|
|
|
public function getValue(string $name, string $type = IConfig::T_ANY, $default = null): mixed {
|
|
if(array_key_exists($name, $this->cache))
|
|
$value = $this->cache[$name];
|
|
else {
|
|
$this->cache[$name] = $value = $this->getRaw($name);
|
|
$this->exists[$name] = $value !== null;
|
|
}
|
|
|
|
if($type !== IConfig::T_ANY && CfgTools::type($value) !== $type)
|
|
$value = null;
|
|
|
|
return $value ?? $default ?? CfgTools::default($type);
|
|
}
|
|
|
|
public function hasValue(string $name): bool {
|
|
if(array_key_exists($name, $this->exists))
|
|
return $this->exists[$name];
|
|
|
|
$exists = array_key_exists($name, $this->cache)
|
|
|| $this->getRaw($name) !== null;
|
|
|
|
return $this->exists[$name] = $exists;
|
|
}
|
|
|
|
public static function open(string $path): self {
|
|
$parsed = parse_ini_file($path, true, self::SCANNER_MODE);
|
|
if($parsed === false)
|
|
throw new InvalidArgumentException('Unable to parse configuration file in $path.');
|
|
|
|
return new static($parsed);
|
|
}
|
|
|
|
public static function from(string $string): self {
|
|
$parsed = parse_ini_string($string, true, self::SCANNER_MODE);
|
|
if($parsed === false)
|
|
throw new InvalidArgumentException('Unable to parse configuration string in $string.');
|
|
|
|
return new static($parsed);
|
|
}
|
|
}
|