Skip to content

Commit b4b2037

Browse files
hotrushDEVizzent
authored andcommitted
Summary and description support for references
1 parent 44920bc commit b4b2037

4 files changed

Lines changed: 116 additions & 11 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ install: composer.lock yarn.lock
4444
test: unit test-recursion.json test-recursion2.yaml test-recursion3_index.yaml test-empty-maps.json
4545

4646
unit:
47-
$(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) vendor/bin/phpunit --verbose --colors=always $(TESTCASE)
47+
$(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) vendor/bin/phpunit --colors=always $(TESTCASE)
4848

4949
test-debug: unit-debug test-recursion.json test-recursion2.yaml test-recursion3_index.yaml test-empty-maps.json
5050

src/json/JsonReference.php

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ final class JsonReference implements JsonSerializable
2828
* @var JsonPointer
2929
*/
3030
private $_pointer;
31+
/**
32+
* @var string|null
33+
*/
34+
private $_summary;
35+
/**
36+
* @var string|null
37+
*/
38+
private $_description;
3139

3240
/**
3341
* Create a JSON Reference instance from a JSON document.
@@ -42,7 +50,11 @@ public static function createFromJson(string $json): JsonReference
4250
if (!isset($refObject['$ref'])) {
4351
throw new MalformedJsonReferenceObjectException('JSON Reference Object must contain the "$ref" member.');
4452
}
45-
return static::createFromReference($refObject['$ref']);
53+
return static::createFromReference(
54+
$refObject['$ref'],
55+
$refObject['summary'] ?? null,
56+
$refObject['description'] ?? null,
57+
);
4658
}
4759

4860
/**
@@ -66,10 +78,16 @@ public static function createFromUri(string $uri, ?JsonPointer $jsonPointer = nu
6678
* @return JsonReference
6779
* @throws InvalidJsonPointerSyntaxException if an invalid JSON pointer string is passed as part of the fragment section.
6880
*/
69-
public static function createFromReference(string $referenceURI): JsonReference
81+
public static function createFromReference(
82+
string $referenceURI,
83+
?string $summary = null,
84+
?string $description = null,
85+
): JsonReference
7086
{
7187
$jsonReference = new JsonReference();
72-
if (strpos($referenceURI, '#') !== false) {
88+
$jsonReference->_summary = $summary;
89+
$jsonReference->_description = $description;
90+
if (str_contains($referenceURI, '#')) {
7391
list($uri, $fragment) = explode('#', $referenceURI, 2);
7492
$jsonReference->_uri = $uri;
7593
$jsonReference->_pointer = new JsonPointer(rawurldecode($fragment));
@@ -129,6 +147,10 @@ public function getReference(): string
129147
#[\ReturnTypeWillChange]
130148
public function jsonSerialize() //: mixed
131149
{
132-
return (object)['$ref' => $this->getReference()];
150+
return (object) array_filter([
151+
'$ref' => $this->getReference(),
152+
'summary' => $this->_summary,
153+
'description' => $this->_description,
154+
]);
133155
}
134156
}

src/spec/Reference.php

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
namespace cebe\openapi\spec;
99

1010
use cebe\openapi\DocumentContextInterface;
11-
use cebe\openapi\exceptions\IOException;
1211
use cebe\openapi\exceptions\TypeErrorException;
1312
use cebe\openapi\exceptions\UnresolvableReferenceException;
1413
use cebe\openapi\json\InvalidJsonPointerSyntaxException;
@@ -17,7 +16,6 @@
1716
use cebe\openapi\json\NonexistentJsonPointerReferenceException;
1817
use cebe\openapi\ReferenceContext;
1918
use cebe\openapi\SpecObjectInterface;
20-
use Symfony\Component\Yaml\Yaml;
2119

2220
/**
2321
* Reference Object
@@ -37,6 +35,14 @@ class Reference implements SpecObjectInterface, DocumentContextInterface
3735
* @var string
3836
*/
3937
private $_ref;
38+
/**
39+
* @var string|null
40+
*/
41+
private $_summary;
42+
/**
43+
* @var string|null
44+
*/
45+
private $_description;
4046
/**
4147
* @var JsonReference|null
4248
*/
@@ -81,15 +87,33 @@ public function __construct(array $data, ?string $to = null)
8187
'Unable to instantiate Reference Object, value of $ref must be a string.'
8288
);
8389
}
90+
if (isset($data['summary']) && !is_string($data['summary'])) {
91+
throw new TypeErrorException(
92+
'Unable to instantiate Reference Object, value of summary must be a string.'
93+
);
94+
}
95+
if (isset($data['description']) && !is_string($data['description'])) {
96+
throw new TypeErrorException(
97+
'Unable to instantiate Reference Object, value of description must be a string.'
98+
);
99+
}
100+
84101
$this->_to = $to;
85102
$this->_ref = $data['$ref'];
103+
$this->_summary = $data['summary'] ?? null;
104+
$this->_description = $data['description'] ?? null;
86105
try {
87-
$this->_jsonReference = JsonReference::createFromReference($this->_ref);
106+
$this->_jsonReference = JsonReference::createFromReference(
107+
$this->_ref,
108+
$this->_summary,
109+
$this->_description
110+
);
88111
} catch (InvalidJsonPointerSyntaxException $e) {
89112
$this->_errors[] = 'Reference: value of $ref is not a valid JSON pointer: ' . $e->getMessage();
90113
}
91-
if (count($data) !== 1) {
92-
$this->_errors[] = 'Reference: additional properties are given. Only $ref should be set in a Reference Object.';
114+
115+
if (!empty(array_diff(array_keys($data), ['$ref', 'summary', 'description']))) {
116+
$this->_errors[] = 'Reference: additional properties are given. Only $ref, summary and description should be set in a Reference Object.';
93117
}
94118
}
95119

