Make WordPress Core

Changeset 59937


Ignore:
Timestamp:
03/05/2025 10:12:06 PM (9 months ago)
Author:
peterwilsoncc
Message:

Query: Ensure preview links show autosave content to logged in users.

Ensures that the global post object is populated with the autosave post when a preview link is used for a published post. This allows post authors to preview the changes to a post prior to publication.

This modifies WP_Query::the_post() to only call get_post() if WP_Query::$posts does not contain WP_Post objects. Other data types (stdClass or numeric) indicates partial data was queried, a WP_Post object indicates the full data was queried and populated.

Props peterwilsoncc, mamaduka, wildworks, audrasjb.
Fixes #56992.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-query.php

    r59919 r59937  
    37803780        $post = $this->next_post();
    37813781
    3782         // Get the post ID.
    3783         if ( is_object( $post ) ) {
    3784             $global_post_id = $post->ID;
    3785         } else {
    3786             $global_post_id = $post;
    3787         }
    3788 
    3789         // Ensure the global $post is the full post object.
    3790         $post = get_post( $global_post_id );
     3782        // Ensure a full post object is available.
     3783        if ( $post instanceof stdClass ) {
     3784            // stdClass indicates that a partial post object was queried.
     3785            $post = get_post( $post->ID );
     3786        } elseif ( is_numeric( $post ) ) {
     3787            // Numeric indicates that only post IDs were queried.
     3788            $post = get_post( $post );
     3789        }
     3790
     3791        // Set up the global post object for the loop.
    37913792        $this->setup_postdata( $post );
    37923793    }
  • trunk/tests/phpunit/tests/query/thePost.php

    r59919 r59937  
    192192        );
    193193    }
     194
     195    /**
     196     * Ensure draft content is shown for post previews and permalinks for logged in users.
     197     *
     198     * @ticket 56992
     199     */
     200    public function test_post_preview_links_draft_posts() {
     201        $user_id = self::$author_ids[0];
     202        wp_set_current_user( $user_id );
     203        $draft_post = $this->factory()->post->create(
     204            array(
     205                'post_status'  => 'draft',
     206                'post_author'  => $user_id,
     207                'post_content' => 'ticket 56992',
     208            )
     209        );
     210
     211        // Ensure the global post is populated with the draft content for the preview link.
     212        $this->go_to( get_preview_post_link( $draft_post ) );
     213        if ( have_posts() ) {
     214            the_post();
     215        }
     216        $this->assertSame( 'ticket 56992', get_the_content(), 'Preview link should show draft content to logged in user' );
     217
     218        // Ensure the global post is populated with the draft content for the permalink.
     219        $this->go_to( get_permalink( $draft_post ) );
     220        if ( have_posts() ) {
     221            the_post();
     222        }
     223        $this->assertSame( 'ticket 56992', get_the_content(), 'Permalink should show draft content to logged in user' );
     224
     225        // Ensure the global post is not populated with the draft content for the preview link when logged out.
     226        wp_set_current_user( 0 );
     227        $this->go_to( get_preview_post_link( $draft_post ) );
     228        if ( have_posts() ) {
     229            the_post();
     230        }
     231        $this->assertEmpty( get_the_content(), 'Preview link should not show draft content to logged out users' );
     232
     233        // Ensure the global post is not populated with the draft content for the permalink when logged out.
     234        $this->go_to( get_permalink( $draft_post ) );
     235        if ( have_posts() ) {
     236            the_post();
     237        }
     238        $this->assertEmpty( get_the_content(), 'Permalink should not show draft content to logged out users' );
     239    }
     240
     241    /**
     242     * Ensure autosave content is shown for post previews.
     243     *
     244     * @ticket 56992
     245     */
     246    public function test_post_preview_links_autosaves() {
     247        $user_id = self::$author_ids[0];
     248        wp_set_current_user( $user_id );
     249        $published_post = $this->factory()->post->create(
     250            array(
     251                'post_status'  => 'publish',
     252                'post_author'  => $user_id,
     253                'post_content' => 'ticket 56992',
     254            )
     255        );
     256
     257        // Create an autosave for the published post.
     258        $autosave                 = get_post( $published_post, ARRAY_A );
     259        $autosave['post_ID']      = $published_post;
     260        $autosave['post_content'] = 'ticket 56992 edited';
     261        wp_create_post_autosave( $autosave );
     262
     263        // Set up the preview $_GET parameters.
     264        $nonce                       = wp_create_nonce( 'post_preview_' . $published_post );
     265        $query_args['preview_id']    = $published_post;
     266        $query_args['preview_nonce'] = $nonce;
     267        $post_preview_link           = get_preview_post_link( $published_post, $query_args );
     268
     269        /*
     270         * Set up the GET parameters for the preview link.
     271         *
     272         * _show_post_preview() checks the $_GET super global for preview
     273         * and nonce parameters. It needs to run prior to the global query
     274         * being set up in WP_Query (via $this->go_to()), so the preview
     275         * parameters are created here to ensure _show_post_preview()
     276         * runs correctly.
     277         */
     278        $_GET['preview_id']    = $published_post;
     279        $_GET['preview_nonce'] = $nonce;
     280        _show_post_preview();
     281
     282        // Ensure the global post is populated with the autosave content for the preview link.
     283        $this->go_to( $post_preview_link );
     284        if ( have_posts() ) {
     285            the_post();
     286        }
     287        $this->assertSame( 'ticket 56992 edited', get_the_content(), 'Preview link should show autosave content to logged in user' );
     288
     289        // Ensure the global post is populated with the published content for the permalink.
     290        $this->go_to( get_permalink( $published_post ) );
     291        if ( have_posts() ) {
     292            the_post();
     293        }
     294        $this->assertSame( 'ticket 56992', get_the_content(), 'Permalink should show published content to logged in user' );
     295
     296        wp_set_current_user( 0 );
     297
     298        // New user, new nonce; set up the preview $_GET parameters.
     299        $nonce                       = wp_create_nonce( 'post_preview_' . $published_post );
     300        $query_args['preview_id']    = $published_post;
     301        $query_args['preview_nonce'] = $nonce;
     302        $post_preview_link           = get_preview_post_link( $published_post, $query_args );
     303
     304        /*
     305         * Set up the GET parameters for the preview link.
     306         *
     307         * _show_post_preview() checks the $_GET super global for preview
     308         * and nonce parameters. It needs to run prior to the global query
     309         * being set up in WP_Query (via $this->go_to()), so the preview
     310         * parameters are created here to ensure _show_post_preview()
     311         * runs correctly.
     312         */
     313        $_GET['preview_id']    = $published_post;
     314        $_GET['preview_nonce'] = $nonce;
     315        _show_post_preview();
     316
     317        // Ensure the global post is not populated with the draft content for the preview link when logged out.
     318        $this->go_to( $post_preview_link );
     319        if ( have_posts() ) {
     320            the_post();
     321        }
     322        $this->assertSame( 'ticket 56992', get_the_content(), 'Preview link should show published content to logged out users' );
     323
     324        // Ensure the global post is not populated with the draft content for the permalink when logged out.
     325        $this->go_to( get_permalink( $published_post ) );
     326        if ( have_posts() ) {
     327            the_post();
     328        }
     329        $this->assertSame( 'ticket 56992', get_the_content(), 'Permalink should show published content to logged out users' );
     330    }
    194331}
Note: See TracChangeset for help on using the changeset viewer.