handle($request); if ($response instanceof Response) { $response->send(); } } catch (\Throwable $e) { self::logException($e); $content = self::debug() ? '
' . htmlspecialchars((string) $e) . '' : 'An error occurred. Please try again later.'; $response = new Response($content, Response::HTTP_INTERNAL_SERVER_ERROR, [ 'Content-Type' => 'text/html; charset=UTF-8', ]); $response->send(); exit(1); } } public static function environment(): string { return self::$kernel->environment(); } public static function debug(): bool { return self::$kernel->debug(); } public static function runtimeKernel(): Kernel { return self::$kernel; } public static function runtimeContainer(): Container { return self::$kernel->container(); } public static function runtimeRootLocation(): string { return self::$kernel->folderRoot(); } public static function runtimeModuleLocation(): string { return self::$kernel->folderRoot() . '/modules'; } /** * Set up global error and exception handlers */ protected static function setupErrorHandlers(): void { // Convert PHP errors to exceptions set_error_handler(function ($errno, $errstr, $errfile, $errline) { // Don't throw exception if error reporting is turned off if (!(error_reporting() & $errno)) { return false; } $message = sprintf( "PHP Error [%d]: %s in %s:%d", $errno, $errstr, $errfile, $errline ); self::logError($message, [ 'errno' => $errno, 'file' => $errfile, 'line' => $errline, ]); // Throw exception for fatal errors if ($errno === E_ERROR || $errno === E_CORE_ERROR || $errno === E_COMPILE_ERROR || $errno === E_USER_ERROR) { throw new ErrorException($errstr, 0, $errno, $errfile, $errline); } return true; }); // Handle uncaught exceptions set_exception_handler(function (Throwable $exception) { self::logException($exception); if (self::debug()) { echo '
Uncaught Exception: ' . $exception . ''; } else { echo 'An unexpected error occurred. Please try again later.'; } exit(1); }); // Handle fatal errors register_shutdown_function(function () { $error = error_get_last(); if ($error !== null && in_array($error['type'], [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE])) { $message = sprintf( "Fatal Error [%d]: %s in %s:%d", $error['type'], $error['message'], $error['file'], $error['line'] ); self::logError($message, $error); if (self::debug()) { echo '
' . $message . ''; } else { echo 'A fatal error occurred. Please try again later.'; } } }); } /** * Log an error message */ protected static function logError(string $message, array $context = []): void { try { if (self::$kernel && self::$kernel->container()->has(LoggerInterface::class)) { $logger = self::$kernel->container()->get(LoggerInterface::class); $logger->error($message, $context); } else { // Fallback to error_log if logger not available error_log($message . ' ' . json_encode($context)); } } catch (Throwable $e) { // Last resort fallback error_log('Error logging failed: ' . $e->getMessage()); error_log($message . ' ' . json_encode($context)); } } /** * Log an exception */ protected static function logException(Throwable $exception): void { try { if (self::$kernel && self::$kernel->container()->has(LoggerInterface::class)) { $logger = self::$kernel->container()->get(LoggerInterface::class); $logger->error('Exception caught: ' . $exception->getMessage(), [ 'exception' => $exception, 'file' => $exception->getFile(), 'line' => $exception->getLine(), 'trace' => $exception->getTraceAsString(), ]); } else { // Fallback to error_log if logger not available error_log('Exception: ' . $exception->getMessage() . ' in ' . $exception->getFile() . ':' . $exception->getLine()); error_log($exception->getTraceAsString()); } } catch (Throwable $e) { // Last resort fallback error_log('Exception logging failed: ' . $e->getMessage()); error_log('Original exception: ' . $exception->getMessage()); } } }