Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions src/wp-includes/option.php
Original file line number Diff line number Diff line change
Expand Up @@ -782,14 +782,30 @@ function update_option( $option, $value, $autoload = null ) {
* The raw value is only used to determine whether a value is present in the database. It is not used anywhere
* else, and is not passed to any of the hooks either.
*/
if ( has_filter( "pre_option_{$option}" ) ) {
$has_pre_option_filter = has_filter( "pre_option_{$option}" );
$has_global_pre_option_filter = has_filter( 'pre_option' );
if ( $has_pre_option_filter || $has_global_pre_option_filter ) {
global $wp_filter;

$old_filters = $wp_filter[ "pre_option_{$option}" ];
unset( $wp_filter[ "pre_option_{$option}" ] );
if ( $has_pre_option_filter ) {
$old_pre_filters = $wp_filter[ "pre_option_{$option}" ];
unset( $wp_filter[ "pre_option_{$option}" ] );
}

if ( $has_global_pre_option_filter ) {
$old_global_pre_filters = $wp_filter['pre_option'];
unset( $wp_filter['pre_option'] );
}

$raw_old_value = get_option( $option );

$raw_old_value = get_option( $option );
$wp_filter[ "pre_option_{$option}" ] = $old_filters;
if ( $has_pre_option_filter ) {
$wp_filter[ "pre_option_{$option}" ] = $old_pre_filters;
}

if ( $has_global_pre_option_filter ) {
$wp_filter['pre_option'] = $old_global_pre_filters;
}
} else {
$raw_old_value = $old_value;
}
Expand Down
41 changes: 34 additions & 7 deletions tests/phpunit/tests/option/option.php
Original file line number Diff line number Diff line change
Expand Up @@ -730,10 +730,16 @@ static function () use ( $default_value ) {
* @ticket 22192
*
* @covers ::update_option
*
* @dataProvider data_pre_filter_hooks
*
* @param string $hook_name The name of the pre-filter hook.
*/
public function test_update_option_with_pre_filter_adds_missing_option() {
public function test_update_option_with_pre_filter_adds_missing_option( $hook_name ) {
$hook_name = str_replace( '{OPTION}', 'foo', $hook_name );

// Force a return value of integer 0.
add_filter( 'pre_option_foo', '__return_zero' );
add_filter( $hook_name, '__return_zero' );

/*
* This should succeed, since the 'foo' option does not exist in the database.
Expand All @@ -748,13 +754,19 @@ public function test_update_option_with_pre_filter_adds_missing_option() {
* @ticket 22192
*
* @covers ::update_option
*
* @dataProvider data_pre_filter_hooks
*
* @param string $hook_name The name of the pre-filter hook.
*/
public function test_update_option_with_pre_filter_updates_option_with_different_value() {
public function test_update_option_with_pre_filter_updates_option_with_different_value( $hook_name ) {
$hook_name = str_replace( '{OPTION}', 'foo', $hook_name );

// Add the option with a value of 1 to the database.
add_option( 'foo', 1 );

// Force a return value of integer 0.
add_filter( 'pre_option_foo', '__return_zero' );
add_filter( $hook_name, '__return_zero' );

/*
* This should succeed, since the 'foo' option has a value of 1 in the database.
Expand All @@ -769,13 +781,28 @@ public function test_update_option_with_pre_filter_updates_option_with_different
* @ticket 22192
*
* @covers ::update_option
*
* @dataProvider data_pre_filter_hooks
*
* @param string $hook_name The name of the pre-filter hook.
*/
public function test_update_option_maintains_pre_filters() {
add_filter( 'pre_option_foo', '__return_zero' );
public function test_update_option_maintains_pre_filters( $hook_name ) {
$hook_name = str_replace( '{OPTION}', 'foo', $hook_name );

add_filter( $hook_name, '__return_zero' );
update_option( 'foo', 0 );

// Assert that the filter is still present.
$this->assertSame( 10, has_filter( 'pre_option_foo', '__return_zero' ) );
$this->assertSame( 10, has_filter( $hook_name, '__return_zero' ) );
}

/**
* Data provider.
*
* @return array[]
*/
public function data_pre_filter_hooks() {
return self::text_array_to_dataprovider( array( 'pre_option_{OPTION}', 'pre_option' ) );
}

/**
Expand Down