Make WordPress Core

Changeset 47181


Ignore:
Timestamp:
02/05/2020 01:31:38 AM (7 years ago)
Author:
SergeyBiryukov
Message:

Posts, Post Types: Fail gracefully when checking whether a single post with an unregistered post status should be displayed in WP_Query::get_posts().

If the post status is not registered, assume it's not public, but still allow access to users with edit permissions (same as for a protected post status, e.g. draft), so that they could recover orphaned content.

Add unit tests.

Follow-up to [47178].

Props roytanck, SergeyBiryukov.
Fixes #48653.

Location:
trunk
Files:
2 edited

Legend:

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

    r47180 r47181  
    30673067                if ( ! empty( $this->posts ) && ( $this->is_single || $this->is_page ) ) {
    30683068                        $status = get_post_status( $this->posts[0] );
     3069
    30693070                        if ( 'attachment' === $this->posts[0]->post_type && 0 === (int) $this->posts[0]->post_parent ) {
    30703071                                $this->is_page       = false;
     
    30723073                                $this->is_attachment = true;
    30733074                        }
    3074                         $post_status_obj = get_post_status_object( $status );
    30753075
    30763076                        // If the post_status was specifically requested, let it pass through.
    3077                         if ( ! $post_status_obj->public && ! in_array( $status, $q_status ) ) {
    3078 
    3079                                 if ( ! is_user_logged_in() ) {
    3080                                         // User must be logged in to view unpublished posts.
    3081                                         $this->posts = array();
    3082                                 } else {
    3083                                         if ( $post_status_obj->protected ) {
    3084                                                 // User must have edit permissions on the draft to preview.
    3085                                                 if ( ! current_user_can( $edit_cap, $this->posts[0]->ID ) ) {
    3086                                                         $this->posts = array();
     3077                        if ( ! in_array( $status, $q_status ) ) {
     3078                                $post_status_obj = get_post_status_object( $status );
     3079
     3080                                if ( $post_status_obj && ! $post_status_obj->public ) {
     3081                                        if ( ! is_user_logged_in() ) {
     3082                                                // User must be logged in to view unpublished posts.
     3083                                                $this->posts = array();
     3084                                        } else {
     3085                                                if ( $post_status_obj->protected ) {
     3086                                                        // User must have edit permissions on the draft to preview.
     3087                                                        if ( ! current_user_can( $edit_cap, $this->posts[0]->ID ) ) {
     3088                                                                $this->posts = array();
     3089                                                        } else {
     3090                                                                $this->is_preview = true;
     3091                                                                if ( 'future' != $status ) {
     3092                                                                        $this->posts[0]->post_date = current_time( 'mysql' );
     3093                                                                }
     3094                                                        }
     3095                                                } elseif ( $post_status_obj->private ) {
     3096                                                        if ( ! current_user_can( $read_cap, $this->posts[0]->ID ) ) {
     3097                                                                $this->posts = array();
     3098                                                        }
    30873099                                                } else {
    3088                                                         $this->is_preview = true;
    3089                                                         if ( 'future' != $status ) {
    3090                                                                 $this->posts[0]->post_date = current_time( 'mysql' );
    3091                                                         }
    3092                                                 }
    3093                                         } elseif ( $post_status_obj->private ) {
    3094                                                 if ( ! current_user_can( $read_cap, $this->posts[0]->ID ) ) {
    30953100                                                        $this->posts = array();
    30963101                                                }
    3097                                         } else {
     3102                                        }
     3103                                } elseif ( ! $post_status_obj ) {
     3104                                        // Post status is not registered, assume it's not public.
     3105                                        if ( ! current_user_can( $edit_cap, $this->posts[0]->ID ) ) {
    30983106                                                $this->posts = array();
    30993107                                        }
  • trunk/tests/phpunit/tests/query/postStatus.php

    r46586 r47181  
    263263        }
    264264
     265        public function test_single_post_with_nonpublic_status_should_not_be_shown_for_any_user() {
     266                register_post_type( 'foo_pt' );
     267                register_post_status( 'foo_ps', array( 'public' => false ) );
     268                $p = self::factory()->post->create(
     269                        array(
     270                                'post_status' => 'foo_ps',
     271                                'post_author' => self::$author_user_id,
     272                        )
     273                );
     274
     275                wp_set_current_user( self::$editor_user_id );
     276
     277                $q = new WP_Query(
     278                        array(
     279                                'p' => $p,
     280                        )
     281                );
     282
     283                $this->assertEmpty( $q->posts );
     284        }
     285
    265286        public function test_single_post_with_nonpublic_and_protected_status_should_not_be_shown_for_user_who_cannot_edit_others_posts() {
    266287                register_post_type( 'foo_pt' );
     
    371392        }
    372393
    373         public function test_single_post_with_nonpublic_and_protected_status_should_not_be_shown_for_any_user() {
    374                 register_post_type( 'foo_pt' );
    375                 register_post_status( 'foo_ps', array( 'public' => false ) );
    376                 $p = self::factory()->post->create(
    377                         array(
    378                                 'post_status' => 'foo_ps',
    379                                 'post_author' => self::$author_user_id,
    380                         )
    381                 );
    382 
    383                 wp_set_current_user( self::$editor_user_id );
    384 
    385                 $q = new WP_Query(
    386                         array(
    387                                 'p' => $p,
    388                         )
    389                 );
    390 
    391                 $this->assertEmpty( $q->posts );
     394        /**
     395         * @ticket 48653
     396         */
     397        public function test_single_post_with_nonexisting_status_should_not_be_shown_for_user_who_cannot_edit_others_posts() {
     398                register_post_type( 'foo_pt' );
     399                register_post_status( 'foo_ps', array( 'public' => true ) );
     400                $p = self::factory()->post->create(
     401                        array(
     402                                'post_status' => 'foo_ps',
     403                                'post_author' => self::$editor_user_id,
     404                        )
     405                );
     406                _unregister_post_status( 'foo_ps' );
     407
     408                wp_set_current_user( self::$author_user_id );
     409
     410                $q = new WP_Query(
     411                        array(
     412                                'p' => $p,
     413                        )
     414                );
     415
     416                $this->assertEmpty( $q->posts );
     417        }
     418
     419        /**
     420         * @ticket 48653
     421         */
     422        public function test_single_post_with_nonexisting_status_should_be_shown_for_user_who_can_edit_others_posts() {
     423                register_post_type( 'foo_pt' );
     424                register_post_status( 'foo_ps', array( 'public' => true ) );
     425                $p = self::factory()->post->create(
     426                        array(
     427                                'post_status' => 'foo_ps',
     428                                'post_author' => self::$author_user_id,
     429                        )
     430                );
     431                _unregister_post_status( 'foo_ps' );
     432
     433                wp_set_current_user( self::$editor_user_id );
     434
     435                $q = new WP_Query(
     436                        array(
     437                                'p' => $p,
     438                        )
     439                );
     440
     441                $this->assertEquals( array( $p ), wp_list_pluck( $q->posts, 'ID' ) );
    392442        }
    393443
Note: See TracChangeset for help on using the changeset viewer.