Skip to content

Commit dfe67fc

Browse files
authored
Merge pull request #40 from swaggest/recursive-references
keep intermediate references in path
2 parents aa438e2 + 0b125cf commit dfe67fc

File tree

5 files changed

+79
-19
lines changed

5 files changed

+79
-19
lines changed

src/Schema.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ private function processObject($data, Context $options, $path, $result = null)
673673
}
674674
}
675675

676-
while (
676+
if (
677677
isset($data->{self::PROP_REF})
678678
&& is_string($data->{self::PROP_REF})
679679
&& $dereference
@@ -1057,9 +1057,7 @@ public function process($data, Context $options, $path = '#', $result = null)
10571057
$data = $data->jsonSerialize();
10581058
}
10591059

1060-
if ($ref = $this->getFromRef()) {
1061-
$path .= '->$ref[' . strtr($ref, array('~' => '~1', ':' => '~2')) . ']';
1062-
}
1060+
$path .= $this->getFromRefPath();
10631061

10641062
if (!$import && is_array($data) && $this->useObjectAsArray) {
10651063
$data = (object)$data;

src/Structure/ClassStructureTrait.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ public static function schema()
2828
$schema->objectItemClass = $className;
2929
$schemaWrapper = new Wrapper($schema);
3030
static::setUpProperties($properties, $schema);
31-
$schema->setFromRef('#/definitions/' . $className);
31+
if (null === $schema->getFromRef()) {
32+
$schema->setFromRef('#/definitions/' . $className);
33+
}
3234
if ($properties->isEmpty()) {
3335
$schema->properties = null;
3436
}

src/Structure/ObjectItemTrait.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,33 @@ public function setDocumentPath($path)
108108
*/
109109
public function getFromRef()
110110
{
111-
return $this->__fromRef;
111+
return null === $this->__fromRef ? null : $this->__fromRef[0];
112112
}
113113

114114
public function setFromRef($ref)
115115
{
116116
if (null === $this->__fromRef) {
117-
$this->__fromRef = $ref;
117+
$this->__fromRef = array($ref);
118+
} else {
119+
if (false !== $this->__fromRef[0]) {
120+
$this->__fromRef[] = $ref;
121+
}
118122
}
119123
return $this;
120124
}
125+
126+
private $__refPath;
127+
protected function getFromRefPath() {
128+
if ($this->__refPath === null) {
129+
$this->__refPath = '';
130+
if ($this->__fromRef) {
131+
foreach ($this->__fromRef as $ref) {
132+
if ($ref) {
133+
$this->__refPath = '->$ref[' . strtr($ref, array('~' => '~1', ':' => '~2')) . ']' . $this->__refPath;
134+
}
135+
}
136+
}
137+
}
138+
return $this->__refPath;
139+
}
121140
}

tests/src/PHPUnit/Error/ErrorTest.php

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ public function testErrorMessage()
5252
0: Enum failed, enum: ["a"], data: "f" at #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[0]
5353
1: Enum failed, enum: ["b"], data: "f" at #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[1]
5454
2: No valid results for anyOf {
55-
0: Enum failed, enum: ["c"], data: "f" at #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/cde]->anyOf[0]
56-
1: Enum failed, enum: ["d"], data: "f" at #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/cde]->anyOf[1]
57-
2: Enum failed, enum: ["e"], data: "f" at #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/cde]->anyOf[2]
58-
} at #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/cde]
55+
0: Enum failed, enum: ["c"], data: "f" at #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/ref-to-cde]->$ref[#/cde]->anyOf[0]
56+
1: Enum failed, enum: ["d"], data: "f" at #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/ref-to-cde]->$ref[#/cde]->anyOf[1]
57+
2: Enum failed, enum: ["e"], data: "f" at #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/ref-to-cde]->$ref[#/cde]->anyOf[2]
58+
} at #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/ref-to-cde]->$ref[#/cde]
5959
} at #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo
6060
TEXT;
6161

