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 60c3c3ab24..7b46905a7a 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 @@ -141,6 +141,7 @@ abstract class WP_REST_Meta_Fields { */ public function update_value( $meta, $object_id ) { $fields = $this->get_registered_fields(); + $error = new WP_Error(); foreach ( $fields as $meta_key => $args ) { $name = $args['name']; @@ -163,35 +164,38 @@ abstract class WP_REST_Meta_Fields { $current = get_metadata( $this->get_meta_type(), $object_id, $meta_key, true ); if ( is_wp_error( rest_validate_value_from_schema( $current, $args['schema'] ) ) ) { - return new WP_Error( + $error->add( 'rest_invalid_stored_value', /* translators: %s: Custom field key. */ sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ), array( 'status' => 500 ) ); + continue; } } $result = $this->delete_meta_value( $object_id, $meta_key, $name ); if ( is_wp_error( $result ) ) { - return $result; + $error->merge_from( $result ); } continue; } if ( ! $args['single'] && is_array( $value ) && count( array_filter( $value, 'is_null' ) ) ) { - return new WP_Error( + $error->add( 'rest_invalid_stored_value', /* translators: %s: Custom field key. */ sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ), array( 'status' => 500 ) ); + continue; } $is_valid = rest_validate_value_from_schema( $value, $args['schema'], 'meta.' . $name ); if ( is_wp_error( $is_valid ) ) { $is_valid->add_data( array( 'status' => 400 ) ); - return $is_valid; + $error->merge_from( $is_valid ); + continue; } $value = rest_sanitize_value_from_schema( $value, $args['schema'] ); @@ -203,10 +207,15 @@ abstract class WP_REST_Meta_Fields { } if ( is_wp_error( $result ) ) { - return $result; + $error->merge_from( $result ); + continue; } } + if ( $error->has_errors() ) { + return $error; + } + return null; } 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 dcf39f59c9..1418db19db 100644 --- a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php +++ b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php @@ -3095,6 +3095,52 @@ class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { $this->assertSame( 'Goodnight Moon', $schema['default'] ); } + /** + * @ticket 48823 + */ + public function test_multiple_errors_are_returned_at_once() { + $this->grant_write_permission(); + register_post_meta( + 'post', + 'error_1', + array( + 'single' => true, + 'show_in_rest' => array( + 'schema' => array( + 'enum' => array( 'a', 'b' ), + ), + ), + ) + ); + register_post_meta( + 'post', + 'error_2', + array( + 'single' => true, + 'show_in_rest' => array( + 'schema' => array( + 'minLength' => 1, + ), + ), + ) + ); + + $request = new WP_REST_Request( 'PUT', '/wp/v2/posts/' . self::$post_id ); + $request->set_body_params( + array( + 'meta' => array( + 'error_1' => 'c', + 'error_2' => '', + ), + ) + ); + $response = rest_do_request( $request ); + $error = $response->as_error(); + $this->assertWPError( $error ); + $this->assertContains( 'meta.error_1 is not one of a and b.', $error->get_error_messages() ); + $this->assertContains( 'meta.error_2 must be at least 1 character long.', $error->get_error_messages() ); + } + /** * Internal function used to disable an insert query which * will trigger a wpdb error for testing purposes.