From 8bc1c60e4c43e02b2bc100241f811723cca64625 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 23 Oct 2026 00:30:07 +0200 Subject: [PATCH] Run CommandMustHaveAsCommandAttributeRule only when composer.json requires symfony/console --- composer.json | 1 + .../CommandMustHaveAsCommandAttributeRule.php | 46 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/composer.json b/composer.json index b6deb776..a048c7c4 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,7 @@ "require-dev": { "nikic/php-parser": "^5.9", "phpunit/phpunit": "^13.4", + "symfony/console": "^6.4", "symfony/framework-bundle": "^6.4", "illuminate/container": "^11.51", "symplify/easy-coding-standard": "^13.3", diff --git a/src/Rules/Symfony/CommandMustHaveAsCommandAttributeRule.php b/src/Rules/Symfony/CommandMustHaveAsCommandAttributeRule.php index 1fbda435..dddd7bfe 100644 --- a/src/Rules/Symfony/CommandMustHaveAsCommandAttributeRule.php +++ b/src/Rules/Symfony/CommandMustHaveAsCommandAttributeRule.php @@ -32,11 +32,18 @@ final class CommandMustHaveAsCommandAttributeRule implements Rule */ private const LARAVEL_COMMAND_CLASS = 'Illuminate\Console\Command'; + /** + * @var string + */ + private const SYMFONY_CONSOLE_PACKAGE = 'symfony/console'; + /** * @var string */ public const ERROR_MESSAGE = 'Class "%s" extends Command but is missing the #[AsCommand] attribute'; + private ?bool $hasSymfonyConsolePackage = null; + public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; @@ -59,6 +66,11 @@ public function processNode(Node $node, Scope $scope): array return []; } + // only projects that depend on symfony/console in composer.json + if (! $this->hasSymfonyConsolePackage()) { + return []; + } + // Laravel commands use $signature instead of the #[AsCommand] attribute if ($this->reflectionProvider->hasClass(self::LARAVEL_COMMAND_CLASS)) { return []; @@ -97,4 +109,38 @@ public function processNode(Node $node, Scope $scope): array return [$identifierRuleError]; } + + private function hasSymfonyConsolePackage(): bool + { + if ($this->hasSymfonyConsolePackage !== null) { + return $this->hasSymfonyConsolePackage; + } + + $composerJsonFilePath = getcwd() . '/composer.json'; + if (! is_file($composerJsonFilePath)) { + return $this->hasSymfonyConsolePackage = false; + } + + $composerJsonContents = file_get_contents($composerJsonFilePath); + if ($composerJsonContents === false) { + return $this->hasSymfonyConsolePackage = false; + } + + $composerJson = json_decode($composerJsonContents, true); + if (! is_array($composerJson)) { + return $this->hasSymfonyConsolePackage = false; + } + + $requirePackages = $composerJson['require'] ?? []; + if (is_array($requirePackages) && isset($requirePackages[self::SYMFONY_CONSOLE_PACKAGE])) { + return $this->hasSymfonyConsolePackage = true; + } + + $requireDevPackages = $composerJson['require-dev'] ?? []; + if (is_array($requireDevPackages) && isset($requireDevPackages[self::SYMFONY_CONSOLE_PACKAGE])) { + return $this->hasSymfonyConsolePackage = true; + } + + return $this->hasSymfonyConsolePackage = false; + } }