*/ private array $values; private function __construct(array $values) { $this->values = $values; } public static function load(string $path): self { if (!is_file($path) || !is_readable($path)) { throw new RuntimeException('The API environment file is not readable.'); } $values = parse_ini_file($path, false, INI_SCANNER_RAW); if ($values === false) { throw new RuntimeException('The API environment file could not be parsed.'); } $normalized = []; foreach ($values as $name => $value) { if (!is_string($value)) { throw new RuntimeException("API setting $name must be a string."); } $normalized[$name] = trim($value); } return new self($normalized); } public function required(string $name): string { $value = $this->values[$name] ?? ''; if ($value === '') { throw new RuntimeException("Required API setting $name is missing."); } return $value; } public function string(string $name, string $default): string { return $this->values[$name] ?? $default; } public function float(string $name, float $default): float { $value = $this->values[$name] ?? ''; if ($value === '') { return $default; } if (!is_numeric($value) || (float) $value <= 0) { throw new RuntimeException("API setting $name must be greater than zero."); } return (float) $value; } public function int(string $name, int $default, int $minimum, int $maximum): int { $value = $this->values[$name] ?? ''; if ($value === '') { return $default; } if (filter_var($value, FILTER_VALIDATE_INT) === false) { throw new RuntimeException("API setting $name must be an integer."); } $integer = (int) $value; if ($integer < $minimum || $integer > $maximum) { throw new RuntimeException( "API setting $name must be between $minimum and $maximum.", ); } return $integer; } public function bool(string $name, bool $default): bool { $value = strtolower($this->values[$name] ?? ''); if ($value === '') { return $default; } return match ($value) { '1', 'true', 'yes', 'on' => true, '0', 'false', 'no', 'off' => false, default => throw new RuntimeException( "API setting $name must be true or false.", ), }; } }