- Fix RedisCache driver to handle MGET failures gracefully with fallback - Add comprehensive discovery context comparison debug tools - Identify root cause: WEB context discovery missing 166 items vs CLI - WEB context missing RequestFactory class entirely (52 vs 69 commands) - Improved exception handling with detailed binding diagnostics
129 lines
4.2 KiB
PHP
129 lines
4.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Framework\Config;
|
|
|
|
/**
|
|
* Lightweight boot-time configuration validator.
|
|
*
|
|
* Non-invasive: reports issues via error_log and returns a list of problems
|
|
* without throwing, so existing environments are not broken inadvertently.
|
|
*/
|
|
final readonly class ConfigValidator
|
|
{
|
|
public function __construct(private Environment $env)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Validate selected environment variables and return a list of issues.
|
|
* Each issue contains: key, issue, severity, recommendation.
|
|
* @return array<int, array<string, string>>
|
|
*/
|
|
public function validate(): array
|
|
{
|
|
/** @var array<int, array<string, string>> */
|
|
$issues = [];
|
|
|
|
// APP_ENV validation
|
|
/** @var array<int, string> */
|
|
$allowedEnvs = ['development', 'testing', 'production'];
|
|
$appEnv = $this->env->getString(EnvKey::APP_ENV, 'production');
|
|
if (! in_array($appEnv, $allowedEnvs, true)) {
|
|
$issues[] = [
|
|
'key' => 'APP_ENV',
|
|
'issue' => 'invalid_value',
|
|
'severity' => 'medium',
|
|
'recommendation' => 'Setze APP_ENV auf einen der Werte: development | testing | production',
|
|
];
|
|
}
|
|
|
|
// APP_DEBUG should be boolean-like if present
|
|
if ($this->env->has(EnvKey::APP_DEBUG)) {
|
|
$raw = $this->env->get(EnvKey::APP_DEBUG);
|
|
if (! is_bool($raw) && ! is_string($raw)) {
|
|
$issues[] = [
|
|
'key' => 'APP_DEBUG',
|
|
'issue' => 'invalid_type',
|
|
'severity' => 'low',
|
|
'recommendation' => 'APP_DEBUG sollte true/false (oder "true"/"false") sein.',
|
|
];
|
|
}
|
|
}
|
|
|
|
// APP_PORT if present should be a valid TCP port
|
|
if ($this->env->has('APP_PORT')) {
|
|
$port = (int) $this->env->get('APP_PORT');
|
|
if ($port < 1 || $port > 65535) {
|
|
$issues[] = [
|
|
'key' => 'APP_PORT',
|
|
'issue' => 'out_of_range',
|
|
'severity' => 'medium',
|
|
'recommendation' => 'APP_PORT muss zwischen 1 und 65535 liegen.',
|
|
];
|
|
}
|
|
}
|
|
|
|
// Redis port if present
|
|
if ($this->env->has('REDIS_PORT')) {
|
|
$redisPort = (int) $this->env->get('REDIS_PORT');
|
|
if ($redisPort < 1 || $redisPort > 65535) {
|
|
$issues[] = [
|
|
'key' => 'REDIS_PORT',
|
|
'issue' => 'out_of_range',
|
|
'severity' => 'low',
|
|
'recommendation' => 'REDIS_PORT muss zwischen 1 und 65535 liegen.',
|
|
];
|
|
}
|
|
}
|
|
|
|
// Rate limit values if present: must be non-negative
|
|
/** @var array<int, string> */
|
|
$rateKeys = [
|
|
'RATE_LIMIT_DEFAULT',
|
|
'RATE_LIMIT_WINDOW',
|
|
'RATE_LIMIT_AUTH',
|
|
'RATE_LIMIT_AUTH_WINDOW',
|
|
'RATE_LIMIT_API',
|
|
'RATE_LIMIT_API_WINDOW',
|
|
];
|
|
foreach ($rateKeys as $rateKey) {
|
|
if ($this->env->has($rateKey)) {
|
|
$value = (int) $this->env->get($rateKey);
|
|
if ($value < 0) {
|
|
$issues[] = [
|
|
'key' => $rateKey,
|
|
'issue' => 'negative_value',
|
|
'severity' => 'low',
|
|
'recommendation' => $rateKey . ' sollte eine nicht-negative Ganzzahl sein.',
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
return $issues;
|
|
}
|
|
|
|
/**
|
|
* Validate and log issues. Returns the list of issues for optional handling.
|
|
* @return array<int, array<string, string>>
|
|
*/
|
|
public function validateAndReport(): array
|
|
{
|
|
$issues = $this->validate();
|
|
foreach ($issues as $issue) {
|
|
$msg = sprintf(
|
|
'[CONFIG] key=%s issue=%s severity=%s recommendation=%s',
|
|
$issue['key'],
|
|
$issue['issue'],
|
|
$issue['severity'],
|
|
$issue['recommendation']
|
|
);
|
|
error_log($msg);
|
|
}
|
|
|
|
return $issues;
|
|
}
|
|
}
|