diff --git a/src/JsonSchema/RefResolver.php b/src/JsonSchema/RefResolver.php index 4786a331..e2048724 100644 --- a/src/JsonSchema/RefResolver.php +++ b/src/JsonSchema/RefResolver.php @@ -39,6 +39,10 @@ class RefResolver * @var UriRetrieverInterface */ protected $uriRetriever = null; + + + protected $rootSchema; + /** * @param UriRetriever $retriever @@ -109,6 +113,10 @@ public function resolve($schema, $sourceUri = null) $sourceUri = $schema->id; } + if (!$this->rootSchema) { + $this->rootSchema = $schema; + } + // Resolve $ref first $this->resolveRef($schema, $sourceUri); @@ -204,8 +212,25 @@ public function resolveRef($schema, $sourceUri) return; } - $refSchema = $this->fetchRef($schema->$ref, $sourceUri); + if ($schema->{$ref}[0] === '#') { + $path = substr($schema->$ref, 1); + if (empty($path)) { + return; + } + + if ($path[0] !== '/') { + return; + } + + $pathParts = explode('/', $path); + array_shift($pathParts); + + $refSchema = $this->resolveRefSegment($this->rootSchema, $pathParts); + } else { + $refSchema = $this->fetchRef($schema->$ref, $sourceUri); + } unset($schema->$ref); + // Augment the current $schema object with properties fetched foreach (get_object_vars($refSchema) as $prop => $value) { @@ -213,6 +238,17 @@ public function resolveRef($schema, $sourceUri) } } + protected function resolveRefSegment($data, $pathParts) + { + if (empty($pathParts) || empty($data)) { + return $data; + } + + $key = $this->transformKey(array_shift($pathParts)); + + return $this->resolveRefSegment(is_array($data) ? $data[$key] : $data->$key, $pathParts); + } + /** * Set URI Retriever for use with the Ref Resolver * @@ -225,4 +261,12 @@ public function setUriRetriever(UriRetriever $retriever) return $this; } + + protected function transformKey($key) + { + return strtr($key, array( + '~1' => '/', + '~0' => '~', + )); + } } diff --git a/tests/JsonSchema/Tests/Drafts/Draft4Test.php b/tests/JsonSchema/Tests/Drafts/Draft4Test.php index 3f1d566c..9bd45e6a 100644 --- a/tests/JsonSchema/Tests/Drafts/Draft4Test.php +++ b/tests/JsonSchema/Tests/Drafts/Draft4Test.php @@ -25,5 +25,54 @@ protected function getSkippedTests() 'zeroTerminatedFloats.json' ); } + + public function testInnerDefinitions(){ + $schema = <<resolve($schemaObj); + + $schema = json_encode($schemaObj); + + $this->testValidCases('{"person": {"name" : "John Doe", "age" : 30} }', $schema); + $this->testInvalidCases('{"person": {"name" : "John Doe", "age" : "wrong"} }', $schema); + $this->testValidCases('{"person-age": 30 }', $schema); + $this->testInvalidCases('{"person-age": "wrong" }', $schema); + $this->testValidCases('{"slash": 30 }', $schema); + $this->testInvalidCases('{"slash": "wrong" }', $schema); + $this->testValidCases('{"tilde": 30 }', $schema); + $this->testInvalidCases('{"tilde": "wrong" }', $schema); + } -} \ No newline at end of file +}