REST API: Improve error handling in REST meta fields

This update modifies the error handling mechanism in the REST API meta fields functionality. Instead of halting execution and returning on the first encountered error, it now collects all errors in a WP_Error object and continues execution. Thus, this enhancement enables handling and displaying of multiple errors in a single response, improving the debugging process. 

Props TimothyBlynJacobs, spacedmonkey, hellofromTonya, oglekler. 
Fixes #48823.

git-svn-id: https://develop.svn.wordpress.org/trunk@57611 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Jonny Harris 2024-02-13 09:55:38 +00:00
parent 2a6fee5537
commit 57b4193b9a
2 changed files with 60 additions and 5 deletions

View File

@ -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;
}

View File

@ -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.