Skip to content

Commit 50901a4

Browse files
committed
Merge pull request #245 from jojo1981/feature/ref-resolver
#240 Fix RefResolver and make it compatible with draft-04
2 parents 61a95a1 + e265e9f commit 50901a4

19 files changed

+1294
-579
lines changed

README.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,12 @@ See [json-schema](http://json-schema.org/) for more details.
2727
<?php
2828

2929
// Get the schema and data as objects
30-
$retriever = new JsonSchema\Uri\UriRetriever;
31-
$schema = $retriever->retrieve('file://' . realpath('schema.json'));
32-
$data = json_decode(file_get_contents('data.json'));
33-
3430
// If you use $ref or if you are unsure, resolve those references here
3531
// This modifies the $schema object
36-
$refResolver = new JsonSchema\RefResolver($retriever);
37-
$refResolver->resolve($schema, 'file://' . __DIR__);
32+
$refResolver = new JsonSchema\RefResolver(new JsonSchema\Uri\UriRetriever(), new JsonSchema\Uri\UriResolver());
33+
$schema = $refResolver->resolve('file://' . realpath('schema.json'));
34+
35+
$data = json_decode(file_get_contents('data.json'));
3836

3937
// Validate
4038
$validator = new JsonSchema\Validator();

bin/validate-json

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -200,22 +200,14 @@ try {
200200
echo $urlSchema . "\n";
201201
exit();
202202
}
203-
204-
$schema = $retriever->retrieve($urlSchema);
205-
if ($schema === null) {
206-
echo "Error loading JSON schema file\n";
207-
echo $urlSchema . "\n";
208-
showJsonError();
209-
exit(2);
210-
}
211203
} catch (Exception $e) {
212204
echo "Error loading JSON schema file\n";
213205
echo $urlSchema . "\n";
214206
echo $e->getMessage() . "\n";
215207
exit(2);
216208
}
217-
$refResolver = new JsonSchema\RefResolver($retriever);
218-
$refResolver->resolve($schema, $urlSchema);
209+
$refResolver = new JsonSchema\RefResolver($retriever, $resolver);
210+
$schema = $refResolver->resolve($urlSchema);
219211

