WordPress.org

Make WordPress Core

#51829 closed defect (bug) (duplicate)

BUG: get_queried_object() in pre_get_posts hook crashes author archive page get_queried_object() call

Reported by: Tkama Owned by:
Milestone: Priority: normal
Severity: normal Version: 5.5.3
Component: Query Keywords:
Focuses: Cc:

Description

Lets call get_queried_object() on wp action:

<?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
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
                } 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
                        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
                // 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().

Change History (1)

#1 @SergeyBiryukov
11 months ago

  • Component changed from General to Query
  • Milestone Awaiting Review deleted
  • Resolution set to duplicate
  • Status changed from new to closed

Hi there, welcome back to WordPress Trac!

Thanks for the report, we're already tracking this issue in #27015.

Note: See TracTickets for help on using tickets.