logError("Command not found: {$command}"); $this->recoveryService->handleCommandNotFound($command, $output); return ExitCode::COMMAND_NOT_FOUND; } public function handleCommandExecutionError( string $command, \Throwable $error, ConsoleOutputInterface $output ): ExitCode { $this->logError("Command execution error in '{$command}': " . $error->getMessage(), [ 'command' => $command, 'error_type' => get_class($error), 'trace' => $error->getTraceAsString(), ]); if ($error instanceof FrameworkException) { return $this->handleFrameworkException($command, $error, $output); } $this->recoveryService->handleCommandExecutionError($command, $error, $output); return $this->determineExitCode($error); } public function handleValidationError( string $command, string $validationError, ConsoleOutputInterface $output ): ExitCode { $this->logError("Validation error in '{$command}': {$validationError}"); $this->recoveryService->handleArgumentError($command, $validationError, $output); return ExitCode::INVALID_INPUT; } public function handlePermissionError( string $command, ConsoleOutputInterface $output ): ExitCode { $this->logError("Permission denied for command: {$command}"); $this->recoveryService->handlePermissionError($command, $output); return ExitCode::PERMISSION_DENIED; } public function handleUnexpectedError( string $command, \Throwable $error, ConsoleOutputInterface $output ): ExitCode { $this->logError("Unexpected error in '{$command}': " . $error->getMessage(), [ 'command' => $command, 'error_type' => get_class($error), 'file' => $error->getFile(), 'line' => $error->getLine(), 'trace' => $error->getTraceAsString(), ]); $output->writeLine("💥 An unexpected error occurred:", ConsoleColor::RED); $output->writeLine(" {$error->getMessage()}", ConsoleColor::RED); $output->newLine(); $output->writeLine("🔍 Debug information:", ConsoleColor::GRAY); $output->writeLine(" Error: " . get_class($error), ConsoleColor::GRAY); $output->writeLine(" File: {$error->getFile()}:{$error->getLine()}", ConsoleColor::GRAY); $output->newLine(); $this->recoveryService->handleGeneralError($command, $error, $output); return ExitCode::GENERAL_ERROR; } public function handleGracefulShutdown(string $reason, ConsoleOutputInterface $output): ExitCode { $this->logInfo("Graceful shutdown: {$reason}"); $output->writeLine("🛑 Operation interrupted: {$reason}", ConsoleColor::YELLOW); $output->writeLine(" The command was safely terminated.", ConsoleColor::GRAY); $output->newLine(); return ExitCode::INTERRUPTED; } private function handleFrameworkException( string $command, FrameworkException $exception, ConsoleOutputInterface $output ): ExitCode { $errorCode = $exception->getErrorCode(); return match ($errorCode) { ErrorCode::CON_COMMAND_NOT_FOUND => $this->handleCommandNotFound($command, $output), ErrorCode::CON_INVALID_ARGUMENTS => $this->handleValidationError( $command, $exception->getMessage(), $output ), ErrorCode::AUTH_UNAUTHORIZED, ErrorCode::AUTH_INSUFFICIENT_PRIVILEGES => $this->handlePermissionError($command, $output), ErrorCode::DB_CONNECTION_FAILED, ErrorCode::DB_QUERY_FAILED => $this->handleDatabaseError($command, $exception, $output), ErrorCode::HTTP_RATE_LIMIT_EXCEEDED => $this->handleRateLimitError($command, $exception, $output), default => $this->handleGeneralFrameworkError($command, $exception, $output) }; } private function handleDatabaseError( string $command, FrameworkException $exception, ConsoleOutputInterface $output ): ExitCode { $output->writeLine("🗄️ Database error in command '{$command}':", ConsoleColor::RED); $output->writeLine(" {$exception->getMessage()}", ConsoleColor::RED); $output->newLine(); $output->writeLine("💡 Database troubleshooting:", ConsoleColor::CYAN); $output->writeLine(" • Check database connection settings", ConsoleColor::WHITE); $output->writeLine(" • Verify database server is running", ConsoleColor::WHITE); $output->writeLine(" • Check network connectivity", ConsoleColor::WHITE); $output->writeLine(" • Verify database credentials", ConsoleColor::WHITE); $output->newLine(); return ExitCode::DATABASE_ERROR; } private function handleRateLimitError( string $command, FrameworkException $exception, ConsoleOutputInterface $output ): ExitCode { $output->writeLine("⏳ Rate limit exceeded for command '{$command}':", ConsoleColor::YELLOW); $output->writeLine(" {$exception->getMessage()}", ConsoleColor::YELLOW); $output->newLine(); if ($exception->hasRetryAfter()) { $retryAfter = $exception->getRetryAfter(); $output->writeLine("🕐 You can retry this command in {$retryAfter} seconds.", ConsoleColor::CYAN); } else { $output->writeLine("🕐 Please wait before retrying this command.", ConsoleColor::CYAN); } $output->newLine(); return ExitCode::RATE_LIMITED; } private function handleGeneralFrameworkError( string $command, FrameworkException $exception, ConsoleOutputInterface $output ): ExitCode { $this->recoveryService->handleCommandExecutionError($command, $exception, $output); return $this->determineExitCode($exception); } private function determineExitCode(\Throwable $error): ExitCode { if ($error instanceof FrameworkException) { return match ($error->getErrorCode()) { ErrorCode::CON_COMMAND_NOT_FOUND => ExitCode::COMMAND_NOT_FOUND, ErrorCode::CON_INVALID_ARGUMENTS => ExitCode::INVALID_INPUT, ErrorCode::AUTH_UNAUTHORIZED, ErrorCode::AUTH_INSUFFICIENT_PRIVILEGES => ExitCode::PERMISSION_DENIED, ErrorCode::DB_CONNECTION_FAILED, ErrorCode::DB_QUERY_FAILED => ExitCode::DATABASE_ERROR, ErrorCode::HTTP_RATE_LIMIT_EXCEEDED => ExitCode::RATE_LIMITED, default => ExitCode::GENERAL_ERROR }; } return match (true) { $error instanceof \ArgumentCountError, $error instanceof \TypeError => ExitCode::INVALID_INPUT, $error instanceof \Error => ExitCode::FATAL_ERROR, default => ExitCode::GENERAL_ERROR }; } private function logError(string $message, array $context = []): void { $this->logger?->error($message, LogContext::withData($context)); } private function logInfo(string $message, array $context = []): void { $this->logger?->info($message, LogContext::withData($context)); } }