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); } }