@@ -99,7 +123,11 @@ public function __construct(array $data, ?string $to = null)
99123
*/
100124
public function getSerializableData()
101125
{
102-
return (object) ['$ref' => $this->_ref];
126+
return (object) array_filter([
127+
'$ref' => $this->_ref,
128+
'summary' => $this->_summary,
129+
'description' => $this->_description,
130+
]);
103131
}
104132

105133
/**
@@ -135,6 +163,16 @@ public function getReference()
135163
return $this->_ref;
136164
}
137165

166+
public function getSummary()
167+
{
168+
return $this->_summary;
169+
}
170+
171+
public function getDescription()
172+
{
173+
return $this->_description;
174+
}
175+
138176
/**
139177
* @return JsonReference the JSON Reference.
140178
*/

tests/spec/ReferenceTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,4 +657,49 @@ public function testResolveRelativePathAll()
657657
}
658658
}
659659

660+
public function testReferenceExtraFields()
661+
{
662+
/** @var $openapi OpenApi */
663+
$openapi = Reader::readFromYaml(<<<'YAML'
664+
openapi: 3.1.0
665+
info:
666+
title: test api
667+
version: 1.0.0
668+
components:
669+
schemas:
670+
Pet:
671+
type: object
672+
properties:
673+
id:
674+
type: integer
675+
paths:
676+
'/pet':
677+
get:
678+
responses:
679+
200:
680+
description: return a pet
681+
content:
682+
'application/json':
683+
schema:
684+
$ref: "#/components/schemas/Pet"
685+
summary: 'Pet Schema'
686+
description: 'This is a pet schema'
687+
YAML
688+
, OpenApi::class);
689+
690+
$result = $openapi->validate();
691+
$this->assertEquals([], $openapi->getErrors());
692+
$this->assertTrue($result);
693+
694+
/** @var $petResponse Response */
695+
$petResponse = $openapi->paths->getPath('/pet')->get->responses['200'];
696+
$this->assertInstanceOf(Reference::class, $ref = $petResponse->content['application/json']->schema);
697+
$this->assertEquals('Pet Schema', $ref->getSummary());
698+
$this->assertEquals('This is a pet schema', $ref->getDescription());
699+
700+
$openapi->resolveReferences(new \cebe\openapi\ReferenceContext($openapi, 'file:///tmp/openapi.yaml'));
701+
702+
$this->assertInstanceOf(Schema::class, $refSchema = $petResponse->content['application/json']->schema);
703+
$this->assertSame($openapi->components->schemas['Pet'], $refSchema);
704+
}
660705
}

0 commit comments

Comments
 (0)