From 75d49a00556ada90f099d351f5d158983941db3c Mon Sep 17 00:00:00 2001 From: Dennis Ploetner Date: Thu, 23 Jul 2026 17:12:55 +0200 Subject: [PATCH 1/4] Added && ! wp_installing() to the guard around get_language_attributes() --- src/wp-includes/functions.php | 5 +++ tests/phpunit/tests/functions.php | 59 +++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index dca95d69b69fe..77a2484b86fc0 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -3955,9 +3955,14 @@ function _default_wp_die_handler( $message, $title = '', $args = array() ) { /* * If `text_direction` was not explicitly passed, * use get_language_attributes() if available. + * + * Skipped while installing: get_language_attributes() queries the + * database, which could re-trigger the DB error that led here and + * loop wp_die() indefinitely. See #50228. */ if ( empty( $args['text_direction'] ) && function_exists( 'language_attributes' ) && function_exists( 'is_rtl' ) + && ! wp_installing() ) { $dir_attr = get_language_attributes(); } diff --git a/tests/phpunit/tests/functions.php b/tests/phpunit/tests/functions.php index 19c721aeaa46a..6301703fa7c55 100644 --- a/tests/phpunit/tests/functions.php +++ b/tests/phpunit/tests/functions.php @@ -2247,4 +2247,63 @@ public function test_wp_recursive_ksort() { ); $this->assertSameSetsWithIndex( $theme_json, $expected_theme_json ); } + + /** + * Tests that _default_wp_die_handler() only queries the database for language + * attributes when WordPress is not installing. + * + * get_language_attributes() queries the database. During install (for example, + * mid-way through Multisite site creation, before the new site's tables exist), + * that query can re-trigger the database error that led to wp_die() in the first + * place, looping wp_die() until PHP's function nesting limit is reached. While + * installing, the handler must fall back to the already-computed `dir` attribute + * instead. + * + * @ticket 50228 + * + * @covers ::_default_wp_die_handler + * + * @dataProvider data_default_wp_die_handler_language_attributes + * + * @param bool $installing Whether WordPress is installing. + * @param string $expected_attr Substring the output is expected to contain. + * @param string $unexpected_attr Substring the output is expected not to contain. + */ + public function test_default_wp_die_handler_language_attributes( $installing, $expected_attr, $unexpected_attr ) { + $was_installing = wp_installing(); + wp_installing( $installing ); + + ob_start(); + _default_wp_die_handler( 'Error message', 'Error title', array( 'exit' => false ) ); + $output = ob_get_clean(); + + wp_installing( $was_installing ); + + $this->assertStringContainsString( $expected_attr, $output ); + $this->assertStringNotContainsString( $unexpected_attr, $output ); + } + + /** + * Data provider for test_default_wp_die_handler_language_attributes(). + * + * @return array[] { + * @type bool $installing Whether WordPress is installing. + * @type string $expected_attr Substring the output is expected to contain. + * @type string $unexpected_attr Substring the output is expected not to contain. + * } + */ + public function data_default_wp_die_handler_language_attributes() { + return array( + 'installing: falls back to the dir attribute' => array( + 'installing' => true, + 'expected_attr' => "", + 'unexpected_attr' => 'lang=', + ), + 'not installing: uses get_language_attributes()' => array( + 'installing' => false, + 'expected_attr' => 'lang="', + 'unexpected_attr' => "dir='ltr'", + ), + ); + } } From c080aa859e891bd7f0e13e2a7ac921dcf3c57d45 Mon Sep 17 00:00:00 2001 From: Dennis Ploetner Date: Thu, 23 Jul 2026 17:19:08 +0200 Subject: [PATCH 2/4] Cleanup --- tests/phpunit/tests/functions.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/phpunit/tests/functions.php b/tests/phpunit/tests/functions.php index 6301703fa7c55..bce44f455629b 100644 --- a/tests/phpunit/tests/functions.php +++ b/tests/phpunit/tests/functions.php @@ -2252,17 +2252,8 @@ public function test_wp_recursive_ksort() { * Tests that _default_wp_die_handler() only queries the database for language * attributes when WordPress is not installing. * - * get_language_attributes() queries the database. During install (for example, - * mid-way through Multisite site creation, before the new site's tables exist), - * that query can re-trigger the database error that led to wp_die() in the first - * place, looping wp_die() until PHP's function nesting limit is reached. While - * installing, the handler must fall back to the already-computed `dir` attribute - * instead. - * * @ticket 50228 - * * @covers ::_default_wp_die_handler - * * @dataProvider data_default_wp_die_handler_language_attributes * * @param bool $installing Whether WordPress is installing. From ce0e4ce96b1aabec0ee3044965f0b83f78be9152 Mon Sep 17 00:00:00 2001 From: Dennis Ploetner Date: Thu, 23 Jul 2026 17:23:22 +0200 Subject: [PATCH 3/4] Coderstyle corrected --- tests/phpunit/tests/functions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/phpunit/tests/functions.php b/tests/phpunit/tests/functions.php index bce44f455629b..1bcaa9ccfa916 100644 --- a/tests/phpunit/tests/functions.php +++ b/tests/phpunit/tests/functions.php @@ -2285,12 +2285,12 @@ public function test_default_wp_die_handler_language_attributes( $installing, $e */ public function data_default_wp_die_handler_language_attributes() { return array( - 'installing: falls back to the dir attribute' => array( + 'installing: falls back to the dir attribute' => array( 'installing' => true, 'expected_attr' => "", 'unexpected_attr' => 'lang=', ), - 'not installing: uses get_language_attributes()' => array( + 'not installing: uses get_language_attributes()' => array( 'installing' => false, 'expected_attr' => 'lang="', 'unexpected_attr' => "dir='ltr'", From f01cf1da68a7e2a4808873affcd0220174098c9f Mon Sep 17 00:00:00 2001 From: Dennis Ploetner Date: Thu, 23 Jul 2026 18:09:24 +0200 Subject: [PATCH 4/4] Tests adjusted --- tests/phpunit/tests/functions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/phpunit/tests/functions.php b/tests/phpunit/tests/functions.php index 1bcaa9ccfa916..69ab0204f1804 100644 --- a/tests/phpunit/tests/functions.php +++ b/tests/phpunit/tests/functions.php @@ -2287,13 +2287,13 @@ public function data_default_wp_die_handler_language_attributes() { return array( 'installing: falls back to the dir attribute' => array( 'installing' => true, - 'expected_attr' => "", + 'expected_attr' => " 'lang=', ), 'not installing: uses get_language_attributes()' => array( 'installing' => false, 'expected_attr' => 'lang="', - 'unexpected_attr' => "dir='ltr'", + 'unexpected_attr' => "dir='", ), ); }