diff --git a/.env.example b/.env.example index 7f06308..7b9a801 100644 --- a/.env.example +++ b/.env.example @@ -2,6 +2,7 @@ APP_NAME=CoreCore APP_URL=http://localhost:8080 APP_ENV=dev APP_DEBUG=true +APP_VENDOR_PHP_ISSUES_MODE=suppress_deprecations APP_CONFIG_VALIDATE=true APP_TIMEZONE=Europe/Berlin APP_STORAGE_PATH=./storage diff --git a/.env.prod.example b/.env.prod.example index 3076456..5b57ff9 100644 --- a/.env.prod.example +++ b/.env.prod.example @@ -2,6 +2,7 @@ APP_NAME=CoreCore APP_URL=https://example.com APP_ENV=prod APP_DEBUG=false +APP_VENDOR_PHP_ISSUES_MODE=strict APP_CONFIG_VALIDATE=true APP_TIMEZONE=Europe/Berlin APP_STORAGE_PATH=./storage diff --git a/lib/App/Bootstrap/EnvValidator.php b/lib/App/Bootstrap/EnvValidator.php index 2b0323d..2c0859e 100644 --- a/lib/App/Bootstrap/EnvValidator.php +++ b/lib/App/Bootstrap/EnvValidator.php @@ -36,7 +36,7 @@ final class EnvValidator } $env = []; - foreach (array_merge(self::REQUIRED_KEYS, ['APP_URL', 'APP_CRYPTO_KEY']) as $key) { + foreach (array_merge(self::REQUIRED_KEYS, ['APP_URL', 'APP_CRYPTO_KEY', 'APP_VENDOR_PHP_ISSUES_MODE']) as $key) { $env[$key] = getenv($key); } @@ -97,6 +97,14 @@ final class EnvValidator $errors[] = "TENANT_SCOPE_STRICT must be a boolean value (true/false/1/0)"; } + $vendorPhpIssuesMode = strtolower(self::value($env, 'APP_VENDOR_PHP_ISSUES_MODE')); + if ( + $vendorPhpIssuesMode !== '' + && !in_array($vendorPhpIssuesMode, ['strict', 'suppress_deprecations', 'suppress_deprecations_warnings'], true) + ) { + $errors[] = 'APP_VENDOR_PHP_ISSUES_MODE must be one of: strict, suppress_deprecations, suppress_deprecations_warnings'; + } + $reverseProxy = self::value($env, 'FIREWALL_REVERSE_PROXY'); if ($reverseProxy !== '' && self::parseBool($reverseProxy) === null) { $errors[] = "FIREWALL_REVERSE_PROXY must be a boolean value (true/false/1/0)"; diff --git a/lib/Http/ErrorDataCollector.php b/lib/Http/ErrorDataCollector.php index 4fe2046..b507d8d 100644 --- a/lib/Http/ErrorDataCollector.php +++ b/lib/Http/ErrorDataCollector.php @@ -30,6 +30,7 @@ final class ErrorDataCollector 'APP_TIMEZONE', 'APP_LOCALE', 'APP_URL', + 'APP_VENDOR_PHP_ISSUES_MODE', 'TENANT_SCOPE_STRICT', ]; diff --git a/lib/Http/ErrorHandler.php b/lib/Http/ErrorHandler.php index c146b73..73b9775 100644 --- a/lib/Http/ErrorHandler.php +++ b/lib/Http/ErrorHandler.php @@ -96,6 +96,10 @@ final class ErrorHandler return true; } + if (self::shouldSuppressVendorIssue($severity, $file)) { + return true; + } + throw new \ErrorException($message, 0, $severity, $file, $line); } @@ -194,4 +198,46 @@ final class ErrorHandler { return defined('PHPUNIT_COMPOSER_INSTALL') || defined('__PHPUNIT_PHAR__'); } + + private static function shouldSuppressVendorIssue(int $severity, string $file): bool + { + if (!self::isVendorPath($file)) { + return false; + } + + return match (self::vendorIssueMode()) { + 'suppress_deprecations' => self::isDeprecationSeverity($severity), + 'suppress_deprecations_warnings' => self::isDeprecationSeverity($severity) || self::isWarningSeverity($severity), + default => false, + }; + } + + private static function vendorIssueMode(): string + { + $raw = getenv('APP_VENDOR_PHP_ISSUES_MODE'); + if ($raw === false) { + return 'strict'; + } + + $mode = strtolower(trim((string) $raw)); + return in_array($mode, ['strict', 'suppress_deprecations', 'suppress_deprecations_warnings'], true) + ? $mode + : 'strict'; + } + + private static function isDeprecationSeverity(int $severity): bool + { + return in_array($severity, [E_DEPRECATED, E_USER_DEPRECATED], true); + } + + private static function isWarningSeverity(int $severity): bool + { + return in_array($severity, [E_WARNING, E_USER_WARNING], true); + } + + private static function isVendorPath(string $file): bool + { + $normalized = str_replace('\\', '/', $file); + return str_contains($normalized, '/vendor/'); + } } diff --git a/pages/admin/tenants/_form.phtml b/pages/admin/tenants/_form.phtml index 081e85d..1067c51 100644 --- a/pages/admin/tenants/_form.phtml +++ b/pages/admin/tenants/_form.phtml @@ -713,6 +713,7 @@ $openOverrideCard = $detailsOpenAll; $openLdapSetupCard = $detailsOpenAll || !$ldapEnabled || ($ldapEnabled && !$ldapConfigComplete); ?>