Changeset 61363
- Timestamp:
- 12/09/2025 06:32:27 PM (4 days ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tests/phpunit/tests/abilities-api/wpRegisterCoreAbilities.php
r61069 r61363 175 175 $this->assertSame( $environment, $ability_data['environment'] ); 176 176 } 177 178 /** 179 * Tests that all core ability schemas only use valid JSON Schema keywords. 180 * 181 * This prevents regressions where invalid keywords like 'examples' are used 182 * in schema properties (not valid in JSON Schema draft-04 used by WordPress). 183 * 184 * @ticket 64384 185 */ 186 public function test_core_abilities_schemas_use_only_valid_keywords(): void { 187 $allowed_keywords = rest_get_allowed_schema_keywords(); 188 // Add 'required' which is valid at the property level for draft-04. 189 $allowed_keywords[] = 'required'; 190 191 $abilities = wp_get_abilities(); 192 193 $this->assertNotEmpty( $abilities, 'Core abilities should be registered.' ); 194 195 foreach ( $abilities as $ability ) { 196 $this->assert_schema_uses_valid_keywords( 197 $ability->get_input_schema(), 198 $allowed_keywords, 199 $ability->get_name() . ' input_schema' 200 ); 201 $this->assert_schema_uses_valid_keywords( 202 $ability->get_output_schema(), 203 $allowed_keywords, 204 $ability->get_name() . ' output_schema' 205 ); 206 } 207 } 208 209 /** 210 * Recursively validates that a schema only uses allowed keywords. 211 * 212 * @param array|null $schema The schema to validate. 213 * @param string[] $allowed_keywords List of allowed schema keywords. 214 * @param string $context Context for error messages. 215 */ 216 private function assert_schema_uses_valid_keywords( ?array $schema, array $allowed_keywords, string $context ): void { 217 if ( null === $schema ) { 218 return; 219 } 220 221 foreach ( $schema as $key => $value ) { 222 // Skip integer keys (array indices). 223 if ( is_int( $key ) ) { 224 continue; 225 } 226 227 // These keywords contain nested schemas that we recurse into. 228 $nesting_keywords = array( 'properties', 'items', 'additionalProperties', 'patternProperties', 'anyOf', 'oneOf' ); 229 230 if ( ! in_array( $key, $nesting_keywords, true ) && ! in_array( $key, $allowed_keywords, true ) ) { 231 $this->fail( "Invalid schema keyword '{$key}' found in {$context}. Valid keywords are: " . implode( ', ', $allowed_keywords ) ); 232 } 233 234 // Recursively check nested schemas. 235 if ( 'properties' === $key && is_array( $value ) ) { 236 foreach ( $value as $prop_name => $prop_schema ) { 237 $this->assert_schema_uses_valid_keywords( 238 $prop_schema, 239 $allowed_keywords, 240 "{$context}.properties.{$prop_name}" 241 ); 242 } 243 } elseif ( 'items' === $key && is_array( $value ) ) { 244 $this->assert_schema_uses_valid_keywords( 245 $value, 246 $allowed_keywords, 247 "{$context}.items" 248 ); 249 } elseif ( ( 'anyOf' === $key || 'oneOf' === $key ) && is_array( $value ) ) { 250 foreach ( $value as $index => $sub_schema ) { 251 $this->assert_schema_uses_valid_keywords( 252 $sub_schema, 253 $allowed_keywords, 254 "{$context}.{$key}[{$index}]" 255 ); 256 } 257 } elseif ( 'additionalProperties' === $key && is_array( $value ) ) { 258 $this->assert_schema_uses_valid_keywords( 259 $value, 260 $allowed_keywords, 261 "{$context}.additionalProperties" 262 ); 263 } 264 } 265 } 177 266 }
Note: See TracChangeset
for help on using the changeset viewer.