diff --git a/src/Annotations/AbstractAnnotation.php b/src/Annotations/AbstractAnnotation.php index de5407cae..e832a7429 100644 --- a/src/Annotations/AbstractAnnotation.php +++ b/src/Annotations/AbstractAnnotation.php @@ -8,6 +8,7 @@ use OpenApi\Context; use OpenApi\Generator; +use OpenApi\Annotations as OA; use OpenApi\Util; use Symfony\Component\Yaml\Yaml; @@ -566,7 +567,7 @@ public function identity(): string /** * Find matching nested details. * - * @param string $class the class to match + * @param class-string $class the class to match * * @return null|object key/value object or `null` */ @@ -587,6 +588,25 @@ public static function matchNested(string $class) return null; } + /** + * Match the annotation root. + * + * @param class-string $rootClass the root class to match + */ + public function isRoot(string $rootClass): bool + { + $parent = get_class($this); + + // only consider the immediate OpenApi parent + do { + if ($parent == $rootClass) { + return true; + } + } while (0 !== strpos($parent, 'OpenApi\\Annotations\\') && $parent = get_parent_class($parent)); + + return false; + } + /** * Helper for generating the identity(). */ diff --git a/src/Processors/AugmentSchemas.php b/src/Processors/AugmentSchemas.php index 1b32f6972..f6147f627 100644 --- a/src/Processors/AugmentSchemas.php +++ b/src/Processors/AugmentSchemas.php @@ -8,7 +8,6 @@ use OpenApi\Analysis; use OpenApi\Annotations as OA; -use OpenApi\Attributes as OAT; use OpenApi\Context; use OpenApi\Generator; @@ -21,8 +20,13 @@ class AugmentSchemas { public function __invoke(Analysis $analysis) { - /** @var OA\Schema $schema */ - foreach ($analysis->getAnnotationsOfType([OA\Schema::class, OAT\Schema::class], true) as $schema) { + /** @var OA\Schema[] $schemas */ + $schemas = $analysis->getAnnotationsOfType(OA\Schema::class); + + foreach ($schemas as $schema) { + if (!$schema->isRoot(OA\Schema::class)) { + continue; + } if (Generator::isDefault($schema->schema)) { if ($schema->_context->is('class')) { $schema->schema = $schema->_context->class; @@ -36,9 +40,6 @@ public function __invoke(Analysis $analysis) } } - /** @var OA\Schema[] $schemas */ - $schemas = $analysis->getAnnotationsOfType(OA\Schema::class); - // Merge unmerged @OA\Property annotations into the @OA\Schema of the class $unmergedProperties = $analysis->unmerged()->getAnnotationsOfType(OA\Property::class); foreach ($unmergedProperties as $property) { diff --git a/tests/Annotations/AbstractAnnotationTest.php b/tests/Annotations/AbstractAnnotationTest.php index 9730238ca..4ab7da5db 100644 --- a/tests/Annotations/AbstractAnnotationTest.php +++ b/tests/Annotations/AbstractAnnotationTest.php @@ -6,9 +6,7 @@ namespace OpenApi\Tests\Annotations; -use OpenApi\Annotations\Get; -use OpenApi\Annotations\Parameter; -use OpenApi\Annotations\Schema; +use OpenApi\Annotations as OA; use OpenApi\Generator; use OpenApi\Tests\OpenApiTestCase; @@ -112,12 +110,12 @@ public function testTypeValidation(): void public function nestedMatches(): iterable { - $parameterMatch = (object) ['key' => Parameter::class, 'value' => ['parameters']]; + $parameterMatch = (object) ['key' => OA\Parameter::class, 'value' => ['parameters']]; return [ 'unknown' => [self::class, null], - 'simple-match' => [Parameter::class, $parameterMatch], - 'invalid-annotation' => [Schema::class, null], + 'simple-match' => [OA\Parameter::class, $parameterMatch], + 'invalid-annotation' => [OA\Schema::class, null], 'sub-annotation' => [SubParameter::class, $parameterMatch], 'sub-sub-annotation' => [SubSubParameter::class, $parameterMatch], 'sub-invalid' => [SubSchema::class, null], @@ -129,7 +127,7 @@ public function nestedMatches(): iterable */ public function testMatchNested(string $class, $expected): void { - $this->assertEquals($expected, Get::matchNested($class)); + $this->assertEquals($expected, OA\Get::matchNested($class)); } public function testDuplicateOperationIdValidation(): void @@ -140,13 +138,20 @@ public function testDuplicateOperationIdValidation(): void $this->assertOpenApiLogEntryContains('operationId must be unique. Duplicate value found: "getItem"'); $this->assertFalse($analysis->validate()); } + + public function testIsRoot(): void + { + $this->assertTrue((new OA\AdditionalProperties([]))->isRoot(OA\AdditionalProperties::class)); + $this->assertFalse((new OA\AdditionalProperties([]))->isRoot(OA\Schema::class)); + $this->assertTrue((new SubSchema([]))->isRoot(OA\Schema::class)); + } } -class SubSchema extends Schema +class SubSchema extends OA\Schema { } -class SubParameter extends Parameter +class SubParameter extends OA\Parameter { } diff --git a/tests/Fixtures/Scratch/CustomAttributeSchema.php b/tests/Fixtures/Scratch/CustomAttributeSchema.php new file mode 100644 index 000000000..f2060314f --- /dev/null +++ b/tests/Fixtures/Scratch/CustomAttributeSchema.php @@ -0,0 +1,32 @@ +