Changeset 49082
- Timestamp:
- 10/01/2020 02:47:08 AM (4 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/rest-api.php
r49063 r49082 1541 1541 1542 1542 /** 1543 * Validates if the JSON Schema pattern matches a value. 1544 * 1545 * @since 5.6.0 1546 * 1547 * @param string $pattern The pattern to match against. 1548 * @param string $value The value to check. 1549 * @return bool True if the pattern matches the given value, false otherwise. 1550 */ 1551 function rest_validate_json_schema_pattern( $pattern, $value ) { 1552 $escaped_pattern = str_replace( '#', '\\#', $pattern ); 1553 1554 return 1 === preg_match( '#' . $escaped_pattern . '#u', $value ); 1555 } 1556 1557 /** 1558 * Finds the schema for a property using the patternProperties keyword. 1559 * 1560 * @since 5.6.0 1561 * 1562 * @param string $property The property name to check. 1563 * @param array $args The schema array to use. 1564 * @return array|null The schema of matching pattern property, or null if no patterns match. 1565 */ 1566 function rest_find_matching_pattern_property_schema( $property, $args ) { 1567 if ( isset( $args['patternProperties'] ) ) { 1568 foreach ( $args['patternProperties'] as $pattern => $child_schema ) { 1569 if ( rest_validate_json_schema_pattern( $pattern, $property ) ) { 1570 return $child_schema; 1571 } 1572 } 1573 } 1574 1575 return null; 1576 } 1577 1578 /** 1543 1579 * Validate a value based on a schema. 1544 1580 * … … 1554 1590 * @since 5.6.0 Support the "minProperties" and "maxProperties" keywords for objects. 1555 1591 * Support the "multipleOf" keyword for numbers and integers. 1592 * Support the "patternProperties" keyword for objects. 1556 1593 * 1557 1594 * @param mixed $value The value to validate. … … 1651 1688 return $is_valid; 1652 1689 } 1653 } elseif ( isset( $args['additionalProperties'] ) ) { 1690 continue; 1691 } 1692 1693 $pattern_property_schema = rest_find_matching_pattern_property_schema( $property, $args ); 1694 if ( null !== $pattern_property_schema ) { 1695 $is_valid = rest_validate_value_from_schema( $v, $pattern_property_schema, $param . '[' . $property . ']' ); 1696 if ( is_wp_error( $is_valid ) ) { 1697 return $is_valid; 1698 } 1699 continue; 1700 } 1701 1702 if ( isset( $args['additionalProperties'] ) ) { 1654 1703 if ( false === $args['additionalProperties'] ) { 1655 1704 /* translators: %s: Property of an object. */ … … 1745 1794 } 1746 1795 1747 if ( isset( $args['pattern'] ) ) { 1748 $pattern = str_replace( '#', '\\#', $args['pattern'] ); 1749 if ( ! preg_match( '#' . $pattern . '#u', $value ) ) { 1750 /* translators: 1: Parameter, 2: Pattern. */ 1751 return new WP_Error( 'rest_invalid_pattern', sprintf( __( '%1$s does not match pattern %2$s.' ), $param, $args['pattern'] ) ); 1752 } 1796 if ( isset( $args['pattern'] ) && ! rest_validate_json_schema_pattern( $args['pattern'], $value ) ) { 1797 /* translators: 1: Parameter, 2: Pattern. */ 1798 return new WP_Error( 'rest_invalid_pattern', sprintf( __( '%1$s does not match pattern %2$s.' ), $param, $args['pattern'] ) ); 1753 1799 } 1754 1800 } … … 1898 1944 if ( isset( $args['properties'][ $property ] ) ) { 1899 1945 $value[ $property ] = rest_sanitize_value_from_schema( $v, $args['properties'][ $property ], $param . '[' . $property . ']' ); 1900 } elseif ( isset( $args['additionalProperties'] ) ) { 1946 continue; 1947 } 1948 1949 $pattern_property_schema = rest_find_matching_pattern_property_schema( $property, $args ); 1950 if ( null !== $pattern_property_schema ) { 1951 $value[ $property ] = rest_sanitize_value_from_schema( $v, $pattern_property_schema, $param . '[' . $property . ']' ); 1952 continue; 1953 } 1954 1955 if ( isset( $args['additionalProperties'] ) ) { 1901 1956 if ( false === $args['additionalProperties'] ) { 1902 1957 unset( $value[ $property ] ); … … 2054 2109 * 2055 2110 * @since 5.5.0 2111 * @since 5.6.0 Support the "patternProperties" keyword for objects. 2056 2112 * 2057 2113 * @param array|object $data The response data to modify. … … 2094 2150 if ( isset( $schema['properties'][ $key ] ) ) { 2095 2151 $check = $schema['properties'][ $key ]; 2096 } elseif ( $has_additional_properties ) { 2097 $check = $schema['additionalProperties']; 2152 } else { 2153 $pattern_property_schema = rest_find_matching_pattern_property_schema( $key, $schema ); 2154 if ( null !== $pattern_property_schema ) { 2155 $check = $pattern_property_schema; 2156 } elseif ( $has_additional_properties ) { 2157 $check = $schema['additionalProperties']; 2158 } 2098 2159 } 2099 2160 } … … 2133 2194 * 2134 2195 * @since 5.5.0 2196 * @since 5.6.0 Support the "patternProperties" keyword. 2135 2197 * 2136 2198 * @param array $schema The schema to modify. … … 2144 2206 foreach ( $schema['properties'] as $key => $child_schema ) { 2145 2207 $schema['properties'][ $key ] = rest_default_additional_properties_to_false( $child_schema ); 2208 } 2209 } 2210 2211 if ( isset( $schema['patternProperties'] ) ) { 2212 foreach ( $schema['patternProperties'] as $key => $child_schema ) { 2213 $schema['patternProperties'][ $key ] = rest_default_additional_properties_to_false( $child_schema ); 2146 2214 } 2147 2215 } … … 2301 2369 'properties', 2302 2370 'additionalProperties', 2371 'patternProperties', 2303 2372 'minProperties', 2304 2373 'maxProperties', -
trunk/tests/phpunit/tests/rest-api.php
r48937 r49082 1285 1285 array( 'additional' => array( 'a' => '1' ) ), 1286 1286 ), 1287 'pattern properties' => array( 1288 array( 1289 '$schema' => 'http://json-schema.org/draft-04/schema#', 1290 'type' => 'object', 1291 'properties' => array( 1292 'a' => array( 1293 'type' => 'string', 1294 'context' => array( 'view', 'edit' ), 1295 ), 1296 ), 1297 'patternProperties' => array( 1298 '[0-9]' => array( 1299 'type' => 'string', 1300 'context' => array( 'view', 'edit' ), 1301 ), 1302 'c.*' => array( 1303 'type' => 'string', 1304 'context' => array( 'edit' ), 1305 ), 1306 ), 1307 'additionalProperties' => array( 1308 'type' => 'string', 1309 'context' => array( 'edit' ), 1310 ), 1311 ), 1312 array( 1313 'a' => '1', 1314 'b' => '2', 1315 '0' => '3', 1316 'ca' => '4', 1317 ), 1318 array( 1319 'a' => '1', 1320 '0' => '3', 1321 ), 1322 ), 1287 1323 'multiple types object' => array( 1288 1324 array( -
trunk/tests/phpunit/tests/rest-api/rest-controller.php
r49063 r49082 292 292 } 293 293 294 foreach ( array( 'properties', 'additionalProperties', 'minProperties', 'maxProperties' ) as $property ) { 294 $object_properties = array( 295 'properties', 296 'patternProperties', 297 'additionalProperties', 298 'minProperties', 299 'maxProperties', 300 ); 301 foreach ( $object_properties as $property ) { 295 302 $this->assertArrayHasKey( $property, $args['someobject'] ); 296 303 } -
trunk/tests/phpunit/tests/rest-api/rest-schema-sanitization.php
r49008 r49082 235 235 $schema 236 236 ) 237 ); 238 } 239 240 /** 241 * @ticket 51024 242 * 243 * @dataProvider data_type_object_pattern_properties 244 * 245 * @param array $pattern_properties 246 * @param array $value 247 * @param array $expected 248 */ 249 public function test_type_object_pattern_properties( $pattern_properties, $value, $expected ) { 250 $schema = array( 251 'type' => 'object', 252 'properties' => array( 253 'propA' => array( 'type' => 'string' ), 254 ), 255 'patternProperties' => $pattern_properties, 256 'additionalProperties' => false, 257 ); 258 259 $this->assertSame( $expected, rest_sanitize_value_from_schema( $value, $schema ) ); 260 } 261 262 /** 263 * @return array 264 */ 265 public function data_type_object_pattern_properties() { 266 return array( 267 array( array(), array(), array() ), 268 array( array(), array( 'propA' => 'a' ), array( 'propA' => 'a' ) ), 269 array( 270 array(), 271 array( 272 'propA' => 'a', 273 'propB' => 'b', 274 ), 275 array( 'propA' => 'a' ), 276 ), 277 array( 278 array( 279 'propB' => array( 'type' => 'string' ), 280 ), 281 array( 'propA' => 'a' ), 282 array( 'propA' => 'a' ), 283 ), 284 array( 285 array( 286 'propB' => array( 'type' => 'string' ), 287 ), 288 array( 289 'propA' => 'a', 290 'propB' => 'b', 291 ), 292 array( 293 'propA' => 'a', 294 'propB' => 'b', 295 ), 296 ), 297 array( 298 array( 299 '.*C' => array( 'type' => 'string' ), 300 ), 301 array( 302 'propA' => 'a', 303 'propC' => 'c', 304 ), 305 array( 306 'propA' => 'a', 307 'propC' => 'c', 308 ), 309 ), 310 array( 311 array( 312 '[0-9]' => array( 'type' => 'integer' ), 313 ), 314 array( 315 'propA' => 'a', 316 'prop0' => '0', 317 ), 318 array( 319 'propA' => 'a', 320 'prop0' => 0, 321 ), 322 ), 323 array( 324 array( 325 '.+' => array( 'type' => 'string' ), 326 ), 327 array( 328 '' => '', 329 'propA' => 'a', 330 ), 331 array( 'propA' => 'a' ), 332 ), 237 333 ); 238 334 } -
trunk/tests/phpunit/tests/rest-api/rest-schema-validation.php
r49063 r49082 287 287 ); 288 288 $this->assertWPError( rest_validate_value_from_schema( array( 'a' => 'invalid' ), $schema ) ); 289 } 290 291 /** 292 * @ticket 51024 293 * 294 * @dataProvider data_type_object_pattern_properties 295 * 296 * @param array $pattern_properties 297 * @param array $value 298 * @param bool $expected 299 */ 300 public function test_type_object_pattern_properties( $pattern_properties, $value, $expected ) { 301 $schema = array( 302 'type' => 'object', 303 'properties' => array( 304 'propA' => array( 'type' => 'string' ), 305 ), 306 'patternProperties' => $pattern_properties, 307 'additionalProperties' => false, 308 ); 309 310 if ( $expected ) { 311 $this->assertTrue( rest_validate_value_from_schema( $value, $schema ) ); 312 } else { 313 $this->assertWPError( rest_validate_value_from_schema( $value, $schema ) ); 314 } 315 } 316 317 /** 318 * @return array 319 */ 320 public function data_type_object_pattern_properties() { 321 return array( 322 array( array(), array(), true ), 323 array( array(), array( 'propA' => 'a' ), true ), 324 array( 325 array(), 326 array( 327 'propA' => 'a', 328 'propB' => 'b', 329 ), 330 false, 331 ), 332 array( 333 array( 334 'propB' => array( 'type' => 'string' ), 335 ), 336 array( 'propA' => 'a' ), 337 true, 338 ), 339 array( 340 array( 341 'propB' => array( 'type' => 'string' ), 342 ), 343 array( 344 'propA' => 'a', 345 'propB' => 'b', 346 ), 347 true, 348 ), 349 array( 350 array( 351 '.*C' => array( 'type' => 'string' ), 352 ), 353 array( 354 'propA' => 'a', 355 'propC' => 'c', 356 ), 357 true, 358 ), 359 array( 360 array( 361 '[0-9]' => array( 'type' => 'integer' ), 362 ), 363 array( 364 'propA' => 'a', 365 'prop0' => 0, 366 ), 367 true, 368 ), 369 array( 370 array( 371 '[0-9]' => array( 'type' => 'integer' ), 372 ), 373 array( 374 'propA' => 'a', 375 'prop0' => 'notAnInteger', 376 ), 377 false, 378 ), 379 array( 380 array( 381 '.+' => array( 'type' => 'string' ), 382 ), 383 array( 384 '' => '', 385 'propA' => 'a', 386 ), 387 false, 388 ), 389 ); 289 390 } 290 391 -
trunk/tests/phpunit/tests/rest-api/rest-test-controller.php
r49063 r49082 122 122 ), 123 123 ), 124 'patternProperties' => array( 125 '[0-9]' => array( 126 'type' => 'string', 127 ), 128 ), 124 129 'minProperties' => 1, 125 130 'maxProperties' => 10,
Note: See TracChangeset
for help on using the changeset viewer.