Skip to content

Commit 2f1f736

Browse files
committed
allow settings context on references without resolving these
this gives better control over iterating the spec by keeping the reference structure
1 parent 03c5e82 commit 2f1f736

7 files changed

+111
-10
lines changed

src/Reader.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@ public static function readFromYaml(string $yaml, string $baseType = OpenApi::cl
6464
public static function readFromJsonFile(string $fileName, string $baseType = OpenApi::class, $resolveReferences = true): SpecObjectInterface
6565
{
6666
$spec = static::readFromJson(file_get_contents($fileName), $baseType);
67+
$spec->setReferenceContext(new ReferenceContext($spec, $fileName));
6768
if ($resolveReferences) {
68-
$spec->resolveReferences(new ReferenceContext($spec, $fileName));
69+
$spec->resolveReferences();
6970
}
7071
return $spec;
7172
}
@@ -88,8 +89,9 @@ public static function readFromJsonFile(string $fileName, string $baseType = Ope
8889
public static function readFromYamlFile(string $fileName, string $baseType = OpenApi::class, $resolveReferences = true): SpecObjectInterface
8990
{
9091
$spec = static::readFromYaml(file_get_contents($fileName), $baseType);
92+
$spec->setReferenceContext(new ReferenceContext($spec, $fileName));
9193
if ($resolveReferences) {
92-
$spec->resolveReferences(new ReferenceContext($spec, $fileName));
94+
$spec->resolveReferences();
9395
}
9496
return $spec;
9597
}

src/SpecBaseObject.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ public function __unset($name)
246246
* Resolves all Reference Objects in this object and replaces them with their resolution.
247247
* @throws exceptions\UnresolvableReferenceException in case resolving a reference fails.
248248
*/
249-
public function resolveReferences(ReferenceContext $context)
249+
public function resolveReferences(ReferenceContext $context = null)
250250
{
251251
foreach ($this->_properties as $property => $value) {
252252
if ($value instanceof Reference) {
@@ -264,4 +264,26 @@ public function resolveReferences(ReferenceContext $context)
264264
}
265265
}
266266
}
267+
268+
/**
269+
* Set context for all Reference Objects in this object.
270+
*/
271+
public function setReferenceContext(ReferenceContext $context)
272+
{
273+
foreach ($this->_properties as $property => $value) {
274+
if ($value instanceof Reference) {
275+
$value->setContext($context);
276+
} elseif ($value instanceof SpecObjectInterface) {
277+
$value->setReferenceContext($context);
278+
} elseif (is_array($value)) {
279+
foreach ($value as $k => $item) {
280+
if ($item instanceof Reference) {
281+
$item->setContext($context);
282+
} elseif ($item instanceof SpecObjectInterface) {
283+
$item->setReferenceContext($context);
284+
}
285+
}
286+
}
287+
}
288+
}
267289
}

src/SpecObjectInterface.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,10 @@ public function getErrors(): array;
3434
/**
3535
* Resolves all Reference Objects in this object and replaces them with their resolution.
3636
*/
37-
public function resolveReferences(ReferenceContext $context);
37+
public function resolveReferences(ReferenceContext $context = null);
38+
39+
/**
40+
* Set context for all Reference Objects in this object.
41+
*/
42+
public function setReferenceContext(ReferenceContext $context);
3843
}

src/spec/Callback.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,20 @@ public function getErrors(): array
8282
* Resolves all Reference Objects in this object and replaces them with their resolution.
8383
* @throws UnresolvableReferenceException
8484
*/
85-
public function resolveReferences(ReferenceContext $context)
85+
public function resolveReferences(ReferenceContext $context = null)
8686
{
8787
if ($this->_pathItem !== null) {
8888
$this->_pathItem->resolveReferences($context);
8989
}
9090
}
91+
92+
/**
93+
* Set context for all Reference Objects in this object.
94+
*/
95+
public function setReferenceContext(ReferenceContext $context)
96+
{
97+
if ($this->_pathItem !== null) {
98+
$this->_pathItem->setReferenceContext($context);
99+
}
100+
}
91101
}

