From 99b04b5cabf524c05f9428955af8406755ab183c Mon Sep 17 00:00:00 2001 From: Martin Rademacher Date: Tue, 3 Oct 2023 12:49:51 +1300 Subject: [PATCH] Remove duplicate `$ref` in `allOf` (#1481) --- src/Processors/AugmentRefs.php | 32 ++++++++++++++++-- tests/Fixtures/Scratch/DuplicateRef.php | 41 ++++++++++++++++++++++++ tests/Fixtures/Scratch/DuplicateRef.yaml | 28 ++++++++++++++++ tests/Processors/ExpandClassesTest.php | 4 +-- 4 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 tests/Fixtures/Scratch/DuplicateRef.php create mode 100644 tests/Fixtures/Scratch/DuplicateRef.yaml diff --git a/src/Processors/AugmentRefs.php b/src/Processors/AugmentRefs.php index 52916d8b..0e532a8f 100644 --- a/src/Processors/AugmentRefs.php +++ b/src/Processors/AugmentRefs.php @@ -18,12 +18,13 @@ public function __invoke(Analysis $analysis) { $this->resolveAllOfRefs($analysis); $this->resolveFQCNRefs($analysis); + $this->removeDuplicateRefs($analysis); } /** * Update refs broken due to `allOf` augmenting. */ - protected function resolveAllOfRefs(Analysis $analysis) + protected function resolveAllOfRefs(Analysis $analysis): void { /** @var OA\Schema[] $schemas */ $schemas = $analysis->getAnnotationsOfType(OA\Schema::class); @@ -55,7 +56,7 @@ protected function resolveAllOfRefs(Analysis $analysis) } } - protected function resolveFQCNRefs(Analysis $analysis) + protected function resolveFQCNRefs(Analysis $analysis): void { /** @var OA\AbstractAnnotation[] $annotations */ $annotations = $analysis->getAnnotationsOfType([OA\Examples::class, OA\Header::class, OA\Link::class, OA\Parameter::class, OA\PathItem::class, OA\RequestBody::class, OA\Response::class, OA\Schema::class, OA\SecurityScheme::class]); @@ -69,4 +70,31 @@ protected function resolveFQCNRefs(Analysis $analysis) } } } + + protected function removeDuplicateRefs(Analysis $analysis): void + { + /** @var OA\Schema[] $schemas */ + $schemas = $analysis->getAnnotationsOfType(OA\Schema::class); + + foreach ($schemas as $schema) { + if (!Generator::isDefault($schema->allOf)) { + $refs = []; + $dupes = []; + foreach ($schema->allOf as $ii => $allOfSchema) { + if (!Generator::isDefault($allOfSchema->ref)) { + if (in_array($allOfSchema->ref, $refs)) { + $dupes[] = $allOfSchema->ref; + $analysis->annotations->detach($allOfSchema); + unset($schema->allOf[$ii]); + continue; + } + $refs[] = $allOfSchema->ref; + } + } + if ($dupes) { + $schema->allOf = array_values($schema->allOf); + } + } + } + } } diff --git a/tests/Fixtures/Scratch/DuplicateRef.php b/tests/Fixtures/Scratch/DuplicateRef.php new file mode 100644 index 00000000..eb2d617b --- /dev/null +++ b/tests/Fixtures/Scratch/DuplicateRef.php @@ -0,0 +1,41 @@ +getAnnotationsOfType(OA\Schema::class, true); - $this->assertCount(5, $schemas); + $this->assertCount(4, $schemas); $extendedSchema = $schemas[0]; $this->assertSame('ExtendedModel', $extendedSchema->schema); $this->assertSame(Generator::UNDEFINED, $extendedSchema->properties); $this->assertArrayHasKey(0, $extendedSchema->allOf); - $this->assertEquals($extendedSchema->allOf[2]->properties[0]->property, 'extendedProperty'); + $this->assertEquals($extendedSchema->allOf[1]->properties[0]->property, 'extendedProperty'); $includeSchemaWithRef = $schemas[1]; $this->assertSame(Generator::UNDEFINED, $includeSchemaWithRef->properties);