@@ -24,7 +24,9 @@ function __autoload($className)
24
24
$ fileName = str_replace ('\\' , DIRECTORY_SEPARATOR , $ namespace ) . DIRECTORY_SEPARATOR ;
25
25
}
26
26
$ fileName .= str_replace ('_ ' , DIRECTORY_SEPARATOR , $ className ) . '.php ' ;
27
- require_once $ fileName ;
27
+ if (stream_resolve_include_path ($ fileName )) {
28
+ require_once $ fileName ;
29
+ }
28
30
}
29
31
30
32
/**
@@ -45,55 +47,198 @@ function showJsonError()
45
47
echo 'JSON parse error: ' . $ json_errors [json_last_error ()] . "\n" ;
46
48
}
47
49
50
+ function getUrlFromPath ($ path )
51
+ {
52
+ if (parse_url ($ path , PHP_URL_SCHEME ) !== null ) {
53
+ //already an URL
54
+ return $ path ;
55
+ }
56
+ if ($ path {0 } == '/ ' ) {
57
+ //absolute path
58
+ return 'file:// ' . $ path ;
59
+ }
60
+
61
+ //relative path: make absolute
62
+ return 'file:// ' . getcwd () . '/ ' . $ path ;
63
+ }
64
+
65
+ /**
66
+ * Take a HTTP header value and split it up into parts.
67
+ *
68
+ * @return array Key "_value" contains the main value, all others
69
+ * as given in the header value
70
+ */
71
+ function parseHeaderValue ($ headerValue )
72
+ {
73
+ if (strpos ($ headerValue , '; ' ) === false ) {
74
+ return array ('_value ' => $ headerValue );
75
+ }
76
+
77
+ $ parts = explode ('; ' , $ headerValue );
78
+ $ arData = array ('_value ' => array_shift ($ parts ));
79
+ foreach ($ parts as $ part ) {
80
+ list ($ name , $ value ) = explode ('= ' , $ part );
81
+ $ arData [$ name ] = trim ($ value , ' " \'' );
82
+ }
83
+ return $ arData ;
84
+ }
85
+
48
86
49
87
// support running this tool from git checkout
50
88
if (is_dir (__DIR__ . '/../src/JsonSchema ' )) {
51
89
set_include_path (__DIR__ . '/../src ' . PATH_SEPARATOR . get_include_path ());
52
90
}
53
91
54
- if ($ argc < 3 ) {
55
- echo "Usage: validate-json schema.json data.json \n" ;
56
- exit (1 );
92
+ $ arOptions = array ();
93
+ $ arArgs = array ();
94
+ array_shift ($ argv );//script itself
95
+ foreach ($ argv as $ arg ) {
96
+ if ($ arg {0 } == '- ' ) {
97
+ $ arOptions [$ arg ] = true ;
98
+ } else {
99
+ $ arArgs [] = $ arg ;
100
+ }
57
101
}
58
102
59
- $ pathSchema = $ argv [1 ];
60
- $ pathData = $ argv [2 ];
103
+ if (count ($ arArgs ) == 0
104
+ || isset ($ arOptions ['--help ' ]) || isset ($ arOptions ['-h ' ])
105
+ ) {
106
+ echo <<<HLP
107
+ Validate schema
108
+ Usage: validate-json data.json
109
+ or: validate-json data.json schema.json
61
110
62
- if (!is_readable ($ pathSchema )) {
63
- echo "Schema file is not readable. \n" ;
64
- exit (2 );
111
+ Options:
112
+ --dump-schema Output full schema and exit
113
+ --dump-schema-url Output URL of schema
114
+ -h --help Show this help
115
+
116
+ HLP ;
117
+ exit (1 );
65
118
}
66
119
67
- if (!is_readable ($ pathData )) {
68
- echo "Data file is not readable. \n" ;
69
- exit (3 );
120
+ if (count ($ arArgs ) == 1 ) {
121
+ $ pathData = $ arArgs [0 ];
122
+ $ pathSchema = null ;
123
+ } else {
124
+ $ pathData = $ arArgs [0 ];
125
+ $ pathSchema = getUrlFromPath ($ arArgs [1 ]);
70
126
}
71
127
72
- $ data = json_decode (file_get_contents ($ pathData ));
128
+ $ urlData = getUrlFromPath ($ pathData );
129
+
130
+ $ context = stream_context_create (
131
+ array (
132
+ 'http ' => array (
133
+ 'header ' => array (
134
+ 'Accept: */* ' ,
135
+ 'Connection: Close '
136
+ ),
137
+ 'max_redirects ' => 5
138
+ )
139
+ )
140
+ );
141
+ $ dataString = file_get_contents ($ pathData , false , $ context );
142
+ if ($ dataString == '' ) {
143
+ echo "Data file is not readable or empty. \n" ;
144
+ exit (3 );
145
+ }
73
146
147
+ $ data = json_decode ($ dataString );
148
+ unset($ dataString );
74
149
if ($ data === null ) {
75
150
echo "Error loading JSON data file \n" ;
76
151
showJsonError ();
77
152
exit (5 );
78
153
}
79
154
80
- $ schema = json_decode (file_get_contents ($ pathSchema ));
155
+ if ($ pathSchema === null ) {
156
+ if (isset ($ http_response_header )) {
157
+ array_shift ($ http_response_header );//HTTP/1.0 line
158
+ foreach ($ http_response_header as $ headerLine ) {
159
+ list ($ hName , $ hValue ) = explode (': ' , $ headerLine , 2 );
160
+ $ hName = strtolower ($ hName );
161
+ if ($ hName == 'link ' ) {
162
+ //Link: <http://example.org/schema#>; rel="describedBy"
163
+ $ hParts = parseHeaderValue ($ hValue );
164
+ if (isset ($ hParts ['rel ' ]) && $ hParts ['rel ' ] == 'describedBy ' ) {
165
+ $ pathSchema = trim ($ hParts ['_value ' ], ' <> ' );
166
+ }
167
+ } else if ($ hName == 'content-type ' ) {
168
+ //Content-Type: application/my-media-type+json;
169
+ // profile=http://example.org/schema#
170
+ $ hParts = parseHeaderValue ($ hValue );
171
+ if (isset ($ hParts ['profile ' ])) {
172
+ $ pathSchema = $ hParts ['profile ' ];
173
+ }
174
+
175
+ }
176
+ }
177
+ }
178
+ if (is_object ($ data ) && property_exists ($ data , '$schema ' )) {
179
+ $ pathSchema = $ data ->{'$schema ' };
180
+ }
181
+
182
+ //autodetect schema
183
+ if ($ pathSchema === null ) {
184
+ echo "JSON data must be an object and have a \$schema property. \n" ;
185
+ echo "You can pass the schema file on the command line as well. \n" ;
186
+ echo "Schema autodetection failed. \n" ;
187
+ exit (6 );
188
+ }
189
+ }
190
+ if ($ pathSchema {0 } == '/ ' ) {
191
+ $ pathSchema = 'file:// ' . $ pathSchema ;
192
+ }
193
+
194
+ $ resolver = new JsonSchema \Uri \UriResolver ();
195
+ $ retriever = new JsonSchema \Uri \UriRetriever ();
196
+ try {
197
+ $ urlSchema = $ resolver ->resolve ($ pathSchema , $ urlData );
198
+
199
+ if (isset ($ arOptions ['--dump-schema-url ' ])) {
200
+ echo $ urlSchema . "\n" ;
201
+ exit ();
202
+ }
81
203
82
- if ($ schema === null ) {
204
+ $ schema = $ retriever ->retrieve ($ urlSchema );
205
+ if ($ schema === null ) {
206
+ echo "Error loading JSON schema file \n" ;
207
+ echo $ urlSchema . "\n" ;
208
+ showJsonError ();
209
+ exit (2 );
210
+ }
211
+ } catch (Exception $ e ) {
83
212
echo "Error loading JSON schema file \n" ;
84
- showJsonError ();
85
- exit (6 );
213
+ echo $ urlSchema . "\n" ;
214
+ echo $ e ->getMessage () . "\n" ;
215
+ exit (2 );
86
216
}
217
+ $ refResolver = new JsonSchema \RefResolver ($ retriever );
218
+ $ refResolver ->resolve ($ schema , $ urlSchema );
87
219
88
- $ validator = new JsonSchema \Validator ();
89
- $ validator ->check ($ data , $ schema );
220
+ if (isset ($ arOptions ['--dump-schema ' ])) {
221
+ echo json_encode ($ schema , JSON_PRETTY_PRINT ) . "\n" ;
222
+ exit ();
223
+ }
90
224
91
- if ($ validator ->isValid ()) {
92
- echo "OK. The supplied JSON validates against the schema. \n" ;
93
- } else {
94
- echo "JSON does not validate. Violations: \n" ;
95
- foreach ($ validator ->getErrors () as $ error ) {
96
- echo sprintf ("[%s] %s \n" , $ error ['property ' ], $ error ['message ' ]);
225
+ try {
226
+ $ validator = new JsonSchema \Validator ();
227
+ $ validator ->check ($ data , $ schema );
228
+
229
+ if ($ validator ->isValid ()) {
230
+ echo "OK. The supplied JSON validates against the schema. \n" ;
231
+ } else {
232
+ echo "JSON does not validate. Violations: \n" ;
233
+ foreach ($ validator ->getErrors () as $ error ) {
234
+ echo sprintf ("[%s] %s \n" , $ error ['property ' ], $ error ['message ' ]);
235
+ }
236
+ exit (23 );
97
237
}
98
- exit (23 );
238
+ } catch (Exception $ e ) {
239
+ echo "JSON does not validate. Error: \n" ;
240
+ echo $ e ->getMessage () . "\n" ;
241
+ echo "Error code: " . $ e ->getCode () . "\n" ;
242
+ exit (24 );
99
243
}
244
+ ?>
0 commit comments