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' ); + } }