Skip to content

Commit 05ff6d8

Browse files
committed
Merge pull request #3 from digitalkaoz/refactoring
cleanup, refactoring, splitted validators, tweaks
2 parents 81532ea + d646610 commit 05ff6d8

25 files changed

+975
-450
lines changed

README.md

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,44 @@
1-
# JSON Schema for PHP [![Build status...](https://secure.travis-ci.org/justinrainbow/json-schema.png)](http://travis-ci.org/justinrainbow/json-schema)
1+
# JSON Schema for PHP [![Build Status](https://secure.travis-ci.org/justinrainbow/json-schema.png)](http://travis-ci.org/justinrainbow/json-schema)
22

3-
Documentation can be found at http://jsonschema.readthedocs.org/
3+
A PHP Implementation for validating `JSON` Structures against a given `Schema`.
4+
5+
See [json-schema](http://json-schema.org/) for more details.
6+
7+
## Installation
8+
9+
### Library
10+
11+
$ git clone https://github.com/justinrainbow/json-schema.git
12+
13+
### Dependencies
14+
15+
#### via `submodules` (*will use the Symfony ClassLoader Component*)
16+
17+
$ git submodule update --init
18+
19+
#### via [`composer`](https://github.com/composer/composer) (*will use the Composer ClassLoader*)
20+
21+
$ wget http://getcomposer.org/composer.phar
22+
$ php composer.phar install
423

524
## Usage
625

726
```php
827
<?php
928

1029
$validator = new JsonSchema\Validator();
11-
$result = $validator->validate(json_decode($json), json_decode($schema));
30+
$validator->check(json_decode($json), json_decode($schema));
1231

13-
if ($result->valid) {
32+
if ($validator->isValid()) {
1433
echo "The supplied JSON validates against the schema.\n";
1534
} else {
1635
echo "JSON does not validate. Violations:\n";
17-
foreach ($result->errors as $error) {
18-
echo "[{$error['property']}] {$error['message']}\n";
36+
foreach ($validator->getErrors() as $error) {
37+
echo sprintf("[%s] %s\n",$error['property'], $error['message']);
1938
}
2039
}
2140
```
2241

2342
## Running the tests
2443

25-
$ git submodule update --init
2644
$ phpunit

composer.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"homepage": "https://github.com/justinrainbow/json-schema",
66
"type": "library",
77
"license": "NewBSD",
8-
"version": "1.0.0",
8+
"version": "1.1.0",
99
"authors": [
1010
{
1111
"name": "Bruno Prieto Reis",
@@ -14,6 +14,14 @@
1414
{
1515
"name": "Justin Rainbow",
1616
"email": "justin.rainbow@gmail.com"
17+
},
18+
{
19+
"name": "Igor Wiedler",
20+
"email": "igor@wiedler.ch"
21+
},
22+
{
23+
"name": "Robert Schönthal",
24+
"email": "seroscho@googlemail.com"
1725
}
1826
],
1927
"require": {

phpunit.xml.dist

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,15 @@
1212
bootstrap="tests/bootstrap.php"
1313
verbose="true"
1414
>
15-
<testsuites>
16-
<testsuite name="JSON Schema Test Suite">
17-
<directory>tests</directory>
18-
</testsuite>
19-
</testsuites>
15+
<testsuites>
16+
<testsuite name="JSON Schema Test Suite">
17+
<directory>tests</directory>
18+
</testsuite>
19+
</testsuites>
20+
21+
<filter>
22+
<whitelist>
23+
<directory>./src/JsonSchema/</directory>
24+
</whitelist>
25+
</filter>
2026
</phpunit>
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
namespace JsonSchema\Constraints;
4+
5+
/**
6+
* The Collection Constraints, validates an array against a given schema
7+
*
8+
* @author Robert Schönthal <seroscho@googlemail.com>
9+
* @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
10+
*/
11+
class Collection extends Constraint
12+
{
13+
/**
14+
* {inheritDoc}
15+
*/
16+
public function check($value, $schema = null, $path = null, $i = null)
17+
{
18+
// verify minItems
19+
if (isset($schema->minItems) && count($value) < $schema->minItems) {
20+
$this->addError($path, "There must be a minimum of " . $schema->minItems . " in the array");
21+
}
22+
// verify maxItems
23+
if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
24+
$this->addError($path, "There must be a maximum of " . $schema->maxItems . " in the array");
25+
}
26+
// verify uniqueItems
27+
//TODO array_unique doesnt work with objects
28+
if (isset($schema->uniqueItems) && array_unique($value) != $value) {
29+
$this->addError($path, "There are no duplicates allowed in the array");
30+
}
31+
32+
//verify items
33+
if (isset($schema->items)) {
34+
$this->validateItems($value, $schema, $path, $i);
35+
}
36+
}
37+
38+
/**
39+
* validates the items
40+
*
41+
* @param array $value
42+
* @param \stdClass $schema
43+
* @param string $path
44+
* @param string $i
45+
*/
46+
protected function validateItems($value, $schema = null, $path = null, $i = null)
47+
{
48+
if (!is_array($schema->items)) {
49+
// just one type definition for the whole array
50+
foreach ($value as $k => $v) {
51+
$initErrors = $this->getErrors();
52+
53+
//first check if its defined in "items"
54+
if (!isset($schema->additionalItems) || $schema->additionalItems === false) {
55+
$this->checkUndefined($v, $schema->items, $path, $k);
56+
}
57+
58+
//recheck with "additionalItems" if the first test fails
59+
if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) {
60+
$secondErrors = $this->getErrors();
61+
$this->checkUndefined($v, $schema->additionalItems, $path, $k);
62+
}
63+
64+
//reset errors if needed
65+
if (isset($secondErrors) && count($secondErrors) < $this->getErrors()) {
66+
$this->errors = $secondErrors;
67+
} elseif (isset($secondErrors) && count($secondErrors) == count($this->getErrors())) {
68+
$this->errors = $initErrors;
69+
}
70+
}
71+
} else {
72+
//defined item type definitions
73+
foreach ($value as $k => $v) {
74+
if (array_key_exists($k, $schema->items)) {
75+
$this->checkUndefined($v, $schema->items[$k], $path, $k);
76+
} else {
77+
// additional items
78+
if (array_key_exists('additionalItems', $schema) && $schema->additionalItems !== false) {
79+
$this->checkUndefined($v, $schema->additionalItems, $path, $k);
80+
} else {
81+
$this->addError(
82+
$path,
83+
'The item ' . $i . '[' . $k . '] is not defined in the objTypeDef and the objTypeDef does not allow additional properties'
84+
);
85+
}
86+
}
87+
}
88+
89+
// treat when we have more schema definitions than values
90+
for ($k = count($value); $k < count($schema->items); $k++) {
91+
$this->checkUndefined(new Undefined(), $schema->items[$k], $path, $k);
92+
}
93+
}
94+
}
95+
}
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
<?php
2+
3+
namespace JsonSchema\Constraints;
4+
5+
/**
6+
* The Base Constraints, all Validators should extend this class
7+
*
8+
* @author Robert Schönthal <seroscho@googlemail.com>
9+
* @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
10+
*/
11+
abstract class Constraint implements ConstraintInterface
12+
{
13+
protected $checkMode = self::CHECK_MODE_NORMAL;
14+
protected $errors = array();
15+
protected $inlineSchemaProperty = '$schema';
16+
17+
const CHECK_MODE_NORMAL = 1;
18+
const CHECK_MODE_TYPE_CAST = 2;
19+
20+
/**
21+
* @param int $checkMode
22+
*/
23+
public function __construct($checkMode = self::CHECK_MODE_NORMAL)
24+
{
25+
$this->checkMode = $checkMode;
26+
}
27+
28+
/**
29+
* {inheritDoc}
30+
*/
31+
public function addError($path, $message)
32+
{
33+
$this->errors[] = array(
34+
'property' => $path,
35+
'message' => $message
36+
);
37+
}
38+
39+
/**
40+
* {inheritDoc}
41+
*/
42+
public function addErrors(array $errors)
43+
{
44+
$this->errors = array_merge($this->errors, $errors);
45+
}
46+
47+
/**
48+
* {inheritDoc}
49+
*/
50+
public function getErrors()
51+
{
52+
return array_unique($this->errors, SORT_REGULAR);
53+
}
54+
55+
/**
56+
* bubble down the path
57+
*
58+
* @param string $path
59+
* @param mixed $i
60+
* @return string
61+
*/
62+
protected function incrementPath($path, $i)
63+
{
64+
if ($path !== '') {
65+
if (is_int($i)) {
66+
$path .= '[' . $i . ']';
67+
} else if ($i == '') {
68+
$path .= '';
69+
} else {
70+
$path .= '.' . $i;
71+
}
72+
} else {
73+
$path = $i;
74+
}
75+
76+
return $path;
77+
}
78+
79+
/**
80+
* validates an array
81+
*
82+
* @param mixed $value
83+
* @param mixed $schema
84+
* @param mixed $path
85+
* @param mixed $i
86+
*/
87+
protected function checkArray($value, $schema = null, $path = null, $i = null)
88+
{
89+
$validator = new Collection($this->checkMode);
90+
$validator->check($value, $schema, $path, $i);
91+
92+
$this->addErrors($validator->getErrors());
93+
}
94+
95+
/**
96+
* validates an object
97+
*
98+
* @param mixed $value
99+
* @param mixed $schema
100+
* @param mixed $path
101+
* @param mixed $i
102+
*/
103+
protected function checkObject($value, $schema = null, $path = null, $i = null)
104+
{
105+
$validator = new Object($this->checkMode);
106+
$validator->check($value, $schema, $path, $i);
107+
108+
$this->addErrors($validator->getErrors());
109+
}
110+
111+
/**
112+
* validates the type of a property
113+
*
114+
* @param mixed $value
115+
* @param mixed $schema
116+
* @param mixed $path
117+
* @param mixed $i
118+
*/
119+
protected function checkType($value, $schema = null, $path = null, $i = null)
120+
{
121+
$validator = new Type($this->checkMode);
122+
$validator->check($value, $schema, $path, $i);
123+
124+
$this->addErrors($validator->getErrors());
125+
}
126+
127+
/**
128+
* checks a undefined element
129+
*
130+
* @param mixed $value
131+
* @param mixed $schema
132+
* @param mixed $path
133+
* @param mixed $i
134+
*/
135+
protected function checkUndefined($value, $schema = null, $path = null, $i = null)
136+
{
137+
$validator = new Undefined($this->checkMode);
138+
$validator->check($value, $schema, $path, $i);
139+
140+
$this->addErrors($validator->getErrors());
141+
}
142+
143+
/**
144+
* checks a string element
145+
*
146+
* @param mixed $value
147+
* @param mixed $schema
148+
* @param mixed $path
149+
* @param mixed $i
150+
*/
151+
protected function checkString($value, $schema = null, $path = null, $i = null)
152+
{
153+
$validator = new String($this->checkMode);
154+
$validator->check($value, $schema, $path, $i);
155+
156+
$this->addErrors($validator->getErrors());
157+
}
158+
159+
/**
160+
* checks a number element
161+
*
162+
* @param mixed $value
163+
* @param mixed $schema
164+
* @param mixed $path
165+
* @param mixed $i
166+
*/
167+
protected function checkNumber($value, $schema = null, $path = null, $i = null)
168+
{
169+
$validator = new Number($this->checkMode);
170+
$validator->check($value, $schema, $path, $i);
171+
172+
$this->addErrors($validator->getErrors());
173+
}
174+
175+
/**
176+
* checks a enum element
177+
*
178+
* @param mixed $value
179+
* @param mixed $schema
180+
* @param mixed $path
181+
* @param mixed $i
182+
*/
183+
protected function checkEnum($value, $schema = null, $path = null, $i = null)
184+
{
185+
$validator = new Enum($this->checkMode);
186+
$validator->check($value, $schema, $path, $i);
187+
188+
$this->addErrors($validator->getErrors());
189+
}
190+
191+
/**
192+
* {inheritDoc}
193+
*/
194+
public function isValid()
195+
{
196+
return !$this->getErrors();
197+
}
198+
}

0 commit comments

Comments
 (0)