From 2c06c9afd5ba32a0f55a9f8313e636fbcb698cab Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Sun, 22 May 2022 15:15:47 +0000 Subject: [PATCH] Query: Check if `$wp_query` is set in query loop functions. This avoids a PHP fatal error if any of these functions are called too early: * `have_posts()` * `in_the_loop()` * `rewind_posts()` * `the_post()` * `have_comments()` * `the_comment()` bringing some consistency with conditional tags: `is_single()`, `is_home()`, etc. This commit also removes unnecessary `return` from `the_comment()`, for consistency with `the_post()`. As `WP_Query::the_comment()` does not have a return value, this statement did not have any effect in practice. Follow-up to [4934], [8807], [16947], [17068], [17083], [49147], [53395], [53396], [53400]. Props vdankbaar, thijso, teunvgisteren, timkersten655, SergeyBiryukov. Fixes #55722. git-svn-id: https://develop.svn.wordpress.org/trunk@53429 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/query.php | 34 ++++++++++++++++++++-- tests/phpunit/tests/query/conditionals.php | 33 +++++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/query.php b/src/wp-includes/query.php index 7a210b09f1..d4ac780212 100644 --- a/src/wp-includes/query.php +++ b/src/wp-includes/query.php @@ -939,6 +939,11 @@ function is_main_query() { */ function have_posts() { global $wp_query; + + if ( ! isset( $wp_query ) ) { + return false; + } + return $wp_query->have_posts(); } @@ -957,6 +962,11 @@ function have_posts() { */ function in_the_loop() { global $wp_query; + + if ( ! isset( $wp_query ) ) { + return false; + } + return $wp_query->in_the_loop; } @@ -969,6 +979,11 @@ function in_the_loop() { */ function rewind_posts() { global $wp_query; + + if ( ! isset( $wp_query ) ) { + return; + } + $wp_query->rewind_posts(); } @@ -981,6 +996,11 @@ function rewind_posts() { */ function the_post() { global $wp_query; + + if ( ! isset( $wp_query ) ) { + return; + } + $wp_query->the_post(); } @@ -999,6 +1019,11 @@ function the_post() { */ function have_comments() { global $wp_query; + + if ( ! isset( $wp_query ) ) { + return false; + } + return $wp_query->have_comments(); } @@ -1008,12 +1033,15 @@ function have_comments() { * @since 2.2.0 * * @global WP_Query $wp_query WordPress Query object. - * - * @return null */ function the_comment() { global $wp_query; - return $wp_query->the_comment(); + + if ( ! isset( $wp_query ) ) { + return; + } + + $wp_query->the_comment(); } /** diff --git a/tests/phpunit/tests/query/conditionals.php b/tests/phpunit/tests/query/conditionals.php index cc191fa1f2..95621882b0 100644 --- a/tests/phpunit/tests/query/conditionals.php +++ b/tests/phpunit/tests/query/conditionals.php @@ -1660,4 +1660,37 @@ class Tests_Query_Conditionals extends WP_UnitTestCase { return $functions; } + /** + * @ticket 55722 + * + * @dataProvider data_loop_functions_do_not_trigger_a_fatal_error_if_wp_query_is_not_set + * + * @param string $function_name The name of the function to test. + * @param false|null $expected Expected return value. + */ + public function test_loop_functions_do_not_trigger_a_fatal_error_if_wp_query_is_not_set( $function_name, $expected ) { + unset( $GLOBALS['wp_query'] ); + + $this->assertSame( $expected, call_user_func( $function_name ) ); + } + + /** + * Data provider. + * + * @return array[] Test parameters { + * @type string $function_name The name of the function to test. + * @type false|null $expected Expected return value. + * } + */ + public function data_loop_functions_do_not_trigger_a_fatal_error_if_wp_query_is_not_set() { + return array( + array( 'have_posts', false ), + array( 'in_the_loop', false ), + array( 'rewind_posts', null ), + array( 'the_post', null ), + array( 'have_comments', false ), + array( 'the_comment', null ), + ); + } + }