Skip to content

Commit 2402bf5

Browse files
author
Michael Chiocca
committed
Add support for draft-04 allOf, anyOf, and oneOf keywords.
1 parent ebcb7c5 commit 2402bf5

File tree

2 files changed

+74
-16
lines changed

2 files changed

+74
-16
lines changed

src/JsonSchema/Constraints/Undefined.php

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,14 @@ public function check($value, $schema = null, $path = null, $i = null)
2626
return;
2727
}
2828

29+
$i = is_null($i) ? "" : $i;
2930
$path = $this->incrementPath($path, $i);
3031

3132
// check special properties
32-
$this->validateCommonProperties($value, $schema, $path);
33+
$this->validateCommonProperties($value, $schema, $path, $i);
34+
35+
// check allOf, anyOf, and oneOf properties
36+
$this->validateOfProperties($value, $schema, $path, $i);
3337

3438
// check known types
3539
$this->validateTypes($value, $schema, $path, $i);
@@ -92,13 +96,12 @@ protected function validateCommonProperties($value, $schema = null, $path = null
9296
if (is_string($schema->extends)) {
9397
$schema->extends = $this->validateUri($schema, $schema->extends);
9498
}
95-
$increment = is_null($i) ? "" : $i;
9699
if (is_array($schema->extends)) {
97100
foreach ($schema->extends as $extends) {
98-
$this->checkUndefined($value, $extends, $path, $increment);
101+
$this->checkUndefined($value, $extends, $path, $i);
99102
}
100103
} else {
101-
$this->checkUndefined($value, $schema->extends, $path, $increment);
104+
$this->checkUndefined($value, $schema->extends, $path, $i);
102105
}
103106
}
104107

@@ -117,10 +120,10 @@ protected function validateCommonProperties($value, $schema = null, $path = null
117120
}
118121
}
119122
} else {
120-
$this->checkType($value, $schema, $path);
123+
$this->checkType($value, $schema, $path, $i);
121124
}
122125
} else {
123-
$this->checkType($value, $schema, $path);
126+
$this->checkType($value, $schema, $path, $i);
124127
}
125128

126129
// Verify disallowed items
@@ -129,23 +132,23 @@ protected function validateCommonProperties($value, $schema = null, $path = null
129132

130133
$typeSchema = new \stdClass();
131134
$typeSchema->type = $schema->disallow;
132-
$this->checkType($value, $typeSchema, $path);
135+
$this->checkType($value, $typeSchema, $path, $i);
133136

134137
// if no new errors were raised it must be a disallowed value
135138
if (count($this->getErrors()) == count($initErrors)) {
136-
$this->addError($path, " disallowed value was matched");
139+
$this->addError($path, "disallowed value was matched");
137140
} else {
138141
$this->errors = $initErrors;
139142
}
140143
}
141144

142145
if (isset($schema->not)) {
143146
$initErrors = $this->getErrors();
144-
$this->checkUndefined($value, $schema->not, $path, is_null($i) ? "" : $i);
147+
$this->checkUndefined($value, $schema->not, $path, $i);
145148

146149
// if no new errors were raised then the instance validated against the "not" schema
147150
if (count($this->getErrors()) == count($initErrors)) {
148-
$this->addError($path, "matches a schema which it should not");
151+
$this->addError($path, "matched a schema which it should not");
149152
} else {
150153
$this->errors = $initErrors;
151154
}
@@ -167,7 +170,64 @@ protected function validateCommonProperties($value, $schema = null, $path = null
167170

168171
// Verify that dependencies are met
169172
if (is_object($value) && isset($schema->dependencies)) {
170-
$this->validateDependencies($value, $schema->dependencies, $path);
173+
$this->validateDependencies($value, $schema->dependencies, $path, $i);
174+
}
175+
}
176+
177+
/**
178+
* Validate allOf, anyOf, and oneOf properties
179+
*
180+
* @param mixed $value
181+
* @param mixed $schema
182+
* @param string $path
183+
* @param string $i
184+
*/
185+
protected function validateOfProperties($value, $schema, $path, $i)
186+
{
187+
if (isset($schema->allOf)) {
188+
$isValid = true;
189+
foreach ($schema->allOf as $allOf) {
190+
$initErrors = $this->getErrors();
191+
$this->checkUndefined($value, $allOf, $path, $i);
192+
$isValid = $isValid && (count($this->getErrors()) == count($initErrors));
193+
}
194+
if (!$isValid) {
195+
$this->addError($path, "failed to match all schemas");
196+
}
197+
}
198+
199+
if (isset($schema->anyOf)) {
200+
$isValid = false;
201+
$startErrors = $this->getErrors();
202+
foreach ($schema->anyOf as $anyOf) {
203+
$initErrors = $this->getErrors();
204+
$this->checkUndefined($value, $anyOf, $path, $i);
205+
if (!$isValid) {
206+
$isValid = (count($this->getErrors()) == count($initErrors));
207+
}
208+
}
209+
if (!$isValid) {
210+
$this->addError($path, "failed to match at least one schema");
211+
} else {
212+
$this->errors = $startErrors;
213+
}
214+
}
215+
216+
if (isset($schema->oneOf)) {
217+
$matchedSchemas = 0;
218+
$startErrors = $this->getErrors();
219+
foreach ($schema->oneOf as $oneOf) {
220+
$initErrors = $this->getErrors();
221+
$this->checkUndefined($value, $oneOf, $path, $i);
222+
if (count($this->getErrors()) == count($initErrors)) {
223+
$matchedSchemas++;
224+
}
225+
}
226+
if ($matchedSchemas !== 1) {
227+
$this->addError($path, "failed to match exactly one schema");
228+
} else {
229+
$this->errors = $startErrors;
230+
}
171231
}
172232
}
173233

@@ -177,8 +237,9 @@ protected function validateCommonProperties($value, $schema = null, $path = null
177237
* @param mixed $value
178238
* @param mixed $dependencies
179239
* @param string $path
240+
* @param string $i
180241
*/
181-
protected function validateDependencies($value, $dependencies, $path)
242+
protected function validateDependencies($value, $dependencies, $path, $i)
182243
{
183244
foreach ($dependencies as $key => $dependency) {
184245
if (property_exists($value, $key)) {
@@ -196,7 +257,7 @@ protected function validateDependencies($value, $dependencies, $path)
196257
}
197258
} else if (is_object($dependency)) {
198259
// Schema - e.g. "dependencies": {"bar": {"properties": {"foo": {...}}}}
199-
$this->checkUndefined($value, $dependency, $path, "");
260+
$this->checkUndefined($value, $dependency, $path, $i);
200261
}
201262
}
202263
}

tests/JsonSchema/Tests/Drafts/Draft4Test.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@ protected function getSkippedTests()
1616
{
1717
return array(
1818
// Not Yet Implemented
19-
'allOf.json',
20-
'anyOf.json',
2119
'definitions.json',
22-
'oneOf.json',
2320
// Partially Implemented
2421
'ref.json',
2522
'refRemote.json',

0 commit comments

Comments
 (0)