From 67324a9234599f4174e503e7b7d9860c28033600 Mon Sep 17 00:00:00 2001 From: Boone Gorges Date: Thu, 5 Mar 2015 19:13:00 +0000 Subject: [PATCH] Introduce `$autoload` parameter to `update_option()`. When creating an option via `add_option()`, the `$autoload` param allows you to tell WP whether the option should be loaded as part of the 'alloptions' cache during every pageload. `update_option()`, when used with a non-existent option calls `add_option()` internally. The new `$autoload` param in `update_option()` is passed along to `add_option()` in cases where the option does not yet exist. The associated unit tests are skipped on multisite due to an issue that causes `WP_INSTALLING` to force cache misses. See #31130. Props codix, nofearinc, MikeHansenMe. Fixes #26394. git-svn-id: https://develop.svn.wordpress.org/trunk@31628 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/option.php | 14 ++-- tests/phpunit/tests/option/option.php | 98 +++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 5 deletions(-) diff --git a/src/wp-includes/option.php b/src/wp-includes/option.php index 566c896331..2f548e6151 100644 --- a/src/wp-includes/option.php +++ b/src/wp-includes/option.php @@ -221,12 +221,15 @@ function wp_load_core_site_options( $site_id = null ) { * to set whether an option is autoloaded, then you need to use the add_option(). * * @since 1.0.0 + * @since 4.2.0 The `$autoload` parameter was added. * - * @param string $option Option name. Expected to not be SQL-escaped. - * @param mixed $value Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped. + * @param string $option Option name. Expected to not be SQL-escaped. + * @param mixed $value Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped. + * @param string|bool $autoload Optional. Whether to load the option when WordPress starts up. Accepts 'yes' or true to + * enable, 'no' or false to disable. Default is enabled. * @return bool False if value was not updated and true if value was updated. */ -function update_option( $option, $value ) { +function update_option( $option, $value, $autoload = 'yes' ) { global $wpdb; $option = trim($option); @@ -269,8 +272,9 @@ function update_option( $option, $value ) { return false; /** This filter is documented in wp-includes/option.php */ - if ( apply_filters( 'default_option_' . $option, false ) === $old_value ) - return add_option( $option, $value ); + if ( apply_filters( 'default_option_' . $option, false ) === $old_value ) { + return add_option( $option, $value, '', $autoload ); + } $serialized_value = maybe_serialize( $value ); diff --git a/tests/phpunit/tests/option/option.php b/tests/phpunit/tests/option/option.php index d2c8473f26..83456e0eb8 100644 --- a/tests/phpunit/tests/option/option.php +++ b/tests/phpunit/tests/option/option.php @@ -149,4 +149,102 @@ class Tests_Option_Option extends WP_UnitTestCase { $actual = $wpdb->get_row( $wpdb->prepare( "SELECT autoload FROM $wpdb->options WHERE option_name = %s LIMIT 1", $name ) ); $this->assertEquals( $expected, $actual->autoload ); } + + /** + * @ticket 26394 + */ + public function test_update_option_should_set_autoload_yes_for_nonexistent_option_when_autoload_param_is_missing() { + if ( is_multisite() ) { + $this->markTestSkipped( 'Not testable in MS: wpmu_create_blog() defines WP_INSTALLING, which causes cache misses.' ); + } + + global $wpdb; + wp_cache_flush(); + update_option( 'test_update_option_default', 'value' ); + wp_cache_flush(); + + // Populate the alloptions cache, which includes autoload=yes options. + wp_load_alloptions(); + + $before = $wpdb->num_queries; + $value = get_option( 'test_update_option_default' ); + $after = $wpdb->num_queries; + + $this->assertEquals( $before, $after ); + $this->assertEquals( $value, 'value' ); + } + + /** + * @ticket 26394 + */ + public function test_update_option_should_set_autoload_yes_for_nonexistent_option_when_autoload_param_is_yes() { + if ( is_multisite() ) { + $this->markTestSkipped( 'Not testable in MS: wpmu_create_blog() defines WP_INSTALLING, which causes cache misses.' ); + } + + global $wpdb; + wp_cache_flush(); + update_option( 'test_update_option_default', 'value', 'yes' ); + wp_cache_flush(); + + // Populate the alloptions cache, which includes autoload=yes options. + wp_load_alloptions(); + + $before = $wpdb->num_queries; + $value = get_option( 'test_update_option_default' ); + $after = $wpdb->num_queries; + + $this->assertEquals( $before, $after ); + $this->assertEquals( $value, 'value' ); + } + + /** + * @ticket 26394 + */ + public function test_update_option_should_set_autoload_yes_for_nonexistent_option_when_autoload_param_is_no() { + if ( is_multisite() ) { + $this->markTestSkipped( 'Not testable in MS: wpmu_create_blog() defines WP_INSTALLING, which causes cache misses.' ); + } + + global $wpdb; + wp_cache_flush(); + update_option( 'test_update_option_default', 'value', 'no' ); + wp_cache_flush(); + + // Populate the alloptions cache, which does not include autoload=no options. + wp_load_alloptions(); + + $before = $wpdb->num_queries; + $value = get_option( 'test_update_option_default' ); + $after = $wpdb->num_queries; + + // Database has been hit. + $this->assertEquals( $before + 1, $after ); + $this->assertEquals( $value, 'value' ); + } + + /** + * @ticket 26394 + */ + public function test_update_option_should_set_autoload_yes_for_nonexistent_option_when_autoload_param_is_false() { + if ( is_multisite() ) { + $this->markTestSkipped( 'Not testable in MS: wpmu_create_blog() defines WP_INSTALLING, which causes cache misses.' ); + } + + global $wpdb; + wp_cache_flush(); + update_option( 'test_update_option_default', 'value', false ); + wp_cache_flush(); + + // Populate the alloptions cache, which does not include autoload=no options. + wp_load_alloptions(); + + $before = $wpdb->num_queries; + $value = get_option( 'test_update_option_default' ); + $after = $wpdb->num_queries; + + // Database has been hit. + $this->assertEquals( $before + 1, $after ); + $this->assertEquals( $value, 'value' ); + } }