|
@@ -7,6 +7,7 @@ namespace App\App;
|
|
|
final class Bootstrap
|
|
final class Bootstrap
|
|
|
{
|
|
{
|
|
|
private static bool $booted = false;
|
|
private static bool $booted = false;
|
|
|
|
|
+ private static bool $errorHandlingInitialized = false;
|
|
|
|
|
|
|
|
/** @var array<string, mixed> */
|
|
/** @var array<string, mixed> */
|
|
|
private static array $config = [];
|
|
private static array $config = [];
|
|
@@ -18,6 +19,7 @@ final class Bootstrap
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
self::$booted = true;
|
|
self::$booted = true;
|
|
|
|
|
+ self::initializeErrorHandling();
|
|
|
|
|
|
|
|
date_default_timezone_set('Europe/Berlin');
|
|
date_default_timezone_set('Europe/Berlin');
|
|
|
|
|
|
|
@@ -29,9 +31,9 @@ final class Bootstrap
|
|
|
]);
|
|
]);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- self::$config['app'] = require self::rootPath() . '/config/app.php';
|
|
|
|
|
- self::$config['mail'] = require self::rootPath() . '/config/mail.php';
|
|
|
|
|
- self::$config['form_schema'] = require self::rootPath() . '/config/form_schema.php';
|
|
|
|
|
|
|
+ self::$config['app'] = self::loadConfigArray(self::rootPath() . '/config/app.php', 'app');
|
|
|
|
|
+ self::$config['mail'] = self::loadConfigArray(self::rootPath() . '/config/mail.php', 'mail');
|
|
|
|
|
+ self::$config['form_schema'] = self::loadConfigArray(self::rootPath() . '/config/form_schema.php', 'form_schema');
|
|
|
|
|
|
|
|
self::ensureStorageDirectories();
|
|
self::ensureStorageDirectories();
|
|
|
}
|
|
}
|
|
@@ -44,7 +46,8 @@ final class Bootstrap
|
|
|
/** @return array<string, mixed> */
|
|
/** @return array<string, mixed> */
|
|
|
public static function config(string $name): array
|
|
public static function config(string $name): array
|
|
|
{
|
|
{
|
|
|
- return self::$config[$name] ?? [];
|
|
|
|
|
|
|
+ $value = self::$config[$name] ?? [];
|
|
|
|
|
+ return is_array($value) ? $value : [];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** @param array<string, mixed> $payload */
|
|
/** @param array<string, mixed> $payload */
|
|
@@ -83,4 +86,70 @@ final class Bootstrap
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ /** @return array<string, mixed> */
|
|
|
|
|
+ private static function loadConfigArray(string $path, string $name): array
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!is_file($path)) {
|
|
|
|
|
+ self::log('php_fatal', sprintf('Missing config file: %s (%s)', $name, $path));
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ $loaded = require $path;
|
|
|
|
|
+ } catch (\Throwable $e) {
|
|
|
|
|
+ self::log('php_fatal', sprintf('Failed loading config %s: %s', $name, $e->getMessage()));
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!is_array($loaded)) {
|
|
|
|
|
+ self::log('php_fatal', sprintf('Config %s must return an array (%s)', $name, $path));
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $loaded;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static function initializeErrorHandling(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ if (self::$errorHandlingInitialized) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ self::$errorHandlingInitialized = true;
|
|
|
|
|
+
|
|
|
|
|
+ $logsDir = self::rootPath() . '/storage/logs';
|
|
|
|
|
+ if (!is_dir($logsDir)) {
|
|
|
|
|
+ @mkdir($logsDir, 0775, true);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $phpErrorLog = $logsDir . '/php_runtime.log';
|
|
|
|
|
+ @ini_set('log_errors', '1');
|
|
|
|
|
+ @ini_set('display_errors', '0');
|
|
|
|
|
+ @ini_set('error_log', $phpErrorLog);
|
|
|
|
|
+
|
|
|
|
|
+ register_shutdown_function(static function (): void {
|
|
|
|
|
+ $lastError = error_get_last();
|
|
|
|
|
+ if (!is_array($lastError)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $fatalTypes = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
|
|
|
|
|
+ if (!in_array((int) ($lastError['type'] ?? 0), $fatalTypes, true)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $line = sprintf(
|
|
|
|
|
+ "[%s] Fatal error on %s: %s in %s:%s\n",
|
|
|
|
|
+ date('c'),
|
|
|
|
|
+ (string) ($_SERVER['REQUEST_URI'] ?? 'CLI'),
|
|
|
|
|
+ (string) ($lastError['message'] ?? 'unknown'),
|
|
|
|
|
+ (string) ($lastError['file'] ?? 'unknown'),
|
|
|
|
|
+ (string) ($lastError['line'] ?? '?')
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ $fatalLog = Bootstrap::rootPath() . '/storage/logs/php_fatal.log';
|
|
|
|
|
+ @file_put_contents($fatalLog, $line, FILE_APPEND);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|