Skip to content

Commit c8f0f00

Browse files
author
Michael Chiocca
committed
Implement dependencies per draft specification. Refactor required.
1 parent c30751a commit c8f0f00

File tree

5 files changed

+217
-31
lines changed

5 files changed

+217
-31
lines changed

src/JsonSchema/Constraints/Constraint.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,11 @@ protected function checkArray($value, $schema = null, $path = null, $i = null)
151151
* @param mixed $path
152152
* @param mixed $i
153153
* @param mixed $patternProperties
154-
* @param mixed $requiredProp
155154
*/
156-
protected function checkObject(
157-
$value, $schema = null, $path = null, $i = null, $patternProperties = null, $requiredProp = null)
155+
protected function checkObject($value, $schema = null, $path = null, $i = null, $patternProperties = null)
158156
{
159157
$validator = new Object($this->checkMode, $this->uriRetriever);
160-
$validator->check($value, $schema, $path, $i, $patternProperties, $requiredProp);
158+
$validator->check($value, $schema, $path, $i, $patternProperties);
161159

162160
$this->addErrors($validator->getErrors());
163161
}

src/JsonSchema/Constraints/Object.php

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ class Object extends Constraint
2020
/**
2121
* {@inheritDoc}
2222
*/
23-
function check(
24-
$element, $definition = null,
25-
$path = null, $additionalProp = null, $patternProperties = null, $requiredProp = null)
23+
function check($element, $definition = null, $path = null, $additionalProp = null, $patternProperties = null)
2624
{
2725
if ($element instanceof Undefined) {
2826
return;
@@ -35,7 +33,7 @@ function check(
3533

3634
if ($definition) {
3735
// validate the definition properties
38-
$this->validateDefinition($element, $definition, $requiredProp, $path);
36+
$this->validateDefinition($element, $definition, $path);
3937
}
4038

4139
// additional the element properties
@@ -108,24 +106,15 @@ public function validateElement($element, $matches, $objectDefinition = null, $p
108106
*
109107
* @param \stdClass $element Element to validate
110108
* @param \stdClass $objectDefinition Object definition
111-
* @param array $requiredProp Required properties
112109
* @param string $path Path?
113110
*/
114-
public function validateDefinition($element, $objectDefinition = null, $requiredProp = null, $path = null)
111+
public function validateDefinition($element, $objectDefinition = null, $path = null)
115112
{
116113
foreach ($objectDefinition as $i => $value) {
117114
$property = $this->getProperty($element, $i, new Undefined());
118115
$definition = $this->getProperty($objectDefinition, $i);
119116
$this->checkUndefined($property, $definition, $path, $i);
120117
}
121-
122-
if ($requiredProp) {
123-
foreach ($requiredProp as $required) {
124-
if (!$this->getProperty($element, $required)) {
125-
$this->addError($path, "the property " . $required . " is required");
126-
}
127-
}
128-
}
129118
}
130119

131120
/**

src/JsonSchema/Constraints/Undefined.php

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ public function check($value, $schema = null, $path = null, $i = null)
4040
/**
4141
* Validates the value against the types
4242
*
43-
* @param $value
44-
* @param null $schema
45-
* @param null $path
46-
* @param null $i
43+
* @param mixed $value
44+
* @param \stdClass $schema
45+
* @param string $path
46+
* @param string $i
4747
*/
4848
public function validateTypes($value, $schema = null, $path = null, $i = null)
4949
{
@@ -59,8 +59,7 @@ public function validateTypes($value, $schema = null, $path = null, $i = null)
5959
isset($schema->properties) ? $schema->properties : null,
6060
$path,
6161
isset($schema->additionalProperties) ? $schema->additionalProperties : null,
62-
isset($schema->patternProperties) ? $schema->patternProperties : null,
63-
isset($schema->required) ? $schema->required : null
62+
isset($schema->patternProperties) ? $schema->patternProperties : null
6463
);
6564
}
6665

@@ -83,10 +82,10 @@ public function validateTypes($value, $schema = null, $path = null, $i = null)
8382
/**
8483
* Validates common properties
8584
*
86-
* @param $value
87-
* @param null $schema
88-
* @param null $path
89-
* @param null $i
85+
* @param mixed $value
86+
* @param \stdClass $schema
87+
* @param string $path
88+
* @param string $i
9089
*/
9190
protected function validateCommonProperties($value, $schema = null, $path = null, $i = null)
9291
{
@@ -99,9 +98,21 @@ protected function validateCommonProperties($value, $schema = null, $path = null
9998
}
10099

101100
// Verify required values
102-
if (is_object($value) && $value instanceof Undefined) {
103-
if (isset($schema->required) && $schema->required) {
104-
$this->addError($path, "is missing and it is required");
101+
if (is_object($value)) {
102+
if ($value instanceof Undefined) {
103+
// Draft 3 - Required attribute - e.g. "foo": {"type": "string", "required": true}
104+
if (isset($schema->required) && $schema->required) {
105+
$this->addError($path, "is missing and it is required");
106+
}
107+
} else if (isset($schema->required)) {
108+
// Draft 4 - Required is an array of strings - e.g. "required": ["foo", ...]
109+
foreach ($schema->required as $required) {
110+
if (!property_exists($value, $required)) {
111+
$this->addError($path, "the property " . $required . " is required");
112+
}
113+
}
114+
} else {
115+
$this->checkType($value, $schema, $path);
105116
}
106117
} else {
107118
$this->checkType($value, $schema, $path);
@@ -122,6 +133,40 @@ protected function validateCommonProperties($value, $schema = null, $path = null
122133
$this->errors = $initErrors;
123134
}
124135
}
136+
137+
// Verify that dependencies are met
138+
if (is_object($value) && isset($schema->dependencies)) {
139+
$this->validateDependencies($value, $schema->dependencies, $path);
140+
}
141+
}
142+
143+
/**
144+
* @param \stdClass $value Element to validate
145+
* @param mixed $dependencies Dependencies
146+
* @param string $path Path?
147+
*/
148+
protected function validateDependencies($value, $dependencies, $path)
149+
{
150+
foreach ($dependencies as $key => $dependency) {
151+
if (property_exists($value, $key)) {
152+
if (is_string($dependency)) {
153+
// Draft 3 string is allowed - e.g. "dependencies": "foo"
154+
if (!property_exists($value, $dependency)) {
155+
$this->addError($path, "$key depends on $dependency and $dependency is missing");
156+
}
157+
} else if (is_array($dependency)) {
158+
// Draft 4 doesn't allow string so must be an array - e.g. "dependencies": ["foo"]
159+
foreach ($dependency as $d) {
160+
if (!property_exists($value, $d)) {
161+
$this->addError($path, "$key depends on $d and $d is missing");
162+
}
163+
}
164+
} else if (is_object($dependency)) {
165+
// The dependency is a schema - e.g. "dependencies": {"properties": {"foo": {...}}}
166+
$this->checkUndefined($value, $dependency, $path, "");
167+
}
168+
}
169+
}
125170
}
126171

127172
protected function validateUri($schemaUri = null, $schema, $path = null, $i = null)
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
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\Tests\Constraints;
11+
12+
class DependenciesTest extends BaseTestCase
13+
{
14+
public function getInvalidTests()
15+
{
16+
return array(
17+
array(
18+
'{"bar": 1}',
19+
'{
20+
"dependencies": {"bar": "foo"}
21+
}'
22+
),
23+
array(
24+
'{"bar": 1}',
25+
'{
26+
"dependencies": {"bar": ["foo"]}
27+
}'
28+
),
29+
array(
30+
'{"bar": 1, "foo": 1}',
31+
'{
32+
"dependencies": {"bar": ["foo", "baz"]}
33+
}'
34+
),
35+
array(
36+
'{"bar": 1, "foo": 1}',
37+
'{
38+
"dependencies": {"bar": {
39+
"properties": {
40+
"foo": {"type": "string"}
41+
}
42+
}}
43+
}'
44+
),
45+
array(
46+
'{"bar": 1}',
47+
'{
48+
"dependencies": {"bar": {
49+
"properties": {
50+
"foo": {"type": "integer", "required": true}
51+
}
52+
}}
53+
}'
54+
),
55+
array(
56+
'{"bar": 1}',
57+
'{
58+
"dependencies": {"bar": {
59+
"properties": {
60+
"foo": {"type": "integer"}
61+
},
62+
"required": ["foo"]
63+
}}
64+
}'
65+
),
66+
array(
67+
'{"bar": true, "foo": "ick"}',
68+
'{
69+
"dependencies": {"bar": {
70+
"properties": {
71+
"bar": {"type": "integer"},
72+
"foo": {"type": "integer"}
73+
}
74+
}}
75+
}'
76+
)
77+
);
78+
}
79+
80+
public function getValidTests()
81+
{
82+
return array(
83+
array(
84+
'{}',
85+
'{
86+
"dependencies": {"bar": "foo"}
87+
}'
88+
),
89+
array(
90+
'{"foo": 1}',
91+
'{
92+
"dependencies": {"bar": "foo"}
93+
}'
94+
),
95+
array(
96+
'"foo"',
97+
'{
98+
"dependencies": {"bar": "foo"}
99+
}'
100+
),
101+
array(
102+
'{"bar": 1, "foo": 1}',
103+
'{
104+
"dependencies": {"bar": "foo"}
105+
}'
106+
),
107+
array(
108+
'{"bar": 1, "foo": 1, "baz": 1}',
109+
'{
110+
"dependencies": {"bar": ["foo", "baz"]}
111+
}'
112+
),
113+
array(
114+
'{}',
115+
'{
116+
"dependencies": {"bar": ["foo", "baz"]}
117+
}'
118+
),
119+
array(
120+
'{"foo": 1, "baz": 1}',
121+
'{
122+
"dependencies": {"bar": ["foo", "baz"]}
123+
}'
124+
),
125+
array(
126+
'{"bar": 1}',
127+
'{
128+
"dependencies": {"bar": {
129+
"properties": {
130+
"foo": {"type": "integer"}
131+
}
132+
}}
133+
}'
134+
),
135+
array(
136+
'{"bar": 1, "foo": 1}',
137+
'{
138+
"dependencies": {"bar": {
139+
"properties": {
140+
"bar": {"type": "integer"},
141+
"foo": {"type": "integer"}
142+
}
143+
}}
144+
}'
145+
)
146+
);
147+
}
148+
}

tests/JsonSchema/Tests/Constraints/RequiredPropertyTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ public function getInvalidTests()
6262
},
6363
"required": ["bar"]
6464
}'
65+
),
66+
array(
67+
'{}',
68+
'{
69+
"required": ["foo"]
70+
}'
6571
)
6672
);
6773
}

0 commit comments

Comments
 (0)