Skip to content

Commit 37fb6b3

Browse files
committed
feat: Progress draft 7 support
1 parent c903df0 commit 37fb6b3

File tree

4 files changed

+111
-29
lines changed

4 files changed

+111
-29
lines changed

src/JsonSchema/Constraints/Drafts/Draft07/Draft07Constraint.php

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,38 +32,39 @@ public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = n
3232
}
3333

3434
// Apply defaults
35-
// $this->checkForKeyword('ref', $value, $schema, $path, $i);
36-
// $this->checkForKeyword('required', $value, $schema, $path, $i);
37-
// $this->checkForKeyword('contains', $value, $schema, $path, $i);
38-
// $this->checkForKeyword('properties', $value, $schema, $path, $i);
39-
// $this->checkForKeyword('propertyNames', $value, $schema, $path, $i);
40-
// $this->checkForKeyword('patternProperties', $value, $schema, $path, $i);
41-
// $this->checkForKeyword('type', $value, $schema, $path, $i);
42-
// $this->checkForKeyword('not', $value, $schema, $path, $i);
43-
// $this->checkForKeyword('dependencies', $value, $schema, $path, $i);
44-
// $this->checkForKeyword('allOf', $value, $schema, $path, $i);
45-
// $this->checkForKeyword('anyOf', $value, $schema, $path, $i);
46-
// $this->checkForKeyword('oneOf', $value, $schema, $path, $i);
47-
//
48-
// $this->checkForKeyword('additionalProperties', $value, $schema, $path, $i);
49-
// $this->checkForKeyword('items', $value, $schema, $path, $i);
50-
// $this->checkForKeyword('additionalItems', $value, $schema, $path, $i);
35+
$this->checkForKeyword('ref', $value, $schema, $path, $i);
36+
$this->checkForKeyword('required', $value, $schema, $path, $i);
37+
$this->checkForKeyword('contains', $value, $schema, $path, $i);
38+
$this->checkForKeyword('properties', $value, $schema, $path, $i);
39+
$this->checkForKeyword('propertyNames', $value, $schema, $path, $i);
40+
$this->checkForKeyword('patternProperties', $value, $schema, $path, $i);
41+
$this->checkForKeyword('type', $value, $schema, $path, $i);
42+
$this->checkForKeyword('not', $value, $schema, $path, $i);
43+
$this->checkForKeyword('dependencies', $value, $schema, $path, $i);
44+
$this->checkForKeyword('allOf', $value, $schema, $path, $i);
45+
$this->checkForKeyword('anyOf', $value, $schema, $path, $i);
46+
$this->checkForKeyword('oneOf', $value, $schema, $path, $i);
47+
$this->checkForKeyword('ifThenElse', $value, $schema, $path, $i);
48+
49+
$this->checkForKeyword('additionalProperties', $value, $schema, $path, $i);
50+
$this->checkForKeyword('items', $value, $schema, $path, $i);
51+
$this->checkForKeyword('additionalItems', $value, $schema, $path, $i);
5152
$this->checkForKeyword('uniqueItems', $value, $schema, $path, $i);
5253
$this->checkForKeyword('minItems', $value, $schema, $path, $i);
53-
// $this->checkForKeyword('minProperties', $value, $schema, $path, $i);
54-
// $this->checkForKeyword('maxProperties', $value, $schema, $path, $i);
55-
// $this->checkForKeyword('minimum', $value, $schema, $path, $i);
56-
// $this->checkForKeyword('maximum', $value, $schema, $path, $i);
57-
// $this->checkForKeyword('minLength', $value, $schema, $path, $i);
58-
// $this->checkForKeyword('exclusiveMinimum', $value, $schema, $path, $i);
59-
// $this->checkForKeyword('maxItems', $value, $schema, $path, $i);
60-
// $this->checkForKeyword('maxLength', $value, $schema, $path, $i);
61-
// $this->checkForKeyword('exclusiveMaximum', $value, $schema, $path, $i);
62-
// $this->checkForKeyword('enum', $value, $schema, $path, $i);
54+
$this->checkForKeyword('minProperties', $value, $schema, $path, $i);
55+
$this->checkForKeyword('maxProperties', $value, $schema, $path, $i);
56+
$this->checkForKeyword('minimum', $value, $schema, $path, $i);
57+
$this->checkForKeyword('maximum', $value, $schema, $path, $i);
58+
$this->checkForKeyword('minLength', $value, $schema, $path, $i);
59+
$this->checkForKeyword('exclusiveMinimum', $value, $schema, $path, $i);
60+
$this->checkForKeyword('maxItems', $value, $schema, $path, $i);
61+
$this->checkForKeyword('maxLength', $value, $schema, $path, $i);
62+
$this->checkForKeyword('exclusiveMaximum', $value, $schema, $path, $i);
63+
$this->checkForKeyword('enum', $value, $schema, $path, $i);
6364
$this->checkForKeyword('const', $value, $schema, $path, $i);
64-
// $this->checkForKeyword('multipleOf', $value, $schema, $path, $i);
65-
// $this->checkForKeyword('format', $value, $schema, $path, $i);
66-
// $this->checkForKeyword('pattern', $value, $schema, $path, $i);
65+
$this->checkForKeyword('multipleOf', $value, $schema, $path, $i);
66+
$this->checkForKeyword('format', $value, $schema, $path, $i);
67+
$this->checkForKeyword('pattern', $value, $schema, $path, $i);
6768
}
6869

