diff --git a/src/Console/src/Attribute/AsInput.php b/src/Console/src/Attribute/AsInput.php new file mode 100644 index 000000000..af75cc48f --- /dev/null +++ b/src/Console/src/Attribute/AsInput.php @@ -0,0 +1,8 @@ +getAttributes(SymfonyAsCommand::class)[0]->newInstance(); } + $parseSourceReflection = $this->getParseSource($reflection); + return new CommandDefinition( name: $attribute->name, - arguments: $this->parseArguments($reflection), - options: $this->parseOptions($reflection), + arguments: $this->parseArguments($parseSourceReflection), + options: $this->parseOptions($parseSourceReflection), description: $attribute->description, help: $attribute instanceof AsCommand ? $attribute->help : null ); @@ -84,6 +87,39 @@ public function fillProperties(Command $command, InputInterface $input): void } } + /** + * Get the method that should be used to parse the command. + * + * This either can be the command itself, of the `#[AsInput]` parameter of the `perform` or `__invoke` method. + */ + private function getParseSource(\ReflectionClass $reflection): \ReflectionClass + { + $method = $reflection->hasMethod('perform') + ? $reflection->getMethod('perform') + : ($reflection->hasMethod('__invoke') + ? $reflection->getMethod('__invoke') + : null); + + if ($method === null) { + return $reflection; + } + + $parameter = null; + foreach ($method->getParameters() as $param) { + $attribute = $this->reader->firstParameterMetadata($param, AsInput::class); + if ($attribute !== null) { + $parameter = $param; + break; + } + } + + if ($parameter === null) { + return $reflection; + } + + return new \ReflectionClass($parameter->getType()->getName()); + } + private function parseArguments(\ReflectionClass $reflection): array { $result = []; diff --git a/src/Console/tests/Configurator/Attribute/InputSourceTest.php b/src/Console/tests/Configurator/Attribute/InputSourceTest.php new file mode 100644 index 000000000..00d69d458 --- /dev/null +++ b/src/Console/tests/Configurator/Attribute/InputSourceTest.php @@ -0,0 +1,35 @@ +parser = new Parser((new Factory())->create()); + } + + public function testWithInvokeMethod(): void + { + $result = $this->parser->parse(new \ReflectionClass(WithInvokeInputParameterCommand::class)); + + self::assertNotEmpty($result->arguments); + self::assertNotEmpty($result->options); + } + + public function testWithPerformMethod(): void + { + $result = $this->parser->parse(new \ReflectionClass(WithPerformInputParameterCommand::class)); + + self::assertNotEmpty($result->arguments); + self::assertNotEmpty($result->options); + } +} diff --git a/src/Console/tests/Fixtures/Attribute/Input/InputSource.php b/src/Console/tests/Fixtures/Attribute/Input/InputSource.php new file mode 100644 index 000000000..9ff13d703 --- /dev/null +++ b/src/Console/tests/Fixtures/Attribute/Input/InputSource.php @@ -0,0 +1,15 @@ +write($this->getDescription()); + + return self::SUCCESS; + } +} diff --git a/src/Console/tests/Fixtures/Attribute/WithPerformInputParameterCommand.php b/src/Console/tests/Fixtures/Attribute/WithPerformInputParameterCommand.php new file mode 100644 index 000000000..309c995fb --- /dev/null +++ b/src/Console/tests/Fixtures/Attribute/WithPerformInputParameterCommand.php @@ -0,0 +1,19 @@ +write($this->getDescription()); + + return self::SUCCESS; + } +}