Skip to content

Commit e3c9bcc

Browse files
eraydbighappyface
authored andcommitted
Backports for 5.2.0 (#368)
* Add URI translation for retrieval & add local copies of spec schema * Add use line for InvalidArgumentException & adjust scope (#372) Fixes issue #371 * add quiet option (#382) * add quiet option * use verbose instead of quiet * add quiet option * always output dump-schema * always output dump-schema-url * fix typo and ws * [BUGFIX] Add provided schema under a dummy / internal URI (fixes #376) (#378) * Add provided schema under a dummy / internal URI (fixes #376) In order to resolve internal $ref references within a user-provided schema, SchemaStorage needs to know about the schema. As user-supplied schemas do not have an associated URI, use a dummy / internal one instead. * Remove dangling use * Change URI to class constant on SchemaStorage * Add option to disable validation of "format" constraint (#383) * Add more unit tests (#366) * Add test coverage for coercion API * Complete test coverage for SchemaStorage * Add test coverage for ObjectIterator * Add exception test for JsonPointer * MabeEnum\Enum appears to use singletons - add testing const * Don't check this line for coverage mbstring is on all test platforms, so this line will never be reached. * Add test for TypeConstraint::validateTypeNameWording() * Add test for exception on TypeConstraint::validateType() * PHPunit doesn't like an explanation with its @codeCoverageIgnore... * Add various tests for UriRetriever * Add tests for FileGetContents * Add tests for JsonSchema\Uri\Retrievers\Curl * Add missing bad-syntax test file * Restrict ignore to the exception line only * Fix exception scope * Allow the schema to be an associative array (#389) * Allow the schema to be an associative array Implements #388. * Use json_decode(json_encode()) for array -> object cast * Skip exception check on PHP versions < 5.5.0 * Skip test on HHVM, as it's happy to encode resources * Enable FILTER_FLAG_EMAIL_UNICODE for email format if present (#398) * Don't throw exceptions until after checking anyOf / oneOf (#394) Fixes #393 * Fix infinite recursion on some schemas when setting defaults (#359) (#365) * Don't try to fetch files that don't exist Throws an exception when the ref can't be resolved to a useful file URI, rather than waiting for something further down the line to fail after the fact. * Refactor defaults code to use LooseTypeCheck where appropriate * Test for not treating non-containers like arrays * Update comments * Rename variable for clarity * Add CHECK_MODE_ONLY_REQUIRED_DEFAULTS If CHECK_MODE_ONLY_REQUIRED_DEFAULTS is set, then only apply defaults if they are marked as required. * Workaround for $this scope issue on PHP-5.3 * Fix infinite recursion via $ref when applying defaults * Add missing second test for array case * Add test for setting a default value for null * Also fix infinite recursion via $ref for array defaults * Move nested closure into separate method * $parentSchema will always be set when $name is, so don't check it * Handle nulls properly - fixes issue #377 * Add option to also validate the schema (#357) * Remove stale files from #357 (obviated by #362) (#400) * Stop #386 sneaking in alongside another PR backport
1 parent ef3ee83 commit e3c9bcc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+1742
-601
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,10 @@ third argument to `Validator::validate()`, or can be provided as the third argum
187187
| `Constraint::CHECK_MODE_TYPE_CAST` | Enable fuzzy type checking for associative arrays and objects |
188188
| `Constraint::CHECK_MODE_COERCE_TYPES` | Convert data types to match the schema where possible |
189189
| `Constraint::CHECK_MODE_APPLY_DEFAULTS` | Apply default values from the schema if not set |
190+
| `Constraint::CHECK_MODE_ONLY_REQUIRED_DEFAULTS` | When applying defaults, only set values that are required |
190191
| `Constraint::CHECK_MODE_EXCEPTIONS` | Throw an exception immediately if validation fails |
192+
| `Constraint::CHECK_MODE_DISABLE_FORMAT` | Do not validate "format" constraints |
193+
| `Constraint::CHECK_MODE_VALIDATE_SCHEMA` | Validate the schema as well as the provided document |
191194

192195
Please note that using `Constraint::CHECK_MODE_COERCE_TYPES` or `Constraint::CHECK_MODE_APPLY_DEFAULTS`
193196
will modify your original data.

bin/validate-json

+69-55
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ function __autoload($className)
1717
{
1818
$className = ltrim($className, '\\');
1919
$fileName = '';
20-
$namespace = '';
2120
if ($lastNsPos = strrpos($className, '\\')) {
2221
$namespace = substr($className, 0, $lastNsPos);
2322
$className = substr($className, $lastNsPos + 1);
@@ -29,6 +28,49 @@ function __autoload($className)
2928
}
3029
}
3130

31+
// support running this tool from git checkout
32+
if (is_dir(__DIR__ . '/../src/JsonSchema')) {
33+
set_include_path(__DIR__ . '/../src' . PATH_SEPARATOR . get_include_path());
34+
}
35+
36+
$arOptions = array();
37+
$arArgs = array();
38+
array_shift($argv);//script itself
39+
foreach ($argv as $arg) {
40+
if ($arg{0} == '-') {
41+
$arOptions[$arg] = true;
42+
} else {
43+
$arArgs[] = $arg;
44+
}
45+
}
46+
47+
if (count($arArgs) == 0
48+
|| isset($arOptions['--help']) || isset($arOptions['-h'])
49+
) {
50+
echo <<<HLP
51+
Validate schema
52+
Usage: validate-json data.json
53+
or: validate-json data.json schema.json
54+
55+
Options:
56+
--dump-schema Output full schema and exit
57+
--dump-schema-url Output URL of schema
58+
--verbose Show additional output
59+
--quiet Suppress all output
60+
-h --help Show this help
61+
62+
HLP;
63+
exit(1);
64+
}
65+
66+
if (count($arArgs) == 1) {
67+
$pathData = $arArgs[0];
68+
$pathSchema = null;
69+
} else {
70+
$pathData = $arArgs[0];
71+
$pathSchema = getUrlFromPath($arArgs[1]);
72+
}
73+
3274
/**
3375
* Show the json parse error that happened last
3476
*
@@ -44,7 +86,7 @@ function showJsonError()
4486
}
4587
}
4688

47-
echo 'JSON parse error: ' . $json_errors[json_last_error()] . "\n";
89+
output('JSON parse error: ' . $json_errors[json_last_error()] . "\n");
4890
}
4991

5092
function getUrlFromPath($path)
@@ -84,48 +126,18 @@ function parseHeaderValue($headerValue)
84126
return $arData;
85127
}
86128

87-
88-
// support running this tool from git checkout
89-
if (is_dir(__DIR__ . '/../src/JsonSchema')) {
90-
set_include_path(__DIR__ . '/../src' . PATH_SEPARATOR . get_include_path());
91-
}
92-
93-
$arOptions = array();
94-
$arArgs = array();
95-
array_shift($argv);//script itself
96-
foreach ($argv as $arg) {
97-
if ($arg{0} == '-') {
98-
$arOptions[$arg] = true;
99-
} else {
100-
$arArgs[] = $arg;
129+
/**
130+
* Send a string to the output stream, but only if --quiet is not enabled
131+
*
132+
* @param $str A string output
133+
*/
134+
function output($str) {
135+
global $arOptions;
136+
if (!isset($arOptions['--quiet'])) {
137+
echo $str;
101138
}
102139
}
103140

104-
if (count($arArgs) == 0
105-
|| isset($arOptions['--help']) || isset($arOptions['-h'])
106-
) {
107-
echo <<<HLP
108-
Validate schema
109-
Usage: validate-json data.json
110-
or: validate-json data.json schema.json
111-
112-
Options:
113-
--dump-schema Output full schema and exit
114-
--dump-schema-url Output URL of schema
115-
-h --help Show this help
116-
117-
HLP;
118-
exit(1);
119-
}
120-
121-
if (count($arArgs) == 1) {
122-
$pathData = $arArgs[0];
123-
$pathSchema = null;
124-
} else {
125-
$pathData = $arArgs[0];
126-
$pathSchema = getUrlFromPath($arArgs[1]);
127-
}
128-
129141
$urlData = getUrlFromPath($pathData);
130142

131143
$context = stream_context_create(
@@ -141,14 +153,14 @@ $context = stream_context_create(
141153
);
142154
$dataString = file_get_contents($pathData, false, $context);
143155
if ($dataString == '') {
144-
echo "Data file is not readable or empty.\n";
156+
output("Data file is not readable or empty.\n");
145157
exit(3);
146158
}
147159

148160
$data = json_decode($dataString);
149161
unset($dataString);
150162
if ($data === null) {
151-
echo "Error loading JSON data file\n";
163+
output("Error loading JSON data file\n");
152164
showJsonError();
153165
exit(5);
154166
}
@@ -182,9 +194,9 @@ if ($pathSchema === null) {
182194

183195
//autodetect schema
184196
if ($pathSchema === null) {
185-
echo "JSON data must be an object and have a \$schema property.\n";
186-
echo "You can pass the schema file on the command line as well.\n";
187-
echo "Schema autodetection failed.\n";
197+
output("JSON data must be an object and have a \$schema property.\n");
198+
output("You can pass the schema file on the command line as well.\n");
199+
output("Schema autodetection failed.\n");
188200
exit(6);
189201
}
190202
}
@@ -202,9 +214,9 @@ try {
202214
exit();
203215
}
204216
} catch (Exception $e) {
205-
echo "Error loading JSON schema file\n";
206-
echo $urlSchema . "\n";
207-
echo $e->getMessage() . "\n";
217+
output("Error loading JSON schema file\n");
218+
output($urlSchema . "\n");
219+
output($e->getMessage() . "\n");
208220
exit(2);
209221
}
210222
$refResolver = new JsonSchema\SchemaStorage($retriever, $resolver);
@@ -221,17 +233,19 @@ try {
221233
$validator->check($data, $schema);
222234

223235
if ($validator->isValid()) {
224-
echo "OK. The supplied JSON validates against the schema.\n";
236+
if(isset($arOptions['--verbose'])) {
237+
output("OK. The supplied JSON validates against the schema.\n");
238+
}
225239
} else {
226-
echo "JSON does not validate. Violations:\n";
240+
output("JSON does not validate. Violations:\n");
227241
foreach ($validator->getErrors() as $error) {
228-
echo sprintf("[%s] %s\n", $error['property'], $error['message']);
242+
output(sprintf("[%s] %s\n", $error['property'], $error['message']));
229243
}
230244
exit(23);
231245
}
232246
} catch (Exception $e) {
233-
echo "JSON does not validate. Error:\n";
234-
echo $e->getMessage() . "\n";
235-
echo "Error code: " . $e->getCode() . "\n";
247+
output("JSON does not validate. Error:\n");
248+
output($e->getMessage() . "\n");
249+
output("Error code: " . $e->getCode() . "\n");
236250
exit(24);
237251
}

dist/schema/json-schema-draft-03.json

+174
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-03/schema#",
3+
"id": "http://json-schema.org/draft-03/schema#",
4+
"type": "object",
5+
6+
"properties": {
7+
"type": {
8+
"type": [ "string", "array" ],
9+
"items": {
10+
"type": [ "string", { "$ref": "#" } ]
11+
},
12+
"uniqueItems": true,
13+
"default": "any"
14+
},
15+
16+
"properties": {
17+
"type": "object",
18+
"additionalProperties": { "$ref": "#" },
19+
"default": {}
20+
},
21+
22+
"patternProperties": {
23+
"type": "object",
24+
"additionalProperties": { "$ref": "#" },
25+
"default": {}
26+
},
27+
28+
"additionalProperties": {
29+
"type": [ { "$ref": "#" }, "boolean" ],
30+
"default": {}
31+
},
32+
33+
"items": {
34+
"type": [ { "$ref": "#" }, "array" ],
35+
"items": { "$ref": "#" },
36+
"default": {}
37+
},
38+
39+
"additionalItems": {
40+
"type": [ { "$ref": "#" }, "boolean" ],
41+
"default": {}
42+
},
43+
44+
"required": {
45+
"type": "boolean",
46+
"default": false
47+
},
48+
49+
"dependencies": {
50+
"type": "object",
51+
"additionalProperties": {
52+
"type": [ "string", "array", { "$ref": "#" } ],
53+
"items": {
54+
"type": "string"
55+
}
56+
},
57+
"default": {}
58+
},
59+
60+
"minimum": {
61+
"type": "number"
62+
},
63+
64+
"maximum": {
65+
"type": "number"
66+
},
67+
68+
"exclusiveMinimum": {
69+
"type": "boolean",
70+
"default": false
71+
},
72+
73+
"exclusiveMaximum": {
74+
"type": "boolean",
75+
"default": false
76+
},
77+
78+
"minItems": {
79+
"type": "integer",
80+
"minimum": 0,
81+
"default": 0
82+
},
83+
84+
"maxItems": {
85+
"type": "integer",
86+
"minimum": 0
87+
},
88+
89+
"uniqueItems": {
90+
"type": "boolean",
91+
"default": false
92+
},
93+
94+
"pattern": {
95+
"type": "string",
96+
"format": "regex"
97+
},
98+
99+
"minLength": {
100+
"type": "integer",
101+
"minimum": 0,
102+
"default": 0
103+
},
104+
105+
"maxLength": {
106+
"type": "integer"
107+
},
108+
109+
"enum": {
110+
"type": "array",
111+
"minItems": 1,
112+
"uniqueItems": true
113+
},
114+
115+
"default": {
116+
"type": "any"
117+
},
118+
119+
"title": {
120+
"type": "string"
121+
},
122+
123+
"description": {
124+
"type": "string"
125+
},
126+
127+
"format": {
128+
"type": "string"
129+
},
130+
131+
"divisibleBy": {
132+
"type": "number",
133+
"minimum": 0,
134+
"exclusiveMinimum": true,
135+
"default": 1
136+
},
137+
138+
"disallow": {
139+
"type": [ "string", "array" ],
140+
"items": {
141+
"type": [ "string", { "$ref": "#" } ]
142+
},
143+
"uniqueItems": true
144+
},
145+
146+
"extends": {
147+
"type": [ { "$ref": "#" }, "array" ],
148+
"items": { "$ref": "#" },
149+
"default": {}
150+
},
151+
152+
"id": {
153+
"type": "string",
154+
"format": "uri"
155+
},
156+
157+
"$ref": {
158+
"type": "string",
159+
"format": "uri"
160+
},
161+
162+
"$schema": {
163+
"type": "string",
164+
"format": "uri"
165+
}
166+
},
167+
168+
"dependencies": {
169+
"exclusiveMinimum": "minimum",
170+
"exclusiveMaximum": "maximum"
171+
},
172+
173+
"default": {}
174+
}

0 commit comments

Comments
 (0)