Skip to content

Commit acb4554

Browse files
committed
Query: Set is_singular in the get_posts() static front page backstop.
The static front page backstop in `WP_Query::get_posts()` sets `is_page = true` and `is_home = false`, but did not update `is_singular`. This caused the query to generate incorrect SQL — using `post_type = 'post'` instead of `post_type = 'page'` — and return zero results. The equivalent check in `parse_query()` correctly maintains the invariant by recalculating `is_singular` at line 1135. The `get_posts()` backstop now does the same. The backstop fires when `parse_query()` fails to detect the static front page because `$this->query` contains unexpected public query vars (anything not in the allowlist of `preview`, `page`, `paged`, `cpage`). This can happen when a plugin registers a query var that collides with a parameter WordPress core uses in preview URLs. Fixes #65072.
1 parent 8e3998b commit acb4554

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

src/wp-includes/class-wp-query.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,6 +2041,7 @@ public function get_posts() {
20412041

20422042
if ( $this->is_home && ( empty( $this->query ) || 'true' === $query_vars['preview'] ) && ( 'page' === get_option( 'show_on_front' ) ) && get_option( 'page_on_front' ) ) {
20432043
$this->is_page = true;
2044+
$this->is_singular = true;
20442045
$this->is_home = false;
20452046
$query_vars['page_id'] = get_option( 'page_on_front' );
20462047
}

tests/phpunit/tests/query/conditionals.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,48 @@ public function test_page_on_front() {
7272
delete_option( 'page_for_posts' );
7373
}
7474

75+
/**
76+
* The get_posts() backstop should set is_singular when promoting a home
77+
* query to a static front page query. Without is_singular, the SQL
78+
* defaults to post_type = 'post' and returns zero results.
79+
*
80+
* @ticket 65072
81+
*
82+
* @covers WP_Query::get_posts
83+
*/
84+
public function test_page_on_front_backstop_sets_is_singular_with_extra_query_vars() {
85+
$page_on_front = self::factory()->post->create(
86+
array(
87+
'post_type' => 'page',
88+
'post_status' => 'publish',
89+
)
90+
);
91+
update_option( 'show_on_front', 'page' );
92+
update_option( 'page_on_front', $page_on_front );
93+
94+
// Register an extra public query var so that the parse_query() static
95+
// front page detection (array_diff check) fails, forcing the
96+
// get_posts() backstop to fire.
97+
add_filter(
98+
'query_vars',
99+
static function ( $vars ) {
100+
$vars[] = 'custom_extra_var';
101+
return $vars;
102+
}
103+
);
104+
105+
$this->go_to( '/?custom_extra_var=1&preview=true' );
106+
107+
$this->assertQueryTrue( 'is_front_page', 'is_page', 'is_singular', 'is_preview' );
108+
109+
// The query should find the front page, not return zero results.
110+
$this->assertCount( 1, $GLOBALS['wp_query']->posts );
111+
$this->assertEquals( $page_on_front, $GLOBALS['wp_query']->posts[0]->ID );
112+
113+
update_option( 'show_on_front', 'posts' );
114+
delete_option( 'page_on_front' );
115+
}
116+
75117
public function test_404() {
76118
$this->go_to( '/notapage' );
77119
$this->assertQueryTrue( 'is_404' );

0 commit comments

Comments
 (0)