Skip to content

Commit 59a58e9

Browse files
committed
WIP references
1 parent 161464f commit 59a58e9

File tree

12 files changed

+465
-6
lines changed

12 files changed

+465
-6
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ coverage: .php-openapi-covA .php-openapi-covB
2222
.php-openapi-covA:
2323
grep -rhPo '@covers .+' tests |cut -c 28- |sort > $@
2424
.php-openapi-covB:
25-
grep -rhPo 'class \w+' src/spec/ | awk '{print $$2}' |grep -v '^Type$$' | sort > $@
25+
grep -rhPo '^class \w+' src/spec/ | awk '{print $$2}' |grep -v '^Type$$' | sort > $@
2626

2727
.PHONY: all check-style fix-style install test coverage
2828

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ This library is currently work in progress, the following list tracks completene
7777
- [ ] [Runtime Expressions](https://github.com/OAI/OpenAPI-Specification/blob/3.0.2/versions/3.0.2.md#runtime-expressions)
7878
- [x] Header Object
7979
- [x] Tag Object
80-
- [ ] Reference Object
80+
- [x] Reference Object
8181
- [x] Schema Object
8282
- [x] load/read
8383
- [ ] validation

src/ReferenceContext.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (c) 2018 Carsten Brandt <mail@cebe.cc> and contributors
5+
* @license https://github.com/cebe/php-openapi/blob/master/LICENSE
6+
*/
7+
8+
namespace cebe\openapi;
9+
use cebe\openapi\exceptions\UnresolvableReferenceException;
10+
11+
/**
12+
* ReferenceContext represents a context in which references are resolved.
13+
*/
14+
class ReferenceContext
15+
{
16+
/**
17+
* @var SpecObjectInterface
18+
*/
19+
private $_baseSpec;
20+
/**
21+
* @var string
22+
*/
23+
private $_uri;
24+
25+
26+
public function __construct(SpecObjectInterface $base, string $uri)
27+
{
28+
$this->_baseSpec = $base;
29+
$this->_uri = $uri;
30+
}
31+
32+
/**
33+
* @return mixed
34+
*/
35+
public function getBaseSpec(): SpecObjectInterface
36+
{
37+
return $this->_baseSpec;
38+
}
39+
40+
/**
41+
* @return mixed
42+
*/
43+
public function getUri(): string
44+
{
45+
return $this->_uri;
46+
}
47+
48+
/**
49+
* Resolve a relative URI to an absolute URI in the current context.
50+
* @param string $uri
51+
* @throws UnresolvableReferenceException
52+
* @return string
53+
*/
54+
public function resolveRelativeUri(string $uri): string
55+
{
56+
$parts = parse_url($uri);
57+
if (!isset($parts['scheme'], $parts['host'])) {
58+
// TODO resolve relative URL
59+
throw new UnresolvableReferenceException('Relative URLs are currently not supported in Reference.');
60+
}
61+
62+
return $uri;
63+
}
64+
}

src/SpecBaseObject.php

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use cebe\openapi\exceptions\ReadonlyPropertyException;
1111
use cebe\openapi\exceptions\TypeErrorException;
1212
use cebe\openapi\exceptions\UnknownPropertyException;
13+
use cebe\openapi\spec\Reference;
1314
use cebe\openapi\spec\Type;
1415

1516
/**
@@ -73,7 +74,6 @@ public function __construct(array $data)
7374
} elseif ($type[0] === Type::ANY || $type[0] === Type::BOOLEAN || $type[0] === Type::INTEGER) { // TODO simplify handling of scalar types
7475
$this->_properties[$property][] = $item;
7576
} else {
76-
// TODO implement reference objects
7777
$this->_properties[$property][] = $this->instantiate($type[0], $item);
7878
}
7979
}
@@ -93,7 +93,6 @@ public function __construct(array $data)
9393
} elseif ($type[1] === Type::ANY || $type[1] === Type::BOOLEAN || $type[1] === Type::INTEGER) { // TODO simplify handling of scalar types
9494
$this->_properties[$property][$key] = $item;
9595
} else {
96-
// TODO implement reference objects
9796
$this->_properties[$property][$key] = $this->instantiate($type[1], $item);
9897
}
9998
}
@@ -114,6 +113,9 @@ public function __construct(array $data)
114113
*/
115114
private function instantiate($type, $data)
116115
{
116+
if (isset($data['$ref'])) {
117+
return new Reference($data, $type);
118+
}
117119
try {
118120
return new $type($data);
119121
} catch (\TypeError $e) {
@@ -239,4 +241,27 @@ public function __unset($name)
239241
{
240242
throw new ReadonlyPropertyException('Unsetting read-only property: ' . \get_class($this) . '::' . $name);
241243
}
244+
245+
/**
246+
* Resolves all Reference Objects in this object and replaces them with their resolution.
247+
* @throws exceptions\UnresolvableReferenceException in case resolving a reference fails.
248+
*/
249+
public function resolveReferences(ReferenceContext $context)
250+
{
251+
foreach ($this->_properties as $property => $value) {
252+
if ($value instanceof Reference) {
253+
$this->_properties[$property] = $value->resolve($context);
254+
} elseif ($value instanceof SpecObjectInterface) {
255+
$value->resolveReferences($context);
256+
} elseif (is_array($value)) {
257+
foreach ($value as $k => $item) {
258+
if ($item instanceof Reference) {
259+
$this->_properties[$property][$k] = $item->resolve($context);
260+
} elseif ($item instanceof SpecObjectInterface) {
261+
$item->resolveReferences($context);
262+
}
263+
}
264+
}
265+
}
266+
}
242267
}

src/SpecObjectInterface.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,9 @@ public function validate(): bool;
3030
* @see validate()
3131
*/
3232
public function getErrors(): array;
33+
34+
/**
35+
* Resolves all Reference Objects in this object and replaces them with their resolution.
36+
*/
37+
public function resolveReferences(ReferenceContext $context);
3338
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (c) 2018 Carsten Brandt <mail@cebe.cc> and contributors
5+
* @license https://github.com/cebe/php-openapi/blob/master/LICENSE
6+
*/
7+
8+
namespace cebe\openapi\exceptions;
9+
10+
/**
11+
*
12+
*
13+
*/
14+
class UnresolvableReferenceException extends \Exception
15+
{
16+
}

src/spec/Callback.php

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

1010
use cebe\openapi\exceptions\TypeErrorException;
11+
use cebe\openapi\exceptions\UnresolvableReferenceException;
12+
use cebe\openapi\ReferenceContext;
1113
use cebe\openapi\SpecObjectInterface;
1214

1315
/**
@@ -75,4 +77,15 @@ public function getErrors(): array
7577
$pathItemErrors = $this->_pathItem === null ? [] : $this->_pathItem->getErrors();
7678
return array_merge($this->_errors, $pathItemErrors);
7779
}
80+
81+
/**
82+
* Resolves all Reference Objects in this object and replaces them with their resolution.
83+
* @throws UnresolvableReferenceException
84+
*/
85+
public function resolveReferences(ReferenceContext $context)
86+
{
87+
if ($this->_pathItem !== null) {
88+
$this->_pathItem->resolveReferences($context);
89+
}
90+
}
7891
}

src/spec/Paths.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
use ArrayAccess;
1111
use ArrayIterator;
1212
use cebe\openapi\exceptions\ReadonlyPropertyException;
13+
use cebe\openapi\exceptions\TypeErrorException;
14+
use cebe\openapi\exceptions\UnresolvableReferenceException;
15+
use cebe\openapi\ReferenceContext;
1316
use cebe\openapi\SpecObjectInterface;
1417
use Countable;
1518
use IteratorAggregate;
@@ -37,11 +40,11 @@ class Paths implements SpecObjectInterface, ArrayAccess, Countable, IteratorAggr
3740
/**
3841
* Create an object from spec data.
3942
* @param array $data spec data read from YAML or JSON
43+
* @throws TypeErrorException in case invalid data is supplied.
4044
*/
4145
public function __construct(array $data)
4246
{
4347
foreach ($data as $path => $object) {
44-
// TODO support reference
4548
if ($object === null) {
4649
$this->_paths[$path] = null;
4750
} else {
@@ -181,4 +184,15 @@ public function getIterator()
181184
{
182185
return new ArrayIterator($this->_paths);
183186
}
187+
188+
/**
189+
* Resolves all Reference Objects in this object and replaces them with their resolution.
190+
* @throws UnresolvableReferenceException
191+
*/
192+
public function resolveReferences(ReferenceContext $context)
193+
{
194+
foreach ($this->_paths as $key => $path) {
195+
$path->resolveReferences($context);
196+
}
197+
}
184198
}

0 commit comments

Comments
 (0)