@@ -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,79 +47,195 @@ 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 < 2 ) {
55
- echo "Usage: validate-json data.json \n" ;
56
- echo " or: validate-json data.json schema.json \n" ;
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
+ }
101
+ }
102
+
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
110
+
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 ;
57
117
exit (1 );
58
118
}
59
119
60
- if ($ argc == 2 ) {
61
- $ pathData = $ argv [ 1 ];
120
+ if (count ( $ arArgs ) == 1 ) {
121
+ $ pathData = $ arArgs [ 0 ];
62
122
$ pathSchema = null ;
63
123
} else {
64
- $ pathData = $ argv [ 1 ];
65
- $ pathSchema = $ argv [ 2 ];
124
+ $ pathData = $ arArgs [ 0 ];
125
+ $ pathSchema = $ arArgs [ 1 ];
66
126
}
67
127
68
- if (!is_readable ($ pathData )) {
69
- echo "Data file is not readable. \n" ;
128
+ $ urlData = getUrlFromPath ($ pathData );
129
+
130
+ $ context = stream_context_create (
131
+ array (
132
+ 'http ' => array (
133
+ 'header ' => 'Accept: */* ' ,
134
+ 'max_redirects ' => 5
135
+ )
136
+ )
137
+ );
138
+ $ dataString = file_get_contents ($ pathData , false , $ context );
139
+ if ($ dataString == '' ) {
140
+ echo "Data file is not readable or empty. \n" ;
70
141
exit (3 );
71
142
}
72
143
73
- $ data = json_decode (file_get_contents ( $ pathData ) );
74
-
144
+ $ data = json_decode ($ dataString );
145
+ unset( $ dataString );
75
146
if ($ data === null ) {
76
147
echo "Error loading JSON data file \n" ;
77
148
showJsonError ();
78
149
exit (5 );
79
150
}
80
151
81
152
if ($ pathSchema === null ) {
153
+ if (isset ($ http_response_header )) {
154
+ array_shift ($ http_response_header );//HTTP/1.0 line
155
+ foreach ($ http_response_header as $ headerLine ) {
156
+ list ($ hName , $ hValue ) = explode (': ' , $ headerLine , 2 );
157
+ $ hName = strtolower ($ hName );
158
+ if ($ hName == 'link ' ) {
159
+ //Link: <http://example.org/schema#>; rel="describedBy"
160
+ $ hParts = parseHeaderValue ($ hValue );
161
+ if (isset ($ hParts ['rel ' ]) && $ hParts ['rel ' ] == 'describedBy ' ) {
162
+ $ pathSchema = trim ($ hParts ['_value ' ], ' <> ' );
163
+ }
164
+ } else if ($ hName == 'content-type ' ) {
165
+ //Content-Type: application/my-media-type+json;
166
+ // profile=http://example.org/schema#
167
+ $ hParts = parseHeaderValue ($ hValue );
168
+ if (isset ($ hParts ['profile ' ])) {
169
+ $ pathSchema = $ hParts ['profile ' ];
170
+ }
171
+
172
+ }
173
+ }
174
+ }
175
+ if (is_object ($ data ) && property_exists ($ data , '$schema ' )) {
176
+ $ pathSchema = $ data ->{'$schema ' };
177
+ }
178
+
82
179
//autodetect schema
83
- if (! is_object ( $ data ) || ! property_exists ( $ data , ' $schema ' ) ) {
180
+ if ($ pathSchema === null ) {
84
181
echo "JSON data must be an object and have a \$schema property. \n" ;
85
182
echo "You can pass the schema file on the command line as well. \n" ;
86
183
echo "Schema autodetection failed. \n" ;
87
184
exit (6 );
88
185
}
89
- $ pathSchema = $ data ->{'$schema ' };
90
- if ($ pathSchema {0 } != '/ '
91
- && parse_url ($ pathSchema , PHP_URL_SCHEME ) === false
92
- ) {
93
- $ pathSchema = dirname ($ pathData ) . '/ ' . $ pathSchema ;
94
- }
95
186
}
96
-
97
- $ schemaData = file_get_contents ($ pathSchema );
98
- if ($ schemaData === false ) {
99
- echo "Schema file ' $ pathSchema' is not readable. \n" ;
100
- exit (2 );
187
+ if ($ pathSchema {0 } == '/ ' ) {
188
+ $ pathSchema = 'file:// ' . $ pathSchema ;
101
189
}
102
190
103
- $ schema = json_decode ($ schemaData );
104
- unset($ schemaData );
191
+ $ resolver = new JsonSchema \Uri \UriResolver ();
192
+ $ retriever = new JsonSchema \Uri \UriRetriever ();
193
+ try {
194
+ $ urlSchema = $ resolver ->resolve ($ pathSchema , $ urlData );
105
195
106
- if ($ schema === null ) {
196
+ if (isset ($ arOptions ['--dump-schema-url ' ])) {
197
+ echo $ urlSchema . "\n" ;
198
+ exit ();
199
+ }
200
+
201
+ $ schema = $ retriever ->retrieve ($ urlSchema );
202
+ if ($ schema === null ) {
203
+ echo "Error loading JSON schema file \n" ;
204
+ echo $ urlSchema . "\n" ;
205
+ showJsonError ();
206
+ exit (2 );
207
+ }
208
+ } catch (Exception $ e ) {
107
209
echo "Error loading JSON schema file \n" ;
108
- showJsonError ();
109
- exit (6 );
210
+ echo $ urlSchema . "\n" ;
211
+ echo $ e ->getMessage () . "\n" ;
212
+ exit (2 );
110
213
}
214
+ $ refResolver = new JsonSchema \RefResolver ($ retriever );
215
+ $ refResolver ->resolve ($ schema , $ urlSchema );
111
216
112
- $ validator = new JsonSchema \Validator ();
113
- $ validator ->check ($ data , $ schema );
217
+ if (isset ($ arOptions ['--dump-schema ' ])) {
218
+ echo json_encode ($ schema , JSON_PRETTY_PRINT ) . "\n" ;
219
+ exit ();
220
+ }
114
221
115
- if ($ validator ->isValid ()) {
116
- echo "OK. The supplied JSON validates against the schema. \n" ;
117
- } else {
118
- echo "JSON does not validate. Violations: \n" ;
119
- foreach ($ validator ->getErrors () as $ error ) {
120
- echo sprintf ("[%s] %s \n" , $ error ['property ' ], $ error ['message ' ]);
222
+ try {
223
+ $ validator = new JsonSchema \Validator ();
224
+ $ validator ->check ($ data , $ schema );
225
+
226
+ if ($ validator ->isValid ()) {
227
+ echo "OK. The supplied JSON validates against the schema. \n" ;
228
+ } else {
229
+ echo "JSON does not validate. Violations: \n" ;
230
+ foreach ($ validator ->getErrors () as $ error ) {
231
+ echo sprintf ("[%s] %s \n" , $ error ['property ' ], $ error ['message ' ]);
232
+ }
233
+ exit (23 );
121
234
}
122
- exit (23 );
235
+ } catch (Exception $ e ) {
236
+ echo "JSON does not validate. Error: \n" ;
237
+ echo $ e ->getMessage () . "\n" ;
238
+ echo "Error code: " . $ e ->getCode () . "\n" ;
239
+ exit (24 );
123
240
}
241
+ ?>
0 commit comments