Skip to content

Commit

Permalink
Options, Meta APIs: Prime notoptions cache when deleting options.
Browse files Browse the repository at this point in the history
Prime the `notoptions` cache within `delete_option` and `delete_network_option` to avoid the need for a database query if `get_option` or `get_network_option` is subsequently called.

Adds some associated tests to ensure that an option is cleared from the notoptions cache when an option is added either via `add_option`, `update_option` or their network option equivalent.

Props pbearne, mukesh27.
Fixes #61484.



git-svn-id: https://develop.svn.wordpress.org/trunk@58782 602fd350-edb4-49c9-b593-d223f7449a82
  • Loading branch information
peterwilsoncc committed Jul 23, 2024
1 parent 954d561 commit fc33ab6
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/wp-includes/option.php
Original file line number Diff line number Diff line change
Expand Up @@ -1217,6 +1217,15 @@ function delete_option( $option ) {
} else {
wp_cache_delete( $option, 'options' );
}

$notoptions = wp_cache_get( 'notoptions', 'options' );

if ( ! is_array( $notoptions ) ) {
$notoptions = array();
}
$notoptions[ $option ] = true;

wp_cache_set( 'notoptions', $notoptions, 'options' );
}

if ( $result ) {
Expand Down Expand Up @@ -2284,6 +2293,15 @@ function delete_network_option( $network_id, $option ) {
*/
do_action( 'delete_site_option', $option, $network_id );

$notoptions_key = "$network_id:notoptions";
$notoptions = wp_cache_get( $notoptions_key, 'site-options' );

if ( ! is_array( $notoptions ) ) {
$notoptions = array();
}
$notoptions[ $option ] = true;
wp_cache_set( $notoptions_key, $notoptions, 'site-options' );

return true;
}

Expand Down
74 changes: 74 additions & 0 deletions tests/phpunit/tests/option/networkOption.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,30 @@ public function test_delete_network_option_on_only_one_network() {
$this->assertSame( $value, get_network_option( $id, $option, false ) );
}

/**
* Tests that calling delete_network_option() updates nooptions when option deleted.
*
* @ticket 61484
*
* @covers ::delete_network_option
*/
public function test_check_delete_network_option_updates_notoptions() {
add_network_option( 1, 'foo', 'value1' );

delete_network_option( 1, 'foo' );
$cache_key = is_multisite() ? '1:notoptions' : 'notoptions';
$cache_group = is_multisite() ? 'site-options' : 'options';
$notoptions = wp_cache_get( $cache_key, $cache_group );
$this->assertIsArray( $notoptions, 'The notoptions cache is expected to be an array.' );
$this->assertTrue( $notoptions['foo'], 'The deleted options is expected to be in notoptions.' );

$before = get_num_queries();
get_network_option( 1, 'foo' );
$queries = get_num_queries() - $before;

$this->assertSame( 0, $queries, 'get_network_option should not make any database queries.' );
}

/**
* @ticket 22846
* @group ms-excluded
Expand Down Expand Up @@ -228,4 +252,54 @@ public function test_update_network_option_array_with_object() {
// Check that no new database queries were performed.
$this->assertSame( $num_queries_pre_update, get_num_queries() );
}

/**
* Tests that calling update_network_option() clears the notoptions cache.
*
* @ticket 61484
*
* @covers ::update_network_option
*/
public function test_update_network_option_clears_the_notoptions_cache() {
$option_name = 'ticket_61484_option_to_be_created';
$cache_key = is_multisite() ? '1:notoptions' : 'notoptions';
$cache_group = is_multisite() ? 'site-options' : 'options';
$notoptions = wp_cache_get( $cache_key, $cache_group );
if ( ! is_array( $notoptions ) ) {
$notoptions = array();
}
$notoptions[ $option_name ] = true;
wp_cache_set( $cache_key, $notoptions, $cache_group );
$this->assertArrayHasKey( $option_name, wp_cache_get( $cache_key, $cache_group ), 'The "foobar" option should be in the notoptions cache.' );

update_network_option( 1, $option_name, 'baz' );

$updated_notoptions = wp_cache_get( $cache_key, $cache_group );
$this->assertArrayNotHasKey( $option_name, $updated_notoptions, 'The "foobar" option should not be in the notoptions cache after updating it.' );
}

/**
* Tests that calling add_network_option() clears the notoptions cache.
*
* @ticket 61484
*
* @covers ::add_network_option
*/
public function test_add_network_option_clears_the_notoptions_cache() {
$option_name = 'ticket_61484_option_to_be_created';
$cache_key = is_multisite() ? '1:notoptions' : 'notoptions';
$cache_group = is_multisite() ? 'site-options' : 'options';
$notoptions = wp_cache_get( $cache_key, $cache_group );
if ( ! is_array( $notoptions ) ) {
$notoptions = array();
}
$notoptions[ $option_name ] = true;
wp_cache_set( $cache_key, $notoptions, $cache_group );
$this->assertArrayHasKey( $option_name, wp_cache_get( $cache_key, $cache_group ), 'The "foobar" option should be in the notoptions cache.' );

add_network_option( 1, $option_name, 'baz' );

$updated_notoptions = wp_cache_get( $cache_key, $cache_group );
$this->assertArrayNotHasKey( $option_name, $updated_notoptions, 'The "foobar" option should not be in the notoptions cache after updating it.' );
}
}
68 changes: 68 additions & 0 deletions tests/phpunit/tests/option/option.php
Original file line number Diff line number Diff line change
Expand Up @@ -478,4 +478,72 @@ public function test_update_option_with_autoload_change_yes_to_no() {
delete_option( 'foo' );
$this->assertFalse( get_option( 'foo' ) );
}

