85 lines
2.5 KiB
PHP
85 lines
2.5 KiB
PHP
<?php
|
|
/**
|
|
* Reads server-side application configuration without bundling secrets.
|
|
* The deploy layout places a .env symlink beside backend/, outside public/.
|
|
*/
|
|
final class AppConfig
|
|
{
|
|
private static $loaded = false;
|
|
|
|
public static function loadEnvironment()
|
|
{
|
|
if (self::$loaded) {
|
|
return;
|
|
}
|
|
|
|
$path = getenv('APP_ENV_FILE');
|
|
if ($path === false || $path === '') {
|
|
$path = dirname(__DIR__) . DIRECTORY_SEPARATOR . '.env';
|
|
}
|
|
|
|
if (!is_file($path) || !is_readable($path)) {
|
|
throw new RuntimeException('Server environment file is missing or unreadable');
|
|
}
|
|
|
|
$lines = file($path, FILE_IGNORE_NEW_LINES);
|
|
if ($lines === false) {
|
|
throw new RuntimeException('Unable to read server environment file');
|
|
}
|
|
|
|
foreach ($lines as $lineNumber => $line) {
|
|
$line = trim($line);
|
|
if ($line === '' || $line[0] === '#') {
|
|
continue;
|
|
}
|
|
|
|
if (!preg_match('/^([A-Z][A-Z0-9_]*)\s*=\s*(.*)$/', $line, $matches)) {
|
|
throw new RuntimeException('Invalid environment entry on line ' . ($lineNumber + 1));
|
|
}
|
|
|
|
$name = $matches[1];
|
|
$value = trim($matches[2]);
|
|
if (strlen($value) >= 2) {
|
|
$first = $value[0];
|
|
$last = substr($value, -1);
|
|
if (($first === '"' && $last === '"') || ($first === "'" && $last === "'")) {
|
|
$value = substr($value, 1, -1);
|
|
}
|
|
}
|
|
|
|
// Explicit process environment values override the file.
|
|
if (getenv($name) === false) {
|
|
putenv($name . '=' . $value);
|
|
$_ENV[$name] = $value;
|
|
}
|
|
}
|
|
|
|
self::$loaded = true;
|
|
}
|
|
|
|
public static function required($name)
|
|
{
|
|
self::loadEnvironment();
|
|
$value = getenv($name);
|
|
if ($value === false || $value === '') {
|
|
throw new RuntimeException('Required server setting is missing: ' . $name);
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
public static function integer($name, $default)
|
|
{
|
|
self::loadEnvironment();
|
|
$value = getenv($name);
|
|
if ($value === false || $value === '') {
|
|
return (int) $default;
|
|
}
|
|
|
|
$parsed = filter_var($value, FILTER_VALIDATE_INT);
|
|
if ($parsed === false) {
|
|
throw new RuntimeException('Server setting must be an integer: ' . $name);
|
|
}
|
|
return $parsed;
|
|
}
|
|
}
|