Changeset 46249
- Timestamp:
- 09/23/2019 05:24:58 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/rest-api.php
r46233 r46249 1210 1210 */ 1211 1211 function rest_validate_value_from_schema( $value, $args, $param = '' ) { 1212 if ( is_array( $args['type'] ) ) { 1213 foreach ( $args['type'] as $type ) { 1214 $type_args = $args; 1215 $type_args['type'] = $type; 1216 1217 if ( true === rest_validate_value_from_schema( $value, $type_args, $param ) ) { 1218 return true; 1219 } 1220 } 1221 1222 /* translators: 1: Parameter, 2: List of types. */ 1223 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s' ), $param, implode( ',', $args['type'] ) ) ); 1224 } 1225 1212 1226 if ( 'array' === $args['type'] ) { 1213 1227 if ( ! is_null( $value ) ) { … … 1260 1274 } 1261 1275 } 1276 } 1277 1278 if ( 'null' === $args['type'] ) { 1279 if ( null !== $value ) { 1280 /* translators: 1: Parameter, 2: Type name. */ 1281 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'null' ) ); 1282 } 1283 1284 return true; 1262 1285 } 1263 1286 … … 1366 1389 */ 1367 1390 function rest_sanitize_value_from_schema( $value, $args ) { 1391 if ( is_array( $args['type'] ) ) { 1392 // Determine which type the value was validated against, and use that type when performing sanitization 1393 $validated_type = ''; 1394 1395 foreach ( $args['type'] as $type ) { 1396 $type_args = $args; 1397 $type_args['type'] = $type; 1398 1399 if ( ! is_wp_error( rest_validate_value_from_schema( $value, $type_args ) ) ) { 1400 $validated_type = $type; 1401 break; 1402 } 1403 } 1404 1405 if ( ! $validated_type ) { 1406 return null; 1407 } 1408 1409 $args['type'] = $validated_type; 1410 } 1411 1368 1412 if ( 'array' === $args['type'] ) { 1369 1413 if ( empty( $args['items'] ) ) { … … 1408 1452 } 1409 1453 1454 if ( 'null' === $args['type'] ) { 1455 return null; 1456 } 1457 1410 1458 if ( 'integer' === $args['type'] ) { 1411 1459 return (int) $value; -
trunk/src/wp-includes/rest-api/class-wp-rest-request.php
r46206 r46249 399 399 400 400 /** 401 * Checks if a parameter exists in the request. 402 * 403 * This allows distinguishing between an omitted parameter, 404 * and a parameter specifically set to null. 405 * 406 * @since 5.3.0 407 * 408 * @param string $key Parameter name. 409 * 410 * @return bool True if a param exists for the given key. 411 */ 412 public function has_param( $key ) { 413 $order = $this->get_parameter_order(); 414 415 foreach ( $order as $type ) { 416 if ( array_key_exists( $key, $this->params[ $type ] ) ) { 417 return true; 418 } 419 } 420 421 return false; 422 } 423 424 /** 401 425 * Sets a parameter on the request. 402 426 * -
trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
r46184 r46249 1037 1037 } 1038 1038 1039 // Sending a null date or date_gmt value resets date and date_gmt to their 1040 // default values (`0000-00-00 00:00:00`). 1041 if ( 1042 ( ! empty( $schema['properties']['date_gmt'] ) && $request->has_param( 'date_gmt' ) && null === $request['date_gmt'] ) || 1043 ( ! empty( $schema['properties']['date'] ) && $request->has_param( 'date' ) && null === $request['date'] ) 1044 ) { 1045 $prepared_post->post_date_gmt = null; 1046 $prepared_post->post_date = null; 1047 } 1048 1039 1049 // Post slug. 1040 1050 if ( ! empty( $schema['properties']['slug'] ) && isset( $request['slug'] ) ) { … … 1892 1902 'date' => array( 1893 1903 'description' => __( "The date the object was published, in the site's timezone." ), 1894 'type' => 'string',1904 'type' => array( 'string', 'null' ), 1895 1905 'format' => 'date-time', 1896 1906 'context' => array( 'view', 'edit', 'embed' ), … … 1898 1908 'date_gmt' => array( 1899 1909 'description' => __( 'The date the object was published, as GMT.' ), 1900 'type' => 'string',1910 'type' => array( 'string', 'null' ), 1901 1911 'format' => 'date-time', 1902 1912 'context' => array( 'view', 'edit' ), -
trunk/tests/phpunit/tests/rest-api/rest-posts-controller.php
r46184 r46249 2624 2624 $this->assertEquals( $params['content'], $post->post_content ); 2625 2625 $this->assertEquals( $params['excerpt'], $post->post_excerpt ); 2626 } 2627 2628 /** 2629 * Verify that updating a post with a `null` date or date_gmt results in a reset post, where all 2630 * date values are equal (date, date_gmt, date_modified and date_modofied_gmt) in the API response. 2631 * In the database, the post_date_gmt field is reset to the default `0000-00-00 00:00:00`. 2632 * 2633 * @ticket 44975 2634 */ 2635 public function test_rest_update_post_with_empty_date() { 2636 // Create a new test post. 2637 $post_id = $this->factory->post->create(); 2638 wp_set_current_user( self::$editor_id ); 2639 2640 // Set the post date to the future. 2641 $future_date = '2919-07-29T18:00:00'; 2642 $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', $post_id ) ); 2643 $request->add_header( 'content-type', 'application/json' ); 2644 $params = $this->set_post_data( 2645 array( 2646 'date_gmt' => $future_date, 2647 'date' => $future_date, 2648 'title' => 'update', 2649 'status' => 'draft', 2650 ) 2651 ); 2652 $request->set_body( wp_json_encode( $params ) ); 2653 $response = rest_get_server()->dispatch( $request ); 2654 $this->check_update_post_response( $response ); 2655 $new_data = $response->get_data(); 2656 2657 // Verify the post is set to the future date. 2658 $this->assertEquals( $new_data['date_gmt'], $future_date ); 2659 $this->assertEquals( $new_data['date'], $future_date ); 2660 $this->assertNotEquals( $new_data['date_gmt'], $new_data['modified_gmt'] ); 2661 $this->assertNotEquals( $new_data['date'], $new_data['modified'] ); 2662 2663 // Update post with a blank field (date or date_gmt). 2664 $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', $post_id ) ); 2665 $request->add_header( 'content-type', 'application/json' ); 2666 $params = $this->set_post_data( 2667 array( 2668 'date_gmt' => null, 2669 'title' => 'test', 2670 'status' => 'draft', 2671 ) 2672 ); 2673 $request->set_body( wp_json_encode( $params ) ); 2674 $response = rest_get_server()->dispatch( $request ); 2675 2676 // Verify the date field values are reset in the API response. 2677 $this->check_update_post_response( $response ); 2678 $new_data = $response->get_data(); 2679 $this->assertEquals( $new_data['date_gmt'], $new_data['date'] ); 2680 $this->assertNotEquals( $new_data['date_gmt'], $future_date ); 2681 2682 $post = get_post( $post_id, 'ARRAY_A' ); 2683 $this->assertEquals( $post['post_date_gmt'], '0000-00-00 00:00:00' ); 2684 $this->assertNotEquals( $new_data['date_gmt'], $future_date ); 2685 $this->assertNotEquals( $new_data['date'], $future_date ); 2626 2686 } 2627 2687 -
trunk/tests/phpunit/tests/rest-api/rest-schema-sanitization.php
r44703 r46249 293 293 $this->assertEquals( 1, rest_sanitize_value_from_schema( 1, $schema ) ); 294 294 } 295 296 public function test_nullable_date() { 297 $schema = array( 298 'type' => array( 'string', 'null' ), 299 'format' => 'date-time', 300 ); 301 302 $this->assertNull( rest_sanitize_value_from_schema( null, $schema ) ); 303 $this->assertEquals( '2019-09-19T18:00:00', rest_sanitize_value_from_schema( '2019-09-19T18:00:00', $schema ) ); 304 $this->assertNull( rest_sanitize_value_from_schema( 'lalala', $schema ) ); 305 } 306 307 public function test_object_or_string() { 308 $schema = array( 309 'type' => array( 'object', 'string' ), 310 'properties' => array( 311 'raw' => array( 312 'type' => 'string', 313 ), 314 ), 315 ); 316 317 $this->assertEquals( 'My Value', rest_sanitize_value_from_schema( 'My Value', $schema ) ); 318 $this->assertEquals( array( 'raw' => 'My Value' ), rest_sanitize_value_from_schema( array( 'raw' => 'My Value' ), $schema ) ); 319 $this->assertNull( rest_sanitize_value_from_schema( array( 'raw' => 1 ), $schema ) ); 320 } 321 322 public function test_object_or_bool() { 323 $schema = array( 324 'type' => array( 'object', 'boolean' ), 325 'properties' => array( 326 'raw' => array( 327 'type' => 'boolean', 328 ), 329 ), 330 ); 331 332 $this->assertTrue( rest_sanitize_value_from_schema( true, $schema ) ); 333 $this->assertTrue( rest_sanitize_value_from_schema( '1', $schema ) ); 334 $this->assertTrue( rest_sanitize_value_from_schema( 1, $schema ) ); 335 336 $this->assertFalse( rest_sanitize_value_from_schema( false, $schema ) ); 337 $this->assertFalse( rest_sanitize_value_from_schema( '0', $schema ) ); 338 $this->assertFalse( rest_sanitize_value_from_schema( 0, $schema ) ); 339 340 $this->assertEquals( array( 'raw' => true ), rest_sanitize_value_from_schema( array( 'raw' => true ), $schema ) ); 341 $this->assertEquals( array( 'raw' => true ), rest_sanitize_value_from_schema( array( 'raw' => '1' ), $schema ) ); 342 $this->assertEquals( array( 'raw' => true ), rest_sanitize_value_from_schema( array( 'raw' => 1 ), $schema ) ); 343 344 $this->assertEquals( array( 'raw' => false ), rest_sanitize_value_from_schema( array( 'raw' => false ), $schema ) ); 345 $this->assertEquals( array( 'raw' => false ), rest_sanitize_value_from_schema( array( 'raw' => '0' ), $schema ) ); 346 $this->assertEquals( array( 'raw' => false ), rest_sanitize_value_from_schema( array( 'raw' => 0 ), $schema ) ); 347 348 $this->assertNull( rest_sanitize_value_from_schema( array( 'raw' => 'something non boolean' ), $schema ) ); 349 } 295 350 } -
trunk/tests/phpunit/tests/rest-api/rest-schema-validation.php
r44546 r46249 297 297 $this->assertTrue( rest_validate_value_from_schema( array(), $schema ) ); 298 298 } 299 300 public function test_type_null() { 301 $this->assertTrue( rest_validate_value_from_schema( null, array( 'type' => 'null' ) ) ); 302 $this->assertWPError( rest_validate_value_from_schema( '', array( 'type' => 'null' ) ) ); 303 $this->assertWPError( rest_validate_value_from_schema( 'null', array( 'type' => 'null' ) ) ); 304 } 305 306 public function test_nullable_date() { 307 $schema = array( 308 'type' => array( 'string', 'null' ), 309 'format' => 'date-time', 310 ); 311 312 $this->assertTrue( rest_validate_value_from_schema( null, $schema ) ); 313 $this->assertTrue( rest_validate_value_from_schema( '2019-09-19T18:00:00', $schema ) ); 314 $this->assertWPError( rest_validate_value_from_schema( 'some random string', $schema ) ); 315 } 316 317 public function test_object_or_string() { 318 $schema = array( 319 'type' => array( 'object', 'string' ), 320 'properties' => array( 321 'raw' => array( 322 'type' => 'string', 323 ), 324 ), 325 ); 326 327 $this->assertTrue( rest_validate_value_from_schema( 'My Value', $schema ) ); 328 $this->assertTrue( rest_validate_value_from_schema( array( 'raw' => 'My Value' ), $schema ) ); 329 $this->assertWPError( rest_validate_value_from_schema( array( 'raw' => array( 'a list' ) ), $schema ) ); 330 } 299 331 } -
trunk/tests/qunit/fixtures/wp-api-generated.js
r46190 r46249 374 374 "required": false, 375 375 "description": "The date the object was published, in the site's timezone.", 376 "type": "string" 376 "type": [ 377 "string", 378 "null" 379 ] 377 380 }, 378 381 "date_gmt": { 379 382 "required": false, 380 383 "description": "The date the object was published, as GMT.", 381 "type": "string" 384 "type": [ 385 "string", 386 "null" 387 ] 382 388 }, 383 389 "slug": { … … 554 560 "required": false, 555 561 "description": "The date the object was published, in the site's timezone.", 556 "type": "string" 562 "type": [ 563 "string", 564 "null" 565 ] 557 566 }, 558 567 "date_gmt": { 559 568 "required": false, 560 569 "description": "The date the object was published, as GMT.", 561 "type": "string" 570 "type": [ 571 "string", 572 "null" 573 ] 562 574 }, 563 575 "slug": { … … 894 906 "required": false, 895 907 "description": "The date the object was published, in the site's timezone.", 896 "type": "string" 908 "type": [ 909 "string", 910 "null" 911 ] 897 912 }, 898 913 "date_gmt": { 899 914 "required": false, 900 915 "description": "The date the object was published, as GMT.", 901 "type": "string" 916 "type": [ 917 "string", 918 "null" 919 ] 902 920 }, 903 921 "slug": { … … 1239 1257 "required": false, 1240 1258 "description": "The date the object was published, in the site's timezone.", 1241 "type": "string" 1259 "type": [ 1260 "string", 1261 "null" 1262 ] 1242 1263 }, 1243 1264 "date_gmt": { 1244 1265 "required": false, 1245 1266 "description": "The date the object was published, as GMT.", 1246 "type": "string" 1267 "type": [ 1268 "string", 1269 "null" 1270 ] 1247 1271 }, 1248 1272 "slug": { … … 1391 1415 "required": false, 1392 1416 "description": "The date the object was published, in the site's timezone.", 1393 "type": "string" 1417 "type": [ 1418 "string", 1419 "null" 1420 ] 1394 1421 }, 1395 1422 "date_gmt": { 1396 1423 "required": false, 1397 1424 "description": "The date the object was published, as GMT.", 1398 "type": "string" 1425 "type": [ 1426 "string", 1427 "null" 1428 ] 1399 1429 }, 1400 1430 "slug": { … … 1703 1733 "required": false, 1704 1734 "description": "The date the object was published, in the site's timezone.", 1705 "type": "string" 1735 "type": [ 1736 "string", 1737 "null" 1738 ] 1706 1739 }, 1707 1740 "date_gmt": { 1708 1741 "required": false, 1709 1742 "description": "The date the object was published, as GMT.", 1710 "type": "string" 1743 "type": [ 1744 "string", 1745 "null" 1746 ] 1711 1747 }, 1712 1748 "slug": { … … 2016 2052 "required": false, 2017 2053 "description": "The date the object was published, in the site's timezone.", 2018 "type": "string" 2054 "type": [ 2055 "string", 2056 "null" 2057 ] 2019 2058 }, 2020 2059 "date_gmt": { 2021 2060 "required": false, 2022 2061 "description": "The date the object was published, as GMT.", 2023 "type": "string" 2062 "type": [ 2063 "string", 2064 "null" 2065 ] 2024 2066 }, 2025 2067 "slug": { … … 2153 2195 "required": false, 2154 2196 "description": "The date the object was published, in the site's timezone.", 2155 "type": "string" 2197 "type": [ 2198 "string", 2199 "null" 2200 ] 2156 2201 }, 2157 2202 "date_gmt": { 2158 2203 "required": false, 2159 2204 "description": "The date the object was published, as GMT.", 2160 "type": "string" 2205 "type": [ 2206 "string", 2207 "null" 2208 ] 2161 2209 }, 2162 2210 "slug": { … … 2400 2448 "required": false, 2401 2449 "description": "The date the object was published, in the site's timezone.", 2402 "type": "string" 2450 "type": [ 2451 "string", 2452 "null" 2453 ] 2403 2454 }, 2404 2455 "date_gmt": { 2405 2456 "required": false, 2406 2457 "description": "The date the object was published, as GMT.", 2407 "type": "string" 2458 "type": [ 2459 "string", 2460 "null" 2461 ] 2408 2462 }, 2409 2463 "slug": { … … 2504 2558 "required": false, 2505 2559 "description": "The date the object was published, in the site's timezone.", 2506 "type": "string" 2560 "type": [ 2561 "string", 2562 "null" 2563 ] 2507 2564 }, 2508 2565 "date_gmt": { 2509 2566 "required": false, 2510 2567 "description": "The date the object was published, as GMT.", 2511 "type": "string" 2568 "type": [ 2569 "string", 2570 "null" 2571 ] 2512 2572 }, 2513 2573 "slug": { … … 2613 2673 "required": false, 2614 2674 "description": "The date the object was published, in the site's timezone.", 2615 "type": "string" 2675 "type": [ 2676 "string", 2677 "null" 2678 ] 2616 2679 }, 2617 2680 "date_gmt": { 2618 2681 "required": false, 2619 2682 "description": "The date the object was published, as GMT.", 2620 "type": "string" 2683 "type": [ 2684 "string", 2685 "null" 2686 ] 2621 2687 }, 2622 2688 "slug": {
Note: See TracChangeset
for help on using the changeset viewer.