diff --git a/bin/openapi b/bin/openapi index 4191205be..c302320d1 100755 --- a/bin/openapi +++ b/bin/openapi @@ -218,6 +218,7 @@ foreach ($options["processor"] as $processor) { } $analyser = new ReflectionAnalyser([new DocBlockAnnotationFactory(), new AttributeAnnotationFactory()]); +$analyser->setGenerator($generator); $openapi = $generator ->setVersion($options['version']) diff --git a/src/Analysers/AnalyserInterface.php b/src/Analysers/AnalyserInterface.php index 864d226a9..fa413e2c6 100644 --- a/src/Analysers/AnalyserInterface.php +++ b/src/Analysers/AnalyserInterface.php @@ -8,11 +8,8 @@ use OpenApi\Analysis; use OpenApi\Context; -use OpenApi\Generator; -interface AnalyserInterface +interface AnalyserInterface extends GeneratorAwareInterface { - public function setGenerator(Generator $generator): void; - public function fromFile(string $filename, Context $context): Analysis; } diff --git a/src/Analysers/AnnotationFactoryInterface.php b/src/Analysers/AnnotationFactoryInterface.php index 5c8365e62..404499295 100644 --- a/src/Analysers/AnnotationFactoryInterface.php +++ b/src/Analysers/AnnotationFactoryInterface.php @@ -10,14 +10,14 @@ use OpenApi\Context; use OpenApi\Generator; -interface AnnotationFactoryInterface +interface AnnotationFactoryInterface extends GeneratorAwareInterface { /** * Checks if this factory is supported by the current runtime. */ public function isSupported(): bool; - public function setGenerator(Generator $generator): void; + public function setGenerator(Generator $generator); /** * @return array top level annotations diff --git a/src/Analysers/AttributeAnnotationFactory.php b/src/Analysers/AttributeAnnotationFactory.php index 29f931d9a..3ecbbdacd 100644 --- a/src/Analysers/AttributeAnnotationFactory.php +++ b/src/Analysers/AttributeAnnotationFactory.php @@ -36,13 +36,17 @@ public function build(\Reflector $reflector, Context $context): array /** @var OA\AbstractAnnotation[] $annotations */ $annotations = []; try { - foreach ($reflector->getAttributes() as $attribute) { + $attributeArgs = $this->generator->isIgnoreOtherAttributes() + ? [OA\AbstractAnnotation::class, \ReflectionAttribute::IS_INSTANCEOF] + : []; + + foreach ($reflector->getAttributes(...$attributeArgs) as $attribute) { if (class_exists($attribute->getName())) { $instance = $attribute->newInstance(); if ($instance instanceof OA\AbstractAnnotation) { $annotations[] = $instance; } else { - if ($context->is('other') === false) { + if (false === $context->is('other')) { $context->other = []; } $context->other[] = $instance; diff --git a/src/Analysers/DocBlockAnnotationFactory.php b/src/Analysers/DocBlockAnnotationFactory.php index 469a10701..238448851 100644 --- a/src/Analysers/DocBlockAnnotationFactory.php +++ b/src/Analysers/DocBlockAnnotationFactory.php @@ -26,11 +26,13 @@ public function isSupported(): bool return DocBlockParser::isEnabled(); } - public function setGenerator(Generator $generator): void + public function setGenerator(Generator $generator) { $this->generator = $generator; $this->docBlockParser->setAliases($generator->getAliases()); + + return $this; } public function build(\Reflector $reflector, Context $context): array diff --git a/src/Analysers/GeneratorAwareInterface.php b/src/Analysers/GeneratorAwareInterface.php new file mode 100644 index 000000000..2985433cb --- /dev/null +++ b/src/Analysers/GeneratorAwareInterface.php @@ -0,0 +1,14 @@ +generator = $generator; + + return $this; } } diff --git a/src/Analysers/ReflectionAnalyser.php b/src/Analysers/ReflectionAnalyser.php index 9657e11c5..f49ab7678 100644 --- a/src/Analysers/ReflectionAnalyser.php +++ b/src/Analysers/ReflectionAnalyser.php @@ -42,13 +42,15 @@ public function __construct(array $annotationFactories = []) } } - public function setGenerator(Generator $generator): void + public function setGenerator(Generator $generator) { $this->generator = $generator; foreach ($this->annotationFactories as $annotationFactory) { $annotationFactory->setGenerator($generator); } + + return $this; } public function fromFile(string $filename, Context $context): Analysis diff --git a/src/Generator.php b/src/Generator.php index 153441d0d..71d3f3fe7 100644 --- a/src/Generator.php +++ b/src/Generator.php @@ -21,6 +21,15 @@ * * This is an object-oriented alternative to using the now deprecated \OpenApi\scan() function and * static class properties of the Analyzer and Analysis classes. + * + * Supported generator config: + * + * [ + * 'generator' => [ + * 'ignoreOtherAttributes' => true|false, + * ] + * ] + * */ class Generator { @@ -135,6 +144,9 @@ public function setAnalyser(?AnalyserInterface $analyser): Generator return $this; } + /** + * @deprecated + */ public function getDefaultConfig(): array { return [ @@ -146,7 +158,16 @@ public function getDefaultConfig(): array public function getConfig(): array { - return $this->config + $this->getDefaultConfig(); + return $this->config + $this->getDefaultConfig() + [ + 'generator' => [ + 'ignoreOtherAttributes' => false, + ], + ]; + } + + public function isIgnoreOtherAttributes(): bool + { + return $this->getConfig()['generator']['ignoreOtherAttributes']; } protected function normaliseConfig(array $config): array diff --git a/tests/Analysers/AttributeAnnotationFactoryTest.php b/tests/Analysers/AttributeAnnotationFactoryTest.php index 711ee48ae..15b4d2d0c 100644 --- a/tests/Analysers/AttributeAnnotationFactoryTest.php +++ b/tests/Analysers/AttributeAnnotationFactoryTest.php @@ -7,6 +7,7 @@ namespace OpenApi\Tests\Analysers; use OpenApi\Analysers\AttributeAnnotationFactory; +use OpenApi\Generator; use OpenApi\Tests\Fixtures\UsingAttributes; use OpenApi\Tests\Fixtures\InvalidPropertyAttribute; use OpenApi\Tests\OpenApiTestCase; @@ -16,11 +17,22 @@ */ class AttributeAnnotationFactoryTest extends OpenApiTestCase { - public function testReturnedAnnotationsCout(): void + protected function getFactory(?array $config = null): AttributeAnnotationFactory + { + $generator = new Generator(); + if (null !== $config) { + $generator->setConfig($config); + } + + return (new AttributeAnnotationFactory()) + ->setGenerator($generator); + } + + public function testReturnedAnnotationsCount(): void { $rc = new \ReflectionClass(UsingAttributes::class); - $annotations = (new AttributeAnnotationFactory())->build($rc, $this->getContext()); + $annotations = $this->getFactory()->build($rc, $this->getContext()); $this->assertCount(1, $annotations); } @@ -32,6 +44,18 @@ public function testErrorOnInvalidAttribute(): void $this->expectException(\TypeError::class); $this->expectExceptionMessage('OpenApi\Attributes\Property::__construct(): Argument #8 ($required) must be of type ?array'); - (new AttributeAnnotationFactory())->build($rm, $this->getContext()); + $this->getFactory()->build($rm, $this->getContext()); + } + + public function testIgnoreOtherAttributes(): void + { + $rc = new \ReflectionClass(UsingAttributes::class); + + $this->getFactory()->build($rc, $context = $this->getContext()); + $this->assertIsArray($context->other); + $this->assertCount(1, $context->other); + + $this->getFactory(['generator' => ['ignoreOtherAttributes' => true]])->build($rc, $context = $this->getContext()); + $this->assertNull($context->other); } } diff --git a/tests/Fixtures/PHP/Label.php b/tests/Fixtures/PHP/Label.php index fedab46b9..bcc53d44a 100644 --- a/tests/Fixtures/PHP/Label.php +++ b/tests/Fixtures/PHP/Label.php @@ -6,12 +6,12 @@ namespace OpenApi\Tests\Fixtures\PHP; -#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::IS_REPEATABLE)] +#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_PROPERTY | \Attribute::IS_REPEATABLE)] class Label { protected $name; - public function __construct(string $name, array $numbers) + public function __construct(string $name, array $numbers = []) { $this->name = $name; } diff --git a/tests/Fixtures/UsingAttributes.php b/tests/Fixtures/UsingAttributes.php index 255a9f907..5481bf635 100644 --- a/tests/Fixtures/UsingAttributes.php +++ b/tests/Fixtures/UsingAttributes.php @@ -7,7 +7,9 @@ namespace OpenApi\Tests\Fixtures; use OpenApi\Attributes as OAT; +use OpenApi\Tests\Fixtures\PHP\Label; +#[Label(name: 'custom')] #[OAT\Response()] #[OAT\Header(header: 'X-Rate-Limit', allowEmptyValue: true)] class UsingAttributes diff --git a/tests/GeneratorTest.php b/tests/GeneratorTest.php index 8ad940749..3507da817 100644 --- a/tests/GeneratorTest.php +++ b/tests/GeneratorTest.php @@ -121,4 +121,14 @@ public function testConfig(array $config, bool $expected): void $generator->setConfig($config); $this->assertOperationIdHash($generator, $expected); } + + public function testIsIgnoreOtherAttributes(): void + { + $generator = new Generator(); + + $this->assertFalse($generator->isIgnoreOtherAttributes()); + + $generator->setConfig(['generator' => ['ignoreOtherAttributes' => true]]); + $this->assertTrue($generator->isIgnoreOtherAttributes()); + } }