diff --git a/src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php b/src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php index 5b7240ddc6..490cf346b8 100644 --- a/src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php +++ b/src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php @@ -350,9 +350,17 @@ abstract class WP_REST_Meta_Fields { // Do the exact same check for a duplicate value as in update_metadata() to avoid update_metadata() returning false. $old_value = get_metadata( $meta_type, $object_id, $meta_key ); $subtype = get_object_subtype( $meta_type, $object_id ); + $args = $this->get_registered_fields()[ $meta_key ]; if ( 1 === count( $old_value ) ) { - if ( (string) sanitize_meta( $meta_key, $value, $meta_type, $subtype ) === $old_value[0] ) { + $sanitized = sanitize_meta( $meta_key, $value, $meta_type, $subtype ); + + if ( in_array( $args['type'], array( 'string', 'number', 'integer', 'boolean' ), true ) ) { + // The return value of get_metadata will always be a string for scalar types. + $sanitized = (string) $sanitized; + } + + if ( $sanitized === $old_value[0] ) { return true; } } diff --git a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php index 71bcfdcd87..1db1798fd6 100644 --- a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php +++ b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php @@ -2120,6 +2120,90 @@ class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { $this->assertEquals( array( 'BuddyPress' ), $meta[1] ); } + /** + * @ticket 47928 + */ + public function test_update_meta_with_unchanged_array_values() { + register_post_meta( + 'post', + 'list', + array( + 'single' => true, + 'type' => 'array', + 'show_in_rest' => array( + 'schema' => array( + 'type' => 'array', + 'items' => array( + 'type' => 'string', + ), + ), + ), + ) + ); + + add_post_meta( self::$post_id, 'list', array( 'WordCamp' ) ); + + $this->grant_write_permission(); + + $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) ); + $request->set_body_params( + array( + 'meta' => array( + 'list' => array( 'WordCamp' ), + ), + ) + ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $data = $response->get_data(); + $this->assertEquals( array( 'WordCamp' ), $data['meta']['list'] ); + } + + /** + * @ticket 47928 + */ + public function test_update_meta_with_unchanged_object_values() { + register_post_meta( + 'post', + 'object', + array( + 'single' => true, + 'type' => 'object', + 'show_in_rest' => array( + 'schema' => array( + 'type' => 'object', + 'properties' => array( + 'project' => array( + 'type' => 'string', + ), + ), + ), + ), + ) + ); + + add_post_meta( self::$post_id, 'object', array( 'project' => 'WordCamp' ) ); + + $this->grant_write_permission(); + + $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) ); + $request->set_body_params( + array( + 'meta' => array( + 'object' => array( 'project' => 'WordCamp' ), + ), + ) + ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $data = $response->get_data(); + $this->assertEquals( array( 'project' => 'WordCamp' ), $data['meta']['object'] ); + } + /** * Internal function used to disable an insert query which * will trigger a wpdb error for testing purposes.