WordPress.org

Make WordPress Core

Ticket #43316: 43316.patch

File 43316.patch, 8.7 KB (added by azaozz, 4 years ago)
  • src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

     
    657657         * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
    658658         */
    659659        public function update_item( $request ) {
    660                 $valid_check = $this->get_post( $request['id'] );
    661                 if ( is_wp_error( $valid_check ) ) {
    662                         return $valid_check;
     660                $existing_post = $this->get_post( $request['id'] );
     661                if ( is_wp_error( $existing_post ) ) {
     662                        return $existing_post;
    663663                }
    664664
    665                 $post = $this->prepare_item_for_database( $request );
     665                $new_post = $this->prepare_item_for_database( $request );
    666666
    667                 if ( is_wp_error( $post ) ) {
    668                         return $post;
     667                if ( is_wp_error( $new_post ) ) {
     668                        return $new_post;
    669669                }
    670670
    671                 // convert the post object to an array, otherwise wp_update_post will expect non-escaped input.
    672                 $post_id = wp_update_post( wp_slash( (array) $post ), true );
     671                // Keep the ID for later.
     672                $post_id = $new_post->ID;
    673673
     674                // The following functions expect array.
     675                $post_data = get_object_vars( $new_post );
     676
     677                // Autosave
     678                if ( ! empty( $request['is_autosave'] ) ) {
     679                        if ( ! defined( 'DOING_AUTOSAVE' ) ) {
     680                                define( 'DOING_AUTOSAVE', true );
     681                        }
     682
     683                        $post_author = get_current_user_id();
     684                        $autosave_id = 0;
     685
     686                        // Also needs to check post lock.
     687                        if ( $post_author == $existing_post->post_author && ( 'auto-draft' === $existing_post->post_status || 'draft' === $existing_post->post_status ) ) {
     688                                // Drafts and auto-drafts are just overwritten by autosave for the same user.
     689                                // Expects escaped input when array.
     690                                $post_id = wp_update_post( wp_slash( $post_data ), true );
     691                        } else {
     692                                // Store one autosave per author. If there is already an autosave, overwrite it.
     693                                if ( $old_autosave = wp_get_post_autosave( $post_data['ID'], $post_author ) ) {
     694                                        $new_autosave                = _wp_post_revision_data( $post_data, true );
     695                                        $new_autosave['ID']          = $old_autosave->ID;
     696                                        $new_autosave['post_author'] = $post_author;
     697
     698                                        // If the new autosave has the same content as the post, delete the autosave.
     699                                        $autosave_is_different = false;
     700
     701                                        foreach ( array_intersect( array_keys( $new_autosave ), array_keys( _wp_post_revision_fields( $existing_post ) ) ) as $field ) {
     702                                                if ( normalize_whitespace( $new_autosave[ $field ] ) != normalize_whitespace( $existing_post->$field ) ) {
     703                                                        $autosave_is_different = true;
     704                                                        break;
     705                                                }
     706                                        }
     707
     708                                        if ( ! $autosave_is_different ) {
     709                                                wp_delete_post_revision( $old_autosave->ID );
     710                                        } else {
     711                                                /**
     712                                                 * Fires before an autosave is stored via the REST API.
     713                                                 *
     714                                                 * @since 5.0.0
     715                                                 *
     716                                                 * @param array           $new_autosave Post array - the autosave that is about to be saved.
     717                                                 * @param WP_REST_Request $request      Request object.     
     718                                                 */
     719                                                do_action( 'rest_creating_autosave', $new_autosave, $request );
     720
     721                                                $autosave_id = wp_update_post( $new_autosave );
     722                                        }
     723                                } else {
     724                                        // Need to merge the autosave data with some of the existing post data.
     725                                        foreach ( array_keys( _wp_post_revision_fields( $existing_post ) ) as $field ) {
     726                                                if ( empty( $post_data[ $field ] ) ) {
     727                                                        $post_data[ $field ] = $existing_post->$field;
     728                                                }
     729                                        }
     730
     731                                        /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php */
     732                                        do_action( 'rest_creating_autosave', $post_data, $request );
     733
     734                                        $autosave_id = _wp_put_post_revision( $post_data, true );
     735                                }
     736
     737                                if ( is_wp_error( $autosave_id ) ) {
     738                                        // Pass on the error.
     739                                        $post_id = $autosave_id;
     740                                }
     741                        }
     742                } else {
     743                        // Expects escaped input when array.
     744                        $post_id = wp_update_post( wp_slash( $post_data ), true );
     745                }
     746
    674747                if ( is_wp_error( $post_id ) ) {
    675748                        if ( 'db_update_error' === $post_id->get_error_code() ) {
    676749                                $post_id->add_data( array( 'status' => 500 ) );
  • tests/phpunit/tests/rest-api/rest-posts-controller.php

     
    23632363                $this->assertEquals( $params['excerpt'], $post->post_excerpt );
    23642364        }
    23652365
     2366        public function test_rest_autosave_published_post() {
     2367                wp_set_current_user( self::$editor_id );
     2368
     2369                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     2370                $request->add_header( 'content-type', 'application/json' );
     2371
     2372                $autosave_data = $this->set_post_data(
     2373                        array(
     2374                                'id' => self::$post_id,
     2375                                'is_autosave' => true,
     2376                                'content' => 'Updated post content',
     2377                        )
     2378                );
     2379
     2380                $request->set_body( wp_json_encode( $autosave_data ) );
     2381                $response = $this->server->dispatch( $request );
     2382
     2383                $this->check_update_post_response( $response );
     2384                $new_data = $response->get_data();
     2385
     2386                // The published post shouldn't change.
     2387                $current_post = get_post( self::$post_id );
     2388                $this->assertEquals( $current_post->ID, $new_data['id'] );
     2389                $this->assertEquals( $current_post->post_title, $new_data['title']['raw'] );
     2390                $this->assertEquals( $current_post->post_content, $new_data['content']['raw'] );
     2391                $this->assertEquals( $current_post->post_excerpt, $new_data['excerpt']['raw'] );
     2392
     2393                $autosave_post = wp_get_post_autosave( self::$post_id );
     2394                $this->assertEquals( $autosave_data['title'], $autosave_post->post_title );
     2395                $this->assertEquals( $autosave_data['content'], $autosave_post->post_content );
     2396                $this->assertEquals( $autosave_data['excerpt'], $autosave_post->post_excerpt );
     2397        }
     2398
     2399        public function test_rest_autosave_draft_post_same_author() {
     2400                wp_set_current_user( self::$editor_id );
     2401
     2402                $post_data = array(
     2403                        'post_content' => 'Test post content',
     2404                        'post_title'   => 'Test post title',
     2405                        'post_excerpt' => 'Test post excerpt',
     2406                );
     2407                $post_id = wp_insert_post( $post_data );
     2408
     2409                $autosave_data = array(
     2410                        'id' => $post_id,
     2411                        'is_autosave' => true,
     2412                        'content' => 'Updated post content',
     2413                );
     2414
     2415                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', $post_id ) );
     2416                $request->add_header( 'content-type', 'application/json' );
     2417                $request->set_body( wp_json_encode( $autosave_data ) );
     2418                $response = $this->server->dispatch( $request );
     2419
     2420                $this->check_update_post_response( $response );
     2421                $new_data = $response->get_data();
     2422
     2423                // The draft post should be updated.
     2424                $this->assertEquals( $post_id, $new_data['id'] );
     2425                $this->assertEquals( $autosave_data['content'], $new_data['content']['raw'] );
     2426
     2427                $post = get_post( $post_id );
     2428                $this->assertEquals( $post_data['post_title'], $post->post_title );
     2429                $this->assertEquals( $autosave_data['content'], $post->post_content );
     2430                $this->assertEquals( $post_data['post_excerpt'], $post->post_excerpt );
     2431
     2432                wp_delete_post( $post_id );
     2433        }
     2434
     2435        public function test_rest_autosave_draft_post_different_author() {
     2436                wp_set_current_user( self::$editor_id );
     2437
     2438                $post_data = array(
     2439                        'post_content' => 'Test post content',
     2440                        'post_title'   => 'Test post title',
     2441                        'post_excerpt' => 'Test post excerpt',
     2442                        'post_author'  => ++self::$editor_id,
     2443                );
     2444                $post_id = wp_insert_post( $post_data );
     2445
     2446                $autosave_data = array(
     2447                        'id' => $post_id,
     2448                        'is_autosave' => true,
     2449                        'content' => 'Updated post content',
     2450                );
     2451
     2452                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', $post_id ) );
     2453                $request->add_header( 'content-type', 'application/json' );
     2454                $request->set_body( wp_json_encode( $autosave_data ) );
     2455                $response = $this->server->dispatch( $request );
     2456
     2457                $this->check_update_post_response( $response );
     2458                $new_data = $response->get_data();
     2459
     2460
     2461                // The draft post shouldn't change.
     2462                $current_post = get_post( $post_id );
     2463                $this->assertEquals( $current_post->ID, $new_data['id'] );
     2464                $this->assertEquals( $current_post->post_title, $new_data['title']['raw'] );
     2465                $this->assertEquals( $current_post->post_content, $new_data['content']['raw'] );
     2466                $this->assertEquals( $current_post->post_excerpt, $new_data['excerpt']['raw'] );
     2467
     2468                $autosave_post = wp_get_post_autosave( $post_id );
     2469                // No changes
     2470                $this->assertEquals( $current_post->post_title, $autosave_post->post_title );
     2471                $this->assertEquals( $current_post->post_excerpt, $autosave_post->post_excerpt );
     2472
     2473                // Has changes
     2474                $this->assertEquals( $autosave_data['content'], $autosave_post->post_content );
     2475
     2476                wp_delete_post( $post_id );
     2477        }
     2478
    23662479        public function test_rest_update_post_raw() {
    23672480                wp_set_current_user( self::$editor_id );
    23682481