src/spec/Paths.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ public function getIterator()
189189
* Resolves all Reference Objects in this object and replaces them with their resolution.
190190
* @throws UnresolvableReferenceException
191191
*/
192-
public function resolveReferences(ReferenceContext $context)
192+
public function resolveReferences(ReferenceContext $context = null)
193193
{
194194
foreach ($this->_paths as $key => $path) {
195195
if ($path === null) {
@@ -198,4 +198,17 @@ public function resolveReferences(ReferenceContext $context)
198198
$path->resolveReferences($context);
199199
}
200200
}
201+
202+
/**
203+
* Set context for all Reference Objects in this object.
204+
*/
205+
public function setReferenceContext(ReferenceContext $context)
206+
{
207+
foreach ($this->_paths as $key => $path) {
208+
if ($path === null) {
209+
continue;
210+
}
211+
$path->setReferenceContext($context);
212+
}
213+
}
201214
}

src/spec/Reference.php

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Reference implements SpecObjectInterface
2525
{
2626
private $_to;
2727
private $_ref;
28+
private $_context;
2829

2930
private $_errors = [];
3031

@@ -88,11 +89,36 @@ public function getReference()
8889

8990
/**
9091
* @param ReferenceContext $context
92+
*/
93+
public function setContext(ReferenceContext $context)
94+
{
95+
$this->_context = $context;
96+
}
97+
98+
/**
99+
* @return ReferenceContext
100+
*/
101+
public function getContext() : ?ReferenceContext
102+
{
103+
return $this->_context;
104+
}
105+
106+
/**
107+
* Resolve this reference.
108+
* @param ReferenceContext $context the reference context to use for resolution.
109+
* If not specified, `getContext()` will be called to determine the context, if
110+
* that does not return a context, the UnresolvableReferenceException will be thrown.
91111
* @return SpecObjectInterface the resolved spec type.
92112
* @throws UnresolvableReferenceException in case of errors.
93113
*/
94-
public function resolve(ReferenceContext $context)
114+
public function resolve(ReferenceContext $context = null)
95115
{
116+
if ($context === null) {
117+
$context = $this->getContext();
118+
if ($context === null) {
119+
throw new UnresolvableReferenceException('No context given for resolving reference.');
120+
}
121+
}
96122
if (($pos = strpos($this->_ref, '#')) === 0) {
97123
// resolve in current document
98124
$jsonPointer = substr($this->_ref, 1);
@@ -111,7 +137,7 @@ public function resolve(ReferenceContext $context)
111137
/** @var $referencedObject SpecObjectInterface */
112138
$referencedObject = new $this->_to($referencedData);
113139
if ($jsonPointer === '') {
114-
$referencedObject->resolveReferences(new ReferenceContext($referencedObject, $file));
140+
$referencedObject->setReferenceContext(new ReferenceContext($referencedObject, $file));
115141
} else {
116142
// TODO resolving references recursively does not work as we do not know the base type of the file at this point
117143
// $referencedObject->resolveReferences(new ReferenceContext($referencedObject, $file));
@@ -183,8 +209,17 @@ private function fetchReferencedFile($uri)
183209
* Resolves all Reference Objects in this object and replaces them with their resolution.
184210
* @throws UnresolvableReferenceException
185211
*/
186-
public function resolveReferences(ReferenceContext $context)
212+
public function resolveReferences(ReferenceContext $context = null)
187213
{
188214
throw new UnresolvableReferenceException('Cyclic reference detected, resolveReferences() called on a Reference Object.');
189215
}
216+
217+
/**
218+
* Set context for all Reference Objects in this object.
219+
* @throws UnresolvableReferenceException
220+
*/
221+
public function setReferenceContext(ReferenceContext $context)
222+
{
223+
throw new UnresolvableReferenceException('Cyclic reference detected, setReferenceContext() called on a Reference Object.');
224+
}
190225
}

src/spec/Responses.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ public function getIterator()
185185
* Resolves all Reference Objects in this object and replaces them with their resolution.
186186
* @throws UnresolvableReferenceException
187187
*/
188-
public function resolveReferences(ReferenceContext $context)
188+
public function resolveReferences(ReferenceContext $context = null)
189189
{
190190
foreach ($this->_responses as $k => $response) {
191191
if ($response instanceof Reference) {
@@ -195,4 +195,18 @@ public function resolveReferences(ReferenceContext $context)
195195
}
196196
}
197197
}
198+
199+
/**
200+
* Set context for all Reference Objects in this object.
201+
*/
202+
public function setReferenceContext(ReferenceContext $context)
203+
{
204+
foreach ($this->_responses as $k => $response) {
205+
if ($response instanceof Reference) {
206+
$response->setContext($context);
207+
} else {
208+
$response->setReferenceContext($context);
209+
}
210+
}
211+
}
198212
}

0 commit comments

Comments
 (0)