diff --git a/src/console/src/ClosureCommand.php b/src/console/src/ClosureCommand.php index 6120379c0..5af6abac4 100644 --- a/src/console/src/ClosureCommand.php +++ b/src/console/src/ClosureCommand.php @@ -47,10 +47,16 @@ public function handle(): int } } - return (int) $this->container->call( - $this->callback->bindTo($this, $this), - $parameters - ); + try { + return (int) $this->container->call( + $this->callback->bindTo($this, $this), + $parameters + ); + } catch (ManuallyFailedException $e) { + $this->components->error($e->getMessage()); + + return static::FAILURE; + } } /** diff --git a/src/console/src/Command.php b/src/console/src/Command.php index b9fdef83b..1e0cc5d7f 100644 --- a/src/console/src/Command.php +++ b/src/console/src/Command.php @@ -41,6 +41,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $this->exitCode = $statusCode; } $this->eventDispatcher?->dispatch(new AfterHandle($this)); + } catch (ManuallyFailedException $e) { + $this->components->error($e->getMessage()); + + return $this->exitCode = static::FAILURE; } catch (Throwable $exception) { if (class_exists(ExitException::class) && $exception instanceof ExitException) { return $this->exitCode = (int) $exception->getStatus(); @@ -79,4 +83,22 @@ protected function replaceOutput(): void $this->output = $this->app->get(OutputInterface::class); } } + + /** + * Fail the command manually. + * + * @throws ManuallyFailedException|Throwable + */ + public function fail(null|string|Throwable $exception = null): void + { + if (is_null($exception)) { + $exception = 'Command failed manually.'; + } + + if (is_string($exception)) { + $exception = new ManuallyFailedException($exception); + } + + throw $exception; + } } diff --git a/src/console/src/ManuallyFailedException.php b/src/console/src/ManuallyFailedException.php new file mode 100644 index 000000000..cc04240a4 --- /dev/null +++ b/src/console/src/ManuallyFailedException.php @@ -0,0 +1,11 @@ +