Skip to content

Commit a4bee9f

Browse files
committed
Merge pull request #182 from araines/resolve-refs
Fix #93 ($ref to local definition not working)
2 parents 34ca930 + 85c60cb commit a4bee9f

File tree

3 files changed

+64
-5
lines changed

3 files changed

+64
-5
lines changed

src/JsonSchema/RefResolver.php

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ class RefResolver
4141
*/
4242
protected $uriRetriever = null;
4343

44+
/**
45+
* @var object
46+
*/
47+
protected $rootSchema = null;
48+
4449
/**
4550
* @param UriRetriever $retriever
4651
*/
@@ -110,6 +115,10 @@ public function resolve($schema, $sourceUri = null)
110115
$sourceUri = $schema->id;
111116
}
112117

118+
if (null === $this->rootSchema) {
119+
$this->rootSchema = $schema;
120+
}
121+
113122
// Resolve $ref first
114123
$this->resolveRef($schema, $sourceUri);
115124

@@ -205,7 +214,30 @@ public function resolveRef($schema, $sourceUri)
205214
return;
206215
}
207216

208-
$refSchema = $this->fetchRef($schema->$ref, $sourceUri);
217+
$splitRef = explode('#', $schema->$ref, 2);
218+
219+
$refDoc = $splitRef[0];
220+
$refPath = null;
221+
if (count($splitRef) === 2) {
222+
$refPath = explode('/', $splitRef[1]);
223+
array_shift($refPath);
224+
}
225+
226+
if (empty($refDoc) && empty($refPath)) {
227+
// TODO: Not yet implemented - root pointer ref, causes recursion issues
228+
return;
229+
}
230+
231+
if (!empty($refDoc)) {
232+
$refSchema = $this->fetchRef($refDoc, $sourceUri);
233+
} else {
234+
$refSchema = $this->rootSchema;
235+
}
236+
237+
if (null !== $refPath) {
238+
$refSchema = $this->resolveRefSegment($refSchema, $refPath);
239+
}
240+
209241
unset($schema->$ref);
210242

211243
// Augment the current $schema object with properties fetched
@@ -226,4 +258,19 @@ public function setUriRetriever(UriRetriever $retriever)
226258

227259
return $this;
228260
}
261+
262+
protected function resolveRefSegment($data, $pathParts)
263+
{
264+
foreach ($pathParts as $path) {
265+
$path = strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
266+
267+
if (is_array($data)) {
268+
$data = $data[$path];
269+
} else {
270+
$data = $data->{$path};
271+
}
272+
}
273+
274+
return $data;
275+
}
229276
}

tests/JsonSchema/Tests/Constraints/BaseTestCase.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
namespace JsonSchema\Tests\Constraints;
1111

12+
use JsonSchema\RefResolver;
13+
use JsonSchema\Uri\UriRetriever;
1214
use JsonSchema\Validator;
1315

1416
abstract class BaseTestCase extends \PHPUnit_Framework_TestCase
@@ -18,9 +20,14 @@ abstract class BaseTestCase extends \PHPUnit_Framework_TestCase
1820
*/
1921
public function testInvalidCases($input, $schema, $checkMode = Validator::CHECK_MODE_NORMAL, $errors = array())
2022
{
23+
$schema = json_decode($schema);
24+
25+
$refResolver = new RefResolver(new UriRetriever);
26+
$refResolver->resolve($schema);
27+
2128
$validator = new Validator($checkMode);
2229

23-
$validator->check(json_decode($input), json_decode($schema));
30+
$validator->check(json_decode($input), $schema);
2431

2532
if (array() !== $errors) {
2633
$this->assertEquals($errors, $validator->getErrors(), print_r($validator->getErrors(),true));
@@ -33,13 +40,18 @@ public function testInvalidCases($input, $schema, $checkMode = Validator::CHECK_
3340
*/
3441
public function testValidCases($input, $schema, $checkMode = Validator::CHECK_MODE_NORMAL)
3542
{
43+
$schema = json_decode($schema);
44+
45+
$refResolver = new RefResolver(new UriRetriever);
46+
$refResolver->resolve($schema);
47+
3648
$validator = new Validator($checkMode);
3749

38-
$validator->check(json_decode($input), json_decode($schema));
50+
$validator->check(json_decode($input), $schema);
3951
$this->assertTrue($validator->isValid(), print_r($validator->getErrors(), true));
4052
}
4153

4254
abstract public function getValidTests();
4355

4456
abstract public function getInvalidTests();
45-
}
57+
}

tests/JsonSchema/Tests/Drafts/Draft4Test.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ protected function getSkippedTests()
2626
);
2727
}
2828

29-
}
29+
}

0 commit comments

Comments
 (0)