Files
michaelschiemer/src/Framework/Config/ConfigValidator.php
Michael Schiemer e30753ba0e fix: resolve RedisCache array offset error and improve discovery diagnostics
- 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
2025-09-12 20:05:18 +02:00

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