- Timestamp:
- 08/15/2019 05:16:21 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php
r45681 r45807 144 144 */ 145 145 if ( is_null( $meta[ $name ] ) ) { 146 $args = $this->get_registered_fields()[ $meta_key ]; 147 148 if ( $args['single'] ) { 149 $current = get_metadata( $this->get_meta_type(), $object_id, $meta_key, true ); 150 151 if ( is_wp_error( rest_validate_value_from_schema( $current, $args['schema'] ) ) ) { 152 return new WP_Error( 153 'rest_invalid_stored_value', 154 /* translators: %s: custom field key */ 155 sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ), 156 array( 'status' => 500 ) 157 ); 158 } 159 } 160 146 161 $result = $this->delete_meta_value( $object_id, $meta_key, $name ); 147 162 if ( is_wp_error( $result ) ) { … … 151 166 } 152 167 153 $is_valid = rest_validate_value_from_schema( $meta[ $name ], $args['schema'], 'meta.' . $name ); 168 $value = $meta[ $name ]; 169 170 if ( ! $args['single'] && is_array( $value ) && count( array_filter( $value, 'is_null' ) ) ) { 171 return new WP_Error( 172 'rest_invalid_stored_value', 173 /* translators: %s: custom field key */ 174 sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ), 175 array( 'status' => 500 ) 176 ); 177 } 178 179 $is_valid = rest_validate_value_from_schema( $value, $args['schema'], 'meta.' . $name ); 154 180 if ( is_wp_error( $is_valid ) ) { 155 181 $is_valid->add_data( array( 'status' => 400 ) ); … … 157 183 } 158 184 159 $value = rest_sanitize_value_from_schema( $ meta[ $name ], $args['schema'] );185 $value = rest_sanitize_value_from_schema( $value, $args['schema'] ); 160 186 161 187 if ( $args['single'] ) { … … 261 287 } 262 288 263 // `delete_metadata` removes _all_ instances of the value, so only call once. 264 $to_remove = array_unique( $to_remove ); 289 // `delete_metadata` removes _all_ instances of the value, so only call once. Otherwise, 290 // `delete_metadata` will return false for subsequent calls of the same value. 291 // Use serialization to produce a predictable string that can be used by array_unique. 292 $to_remove = array_map( 'maybe_unserialize', array_unique( array_map( 'maybe_serialize', $to_remove ) ) ); 265 293 266 294 foreach ( $to_remove as $value ) { … … 394 422 $type = ! empty( $rest_args['schema']['type'] ) ? $rest_args['schema']['type'] : $type; 395 423 396 if ( ! in_array( $type, array( 'string', 'boolean', 'integer', 'number' ) ) ) { 424 if ( null === $rest_args['schema']['default'] ) { 425 $rest_args['schema']['default'] = $this->get_default_for_type( $type ); 426 } 427 428 $rest_args['schema'] = $this->default_additional_properties_to_false( $rest_args['schema'] ); 429 430 if ( ! in_array( $type, array( 'string', 'boolean', 'integer', 'number', 'array', 'object' ) ) ) { 397 431 continue; 398 432 } 399 433 400 434 if ( empty( $rest_args['single'] ) ) { 401 $rest_args['schema']['items'] = array( 402 'type' => $rest_args['type'], 435 $rest_args['schema'] = array( 436 'type' => 'array', 437 'items' => $rest_args['schema'], 403 438 ); 404 $rest_args['schema']['type'] = 'array';405 439 } 406 440 … … 453 487 */ 454 488 public static function prepare_value( $value, $request, $args ) { 455 $type = $args['schema']['type']; 456 457 // For multi-value fields, check the item type instead. 458 if ( 'array' === $type && ! empty( $args['schema']['items']['type'] ) ) { 459 $type = $args['schema']['items']['type']; 460 } 461 462 switch ( $type ) { 463 case 'string': 464 $value = (string) $value; 465 break; 466 case 'integer': 467 $value = (int) $value; 468 break; 469 case 'number': 470 $value = (float) $value; 471 break; 472 case 'boolean': 473 $value = (bool) $value; 474 break; 475 } 476 477 // Don't allow objects to be output. 478 if ( is_object( $value ) && ! ( $value instanceof JsonSerializable ) ) { 489 490 if ( $args['single'] ) { 491 $schema = $args['schema']; 492 } else { 493 $schema = $args['schema']['items']; 494 } 495 496 if ( is_wp_error( rest_validate_value_from_schema( $value, $schema ) ) ) { 479 497 return null; 480 498 } 481 499 482 return $value;500 return rest_sanitize_value_from_schema( $value, $schema ); 483 501 } 484 502 … … 500 518 return $value; 501 519 } 520 521 /** 522 * Recursively add additionalProperties = false to all objects in a schema if no additionalProperties setting 523 * is specified. 524 * 525 * This is needed to restrict properties of objects in meta values to only 526 * registered items, as the REST API will allow additional properties by 527 * default. 528 * 529 * @since 5.3.0 530 * 531 * @param array $schema The schema array. 532 * @return array 533 */ 534 protected function default_additional_properties_to_false( $schema ) { 535 switch ( $schema['type'] ) { 536 case 'object': 537 foreach ( $schema['properties'] as $key => $child_schema ) { 538 $schema['properties'][ $key ] = $this->default_additional_properties_to_false( $child_schema ); 539 } 540 541 if ( ! isset( $schema['additionalProperties'] ) ) { 542 $schema['additionalProperties'] = false; 543 } 544 break; 545 case 'array': 546 $schema['items'] = $this->default_additional_properties_to_false( $schema['items'] ); 547 break; 548 } 549 550 return $schema; 551 } 552 553 /** 554 * Gets the default value for a schema type. 555 * 556 * @since 5.3.0 557 * 558 * @param string $type 559 * @return mixed 560 */ 561 protected function get_default_for_type( $type ) { 562 switch ( $type ) { 563 case 'string': 564 return ''; 565 case 'boolean': 566 return false; 567 case 'integer': 568 return 0; 569 case 'number': 570 return 0.0; 571 case 'array': 572 return array(); 573 case 'object': 574 return array(); 575 default: 576 return null; 577 } 578 } 502 579 }
Note: See TracChangeset
for help on using the changeset viewer.