/**
* Tests that calling delete_option() updates notoptions when option deleted.
*
* @ticket 61484
*
* @covers ::delete_option
*/
public function test_check_delete_option_updates_notoptions() {
add_option( 'foo', 'value1' );

delete_option( 'foo' );
$notoptions = wp_cache_get( 'notoptions', 'options' );
$this->assertIsArray( $notoptions, 'The notoptions cache is expected to be an array.' );
$this->assertTrue( $notoptions['foo'], 'The deleted options is expected to be in notoptions.' );

$before = get_num_queries();
get_option( 'foo' );
$queries = get_num_queries() - $before;

$this->assertSame( 0, $queries, 'get_option should not make any database queries.' );
}

/**
* Tests that calling update_option() clears the notoptions cache.
*
* @ticket 61484
*
* @covers ::update_option
*/
public function test_update_option_clears_the_notoptions_cache() {
$option_name = 'ticket_61484_option_to_be_created';
$notoptions = wp_cache_get( 'notoptions', 'options' );
if ( ! is_array( $notoptions ) ) {
$notoptions = array();
}
$notoptions[ $option_name ] = true;
wp_cache_set( 'notoptions', $notoptions, 'options' );
$this->assertArrayHasKey( $option_name, wp_cache_get( 'notoptions', 'options' ), 'The "foobar" option should be in the notoptions cache.' );

update_option( $option_name, 'baz' );

$updated_notoptions = wp_cache_get( 'notoptions', 'options' );
$this->assertArrayNotHasKey( $option_name, $updated_notoptions, 'The "foobar" option should not be in the notoptions cache after updating it.' );
}

/**
* Tests that calling add_option() clears the notoptions cache.
*
* @ticket 61484
*
* @covers ::add_option
*/
public function test_add_option_clears_the_notoptions_cache() {
$option_name = 'ticket_61484_option_to_be_created';
$notoptions = wp_cache_get( 'notoptions', 'options' );
if ( ! is_array( $notoptions ) ) {
$notoptions = array();
}
$notoptions[ $option_name ] = true;
wp_cache_set( 'notoptions', $notoptions, 'options' );
$this->assertArrayHasKey( $option_name, wp_cache_get( 'notoptions', 'options' ), 'The "foobar" option should be in the notoptions cache.' );

add_option( $option_name, 'baz' );

$updated_notoptions = wp_cache_get( 'notoptions', 'options' );
$this->assertArrayNotHasKey( $option_name, $updated_notoptions, 'The "foobar" option should not be in the notoptions cache after adding it.' );
}
}

0 comments on commit fc33ab6

Please sign in to comment.