6970
/**

src/JsonSchema/Constraints/Drafts/Draft07/Factory.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class Factory extends \JsonSchema\Constraints\Factory
3535
'allOf' => AllOfConstraint::class,
3636
'oneOf' => OneOfConstraint::class,
3737
'not' => NotConstraint::class,
38+
'ifThenElse' => IfThenElseConstraint::class,
3839
'contains' => ContainsConstraint::class,
3940
'propertyNames' => PropertiesNamesConstraint::class,
4041
'patternProperties' => PatternPropertiesConstraint::class,
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace JsonSchema\Constraints\Drafts\Draft07;
6+
7+
use JsonSchema\ConstraintError;
8+
use JsonSchema\Constraints\ConstraintInterface;
9+
use JsonSchema\Entity\ErrorBagProxy;
10+
use JsonSchema\Entity\JsonPointer;
11+
12+
class IfThenElseConstraint implements ConstraintInterface
13+
{
14+
use ErrorBagProxy;
15+
16+
/** @var Factory */
17+
private $factory;
18+
19+
public function __construct(?Factory $factory = null)
20+
{
21+
$this->factory = $factory ?: new Factory();
22+
$this->initialiseErrorBag($this->factory);
23+
}
24+
25+
public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
26+
{
27+
if (!property_exists($schema, 'if')) {
28+
return;
29+
}
30+
31+
$schemaConstraint = $this->factory->createInstanceFor('schema');
32+
$ifSchema = $schema->if;
33+
34+
if (!is_bool($ifSchema)) {
35+
$schemaConstraint->check($value, $ifSchema, $path, $i);
36+
$meetsIfConditions = $schemaConstraint->isValid();
37+
} else {
38+
$meetsIfConditions = $ifSchema;
39+
}
40+
41+
if ($meetsIfConditions) {
42+
if (!property_exists($schema, 'then')) {
43+
return;
44+
}
45+
46+
$schemaConstraint->check($value, $schema->then, $path, $i);
47+
if ($schemaConstraint->isValid()) {
48+
return;
49+
}
50+
51+
$this->addErrors($schemaConstraint->getErrors());
52+
return;
53+
}
54+
55+
if (!property_exists($schema, 'else')) {
56+
return;
57+
}
58+
59+
$schemaConstraint->check($value, $schema->else, $path, $i);
60+
if ($schemaConstraint->isValid()) {
61+
return;
62+
}
63+
64+
$this->addErrors($schemaConstraint->getErrors());
65+
}
66+
}

tests/JsonSchemaTestSuiteTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,20 @@ private function shouldNotYieldTest(string $name): bool
174174
'[draft6/ref.json]: URN base URI with r-component: a non-string is invalid is expected to be invalid',
175175
'[draft6/ref.json]: URN base URI with q-component: a non-string is invalid is expected to be invalid',
176176
'[draft6/ref.json]: URN base URI with URN and anchor ref: a non-string is invalid is expected to be invalid',
177+
'[draft7/unknownKeyword.json]: $id inside an unknown keyword is not a real identifier: type matches second anyOf, which has a real schema in it is expected to be valid',
178+
'[draft7/unknownKeyword.json]: $id inside an unknown keyword is not a real identifier: type matches non-schema in third anyOf is expected to be invalid',
179+
'[draft7/refRemote.json]: $ref to $ref finds location-independent $id: non-number is invalid is expected to be invalid',
180+
'[draft7/ref.json]: ref overrides any sibling keywords: ref valid, maxItems ignored is expected to be valid',
181+
'[draft7/ref.json]: Reference an anchor with a non-relative URI: mismatch is expected to be invalid',
182+
'[draft7/ref.json]: refs with relative uris and defs: invalid on inner field is expected to be invalid',
183+
'[draft7/ref.json]: refs with relative uris and defs: invalid on outer field is expected to be invalid',
184+
'[draft7/ref.json]: relative refs with absolute uris and defs: invalid on inner field is expected to be invalid',
185+
'[draft7/ref.json]: relative refs with absolute uris and defs: invalid on outer field is expected to be invalid',
186+
'[draft7/ref.json]: simple URN base URI with JSON pointer: a non-string is invalid is expected to be invalid',
187+
'[draft7/ref.json]: URN base URI with NSS: a non-string is invalid is expected to be invalid',
188+
'[draft7/ref.json]: URN base URI with r-component: a non-string is invalid is expected to be invalid',
189+
'[draft7/ref.json]: URN base URI with q-component: a non-string is invalid is expected to be invalid',
190+
'[draft7/ref.json]: URN base URI with URN and anchor ref: a non-string is invalid is expected to be invalid',
177191
];
178192

179193
if ($this->is32Bit()) {

0 commit comments

Comments
 (0)