Skip to content

Commit

Permalink
Remove duplicate $ref in allOf (#1481)
Browse files Browse the repository at this point in the history
  • Loading branch information
DerManoMann authored Oct 2, 2023
1 parent 430d4aa commit 99b04b5
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 4 deletions.
32 changes: 30 additions & 2 deletions src/Processors/AugmentRefs.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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]);
Expand All @@ -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);
}
}
}
}
}
41 changes: 41 additions & 0 deletions tests/Fixtures/Scratch/DuplicateRef.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php declare(strict_types=1);

/**
* @license Apache 2.0
*/

namespace OpenApi\Tests\Fixtures\Scratch;

use OpenApi\Attributes as OAT;

#[OAT\Info(title: 'DuplicateRef', version: '1.0')]
#[OAT\Get(
path: '/api/endpoint',
description: 'An endpoint',
responses: [new OAT\Response(response: 200, description: 'OK')]
)]
class DuplicateRefEndpoint
{
}

#[OAT\Schema(
schema: 'abstract-user',
properties: [
new OAT\Property(property: 'name', type: 'string'),
new OAT\Property(property: 'email', type: 'string'),
]
)]
class AbstractUser
{
}

#[OAT\Schema(
schema: 'create-user',
allOf: [
new OAT\Schema(ref: '#/components/schemas/abstract-user'),
new OAT\Schema(required: ['name', 'email']),
]
)]
class CreateUser extends AbstractUser
{
}
28 changes: 28 additions & 0 deletions tests/Fixtures/Scratch/DuplicateRef.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
openapi: 3.0.0
info:
title: DuplicateRef
version: '1.0'
paths:
/api/endpoint:
get:
description: 'An endpoint'
responses:
'200':
description: OK
components:
schemas:
abstract-user:
properties:
name:
type: string
email:
type: string
type: object
create-user:
allOf:
-
$ref: '#/components/schemas/abstract-user'
-
required:
- name
- email
4 changes: 2 additions & 2 deletions tests/Processors/ExpandClassesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,14 @@ public function testExpandClassesWithAllOf(): void

/** @var OA\Schema[] $schemas */
$schemas = $analysis->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);
Expand Down

0 comments on commit 99b04b5

Please sign in to comment.