Skip to content

Commit 6ebe63f

Browse files
committed
swagger reader
1 parent 18f803d commit 6ebe63f

File tree

4 files changed

+229
-20
lines changed

4 files changed

+229
-20
lines changed

src/Constraint/Ref.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Swaggest\JsonSchema\Constraint;
44

5+
use Swaggest\JsonSchema\RefResolver;
6+
57
class Ref implements Constraint
68
{
79
public $ref;
@@ -14,6 +16,9 @@ public function __construct($ref, $data = null)
1416
/** @var mixed */
1517
private $data;
1618

19+
/** @var RefResolver */
20+
public $resolver;
21+
1722
/** @var mixed */
1823
private $imported;
1924
/** @var boolean */

src/RefResolver.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,17 @@ public function resolveReference($referencePath)
7373
$referencePath = Helper::resolveURI($this->resolutionScope, $referencePath);
7474
}
7575
$ref = &$this->refs[$referencePath];
76+
77+
$refResolver = $this;
78+
7679
if (null === $ref) {
7780
if ($referencePath[0] === '#') {
7881
if ($referencePath === '#') {
7982
$ref = new Ref($referencePath, $this->rootData);
83+
$ref->resolver = $this;
8084
} else {
8185
$ref = new Ref($referencePath);
86+
$ref->resolver = $this;
8287
$path = explode('/', trim($referencePath, '#/'));
8388
$branch = &$this->rootData;
8489
while (!empty($path)) {
@@ -106,7 +111,9 @@ public function resolveReference($referencePath)
106111
$refLocalPath = isset($refParts[1]) ? '#' . $refParts[1] : '#';
107112
$refResolver = &$this->remoteRefResolvers[$url];
108113
if (null === $refResolver) {
109-
$refResolver = new RefResolver($this->getRefProvider()->getSchemaData($url));
114+
$rootData = $this->getRefProvider()->getSchemaData($url);
115+
$refResolver = new RefResolver($rootData);
116+
$refResolver->refProvider = $this->refProvider;
110117
$refResolver->url = $url;
111118
}
112119

@@ -117,7 +124,7 @@ public function resolveReference($referencePath)
117124
$refData = $ref->getData();
118125
// we need to go deeper
119126
if (isset($refData->{'$ref'})) {
120-
return $this->resolveReference($refData->{'$ref'});
127+
return $refResolver->resolveReference($refData->{'$ref'});
121128
}
122129

123130
return $ref;

src/Schema.php

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,17 @@
2424
*/
2525
class Schema extends ObjectItem
2626
{
27+
public $fromRef;
28+
public $originPath;
29+
2730
/*
28-
public $seqId;
31+
public $__seqId;
32+
2933
public function __construct()
3034
{
3135
static $seq = 0;
3236
$seq++;
33-
$this->seqId = $seq;
37+
$this->__seqId = $seq;
3438
}
3539
*/
3640

@@ -150,6 +154,7 @@ public function export($data, ProcessingOptions $options = null)
150154
public function process($data, ProcessingOptions $options, $path = '#')
151155
{
152156
$import = $options->import;
157+
//$pathTrace = explode('->', $path);
153158

154159
if (!$import && $data instanceof ObjectItem) {
155160
$data = $data->jsonSerialize();
@@ -200,6 +205,7 @@ public function process($data, ProcessingOptions $options, $path = '#')
200205

201206
if ($this->oneOf !== null) {
202207
$successes = 0;
208+
$failures = '';
203209
foreach ($this->oneOf as $index => $item) {
204210
try {
205211
$result = $item->process($data, $options, $path . '->oneOf:' . $index);
@@ -208,16 +214,21 @@ public function process($data, ProcessingOptions $options, $path = '#')
208214
break;
209215
}
210216
} catch (InvalidValue $exception) {
217+
$failures .= ' ' . $index . ': ' . $exception->getMessage() . "\n";
211218
// Expected exception
212219
}
213220
}
214-
if ($successes !== 1) {
215-
$this->fail(new LogicException('Failed due to logical constraint: oneOf'), $path);
221+
if ($successes === 0) {
222+
$this->fail(new LogicException('Failed due to logical constraint: no valid results for oneOf {' . "\n" . substr($failures, 0, -1) . "\n}"), $path);
223+
} elseif ($successes > 1) {
224+
$this->fail(new LogicException('Failed due to logical constraint: '
225+
. $successes . '/' . count($this->oneOf) . ' valid results for oneOf'), $path);
216226
}
217227
}
218228

219229
if ($this->anyOf !== null) {
220230
$successes = 0;
231+
$failures = '';
221232
foreach ($this->anyOf as $index => $item) {
222233
try {
223234
$result = $item->process($data, $options, $path . '->anyOf:' . $index);
@@ -226,11 +237,12 @@ public function process($data, ProcessingOptions $options, $path = '#')
226237
break;
227238
}
228239
} catch (InvalidValue $exception) {
240+
$failures .= ' ' . $index . ': ' . $exception->getMessage() . "\n";
229241
// Expected exception
230242
}
231243
}
232244
if (!$successes) {
233-
$this->fail(new LogicException('Failed due to logical constraint: anyOf'), $path);
245+
$this->fail(new LogicException('Failed due to logical constraint: no valid results for anyOf {' . "\n" . substr($failures, 0, -1) . "\n}"), $path);
234246
}
235247
}
236248

@@ -319,6 +331,10 @@ public function process($data, ProcessingOptions $options, $path = '#')
319331
});
320332
}
321333
}
334+
335+
if ($result instanceof Schema) {
336+
$result->originPath = $path;
337+
}
322338
}
323339
}
324340

@@ -335,8 +351,23 @@ public function process($data, ProcessingOptions $options, $path = '#')
335351
return $ref->getImported();
336352
}
337353
$data = $ref->getData();
354+
if ($result instanceof Schema) {
355+
$result->fromRef = $refString;
356+
357+
}
358+
$result->fromPath = $refString;
338359
$ref->setImported($result);
339360
$path .= '->$ref:' . $refString;
361+
362+
if ($ref->resolver !== $options->refResolver) {
363+
$prevResolver = $options->refResolver;
364+
$options->refResolver = $ref->resolver;
365+
/** @noinspection PhpUnusedLocalVariableInspection */
366+
$deferResolver = new ScopeExit(function () use ($prevResolver, $options) {
367+
$options->refResolver = $prevResolver;
368+
});
369+
370+
}
340371
}
341372
} catch (InvalidValue $exception) {
342373
$this->fail($exception, $path);
@@ -438,7 +469,7 @@ public function process($data, ProcessingOptions $options, $path = '#')
438469
if (preg_match(Helper::toPregPattern($pattern), $key)) {
439470
$found = true;
440471
$value = $propertySchema->process($value, $options,
441-
$path . '->patternProperties:' . $pattern . '(' . $key . ')');
472+
$path . '->patternProperties[' . $pattern . ']:' . $key);
442473
if ($import) {
443474
$result->addPatternPropertyName($pattern, $key);
444475
}
@@ -468,8 +499,9 @@ public function process($data, ProcessingOptions $options, $path = '#')
468499
if ($this->useObjectAsArray && $import) {
469500
$result[$key] = $value;
470501
} else {
471-
$resultValue = $result->$key;
472-
if (!$import || !($resultValue instanceof ObjectItem && $value instanceof \stdClass)) {
502+
if ($found || !$import) {
503+
$result->$key = $value;
504+
} elseif (!isset($result->$key)) {
473505
$result->$key = $value;
474506
}
475507
}

0 commit comments

Comments
 (0)