@@ -104,11 +104,12 @@ public function testErrorMessage()
104104
[schemaPointers] => Array
105105
(
106106
[0] => /properties/root/patternProperties/^[a-zA-Z0-9_]+$/oneOf/2/$ref
107-
[1] => /cde
107+
[1] => /ref-to-cde/$ref
108+
[2] => /cde
108109
)
109110
110111
[dataPointer] => /root/zoo
111-
[processingPath] => #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/cde]
112+
[processingPath] => #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/ref-to-cde]->$ref[#/cde]
112113
[subErrors] => Array
113114
(
114115
[0] => Swaggest\JsonSchema\Exception\Error Object
@@ -117,11 +118,12 @@ public function testErrorMessage()
117118
[schemaPointers] => Array
118119
(
119120
[0] => /properties/root/patternProperties/^[a-zA-Z0-9_]+$/oneOf/2/$ref
120-
[1] => /cde/anyOf/0
121+
[1] => /ref-to-cde/$ref
122+
[2] => /cde/anyOf/0
121123
)
122124
123125
[dataPointer] => /root/zoo
124-
[processingPath] => #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/cde]->anyOf[0]
126+
[processingPath] => #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/ref-to-cde]->$ref[#/cde]->anyOf[0]
125127
[subErrors] =>
126128
)
127129
@@ -131,11 +133,12 @@ public function testErrorMessage()
131133
[schemaPointers] => Array
132134
(
133135
[0] => /properties/root/patternProperties/^[a-zA-Z0-9_]+$/oneOf/2/$ref
134-
[1] => /cde/anyOf/1
136+
[1] => /ref-to-cde/$ref
137+
[2] => /cde/anyOf/1
135138
)
136139
137140
[dataPointer] => /root/zoo
138-
[processingPath] => #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/cde]->anyOf[1]
141+
[processingPath] => #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/ref-to-cde]->$ref[#/cde]->anyOf[1]
139142
[subErrors] =>
140143
)
141144
@@ -145,11 +148,12 @@ public function testErrorMessage()
145148
[schemaPointers] => Array
146149
(
147150
[0] => /properties/root/patternProperties/^[a-zA-Z0-9_]+$/oneOf/2/$ref
148-
[1] => /cde/anyOf/2
151+
[1] => /ref-to-cde/$ref
152+
[2] => /cde/anyOf/2
149153
)
150154
151155
[dataPointer] => /root/zoo
152-
[processingPath] => #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/cde]->anyOf[2]
156+
[processingPath] => #->properties:root->patternProperties[^[a-zA-Z0-9_]+$]:zoo->oneOf[2]->$ref[#/ref-to-cde]->$ref[#/cde]->anyOf[2]
153157
[subErrors] =>
154158
)
155159
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Swaggest\JsonSchema\Tests\PHPUnit\Ref;
4+
5+
6+
use Swaggest\JsonSchema\Context;
7+
use Swaggest\JsonSchema\InvalidValue;
8+
use Swaggest\JsonSchema\Schema;
9+
10+
class RecursiveReferencesTest extends \PHPUnit_Framework_TestCase
11+
{
12+
public function testRecursiveReferences()
13+
{
14+
$schemaJson = <<<'JSON'
15+
{
16+
"allOf": [
17+
{"$ref": "#/a"}
18+
],
19+
"a": {"$ref": "#/b"},
20+
"b": {"$ref": "#/c"},
21+
"c": {"$ref": "#/d"},
22+
"d": {"type": "string"}
23+
}
24+
JSON;
25+
$options = new Context();
26+
$schema = Schema::import(json_decode($schemaJson), $options);
27+
28+
29+
$schema->in("seven"); // lucky number
30+
31+
$this->setExpectedException(get_class(new InvalidValue()),
32+
'String expected, 13 received at #->allOf[0]->$ref[#/a]->$ref[#/b]->$ref[#/c]->$ref[#/d]');
33+
$schema->in(13); // unlucky number
34+
35+
}
36+
37+
}

0 commit comments

Comments
 (0)