Make WordPress Core

Changeset 62399


Ignore:
Timestamp:
05/21/2026 10:18:57 AM (3 months ago)
Author:
gziolo
Message:

EST API: Preserve custom status for ability validation errors

he REST run controller for the Abilities API already preserves a custom
HTTP status returned by wp_ability_normalize_input filter errors. Apply
the same behavior to validation errors from wp_ability_validate_input:
a WP_Error is only defaulted to a 400 status when it does not already
include one.

The shared defaulting logic is extracted into a new private
ensure_error_status() helper and reused for both normalization and
validation errors.

Follow-up to [62398].
See #64311.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-abilities-v1-run-controller.php

    r62397 r62399  
    162162                $input = $ability->normalize_input( $input );
    163163                if ( is_wp_error( $input ) ) {
    164                         $error_data = $input->get_error_data();
    165                         if ( ! is_array( $error_data ) || ! isset( $error_data['status'] ) ) {
    166                                 $input->add_data( array( 'status' => 400 ) );
    167                         }
    168 
    169                         return $input;
     164                        return $this->ensure_error_status( $input, 400 );
    170165                }
    171166
    172167                $is_valid = $ability->validate_input( $input );
    173168                if ( is_wp_error( $is_valid ) ) {
    174                         $is_valid->add_data( array( 'status' => 400 ) );
    175                         return $is_valid;
     169                        return $this->ensure_error_status( $is_valid, 400 );
    176170                }
    177171
     
    190184
    191185                return true;
     186        }
     187
     188        /**
     189         * Ensures a WP_Error object carries an HTTP status, adding a default when none is set.
     190         *
     191         * @since 7.1.0
     192         *
     193         * @param WP_Error $error  Error object to update.
     194         * @param int      $status HTTP status code to add if not already present.
     195         * @return WP_Error The error object, with a default status when needed.
     196         */
     197        private function ensure_error_status( WP_Error $error, int $status ): WP_Error {
     198                $error_data = $error->get_error_data();
     199                if ( ! is_array( $error_data ) || ! isset( $error_data['status'] ) ) {
     200                        $error->add_data( array( 'status' => $status ) );
     201                }
     202
     203                return $error;
    192204        }
    193205
  • trunk/tests/phpunit/tests/rest-api/wpRestAbilitiesV1RunController.php

    r62397 r62399  
    978978
    979979        /**
     980         * Tests that a validation filter error defaults to a 400 REST response.
     981         *
     982         * @ticket 64311
     983         */
     984        public function test_validate_input_filter_error_defaults_to_bad_request_status(): void {
     985                $filter = static function () {
     986                        return new WP_Error( 'validate_rejected', 'Rejected input.' );
     987                };
     988
     989                add_filter( 'wp_ability_validate_input', $filter );
     990
     991                $request = new WP_REST_Request( 'POST', '/wp-abilities/v1/abilities/test/calculator/run' );
     992                $request->set_header( 'Content-Type', 'application/json' );
     993                $request->set_body(
     994                        wp_json_encode(
     995                                array(
     996                                        'input' => array(
     997                                                'a' => 5,
     998                                                'b' => 3,
     999                                        ),
     1000                                )
     1001                        )
     1002                );
     1003
     1004                $response = $this->server->dispatch( $request );
     1005
     1006                remove_filter( 'wp_ability_validate_input', $filter );
     1007
     1008                $this->assertSame( 400, $response->get_status() );
     1009                $data = $response->get_data();
     1010                $this->assertSame( 'validate_rejected', $data['code'] );
     1011                $this->assertSame( 'Rejected input.', $data['message'] );
     1012        }
     1013
     1014        /**
     1015         * Tests that a validation filter error with custom status keeps that status.
     1016         *
     1017         * @ticket 64311
     1018         */
     1019        public function test_validate_input_filter_error_preserves_custom_status(): void {
     1020                $filter = static function () {
     1021                        return new WP_Error(
     1022                                'validate_unprocessable',
     1023                                'Input cannot be validated.',
     1024                                array( 'status' => 422 )
     1025                        );
     1026                };
     1027
     1028                add_filter( 'wp_ability_validate_input', $filter );
     1029
     1030                $request = new WP_REST_Request( 'POST', '/wp-abilities/v1/abilities/test/calculator/run' );
     1031                $request->set_header( 'Content-Type', 'application/json' );
     1032                $request->set_body(
     1033                        wp_json_encode(
     1034                                array(
     1035                                        'input' => array(
     1036                                                'a' => 5,
     1037                                                'b' => 3,
     1038                                        ),
     1039                                )
     1040                        )
     1041                );
     1042
     1043                $response = $this->server->dispatch( $request );
     1044
     1045                remove_filter( 'wp_ability_validate_input', $filter );
     1046
     1047                $this->assertSame( 422, $response->get_status() );
     1048                $data = $response->get_data();
     1049                $this->assertSame( 'validate_unprocessable', $data['code'] );
     1050                $this->assertSame( 'Input cannot be validated.', $data['message'] );
     1051        }
     1052
     1053        /**
    9801054         * Test ability without annotations defaults to POST method.
    9811055         *
Note: See TracChangeset for help on using the changeset viewer.