From a7e7deeec585ea7ee5335f77b3ac76b22cbc15d0 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 25 Feb 2026 21:27:28 +0700 Subject: [PATCH 1/7] [DX] Define list of allowed implicit commands on ConsoleApplication --- src/Console/ConsoleApplication.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Console/ConsoleApplication.php b/src/Console/ConsoleApplication.php index 8b637b16f14..e65afcf4812 100644 --- a/src/Console/ConsoleApplication.php +++ b/src/Console/ConsoleApplication.php @@ -22,6 +22,16 @@ final class ConsoleApplication extends Application { private const string NAME = 'Rector'; + private const ALLOWED_COMMANDS = [ + 'custom-rule', + 'process', + 'list', + 'setup-ci', + 'worker', + 'help', + 'completion', + ]; + /** * @param Command[] $commands */ @@ -73,6 +83,8 @@ public function doRun(InputInterface $input, OutputInterface $output): int $tokens = $privatesAccessor->getPrivateProperty($input, 'tokens'); $tokens = array_merge(['process'], $tokens); $privatesAccessor->setPrivateProperty($input, 'tokens', $tokens); + } elseif (! in_array($commandName, self::ALLOWED_COMMANDS, true)) { + Assert::fileExists($commandName); } return parent::doRun($input, $output); From 2b87031aaa4260c99e24a1eae06af4031e02dab2 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Wed, 25 Feb 2026 14:31:22 +0000 Subject: [PATCH 2/7] [ci-review] Rector Rectify --- src/Console/ConsoleApplication.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Console/ConsoleApplication.php b/src/Console/ConsoleApplication.php index e65afcf4812..7ce079001de 100644 --- a/src/Console/ConsoleApplication.php +++ b/src/Console/ConsoleApplication.php @@ -22,7 +22,7 @@ final class ConsoleApplication extends Application { private const string NAME = 'Rector'; - private const ALLOWED_COMMANDS = [ + private const array ALLOWED_COMMANDS = [ 'custom-rule', 'process', 'list', From 951b071e4dfe45f8af85c2f8932384eaee5eef9a Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 25 Feb 2026 21:33:27 +0700 Subject: [PATCH 3/7] fix null command --- src/Console/ConsoleApplication.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Console/ConsoleApplication.php b/src/Console/ConsoleApplication.php index 7ce079001de..e94461917aa 100644 --- a/src/Console/ConsoleApplication.php +++ b/src/Console/ConsoleApplication.php @@ -23,6 +23,10 @@ final class ConsoleApplication extends Application private const string NAME = 'Rector'; private const array ALLOWED_COMMANDS = [ + // null is for example: bin/rector --version + null, + + // default commands 'custom-rule', 'process', 'list', From 8a8b3923ea681790f860de34299c0e615b63bb3f Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 25 Feb 2026 21:35:37 +0700 Subject: [PATCH 4/7] define array docblock --- src/Console/ConsoleApplication.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Console/ConsoleApplication.php b/src/Console/ConsoleApplication.php index e94461917aa..7dc98edad30 100644 --- a/src/Console/ConsoleApplication.php +++ b/src/Console/ConsoleApplication.php @@ -22,6 +22,9 @@ final class ConsoleApplication extends Application { private const string NAME = 'Rector'; + /** + * @var array + */ private const array ALLOWED_COMMANDS = [ // null is for example: bin/rector --version null, From 7415d8de5001f0b462b4614ea6e40f088aa39008 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 25 Feb 2026 21:44:47 +0700 Subject: [PATCH 5/7] fix exit code --- src/Console/ConsoleApplication.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Console/ConsoleApplication.php b/src/Console/ConsoleApplication.php index 7dc98edad30..c17866b6e36 100644 --- a/src/Console/ConsoleApplication.php +++ b/src/Console/ConsoleApplication.php @@ -16,6 +16,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; use Webmozart\Assert\Assert; final class ConsoleApplication extends Application @@ -42,7 +43,7 @@ final class ConsoleApplication extends Application /** * @param Command[] $commands */ - public function __construct(array $commands) + public function __construct(array $commands, private readonly SymfonyStyle $symfonyStyle) { parent::__construct(self::NAME, VersionResolver::PACKAGE_VERSION); @@ -91,7 +92,15 @@ public function doRun(InputInterface $input, OutputInterface $output): int $tokens = array_merge(['process'], $tokens); $privatesAccessor->setPrivateProperty($input, 'tokens', $tokens); } elseif (! in_array($commandName, self::ALLOWED_COMMANDS, true)) { - Assert::fileExists($commandName); + $this->symfonyStyle->error( + sprintf( + 'The following given path does not match any files or directories: %s%s', + "\n\n - ", + $commandName + ) + ); + + return ExitCode::FAILURE; } return parent::doRun($input, $output); From 62328c705851992148d0595ae75ab30534835abe Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 1 Mar 2026 21:42:47 +0700 Subject: [PATCH 6/7] final touch: early return on null first argument --- src/Console/ConsoleApplication.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Console/ConsoleApplication.php b/src/Console/ConsoleApplication.php index c17866b6e36..8aa52a41229 100644 --- a/src/Console/ConsoleApplication.php +++ b/src/Console/ConsoleApplication.php @@ -24,13 +24,9 @@ final class ConsoleApplication extends Application private const string NAME = 'Rector'; /** - * @var array + * @var string[] */ private const array ALLOWED_COMMANDS = [ - // null is for example: bin/rector --version - null, - - // default commands 'custom-rule', 'process', 'list', @@ -75,12 +71,15 @@ public function doRun(InputInterface $input, OutputInterface $output): int $commandName = $input->getFirstArgument(); + if ($commandName === null) { + return parent::doRun($input, $output); + } + // if paths exist or if the command name is not the first argument but with --option, eg: // bin/rector src // bin/rector --only "RemovePhpVersionIdCheckRector" // file_exists() can check directory and file - if (is_string($commandName) && ( - file_exists($commandName) || isset($_SERVER['argv'][1]) + if ((file_exists($commandName) || isset($_SERVER['argv'][1]) && $commandName !== $_SERVER['argv'][1] // ensure verify has parameter option, eg: --only && $input->hasParameterOption($_SERVER['argv'][1]) From 21caaf8efdc8c5bb143cbd34367cb2cd210f49cc Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 1 Mar 2026 21:51:20 +0700 Subject: [PATCH 7/7] refactor to use ->has() method --- src/Console/ConsoleApplication.php | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/Console/ConsoleApplication.php b/src/Console/ConsoleApplication.php index 8aa52a41229..116d17919f2 100644 --- a/src/Console/ConsoleApplication.php +++ b/src/Console/ConsoleApplication.php @@ -23,19 +23,6 @@ final class ConsoleApplication extends Application { private const string NAME = 'Rector'; - /** - * @var string[] - */ - private const array ALLOWED_COMMANDS = [ - 'custom-rule', - 'process', - 'list', - 'setup-ci', - 'worker', - 'help', - 'completion', - ]; - /** * @param Command[] $commands */ @@ -90,7 +77,7 @@ public function doRun(InputInterface $input, OutputInterface $output): int $tokens = $privatesAccessor->getPrivateProperty($input, 'tokens'); $tokens = array_merge(['process'], $tokens); $privatesAccessor->setPrivateProperty($input, 'tokens', $tokens); - } elseif (! in_array($commandName, self::ALLOWED_COMMANDS, true)) { + } elseif (! $this->has($commandName)) { $this->symfonyStyle->error( sprintf( 'The following given path does not match any files or directories: %s%s',