220212
if (isset($arOptions['--dump-schema'])) {
221213
$options = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0;
@@ -242,4 +234,3 @@ try {
242234
echo "Error code: " . $e->getCode() . "\n";
243235
exit(24);
244236
}
245-
?>

src/JsonSchema/Constraints/ObjectConstraint.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,13 @@ protected function getProperty($element, $property, $fallback = null)
159159
*/
160160
protected function validateMinMaxConstraint($element, $objectDefinition, $path) {
161161
// Verify minimum number of properties
162-
if (isset($objectDefinition->minProperties)) {
162+
if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) {
163163
if (count(get_object_vars($element)) < $objectDefinition->minProperties) {
164164
$this->addError($path, "Must contain a minimum of " . $objectDefinition->minProperties . " properties", 'minProperties', array('minProperties' => $objectDefinition->minProperties,));
165165
}
166166
}
167167
// Verify maximum number of properties
168-
if (isset($objectDefinition->maxProperties)) {
168+
if (isset($objectDefinition->maxProperties) && !is_object($objectDefinition->maxProperties)) {
169169
if (count(get_object_vars($element)) > $objectDefinition->maxProperties) {
170170
$this->addError($path, "Must contain no more than " . $objectDefinition->maxProperties . " properties", 'maxProperties', array('maxProperties' => $objectDefinition->maxProperties,));
171171
}

src/JsonSchema/Entity/JsonPointer.php

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the JsonSchema package.
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
namespace JsonSchema\Entity;
11+
12+
/**
13+
* @package JsonSchema\Entity
14+
* @author Joost Nijhuis <[email protected]>
15+
*/
16+
class JsonPointer
17+
{
18+
/** @var string */
19+
private $filename;
20+
21+
/** @var string[] */
22+
private $propertyPaths = array();
23+
24+
/**
25+
* @param string $value
26+
* @throws \InvalidArgumentException when $value is not a string
27+
*/
28+
public function __construct($value)
29+
{
30+
if (!is_string($value)) {
31+
throw new \InvalidArgumentException('Ref value must be a string');
32+
}
33+
34+
$splitRef = explode('#', $value, 2);
35+
$this->filename = $splitRef[0];
36+
if (array_key_exists(1, $splitRef)) {
37+
$this->propertyPaths = $this->decodePropertyPaths($splitRef[1]);
38+
}
39+
}
40+
41+
/**
42+
* @param string $propertyPathString
43+
* @return string[]
44+
*/
45+
private function decodePropertyPaths($propertyPathString)
46+
{
47+
$paths = array();
48+
foreach (explode('/', trim($propertyPathString, '/')) as $path) {
49+
$path = $this->decodePath($path);
50+
if (is_string($path) && '' !== $path) {
51+
$paths[] = $path;
52+
}
53+
}
54+
55+
return $paths;
56+
}
57+
58+
/**
59+
* @return array
60+
*/
61+
private function encodePropertyPaths()
62+
{
63+
return array_map(
64+
array($this, 'encodePath'),
65+
$this->getPropertyPaths()
66+
);
67+
}
68+
69+
/**
70+
* @param string $path
71+
* @return string
72+
*/
73+
private function decodePath($path)
74+
{
75+
return strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
76+
}
77+
78+
/**
79+
* @param string $path
80+
* @return string
81+
*/
82+
private function encodePath($path)
83+
{
84+
return strtr($path, array('/' => '~1', '~' => '~0', '%' => '%25'));
85+
}
86+
87+
/**
88+
* @return string
89+
*/
90+
public function getFilename()
91+
{
92+
return $this->filename;
93+
}
94+
95+
/**
96+
* @return string[]
97+
*/
98+
public function getPropertyPaths()
99+
{
100+
return $this->propertyPaths;
101+
}
102+
103+
/**
104+
* @return string
105+
*/
106+
public function getPropertyPathAsString()
107+
{
108+
return rtrim('#/' . implode('/', $this->encodePropertyPaths()), '/');
109+
}
110+
111+
/**
112+
* @return string
113+
*/
114+
public function __toString()
115+
{
116+
return $this->getFilename() . $this->getPropertyPathAsString();
117+
}
118+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the JsonSchema package.
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
namespace JsonSchema\Exception;
11+
12+
/**
13+
* @package JsonSchema\Exception
14+
* @author Joost Nijhuis <[email protected]>
15+
*/
16+
class UnresolvableJsonPointerException extends \InvalidArgumentException
17+
{
18+
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the JsonSchema package.
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
namespace JsonSchema\Iterator;
11+
12+
/**
13+
* @package JsonSchema\Iterator
14+
* @author Joost Nijhuis <[email protected]>
15+
*/
16+
class ObjectIterator implements \Iterator, \Countable
17+
{
18+
/** @var object */
19+
private $object;
20+
21+
/** @var int */
22+
private $position = 0;
23+
24+
/** @var array */
25+
private $data = array();
26+
27+
/** @var bool */
28+
private $initialized = false;
29+
30+
/**
31+
* @param object $object
32+
*/
33+
public function __construct($object)
34+
{
35+
$this->object = $object;
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
public function current()
42+
{
43+
$this->initialize();
44+
45+
return $this->data[$this->position];
46+
}
47+
48+
/**
49+
* {@inheritdoc}
50+
*/
51+
public function next()
52+
{
53+
$this->initialize();
54+
$this->position++;
55+
}
56+
57+
/**
58+
* {@inheritdoc}
59+
*/
60+
public function key()
61+
{
62+
$this->initialize();
63+
64+
return $this->position;
65+
}
66+
67+
/**
68+
* {@inheritdoc}
69+
*/
70+
public function valid()
71+
{
72+
$this->initialize();
73+
74+
return isset($this->data[$this->position]);
75+
}
76+
77+
/**
78+
* {@inheritdoc}
79+
*/
80+
public function rewind()
81+
{
82+
$this->initialize();
83+
$this->position = 0;
84+
}
85+
86+
/**
87+
* {@inheritdoc}
88+
*/
89+
public function count()
90+
{
91+
$this->initialize();
92+
93+
return count($this->data);
94+
}
95+
96+
/**
97+
* Initializer
98+
*/
99+
private function initialize()
100+
{
101+
if (!$this->initialized) {
102+
$this->data = $this->buildDataFromObject($this->object);
103+
$this->initialized = true;
104+
}
105+
}
106+
107+
/**
108+
* @param object $object
109+
* @return array
110+
*/
111+
private function buildDataFromObject($object)
112+
{
113+
$result = array();
114+
115+
$stack = new \SplStack();
116+
$stack->push($object);
117+
118+
while (!$stack->isEmpty()) {
119+
120+
$current = $stack->pop();
121+
if (is_object($current)) {
122+
array_push($result, $current);
123+
}
124+
125+
foreach ($this->getDataFromItem($current) as $propertyName => $propertyValue) {
126+
if (is_object($propertyValue) || is_array($propertyValue)) {
127+
$stack->push($propertyValue);
128+
}
129+
}
130+
}
131+
132+
return $result;
133+
}
134+
135+
/**
136+
* @param object|array $item
137+
* @return array
138+
*/
139+
private function getDataFromItem($item)
140+
{
141+
if (!is_object($item) && !is_array($item)) {
142+
return array();
143+
}
144+
145+
return is_object($item) ? get_object_vars($item) : $item;
146+
}
147+
}

0 commit comments

Comments
 (0)