Allow `$autoload` setting to be changed for existing options using `update_option()`.

[31628] made it possible to pass an `$autoload` param to `update_option()` that
applies when the option does not yet exist in the database. The current
changeset introduces parity for existing options: the `$autoload` setting
for existing options can be changed via the `$autoload` parameter. For internal
simplicity, `$autoload` is ignored for existing options when `$value` is not
also changed.

This changeset also moves `update_option()` tests into their own class.

Props dd32.
Fixes #26394.

git-svn-id: https://develop.svn.wordpress.org/trunk@31640 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Boone Gorges 2015-03-06 13:56:44 +00:00
parent 98322a7143
commit b9e222fd6a
3 changed files with 221 additions and 114 deletions

View File

@ -225,11 +225,13 @@ function wp_load_core_site_options( $site_id = null ) {
*
* @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.
* @param string|bool $autoload Optional. Whether to load the option when WordPress starts up. For existing options,
* `$autoload` can only be updated using `update_option()` if `$value` is also changed.
* Accepts 'yes' or true to enable, 'no' or false to disable. For non-existent options,
* the default value is 'yes'.
* @return bool False if value was not updated and true if value was updated.
*/
function update_option( $option, $value, $autoload = 'yes' ) {
function update_option( $option, $value, $autoload = null ) {
global $wpdb;
$option = trim($option);
@ -273,6 +275,11 @@ function update_option( $option, $value, $autoload = 'yes' ) {
/** This filter is documented in wp-includes/option.php */
if ( apply_filters( 'default_option_' . $option, false ) === $old_value ) {
// Default setting for new options is 'yes'.
if ( null === $autoload ) {
$autoload = 'yes';
}
return add_option( $option, $value, '', $autoload );
}
@ -289,7 +296,15 @@ function update_option( $option, $value, $autoload = 'yes' ) {
*/
do_action( 'update_option', $option, $old_value, $value );
$result = $wpdb->update( $wpdb->options, array( 'option_value' => $serialized_value ), array( 'option_name' => $option ) );
$update_args = array(
'option_value' => $serialized_value,
);
if ( null !== $autoload ) {
$update_args['autoload'] = ( 'no' === $autoload || false === $autoload ) ? 'no' : 'yes';
}
$result = $wpdb->update( $wpdb->options, $update_args, array( 'option_name' => $option ) );
if ( ! $result )
return false;

View File

@ -71,18 +71,6 @@ class Tests_Option_Option extends WP_UnitTestCase {
$this->assertSame( 'bar', get_option( 'doesnotexist' ) );
}
/**
* @ticket 31047
*/
public function test_update_option_should_respect_default_option_filter_when_option_does_not_yet_exist_in_database() {
add_filter( 'default_option_doesnotexist', array( $this, '__return_foo' ) );
$added = update_option( 'doesnotexist', 'bar' );
remove_filter( 'default_option_doesnotexist', array( $this, '__return_foo' ) );
$this->assertTrue( $added );
$this->assertSame( 'bar', get_option( 'doesnotexist' ) );
}
function test_serialized_data() {
$key = rand_str();
$value = array( 'foo' => true, 'bar' => true );
@ -149,102 +137,4 @@ 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' );
}
}

View File

@ -0,0 +1,202 @@
<?php
/**
* @group option
*/
class Tests_Option_UpdateOption extends WP_UnitTestCase {
/**
* @ticket 31047
*/
public function test_should_respect_default_option_filter_when_option_does_not_yet_exist_in_database() {
add_filter( 'default_option_doesnotexist', array( $this, '__return_foo' ) );
$added = update_option( 'doesnotexist', 'bar' );
remove_filter( 'default_option_doesnotexist', array( $this, '__return_foo' ) );
$this->assertTrue( $added );
$this->assertSame( 'bar', get_option( 'doesnotexist' ) );
}
/**
* @ticket 26394
*/
public function test_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_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_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_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' );
}
/**
* @group 26394
*/
public function test_autoload_should_be_updated_for_existing_option_when_value_is_changed() {
if ( is_multisite() ) {
$this->markTestSkipped( 'Not testable in MS: wpmu_create_blog() defines WP_INSTALLING, which causes cache misses.' );
}
global $wpdb;
add_option( 'foo', 'bar', '', 'no' );
$updated = update_option( 'foo', 'bar2', true );
$this->assertTrue( $updated );
wp_cache_flush();
// Populate the alloptions cache, which includes autoload=yes options.
wp_load_alloptions();
$before = $wpdb->num_queries;
$value = get_option( 'foo' );
$this->assertEquals( $before, $wpdb->num_queries );
$this->assertEquals( $value, 'bar2' );
}
/**
* @group 26394
*/
public function test_autoload_should_not_be_updated_for_existing_option_when_value_is_unchanged() {
if ( is_multisite() ) {
$this->markTestSkipped( 'Not testable in MS: wpmu_create_blog() defines WP_INSTALLING, which causes cache misses.' );
}
global $wpdb;
add_option( 'foo', 'bar', '', 'yes' );
$updated = update_option( 'foo', 'bar', false );
$this->assertFalse( $updated );
wp_cache_flush();
// Populate the alloptions cache, which includes autoload=yes options.
wp_load_alloptions();
$before = $wpdb->num_queries;
$value = get_option( 'foo' );
// 'foo' should still be autoload=yes, so we should see no additional querios.
$this->assertEquals( $before, $wpdb->num_queries );
$this->assertEquals( $value, 'bar' );
}
/**
* @group 26394
*/
public function test_autoload_should_not_be_updated_for_existing_option_when_value_is_changed_but_no_value_of_autoload_is_provided() {
if ( is_multisite() ) {
$this->markTestSkipped( 'Not testable in MS: wpmu_create_blog() defines WP_INSTALLING, which causes cache misses.' );
}
global $wpdb;
add_option( 'foo', 'bar', '', 'yes' );
// Don't pass a value for `$autoload`.
$updated = update_option( 'foo', 'bar2' );
$this->assertTrue( $updated );
wp_cache_flush();
// Populate the alloptions cache, which includes autoload=yes options.
wp_load_alloptions();
$before = $wpdb->num_queries;
$value = get_option( 'foo' );
// 'foo' should still be autoload=yes, so we should see no additional querios.
$this->assertEquals( $before, $wpdb->num_queries );
$this->assertEquals( $value, 'bar2' );
}
/**
* `add_filter()` callback for test_should_respect_default_option_filter_when_option_does_not_yet_exist_in_database().
*/
public function __return_foo() {
return 'foo';
}
}