<!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>[42723] trunk/src/wp-includes/load.php: Cache API: Allow external object caches to gracefully degrade to the default object cache.</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 { 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/42723">42723</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/42723","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>markjaquith</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2018-02-21 14:58:14 +0000 (Wed, 21 Feb 2018)</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'>Cache API: Allow external object caches to gracefully degrade to the default object cache.

Rework logic for how external object caches are detected, so that if
an external cache does not define a `wp_cache_init()`, the built-in
object cache will be used.

Object caches can now wrap their entire contents in logic checks. So a
Redis caching backend could make sure that the `Redis` PHP class is
available before defining all the caching functions. And if Redis is
not available, the site doesn't break or throw errors or think it is
using caching when it isn't. This is particularly useful for doing
local development, where you might want to develop on a site without
running Memcache or Redis like you are in production.

* Accounts for multisite, which may re-initialize the object cache
multiple times.
* Accounts for object caches that may include `object-cache.php` during
`advanced-cache.php` (before WP loads it).

Props jtsternberg, markjaquith.
Fixes <a href="https://core.trac.wordpress.org/ticket/22661">#22661</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesloadphp">trunk/src/wp-includes/load.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesloadphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/load.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/load.php    2018-02-21 09:34:33 UTC (rev 42722)
+++ trunk/src/wp-includes/load.php      2018-02-21 14:58:14 UTC (rev 42723)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -530,30 +530,39 @@
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><span class="cx" style="display: block; padding: 0 10px"> function wp_start_object_cache() {
</span><span class="cx" style="display: block; padding: 0 10px">        global $wp_filter;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        static $first_init = true;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $first_init = false;
-       if ( ! function_exists( 'wp_cache_init' ) ) {
-               if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
-                       require_once( WP_CONTENT_DIR . '/object-cache.php' );
-                       if ( function_exists( 'wp_cache_init' ) ) {
-                               wp_using_ext_object_cache( true );
-                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Only perform the following checks once.
+       if ( $first_init ) {
+               if ( ! function_exists( 'wp_cache_init' ) ) {
+                       /*
+                        * This is the normal situation. First-run of this function. No
+                        * caching backend has been loaded.
+                        *
+                        * We try to load a custom caching backend, and then, if it
+                        * results in a wp_cache_init() function existing, we note
+                        * that an external object cache is being used.
+                        */
+                       if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
+                               require_once( WP_CONTENT_DIR . '/object-cache.php' );
+                               if ( function_exists( 'wp_cache_init' ) ) {
+                                       wp_using_ext_object_cache( true );
+                               }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        // Re-initialize any hooks added manually by object-cache.php
-                       if ( $wp_filter ) {
-                               $wp_filter = WP_Hook::build_preinitialized_hooks( $wp_filter );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         // Re-initialize any hooks added manually by object-cache.php
+                               if ( $wp_filter ) {
+                                       $wp_filter = WP_Hook::build_preinitialized_hooks( $wp_filter );
+                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                } elseif ( ! wp_using_ext_object_cache() && file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
+                       /*
+                        * Sometimes advanced-cache.php can load object-cache.php before
+                        * this function is run. This breaks the function_exists() check
+                        * above and can result in wp_using_ext_object_cache() returning
+                        * false when actually an external cache is in use.
+                        */
+                       wp_using_ext_object_cache( true );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-               $first_init = true;
-       } elseif ( ! wp_using_ext_object_cache() && file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
-               /*
-                * Sometimes advanced-cache.php can load object-cache.php before
-                * it is loaded here. This breaks the function_exists check above
-                * and can result in `$_wp_using_ext_object_cache` being set
-                * incorrectly. Double check if an external cache exists.
-                */
-               wp_using_ext_object_cache( true );
</del><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">        if ( ! wp_using_ext_object_cache() ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -575,6 +584,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'site-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites' ) );
</span><span class="cx" style="display: block; padding: 0 10px">                wp_cache_add_non_persistent_groups( array( 'counts', 'plugins' ) );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       $first_init = false;
</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></pre>
</div>
</div>

</body>
</html>