[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