[wp-trac] [WordPress Trac] #51829: BUG: get_queried_object() in pre_get_posts hook crashes author archive page get_queried_object() call

WordPress Trac noreply at wordpress.org
Thu Nov 19 22:57:58 UTC 2020


#51829: BUG: get_queried_object() in pre_get_posts hook crashes author archive page
get_queried_object() call
--------------------------+-----------------------------
 Reporter:  Tkama         |      Owner:  (none)
     Type:  defect (bug)  |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  General       |    Version:  5.5.3
 Severity:  normal        |   Keywords:
  Focuses:                |
--------------------------+-----------------------------
 Lets call `get_queried_object()` on `wp` action:

 {{{#!php
 <?php
 add_action( 'wp', function(){

         var_dump( get_queried_object() );

         // on author archive page //> object(WP_User)
         // on single post page    //> object(WP_Post)
         // on category page       //> object(WP_Post)
 } );

 }}}

 Now do the same, but call `get_queried_object()` on `pre_get_posts` action
 before:

 {{{#!php
 <?php
 add_action( 'wp', function(){

         var_dump( get_queried_object() );

         // on author archive page //> bool(false)
         // on single post page    //> object(WP_Post)
         // on category page       //> object(WP_Post)
 } );

 add_action( 'pre_get_posts', function(){
         get_queried_object();
 } );
 }}}

 As we can see we lose WP_User object in this case.


 == Why it happens?

 Because `get_queried_object()` get user only by `'author'` parameter:
 {{{#!php
 <?php
                 } elseif ( $this->is_author ) {
                         $this->queried_object_id = (int) $this->get(
 'author' );
                         $this->queried_object    = get_userdata(
 $this->queried_object_id );
                 }
 }}}

 but `WP_Query::parse_query()` sets `$this->is_author` by `'author_name'`
 parameter too (not only 'author'):
 {{{#!php
 <?php
                         if ( empty( $qv['author'] ) || ( '0' ==
 $qv['author'] ) ) {
                                 $this->is_author = false;
                         } else {
                                 $this->is_author = true;
                         }

                         if ( '' !== $qv['author_name'] ) {
                                 $this->is_author = true;
                         }
 }}}

 So `get_queried_object()` can't properly set user object when only
 `'author_name'` query_var is set by request.

 The `'author'` query_var is sets later by `WP_Query::get_posts()`:

 {{{#!php
 <?php
                 // Author stuff for nice URLs.

                 if ( '' !== $q['author_name'] ) {
                         if ( strpos( $q['author_name'], '/' ) !== false )
 {
                                 $q['author_name'] = explode( '/',
 $q['author_name'] );
                                 if ( $q['author_name'][ count(
 $q['author_name'] ) - 1 ] ) {
                                         $q['author_name'] =
 $q['author_name'][ count( $q['author_name'] ) - 1 ]; // No trailing slash.
                                 } else {
                                         $q['author_name'] =
 $q['author_name'][ count( $q['author_name'] ) - 2 ]; // There was a
 trailing slash.
                                 }
                         }
                         $q['author_name'] = sanitize_title_for_query(
 $q['author_name'] );
                         $q['author']      = get_user_by( 'slug',
 $q['author_name'] );
                         if ( $q['author'] ) {
                                 $q['author'] = $q['author']->ID;
                         }
                         $whichauthor .= " AND ({$wpdb->posts}.post_author
 = " . absint( $q['author'] ) . ')';
                 }
 }}}

 But it's too late and the earlier call of `get_queried_object()` already
 setup the `$wp_query->queried_object` property to NULL.



 == What to do?

 I think it's better to setup `'author'` query_var from `'author_name'`
 query_var earlier in `WP_Query::parse_query()` method, but not in
 `WP_Query::get_posts()`.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/51829>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list