Skip to content

Commit 4a0849c

Browse files
committed
Merge remote-tracking branch 'upstream/master' into feature/some-optimization
# Conflicts: # src/JsonSchema/Constraints/Factory.php
2 parents 2f590d5 + 1296583 commit 4a0849c

25 files changed

+654
-509
lines changed

README.md

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,11 @@ See [json-schema](http://json-schema.org/) for more details.
2626
```php
2727
<?php
2828

29-
// Get the schema and data as objects
30-
// If you use $ref or if you are unsure, resolve those references here
31-
// This modifies the $schema object
32-
$refResolver = new JsonSchema\RefResolver(new JsonSchema\Uri\UriRetriever(), new JsonSchema\Uri\UriResolver());
33-
$schema = $refResolver->resolve('file://' . realpath('schema.json'));
34-
3529
$data = json_decode(file_get_contents('data.json'));
3630

3731
// Validate
38-
$validator = new JsonSchema\Validator();
39-
$validator->check($data, $schema);
32+
$validator = new JsonSchema\Validator;
33+
$validator->check($data, (object)['$ref' => 'file://' . realpath('schema.json')]);
4034

4135
if ($validator->isValid()) {
4236
echo "The supplied JSON validates against the schema.\n";

src/JsonSchema/Constraints/CollectionConstraint.php

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

1010
namespace JsonSchema\Constraints;
1111

12+
use JsonSchema\Entity\JsonPointer;
13+
1214
/**
1315
* The CollectionConstraint Constraints, validates an array against a given schema
1416
*
@@ -20,7 +22,7 @@ class CollectionConstraint extends Constraint
2022
/**
2123
* {@inheritDoc}
2224
*/
23-
public function check($value, $schema = null, $path = null, $i = null)
25+
public function check($value, $schema = null, JsonPointer $path = null, $i = null)
2426
{
2527
// Verify minItems
2628
if (isset($schema->minItems) && count($value) < $schema->minItems) {
@@ -52,12 +54,12 @@ public function check($value, $schema = null, $path = null, $i = null)
5254
/**
5355
* Validates the items
5456
*
55-
* @param array $value
56-
* @param \stdClass $schema
57-
* @param string $path
58-
* @param string $i
57+
* @param array $value
58+
* @param \stdClass $schema
59+
* @param JsonPointer|null $path
60+
* @param string $i
5961
*/
60-
protected function validateItems($value, $schema = null, $path = null, $i = null)
62+
protected function validateItems($value, $schema = null, JsonPointer $path = null, $i = null)
6163
{
6264
if (is_object($schema->items)) {
6365
// just one type definition for the whole array

src/JsonSchema/Constraints/Constraint.php

Lines changed: 109 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99

1010
namespace JsonSchema\Constraints;
1111

12+
use JsonSchema\SchemaStorage;
1213
use JsonSchema\Uri\UriRetriever;
13-
use JsonSchema\Validator;
14+
use JsonSchema\UriRetrieverInterface;
15+
use JsonSchema\Entity\JsonPointer;
1416

1517
/**
1618
* The Base Constraints, all Validators should extend this class
@@ -20,6 +22,7 @@
2022
*/
2123
abstract class Constraint implements ConstraintInterface
2224
{
25+
protected $schemaStorage;
2326
protected $checkMode = self::CHECK_MODE_NORMAL;
2427
protected $uriRetriever;
2528
protected $errors = array();
@@ -34,19 +37,25 @@ abstract class Constraint implements ConstraintInterface
3437
private $factory;
3538

3639
/**
37-
* @param int $checkMode
38-
* @param UriRetriever $uriRetriever
39-
* @param Factory $factory
40+
* @param int $checkMode
41+
* @param SchemaStorage $schemaStorage
42+
* @param UriRetrieverInterface $uriRetriever
43+
* @param Factory $factory
4044
*/
41-
public function __construct($checkMode = self::CHECK_MODE_NORMAL, UriRetriever $uriRetriever = null, Factory $factory = null)
42-
{
43-
$this->checkMode = $checkMode;
44-
$this->uriRetriever = $uriRetriever;
45-
$this->factory = $factory;
45+
public function __construct(
46+
$checkMode = self::CHECK_MODE_NORMAL,
47+
SchemaStorage $schemaStorage = null,
48+
UriRetrieverInterface $uriRetriever = null,
49+
Factory $factory = null
50+
) {
51+
$this->checkMode = $checkMode;
52+
$this->uriRetriever = $uriRetriever;
53+
$this->factory = $factory;
54+
$this->schemaStorage = $schemaStorage;
4655
}
4756

4857
/**
49-
* @return UriRetriever $uriRetriever
58+
* @return UriRetrieverInterface $uriRetriever
5059
*/
5160
public function getUriRetriever()
5261
{
@@ -63,27 +72,40 @@ public function getUriRetriever()
6372
public function getFactory()
6473
{
6574
if (!$this->factory) {
66-
$this->factory = new Factory($this->getUriRetriever(), $this->checkMode);
75+
$this->factory = new Factory($this->getSchemaStorage(), $this->getUriRetriever(), $this->checkMode);
6776
}
6877

6978
return $this->factory;
7079
}
7180

7281
/**
73-
* @param UriRetriever $uriRetriever
82+
* @return SchemaStorage
7483
*/
75-
public function setUriRetriever(UriRetriever $uriRetriever)
84+
public function getSchemaStorage()
85+
{
86+
if (is_null($this->schemaStorage)) {
87+
$this->schemaStorage = new SchemaStorage($this->getUriRetriever());
88+
}
89+
90+
return $this->schemaStorage;
91+
}
92+
93+
/**
94+
* @param UriRetrieverInterface $uriRetriever
95+
*/
96+
public function setUriRetriever(UriRetrieverInterface $uriRetriever)
7697
{
7798
$this->uriRetriever = $uriRetriever;
7899
}
79100

80101
/**
81102
* {@inheritDoc}
82103
*/
83-
public function addError($path, $message, $constraint='', array $more=null)
104+
public function addError(JsonPointer $path = null, $message, $constraint='', array $more=null)
84105
{
85106
$error = array(
86-
'property' => $path,
107+
'property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')),
108+
'pointer' => ltrim(strval($path ?: new JsonPointer('')), '#'),
87109
'message' => $message,
88110
'constraint' => $constraint,
89111
);
@@ -132,37 +154,32 @@ public function reset()
132154
/**
133155
* Bubble down the path
134156
*
135-
* @param string $path Current path
136-
* @param mixed $i What to append to the path
157+
* @param JsonPointer|null $path Current path
158+
* @param mixed $i What to append to the path
137159
*
138-
* @return string
160+
* @return JsonPointer;
139161
*/
140-
protected function incrementPath($path, $i)
162+
protected function incrementPath(JsonPointer $path = null, $i)
141163
{
142-
if ($path !== '') {
143-
if (is_int($i)) {
144-
$path .= '[' . $i . ']';
145-
} elseif ($i == '') {
146-
$path .= '';
147-
} else {
148-
$path .= '.' . $i;
149-
}
150-
} else {
151-
$path = $i;
152-
}
153-
164+
$path = $path ?: new JsonPointer('');
165+
$path = $path->withPropertyPaths(
166+
array_merge(
167+
$path->getPropertyPaths(),
168+
array_filter(array($i), 'strlen')
169+
)
170+
);
154171
return $path;
155172
}
156173

157174
/**
158175
* Validates an array
159176
*
160-
* @param mixed $value
161-
* @param mixed $schema
162-
* @param mixed $path
163-
* @param mixed $i
177+
* @param mixed $value
178+
* @param mixed $schema
179+
* @param JsonPointer|null $path
180+
* @param mixed $i
164181
*/
165-
protected function checkArray($value, $schema = null, $path = null, $i = null)
182+
protected function checkArray($value, $schema = null, JsonPointer $path = null, $i = null)
166183
{
167184
$validator = $this->getFactory()->createInstanceFor('collection');
168185
$validator->check($value, $schema, $path, $i);
@@ -173,13 +190,13 @@ protected function checkArray($value, $schema = null, $path = null, $i = null)
173190
/**
174191
* Validates an object
175192
*
176-
* @param mixed $value
177-
* @param mixed $schema
178-
* @param mixed $path
179-
* @param mixed $i
180-
* @param mixed $patternProperties
193+
* @param mixed $value
194+
* @param mixed $schema
195+
* @param JsonPointer|null $path
196+
* @param mixed $i
197+
* @param mixed $patternProperties
181198
*/
182-
protected function checkObject($value, $schema = null, $path = null, $i = null, $patternProperties = null)
199+
protected function checkObject($value, $schema = null, JsonPointer $path = null, $i = null, $patternProperties = null)
183200
{
184201
$validator = $this->getFactory()->createInstanceFor('object');
185202
$validator->check($value, $schema, $path, $i, $patternProperties);
@@ -190,12 +207,12 @@ protected function checkObject($value, $schema = null, $path = null, $i = null,
190207
/**
191208
* Validates the type of a property
192209
*
193-
* @param mixed $value
194-
* @param mixed $schema
195-
* @param mixed $path
196-
* @param mixed $i
210+
* @param mixed $value
211+
* @param mixed $schema
212+
* @param JsonPointer|null $path
213+
* @param mixed $i
197214
*/
198-
protected function checkType($value, $schema = null, $path = null, $i = null)
215+
protected function checkType($value, $schema = null, JsonPointer $path = null, $i = null)
199216
{
200217
$validator = $this->getFactory()->createInstanceFor('type');
201218
$validator->check($value, $schema, $path, $i);
@@ -206,28 +223,28 @@ protected function checkType($value, $schema = null, $path = null, $i = null)
206223
/**
207224
* Checks a undefined element
208225
*
209-
* @param mixed $value
210-
* @param mixed $schema
211-
* @param mixed $path
212-
* @param mixed $i
226+
* @param mixed $value
227+
* @param mixed $schema
228+
* @param JsonPointer|null $path
229+
* @param mixed $i
213230
*/
214-
protected function checkUndefined($value, $schema = null, $path = null, $i = null)
231+
protected function checkUndefined($value, $schema = null, JsonPointer $path = null, $i = null)
215232
{
216233
$validator = $this->getFactory()->createInstanceFor('undefined');
217-
$validator->check($value, $schema, $path, $i);
234+
$validator->check($value, $this->schemaStorage->resolveRefSchema($schema), $path, $i);
218235

219236
$this->addErrors($validator->getErrors());
220237
}
221238

222239
/**
223240
* Checks a string element
224241
*
225-
* @param mixed $value
226-
* @param mixed $schema
227-
* @param mixed $path
228-
* @param mixed $i
242+
* @param mixed $value
243+
* @param mixed $schema
244+
* @param JsonPointer|null $path
245+
* @param mixed $i
229246
*/
230-
protected function checkString($value, $schema = null, $path = null, $i = null)
247+
protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null)
231248
{
232249
$validator = $this->getFactory()->createInstanceFor('string');
233250
$validator->check($value, $schema, $path, $i);
@@ -238,12 +255,12 @@ protected function checkString($value, $schema = null, $path = null, $i = null)
238255
/**
239256
* Checks a number element
240257
*
241-
* @param mixed $value
242-
* @param mixed $schema
243-
* @param mixed $path
244-
* @param mixed $i
258+
* @param mixed $value
259+
* @param mixed $schema
260+
* @param JsonPointer $path
261+
* @param mixed $i
245262
*/
246-
protected function checkNumber($value, $schema = null, $path = null, $i = null)
263+
protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null)
247264
{
248265
$validator = $this->getFactory()->createInstanceFor('number');
249266
$validator->check($value, $schema, $path, $i);
@@ -254,41 +271,35 @@ protected function checkNumber($value, $schema = null, $path = null, $i = null)
254271
/**
255272
* Checks a enum element
256273
*
257-
* @param mixed $value
258-
* @param mixed $schema
259-
* @param mixed $path
260-
* @param mixed $i
274+
* @param mixed $value
275+
* @param mixed $schema
276+
* @param JsonPointer|null $path
277+
* @param mixed $i
261278
*/
262-
protected function checkEnum($value, $schema = null, $path = null, $i = null)
279+
protected function checkEnum($value, $schema = null, JsonPointer $path = null, $i = null)
263280
{
264281
$validator = $this->getFactory()->createInstanceFor('enum');
265282
$validator->check($value, $schema, $path, $i);
266283

267284
$this->addErrors($validator->getErrors());
268285
}
269286

270-
protected function checkFormat($value, $schema = null, $path = null, $i = null)
287+
/**
288+
* Checks format of an element
289+
*
290+
* @param mixed $value
291+
* @param mixed $schema
292+
* @param JsonPointer|null $path
293+
* @param mixed $i
294+
*/
295+
protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null)
271296
{
272297
$validator = $this->getFactory()->createInstanceFor('format');
273298
$validator->check($value, $schema, $path, $i);
274299

275300
$this->addErrors($validator->getErrors());
276301
}
277302

278-
/**
279-
* @param string $uri JSON Schema URI
280-
* @return string JSON Schema contents
281-
*/
282-
protected function retrieveUri($uri)
283-
{
284-
if (null === $this->uriRetriever) {
285-
$this->setUriRetriever(new UriRetriever);
286-
}
287-
$jsonSchema = $this->uriRetriever->retrieve($uri);
288-
// TODO validate using schema
289-
return $jsonSchema;
290-
}
291-
292303
/**
293304
* Get the type check based on the set check mode.
294305
*
@@ -298,4 +309,19 @@ protected function getTypeCheck()
298309
{
299310
return $this->getFactory()->getTypeCheck();
300311
}
312+
313+
/**
314+
* @param JsonPointer $pointer
315+
* @return string property path
316+
*/
317+
protected function convertJsonPointerIntoPropertyPath(JsonPointer $pointer)
318+
{
319+
$result = array_map(
320+
function($path) {
321+
return sprintf(is_numeric($path) ? '[%d]' : '.%s', $path);
322+
},
323+
$pointer->getPropertyPaths()
324+
);
325+
return trim(implode('', $result), '.');
326+
}
301327
}

0 commit comments

Comments
 (0)