@@ -45,7 +45,7 @@ public function getUriResolver()
45
45
/**
46
46
* {@inheritdoc}
47
47
*/
48
- public function addSchema ($ id , $ schema = null )
48
+ public function addSchema (string $ id , $ schema = null ): void
49
49
{
50
50
if (is_null ($ schema ) && $ id !== self ::INTERNAL_PROVIDED_SCHEMA_URI ) {
51
51
// if the schema was user-provided to Validator and is still null, then assume this is
@@ -62,14 +62,16 @@ public function addSchema($id, $schema = null)
62
62
// workaround for bug in draft-03 & draft-04 meta-schemas (id & $ref defined with incorrect format)
63
63
// see https://github.com/json-schema-org/JSON-Schema-Test-Suite/issues/177#issuecomment-293051367
64
64
if (is_object ($ schema ) && property_exists ($ schema , 'id ' )) {
65
- if ($ schema ->id == 'http://json-schema.org/draft-04/schema# ' ) {
65
+ if ($ schema ->id === 'http://json-schema.org/draft-04/schema# ' ) {
66
66
$ schema ->properties ->id ->format = 'uri-reference ' ;
67
- } elseif ($ schema ->id == 'http://json-schema.org/draft-03/schema# ' ) {
67
+ } elseif ($ schema ->id === 'http://json-schema.org/draft-03/schema# ' ) {
68
68
$ schema ->properties ->id ->format = 'uri-reference ' ;
69
69
$ schema ->properties ->{'$ref ' }->format = 'uri-reference ' ;
70
70
}
71
71
}
72
72
73
+ $ this ->scanForSubschemas ($ schema , $ id );
74
+
73
75
// resolve references
74
76
$ this ->expandRefs ($ schema , $ id );
75
77
@@ -79,39 +81,44 @@ public function addSchema($id, $schema = null)
79
81
/**
80
82
* Recursively resolve all references against the provided base
81
83
*
82
- * @param mixed $schema
83
- * @param string $base
84
+ * @param mixed $schema
84
85
*/
85
- private function expandRefs (&$ schema , $ base = null )
86
+ private function expandRefs (&$ schema , ? string $ parentId = null ): void
86
87
{
87
88
if (!is_object ($ schema )) {
88
89
if (is_array ($ schema )) {
89
90
foreach ($ schema as &$ member ) {
90
- $ this ->expandRefs ($ member , $ base );
91
+ $ this ->expandRefs ($ member , $ parentId );
91
92
}
92
93
}
93
94
94
95
return ;
95
96
}
96
97
97
- if (property_exists ($ schema , 'id ' ) && is_string ($ schema ->id ) && $ base != $ schema ->id ) {
98
- $ base = $ this ->uriResolver ->resolve ($ schema ->id , $ base );
99
- }
100
-
101
98
if (property_exists ($ schema , '$ref ' ) && is_string ($ schema ->{'$ref ' })) {
102
- $ refPointer = new JsonPointer ($ this ->uriResolver ->resolve ($ schema ->{'$ref ' }, $ base ));
99
+ $ refPointer = new JsonPointer ($ this ->uriResolver ->resolve ($ schema ->{'$ref ' }, $ parentId ));
103
100
$ schema ->{'$ref ' } = (string ) $ refPointer ;
104
101
}
105
102
106
- foreach ($ schema as &$ member ) {
107
- $ this ->expandRefs ($ member , $ base );
103
+ foreach ($ schema as $ propertyName => &$ member ) {
104
+ if (in_array ($ propertyName , ['enum ' , 'const ' ])) {
105
+ // Enum and const don't allow $ref as a keyword, see https://github.com/json-schema-org/JSON-Schema-Test-Suite/pull/445
106
+ continue ;
107
+ }
108
+
109
+ $ childId = $ parentId ;
110
+ if (property_exists ($ schema , 'id ' ) && is_string ($ schema ->id ) && $ childId !== $ schema ->id ) {
111
+ $ childId = $ this ->uriResolver ->resolve ($ schema ->id , $ childId );
112
+ }
113
+
114
+ $ this ->expandRefs ($ member , $ childId );
108
115
}
109
116
}
110
117
111
118
/**
112
119
* {@inheritdoc}
113
120
*/
114
- public function getSchema ($ id )
121
+ public function getSchema (string $ id )
115
122
{
116
123
if (!array_key_exists ($ id , $ this ->schemas )) {
117
124
$ this ->addSchema ($ id );
@@ -123,7 +130,7 @@ public function getSchema($id)
123
130
/**
124
131
* {@inheritdoc}
125
132
*/
126
- public function resolveRef ($ ref , $ resolveStack = [])
133
+ public function resolveRef (string $ ref , $ resolveStack = [])
127
134
{
128
135
$ jsonPointer = new JsonPointer ($ ref );
129
136
@@ -174,4 +181,32 @@ public function resolveRefSchema($refSchema, $resolveStack = [])
174
181
175
182
return $ refSchema ;
176
183
}
184
+
185
+ /**
186
+ * @param mixed $schema
187
+ */
188
+ private function scanForSubschemas ($ schema , string $ parentId ): void
189
+ {
190
+ if (!$ schema instanceof \stdClass && !is_array ($ schema )) {
191
+ return ;
192
+ }
193
+
194
+ foreach ($ schema as $ propertyName => $ potentialSubSchema ) {
195
+ if (!is_object ($ potentialSubSchema )) {
196
+ continue ;
197
+ }
198
+
199
+ if (property_exists ($ potentialSubSchema , 'id ' ) && is_string ($ potentialSubSchema ->id ) && property_exists ($ potentialSubSchema , 'type ' )) {
200
+ // Enum and const don't allow id as a keyword, see https://github.com/json-schema-org/JSON-Schema-Test-Suite/pull/471
201
+ if (in_array ($ propertyName , ['enum ' , 'const ' ])) {
202
+ continue ;
203
+ }
204
+
205
+ // Found sub schema
206
+ $ this ->addSchema ($ this ->uriResolver ->resolve ($ potentialSubSchema ->id , $ parentId ), $ potentialSubSchema );
207
+ }
208
+
209
+ $ this ->scanForSubschemas ($ potentialSubSchema , $ parentId );
210
+ }
211
+ }
177
212
}
0 commit comments