From 8f649867bd9787142a99688defc8694c9e461194 Mon Sep 17 00:00:00 2001 From: Sainath Poojary Date: Tue, 14 Jul 2026 18:31:42 +0530 Subject: [PATCH 1/3] Options: Return false from get_transient() when transient timeout is missing --- src/wp-includes/option.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/option.php b/src/wp-includes/option.php index 8bd6a1821162e..552823bba75bb 100644 --- a/src/wp-includes/option.php +++ b/src/wp-includes/option.php @@ -1464,7 +1464,9 @@ function get_transient( $transient ) { $transient_timeout = '_transient_timeout_' . $transient; wp_prime_option_caches( array( $transient_option, $transient_timeout ) ); $timeout = get_option( $transient_timeout ); - if ( false !== $timeout && $timeout < time() ) { + if ( false === $timeout ) { + $value = false; + } elseif ( $timeout < time() ) { delete_option( $transient_option ); delete_option( $transient_timeout ); $value = false; @@ -2596,7 +2598,9 @@ function get_site_transient( $transient ) { wp_prime_site_option_caches( array( $transient_option, $transient_timeout ) ); $timeout = get_site_option( $transient_timeout ); - if ( false !== $timeout && $timeout < time() ) { + if ( false === $timeout ) { + $value = false; + } elseif ( $timeout < time() ) { delete_site_option( $transient_option ); delete_site_option( $transient_timeout ); $value = false; From 17c166f7a91ac3862f6eaeb0c26cb8c500f85efd Mon Sep 17 00:00:00 2001 From: Sainath Poojary Date: Tue, 14 Jul 2026 18:32:25 +0530 Subject: [PATCH 2/3] Tests/Options: Add tests for get_transient() and get_site_transient() --- tests/phpunit/tests/option/siteTransient.php | 20 ++++++++++++++++++++ tests/phpunit/tests/option/transient.php | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/tests/phpunit/tests/option/siteTransient.php b/tests/phpunit/tests/option/siteTransient.php index daabc1edf5a97..a06741cdbe196 100644 --- a/tests/phpunit/tests/option/siteTransient.php +++ b/tests/phpunit/tests/option/siteTransient.php @@ -155,4 +155,24 @@ public function test_site_transients_not_stored_in_options_table_on_ms() { $this->assertNull( $option, 'Querying option table should not return transient on multisite.' ); } + + /** + * Ensure get_site_transient() returns false when the transient timeout option is missing (broken transient). + * + * @ticket 33561 + * @group ms-excluded + * + * @covers ::get_site_transient + */ + public function test_get_site_transient_returns_false_when_timeout_is_missing() { + $key = 'test_site_transient_broken'; + $value = 'test_value'; + + set_site_transient( $key, $value, 60 * 10 ); + $this->assertSame( $value, get_site_transient( $key ) ); + + delete_option( '_site_transient_timeout_' . $key ); + + $this->assertFalse( get_site_transient( $key ) ); + } } diff --git a/tests/phpunit/tests/option/transient.php b/tests/phpunit/tests/option/transient.php index d4f6c6ce43ae9..034973d9bc6ae 100644 --- a/tests/phpunit/tests/option/transient.php +++ b/tests/phpunit/tests/option/transient.php @@ -265,4 +265,23 @@ public function test_nonexistent_key_old_timeout() { ); $this->assertSame( $expected, $a->get_events() ); } + + /** + * Ensure get_transient() returns false when the transient timeout option is missing (broken transient). + * + * @ticket 33561 + * + * @covers ::get_transient + */ + public function test_get_transient_returns_false_when_timeout_is_missing() { + $key = 'test_transient_broken'; + $value = 'test_value'; + + set_transient( $key, $value, 60 * 10 ); + $this->assertSame( $value, get_transient( $key ) ); + + delete_option( '_transient_timeout_' . $key ); + + $this->assertFalse( get_transient( $key ) ); + } } From a692d5cd139c43c0fd4bfdc9b8eb2a67f12f7125 Mon Sep 17 00:00:00 2001 From: Sainath Poojary Date: Tue, 14 Jul 2026 20:47:59 +0530 Subject: [PATCH 3/3] Options: Revert site transient changes --- src/wp-includes/option.php | 4 +--- tests/phpunit/tests/option/siteTransient.php | 20 -------------------- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/src/wp-includes/option.php b/src/wp-includes/option.php index 552823bba75bb..a2779651d2e6f 100644 --- a/src/wp-includes/option.php +++ b/src/wp-includes/option.php @@ -2598,9 +2598,7 @@ function get_site_transient( $transient ) { wp_prime_site_option_caches( array( $transient_option, $transient_timeout ) ); $timeout = get_site_option( $transient_timeout ); - if ( false === $timeout ) { - $value = false; - } elseif ( $timeout < time() ) { + if ( false !== $timeout && $timeout < time() ) { delete_site_option( $transient_option ); delete_site_option( $transient_timeout ); $value = false; diff --git a/tests/phpunit/tests/option/siteTransient.php b/tests/phpunit/tests/option/siteTransient.php index a06741cdbe196..daabc1edf5a97 100644 --- a/tests/phpunit/tests/option/siteTransient.php +++ b/tests/phpunit/tests/option/siteTransient.php @@ -155,24 +155,4 @@ public function test_site_transients_not_stored_in_options_table_on_ms() { $this->assertNull( $option, 'Querying option table should not return transient on multisite.' ); } - - /** - * Ensure get_site_transient() returns false when the transient timeout option is missing (broken transient). - * - * @ticket 33561 - * @group ms-excluded - * - * @covers ::get_site_transient - */ - public function test_get_site_transient_returns_false_when_timeout_is_missing() { - $key = 'test_site_transient_broken'; - $value = 'test_value'; - - set_site_transient( $key, $value, 60 * 10 ); - $this->assertSame( $value, get_site_transient( $key ) ); - - delete_option( '_site_transient_timeout_' . $key ); - - $this->assertFalse( get_site_transient( $key ) ); - } }