Skip to content

Commit

Permalink
Fix transitive reference resolving in the current document context
Browse files Browse the repository at this point in the history
fixes #57
  • Loading branch information
cebe committed Feb 28, 2020
1 parent 497683f commit 5b89a81
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/spec/Reference.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,24 @@ public function resolve(ReferenceContext $context = null)
// TODO type error if resolved object does not match $this->_to ?
/** @var $referencedObject SpecObjectInterface */
$referencedObject = $jsonReference->getJsonPointer()->evaluate($baseSpec);
// transitive reference
if ($referencedObject instanceof Reference) {
if ($referencedObject->_to === null) {
$referencedObject->_to = $this->_to;
}
$referencedObject->setContext($context);

if ($referencedObject === $this) { // catch recursion
throw new UnresolvableReferenceException('Cyclic reference detected on a Reference Object.');
}

$transitiveRefResult = $referencedObject->resolve();

if ($transitiveRefResult === $this) { // catch recursion
throw new UnresolvableReferenceException('Cyclic reference detected on a Reference Object.');
}
return $transitiveRefResult;
}
if ($referencedObject instanceof SpecObjectInterface) {
$referencedObject->setReferenceContext($context);
}
Expand Down
74 changes: 74 additions & 0 deletions tests/spec/ReferenceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -304,4 +304,78 @@ enum:
$this->assertEquals(['Four', 'Five'], $openapi->components->schemas['Pet']->properties['typeD']->enum);
$this->assertEquals(['Five', 'Six'], $openapi->components->schemas['Pet']->properties['typeE']->enum);
}

/**
* References to references fail as "cyclic reference"
* @see https://github.com/cebe/php-openapi/issues/57
*/
public function testTransitiveReference()
{
$schema = <<<'YAML'
openapi: 3.0.2
info:
title: 'City API'
version: dev
paths:
'/city':
get:
description: 'Get City'
responses:
'200':
description: 'success'
content:
application/json:
schema:
$ref: '#/components/schemas/City'
components:
schemas:
City:
$ref: '#/components/schemas/Named'
Named:
type: string

YAML;

$openapi = Reader::readFromYaml($schema);
$openapi->resolveReferences(new \cebe\openapi\ReferenceContext($openapi, 'file:///tmp/openapi.yaml'));

$this->assertTrue(isset($openapi->components->schemas['City']));
$this->assertTrue(isset($openapi->components->schemas['Named']));
$this->assertEquals('string', $openapi->components->schemas['Named']->type);
$this->assertEquals('string', $openapi->components->schemas['City']->type);
$this->assertEquals('string', $openapi->paths['/city']->get->responses[200]->content['application/json']->schema->type);
}

public function testTransitiveReferenceCyclic()
{
$schema = <<<'YAML'
openapi: 3.0.2
info:
title: 'City API'
version: dev
paths:
'/city':
get:
description: 'Get City'
responses:
'200':
description: 'success'
content:
application/json:
schema:
$ref: '#/components/schemas/City'
components:
schemas:
City:
$ref: '#/components/schemas/City'

YAML;

$openapi = Reader::readFromYaml($schema);

$this->expectException(\cebe\openapi\exceptions\UnresolvableReferenceException::class);
$this->expectExceptionMessage('Cyclic reference detected on a Reference Object.');

$openapi->resolveReferences(new \cebe\openapi\ReferenceContext($openapi, 'file:///tmp/openapi.yaml'));
}
}

0 comments on commit 5b89a81

Please sign in to comment.