Make WordPress Core

Changeset 49302


Ignore:
Timestamp:
10/24/2020 04:02:34 PM (4 years ago)
Author:
TimothyBlynJacobs
Message:

REST API: Don't validate status if it hasn't changed.

In particular, this allows for sending status=inherit to an attachment if it's current status is inherit. This status would be rejected because it is an "internal" post status which isn't exposed.

As a general rule, a developer should always be able to PUT back a GET response without error.

Props dfenton, pputzer, TimothyBlynJacobs.
Fixes #40399.

Location:
trunk
Files:
2 edited

Legend:

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

    r49301 r49302  
    10531053     */
    10541054    protected function prepare_item_for_database( $request ) {
    1055         $prepared_post = new stdClass();
     1055        $prepared_post  = new stdClass();
     1056        $current_status = '';
    10561057
    10571058        // Post ID.
     
    10631064
    10641065            $prepared_post->ID = $existing_post->ID;
     1066            $current_status    = $existing_post->post_status;
    10651067        }
    10661068
     
    11061108
    11071109        // Post status.
    1108         if ( ! empty( $schema['properties']['status'] ) && isset( $request['status'] ) ) {
     1110        if (
     1111            ! empty( $schema['properties']['status'] ) &&
     1112            isset( $request['status'] ) &&
     1113            ( ! $current_status || $current_status !== $request['status'] )
     1114        ) {
    11091115            $status = $this->handle_status_param( $request['status'], $post_type );
    11101116
     
    12541260        return apply_filters( "rest_pre_insert_{$this->post_type}", $prepared_post, $request );
    12551261
     1262    }
     1263
     1264    /**
     1265     * Checks whether the status is valid for the given post.
     1266     *
     1267     * Allows for sending an update request with the current status, even if that status would not be acceptable.
     1268     *
     1269     * @since 5.6.0
     1270     *
     1271     * @param string          $status  The provided status.
     1272     * @param WP_REST_Request $request The request object.
     1273     * @param string          $param   The parameter name.
     1274     * @return true|WP_Error True if the status is valid, or WP_Error if not.
     1275     */
     1276    public function check_status( $status, $request, $param ) {
     1277        if ( $request['id'] ) {
     1278            $post = $this->get_post( $request['id'] );
     1279
     1280            if ( ! is_wp_error( $post ) && $post->post_status === $status ) {
     1281                return true;
     1282            }
     1283        }
     1284
     1285        $args = $request->get_attributes()['args'][ $param ];
     1286
     1287        return rest_validate_value_from_schema( $status, $args, $param );
    12561288    }
    12571289
     
    21162148                    'enum'        => array_keys( get_post_stati( array( 'internal' => false ) ) ),
    21172149                    'context'     => array( 'view', 'edit' ),
     2150                    'arg_options' => array(
     2151                        'validate_callback' => array( $this, 'check_status' ),
     2152                    ),
    21182153                ),
    21192154                'type'         => array(
  • trunk/tests/phpunit/tests/rest-api/rest-attachments-controller.php

    r49215 r49302  
    10051005        $request->set_param( 'post', $attachment_id );
    10061006        $response = rest_get_server()->dispatch( $request );
     1007        $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
     1008    }
     1009
     1010    /**
     1011     * @ticket 40399
     1012     */
     1013    public function test_update_item_with_existing_inherit_status() {
     1014        wp_set_current_user( self::$editor_id );
     1015        $parent_id     = self::factory()->post->create( array() );
     1016        $attachment_id = self::factory()->attachment->create_object(
     1017            $this->test_file,
     1018            $parent_id,
     1019            array(
     1020                'post_mime_type' => 'image/jpeg',
     1021                'post_excerpt'   => 'A sample caption',
     1022                'post_author'    => self::$editor_id,
     1023            )
     1024        );
     1025
     1026        $request = new WP_REST_Request( 'POST', '/wp/v2/media/' . $attachment_id );
     1027        $request->set_param( 'status', 'inherit' );
     1028        $response = rest_get_server()->dispatch( $request );
     1029
     1030        $this->assertNotWPError( $response->as_error() );
     1031        $this->assertEquals( 'inherit', $response->get_data()['status'] );
     1032    }
     1033
     1034    /**
     1035     * @ticket 40399
     1036     */
     1037    public function test_update_item_with_new_inherit_status() {
     1038        wp_set_current_user( self::$editor_id );
     1039        $attachment_id = self::factory()->attachment->create_object(
     1040            $this->test_file,
     1041            0,
     1042            array(
     1043                'post_mime_type' => 'image/jpeg',
     1044                'post_excerpt'   => 'A sample caption',
     1045                'post_author'    => self::$editor_id,
     1046                'post_status'    => 'private',
     1047            )
     1048        );
     1049
     1050        $request = new WP_REST_Request( 'POST', '/wp/v2/media/' . $attachment_id );
     1051        $request->set_param( 'status', 'inherit' );
     1052        $response = rest_get_server()->dispatch( $request );
     1053
    10071054        $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
    10081055    }
Note: See TracChangeset for help on using the changeset viewer.