<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[57030] branches/6.4/tests/phpunit/tests/option: Options, Meta APIs: Fast follow fixes for option cache priming functions.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/57030">57030</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/57030","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>peterwilsoncc</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2023-10-30 23:21:03 +0000 (Mon, 30 Oct 2023)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Options, Meta APIs: Fast follow fixes for option cache priming functions.
A collection of fixes for `wp_prime_option_caches()`:
* cache arrays and objects in their serialized form for consistency with `get_option()` and `wp_load_alloptions()`
* prevent repeat database queries for falsey and known non-existent options (notoptions)
Additional tests for `wp_prime_option_caches()` to ensure:
* additional database queries are not made repriming options (known, known-unknown and alloptions)
* cache is primed consistently
* `get_option()` returns a consistent value regardless of how it is primed
* database queries do not contain earlier primed options
* `get_option` does not prime the cache when testing the cache has been successfully primed
Fixes a test for `wp_prime_option_caches_by_group()` to ensure `get_option` does not prime the cache when testing the cache has been successfully primed.
Follow up to <a href="https://core.trac.wordpress.org/changeset/56445">[56445]</a>,<a href="https://core.trac.wordpress.org/changeset/56990">[56990]</a>,<a href="https://core.trac.wordpress.org/changeset/57013">[57013]</a>.
Reviewed by flixos90, hellofromTonya, joemcgill.
Merges <a href="https://core.trac.wordpress.org/changeset/57029">[57029]</a> to the 6.4 branch.
Props peterwilsoncc, costdev, flixos90, hellofromTonya, mikeschroder, joemcgill.
Fixes <a href="https://core.trac.wordpress.org/ticket/59738">#59738</a>. See <a href="https://core.trac.wordpress.org/ticket/58962">#58962</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#branches64srcwpincludesoptionphp">branches/6.4/src/wp-includes/option.php</a></li>
<li><a href="#branches64testsphpunittestsoptionwpPrimeOptionCachesphp">branches/6.4/tests/phpunit/tests/option/wpPrimeOptionCaches.php</a></li>
<li><a href="#branches64testsphpunittestsoptionwpPrimeOptionCachesByGroupphp">branches/6.4/tests/phpunit/tests/option/wpPrimeOptionCachesByGroup.php</a></li>
</ul>
<h3>Property Changed</h3>
<ul>
<li><a href="#branches64">branches/6.4/</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<span class="cx" style="display: block; padding: 0 10px">Index: branches/6.4
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- branches/6.4 2023-10-30 22:56:25 UTC (rev 57029)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ branches/6.4 2023-10-30 23:21:03 UTC (rev 57030)
</ins><a id="branches64"></a>
<div class="propset"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Property changes: branches/6.4</h4>
<pre class="diff"><span>
</span></pre></div>
<a id="svnmergeinfo"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: svn:mergeinfo</h4></div>
<span class="cx" style="display: block; padding: 0 10px"> /branches/5.0:43681-43682,43684-43688,43719-43720,43723,43726-43727,43729-43731,43734-43744,43747,43751-43754,43758,43760-43765,43767-43770,43772,43774-43781,43783,43785,43790-43806,43808-43821,43825,43828,43830-43834,43836-43843,43846-43863,43867-43889,43891-43894,43897-43905,43908-43909,43911-43929,43931-43942,43946-43947,43949-43956,43959-43964,43967-43969,43988,43994,44014,44017,44047,44183,44185,44187-44206,44208-44213,44231-44232,44235,44248,44284,44287-44288
</span><span class="cx" style="display: block; padding: 0 10px"> /branches/5.5:49373-49379,49381
</span><span class="cx" style="display: block; padding: 0 10px"> /branches/5.8:51889
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/trunk:56974,56978,56984,56987,56990-56992,56996,56999,57003,57009,57012-57013,57018-57019,57021-57022
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/trunk:56974,56978,56984,56987,56990-56992,56996,56999,57003,57009,57012-57013,57018-57019,57021-57022,57029
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="branches64srcwpincludesoptionphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/6.4/src/wp-includes/option.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/6.4/src/wp-includes/option.php 2023-10-30 22:56:25 UTC (rev 57029)
+++ branches/6.4/src/wp-includes/option.php 2023-10-30 23:21:03 UTC (rev 57030)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -261,11 +261,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> function wp_prime_option_caches( $options ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $alloptions = wp_load_alloptions();
</span><span class="cx" style="display: block; padding: 0 10px"> $cached_options = wp_cache_get_multiple( $options, 'options' );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $notoptions = wp_cache_get( 'notoptions', 'options' );
+ if ( ! is_array( $notoptions ) ) {
+ $notoptions = array();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Filter options that are not in the cache.
</span><span class="cx" style="display: block; padding: 0 10px"> $options_to_prime = array();
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ( $options as $option ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( ( ! isset( $cached_options[ $option ] ) || ! $cached_options[ $option ] ) && ! isset( $alloptions[ $option ] ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (
+ ( ! isset( $cached_options[ $option ] ) || false === $cached_options[ $option ] )
+ && ! isset( $alloptions[ $option ] )
+ && ! isset( $notoptions[ $option ] )
+ ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $options_to_prime[] = $option;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -288,7 +296,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $options_found = array();
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ( $results as $result ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $options_found[ $result->option_name ] = maybe_unserialize( $result->option_value );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*
+ * The cache is primed with the raw value (i.e. not maybe_unserialized).
+ *
+ * `get_option()` will handle unserializing the value as needed.
+ */
+ $options_found[ $result->option_name ] = $result->option_value;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> wp_cache_set_multiple( $options_found, 'options' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -299,12 +312,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $options_not_found = array_diff( $options_to_prime, array_keys( $options_found ) );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $notoptions = wp_cache_get( 'notoptions', 'options' );
-
- if ( ! is_array( $notoptions ) ) {
- $notoptions = array();
- }
-
</del><span class="cx" style="display: block; padding: 0 10px"> // Add the options that were not found to the cache.
</span><span class="cx" style="display: block; padding: 0 10px"> $update_notoptions = false;
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ( $options_not_found as $option_name ) {
</span></span></pre></div>
<a id="branches64testsphpunittestsoptionwpPrimeOptionCachesphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/6.4/tests/phpunit/tests/option/wpPrimeOptionCaches.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/6.4/tests/phpunit/tests/option/wpPrimeOptionCaches.php 2023-10-30 22:56:25 UTC (rev 57029)
+++ branches/6.4/tests/phpunit/tests/option/wpPrimeOptionCaches.php 2023-10-30 23:21:03 UTC (rev 57030)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -41,15 +41,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Check that options are only in the 'options' cache group.
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ( $options_to_prime as $option ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame(
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "value_$option",
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_cache_get( $option, 'options' ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- get_option( $option ),
</del><span class="cx" style="display: block; padding: 0 10px"> "$option was not primed in the 'options' cache group."
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertFalse(
- wp_cache_get( $option, 'notoptions' ),
- get_option( $option ),
- "$option was primed in the 'notoptions' cache group."
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $new_notoptions = wp_cache_get( $option, 'notoptions' );
+ if ( ! is_array( $new_notoptions ) ) {
+ $new_notoptions = array();
+ }
+ $this->assertArrayNotHasKey(
+ $option,
+ $new_notoptions,
+ "$option was primed in the 'notoptions' cache."
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -62,9 +66,69 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Tests that wp_prime_option_caches() handles a mix of primed and unprimed options.
+ *
+ * @ticket 58962
+ */
+ public function test_wp_prime_option_caches_handles_a_mix_of_primed_and_unprimed_options() {
+ global $wpdb;
+ // Create some options to prime.
+ $options_to_prime = array(
+ 'option1',
+ 'option2',
+ 'option3',
+ );
+
+ /*
+ * Set values for the options,
+ * clear the cache for the options,
+ * check options are not in cache initially.
+ */
+ foreach ( $options_to_prime as $option ) {
+ update_option( $option, "value_$option", false );
+ wp_cache_delete( $option, 'options' );
+ $this->assertFalse( wp_cache_get( $option, 'options' ), "$option was not deleted from the cache." );
+ }
+
+ // Add non-existent option to the options to prime.
+ $options_to_prime[] = 'option404notfound';
+
+ // Prime the first option with a non-existent option.
+ wp_prime_option_caches( array( 'option1', 'option404notfound' ) );
+
+ // Store the initial database query count.
+ $initial_query_count = get_num_queries();
+
+ // Prime all the options, including the pre-primed option.
+ wp_prime_option_caches( $options_to_prime );
+
+ // Ensure an additional database query was made.
+ $this->assertSame(
+ 1,
+ get_num_queries() - $initial_query_count,
+ 'Additional database queries were not made.'
+ );
+
+ // Ensure the last query does not contain the pre-primed option.
+ $this->assertStringNotContainsString(
+ "\'option1\'",
+ $wpdb->last_query,
+ 'The last query should not contain the pre-primed option.'
+ );
+
+ // Ensure the last query does not contain the pre-primed notoption.
+ $this->assertStringNotContainsString(
+ "\'option404notfound\'",
+ $wpdb->last_query,
+ 'The last query should not contain the pre-primed non-existent option.'
+ );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Tests wp_prime_option_caches() with options that do not exist in the database.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 58962
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 59738
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_prime_option_caches_with_nonexistent_options() {
</span><span class="cx" style="display: block; padding: 0 10px"> // Create some options to prime.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -96,6 +160,24 @@
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ( $options_to_prime as $option ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertArrayHasKey( $option, $new_notoptions, "$option was not added to the notoptions cache." );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ // Check getting and re-priming the options does not result in additional database queries.
+ $initial_query_count = get_num_queries();
+ foreach ( $options_to_prime as $option ) {
+ get_option( $option );
+ $this->assertSame(
+ 0,
+ get_num_queries() - $initial_query_count,
+ "Additional database queries were made getting option $option."
+ );
+ }
+
+ wp_prime_option_caches( $options_to_prime );
+ $this->assertSame(
+ 0,
+ get_num_queries() - $initial_query_count,
+ 'Additional database queries were made re-priming the options.'
+ );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -102,15 +184,24 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Tests wp_prime_option_caches() with an empty array.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 58962
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 59738
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_prime_option_caches_with_empty_array() {
</span><span class="cx" style="display: block; padding: 0 10px"> $alloptions = wp_load_alloptions();
</span><span class="cx" style="display: block; padding: 0 10px"> $notoptions = wp_cache_get( 'notoptions', 'options' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $initial_query_count = get_num_queries();
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_prime_option_caches( array() );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $alloptions, wp_cache_get( 'alloptions', 'options' ), 'The alloptions cache was modified.' );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $notoptions, wp_cache_get( 'notoptions', 'options' ), 'The notoptions cache was modified.' );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ // Check priming an empty array does not result in additional database queries.
+ $this->assertSame(
+ 0,
+ get_num_queries() - $initial_query_count,
+ 'Additional database queries were made.'
+ );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -117,6 +208,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Tests that wp_prime_option_caches() handles an empty "notoptions" cache.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 58962
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 59738
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_prime_option_caches_handles_empty_notoptions_cache() {
</span><span class="cx" style="display: block; padding: 0 10px"> wp_cache_delete( 'notoptions', 'options' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -126,5 +218,244 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $notoptions = wp_cache_get( 'notoptions', 'options' );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertIsArray( $notoptions, 'The notoptions cache should be an array.' );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertArrayHasKey( 'nonexistent_option', $notoptions, 'nonexistent_option was not added to notoptions.' );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ // Check getting and re-priming the options does not result in additional database queries.
+ $initial_query_count = get_num_queries();
+
+ get_option( 'nonexistent_option' );
+ $this->assertSame(
+ 0,
+ get_num_queries() - $initial_query_count,
+ 'Additional database queries were made getting nonexistent_option.'
+ );
+
+ wp_prime_option_caches( array( 'nonexistent_option' ) );
+ $this->assertSame(
+ 0,
+ get_num_queries() - $initial_query_count,
+ 'Additional database queries were made.'
+ );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /**
+ * Test options primed by the wp_prime_option_caches() function are identical to those primed by get_option().
+ *
+ * @ticket 59738
+ *
+ * @dataProvider data_option_types
+ *
+ * @param mixed $option_value An option value.
+ */
+ public function test_get_option_should_return_identical_value_when_pre_primed_by_wp_prime_option_caches( $option_value ) {
+ // As this includes a test setting the value to `(bool) false`, update_option() can not be used so add_option() is used instead.
+ add_option( 'type_of_option', $option_value, '', false );
+ wp_cache_delete( 'type_of_option', 'options' );
+
+ $this->assertFalse( wp_cache_get( 'type_of_option', 'options' ), 'type_of_option was not deleted from the cache for priming.' );
+
+ // Call the wp_prime_option_caches function to prime the options.
+ wp_prime_option_caches( array( 'type_of_option' ) );
+ $value_after_pre_priming = get_option( 'type_of_option' );
+
+ // Clear the cache and call get_option directly.
+ wp_cache_delete( 'type_of_option', 'options' );
+ $this->assertFalse( wp_cache_get( 'type_of_option', 'options' ), 'type_of_option was not deleted from the cache for get_option.' );
+ $value_after_get_option = get_option( 'type_of_option' );
+
+ /*
+ * If the option value is an object, use assertEquals() to compare the values.
+ *
+ * This is to compare the shape of the object rather than the identity of the object.
+ */
+ if ( is_object( $option_value ) ) {
+ $this->assertEquals( $value_after_get_option, $value_after_pre_priming, 'The values should be equal.' );
+ } else {
+ $this->assertSame( $value_after_get_option, $value_after_pre_priming, 'The values should be identical.' );
+ }
+ }
+
+ /**
+ * Tests that wp_prime_option_caches() shapes the cache in the same fashion as get_option()
+ *
+ * @ticket 59738
+ *
+ * @dataProvider data_option_types
+ *
+ * @param mixed $option_value An option value.
+ */
+ public function test_wp_prime_option_caches_cache_should_be_identical_to_get_option_cache( $option_value ) {
+ // As this includes a test setting the value to `(bool) false`, update_option() can not be used so add_option() is used instead.
+ add_option( 'type_of_option', $option_value, '', false );
+ wp_cache_delete( 'type_of_option', 'options' );
+
+ $this->assertFalse( wp_cache_get( 'type_of_option', 'options' ), 'type_of_option was not deleted from the cache for wp_prime_option_caches().' );
+
+ // Call the wp_prime_option_caches function to prime the options.
+ wp_prime_option_caches( array( 'type_of_option' ) );
+ $value_from_priming = wp_cache_get( 'type_of_option', 'options' );
+
+ wp_cache_delete( 'type_of_option', 'options' );
+ $this->assertFalse( wp_cache_get( 'type_of_option', 'options' ), 'type_of_option was not deleted from the cache for get_option().' );
+
+ // Call get_option() to prime the options.
+ get_option( 'type_of_option' );
+ $value_from_get_option = wp_cache_get( 'type_of_option', 'options' );
+
+ $this->assertIsString( $value_from_get_option, 'Cache from get_option() should always be a string' );
+ $this->assertIsString( $value_from_priming, 'Cache from wp_prime_option_caches() should always be a string' );
+ $this->assertSame( $value_from_get_option, $value_from_priming, 'The values should be identical.' );
+ }
+
+ /**
+ * Tests that wp_prime_option_caches() doesn't trigger DB queries on already primed options.
+ *
+ * @ticket 59738
+ *
+ * @dataProvider data_option_types
+ *
+ * @param mixed $option_value An option value.
+ */
+ public function test_wp_prime_option_caches_does_not_trigger_db_queries_repriming_options( $option_value ) {
+ // As this includes a test setting the value to `(bool) false`, update_option() can not be used so add_option() is used instead.
+ add_option( 'double_primed_option', $option_value, '', false );
+ wp_cache_delete( 'double_primed_option', 'options' );
+ $options_to_prime = array( 'double_primed_option' );
+
+ $this->assertFalse( wp_cache_get( 'double_primed_option', 'options' ), 'double_primed_option was not deleted from the cache.' );
+
+ // Call the wp_prime_option_caches function to prime the options.
+ wp_prime_option_caches( $options_to_prime );
+
+ // Store the initial database query count.
+ $initial_query_count = get_num_queries();
+
+ // Check that options are only in the 'options' cache group.
+ foreach ( $options_to_prime as $option ) {
+ $this->assertNotFalse(
+ wp_cache_get( $option, 'options' ),
+ "$option was not primed in the 'options' cache group."
+ );
+
+ $new_notoptions = wp_cache_get( $option, 'notoptions' );
+ if ( ! is_array( $new_notoptions ) ) {
+ $new_notoptions = array();
+ }
+ $this->assertArrayNotHasKey(
+ $option,
+ $new_notoptions,
+ "$option was primed in the 'notoptions' cache."
+ );
+ }
+
+ // Call the wp_prime_option_caches function to prime the options.
+ wp_prime_option_caches( $options_to_prime );
+
+ // Ensure no additional database queries were made.
+ $this->assertSame(
+ $initial_query_count,
+ get_num_queries(),
+ 'Additional database queries were made.'
+ );
+ }
+
+ /**
+ * Tests that wp_prime_option_caches() doesn't trigger DB queries for items primed in alloptions.
+ *
+ * @ticket 59738
+ *
+ * @dataProvider data_option_types
+ *
+ * @param mixed $option_value An option value.
+ */
+ public function test_wp_prime_option_caches_does_not_trigger_db_queries_for_alloptions( $option_value ) {
+ // As this includes a test setting the value to `(bool) false`, update_option() can not be used so add_option() is used instead.
+ add_option( 'option_in_alloptions', $option_value, '', true );
+ wp_cache_delete( 'alloptions', 'options' );
+ wp_cache_delete( 'option_in_alloptions', 'options' );
+ $options_to_prime = array( 'option_in_alloptions' );
+
+ $this->assertFalse( wp_cache_get( 'option_in_alloptions', 'options' ), 'option_in_alloptions was not deleted from the cache.' );
+ $this->assertFalse( wp_cache_get( 'alloptions', 'options' ), 'alloptions was not deleted from the cache.' );
+
+ // Prime the alloptions cache.
+ wp_load_alloptions();
+
+ // Store the initial database query count.
+ $initial_query_count = get_num_queries();
+
+ // Call the wp_prime_option_caches function to reprime the option.
+ wp_prime_option_caches( $options_to_prime );
+
+ // Check that options are in the 'alloptions' cache only.
+ foreach ( $options_to_prime as $option ) {
+ $this->assertFalse(
+ wp_cache_get( $option, 'options' ),
+ "$option was primed in the 'options' cache group."
+ );
+
+ $new_notoptions = wp_cache_get( $option, 'notoptions' );
+ if ( ! is_array( $new_notoptions ) ) {
+ $new_notoptions = array();
+ }
+ $this->assertArrayNotHasKey(
+ $option,
+ $new_notoptions,
+ "$option was primed in the 'notoptions' cache."
+ );
+
+ $new_alloptions = wp_cache_get( 'alloptions', 'options' );
+ if ( ! is_array( $new_alloptions ) ) {
+ $new_alloptions = array();
+ }
+ $this->assertArrayHasKey(
+ $option,
+ $new_alloptions,
+ "$option was not primed in the 'alloptions' cache."
+ );
+ }
+
+ // Ensure no additional database queries were made.
+ $this->assertSame(
+ 0,
+ get_num_queries() - $initial_query_count,
+ 'Additional database queries were made.'
+ );
+ }
+
+ /**
+ * Data provider.
+ *
+ * @return array[]
+ */
+ public function data_option_types() {
+ return array(
+ 'null' => array( null ),
+ '(bool) false' => array( false ),
+ '(bool) true' => array( true ),
+ '(int) 0' => array( 0 ),
+ '(int) -0' => array( -0 ),
+ '(int) 1' => array( 1 ),
+ '(int) -1' => array( -1 ),
+ '(float) 0.0' => array( 0.0 ),
+ '(float) -0.0' => array( -0.0 ),
+ '(float) 1.0' => array( 1.0 ),
+ 'empty string' => array( '' ),
+ 'string with only tabs' => array( "\t\t" ),
+ 'string with only newlines' => array( "\n\n" ),
+ 'string with only carriage returns' => array( "\r\r" ),
+ 'string with only spaces' => array( ' ' ),
+ 'populated string' => array( 'string' ),
+ 'string (1)' => array( '1' ),
+ 'string (0)' => array( '0' ),
+ 'string (0.0)' => array( '0.0' ),
+ 'string (-0)' => array( '-0' ),
+ 'string (-0.0)' => array( '-0.0' ),
+ 'empty array' => array( array() ),
+ 'populated array' => array( array( 'string' ) ),
+ 'empty object' => array( new stdClass() ),
+ 'populated object' => array( (object) array( 'string' ) ),
+ 'INF' => array( INF ),
+ 'NAN' => array( NAN ),
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="branches64testsphpunittestsoptionwpPrimeOptionCachesByGroupphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/6.4/tests/phpunit/tests/option/wpPrimeOptionCachesByGroup.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/6.4/tests/phpunit/tests/option/wpPrimeOptionCachesByGroup.php 2023-10-30 22:56:25 UTC (rev 57029)
+++ branches/6.4/tests/phpunit/tests/option/wpPrimeOptionCachesByGroup.php 2023-10-30 23:21:03 UTC (rev 57030)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -47,9 +47,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Call the wp_prime_option_caches_by_group function to prime the options.
</span><span class="cx" style="display: block; padding: 0 10px"> wp_prime_option_caches_by_group( 'group1' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check that options are now in the cache.
- $this->assertSame( get_option( 'option1' ), wp_cache_get( 'option1', 'options' ), 'option1\'s cache was not primed.' );
- $this->assertSame( get_option( 'option2' ), wp_cache_get( 'option2', 'options' ), 'option2\'s cache was not primed.' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*
+ * Check that options are now in the cache.
+ *
+ * Repeat the string here rather than using get_option as get_option
+ * will prime the cache before the call to wp_cache_get if the option
+ * is not in the cache. Thus causing the tests to pass when they should
+ * fail.
+ */
+ $this->assertSame( 'value_option1', wp_cache_get( 'option1', 'options' ), 'option1\'s cache was not primed.' );
+ $this->assertSame( 'value_option2', wp_cache_get( 'option2', 'options' ), 'option2\'s cache was not primed.' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Make sure option3 is still not in cache.
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertFalse( wp_cache_get( 'option3', 'options' ), 'option3 was not deleted from the cache.' );
</span></span></pre>
</div>
</div>
</body>
</html>