<!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>[BuddyPress][11053] trunk/src/bp-core/bp-core-cache.php: Introduce cache incrementor 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 { 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="http://buddypress.trac.wordpress.org/changeset/11053">11053</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://buddypress.trac.wordpress.org/changeset/11053","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>boonebgorges</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2016-09-01 03:27:05 +0000 (Thu, 01 Sep 2016)</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'>Introduce cache incrementor functions.

A cache incrementor is a unique string that allows for easy bulk
invalidation of specific cache items. In the BuddyPress context, this
is useful for things like object queries. Object queries have more
permutations of query parameters than can be individually invalidated.
As a workaround, we can ensure that all cache keys for query results
are hashed with the same incrementor; bumping this incrementor will
then effectively invalidate all of these caches.

See <a href="http://buddypress.trac.wordpress.org/ticket/7237">#7237</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcbpcorebpcorecachephp">trunk/src/bp-core/bp-core-cache.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcbpcorebpcorecachephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/bp-core/bp-core-cache.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/bp-core/bp-core-cache.php       2016-09-01 00:50:06 UTC (rev 11052)
+++ trunk/src/bp-core/bp-core-cache.php 2016-09-01 03:27:05 UTC (rev 11053)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -262,3 +262,100 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        return $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">+
+/**
+ * Gets a value that has been cached using an incremented key.
+ *
+ * A utility function for use by query methods like BP_Activity_Activity::get().
+ *
+ * @since 2.7.0
+ * @see bp_core_set_incremented_cache()
+ *
+ * @param string $key   Unique key for the query. Usually a SQL string.
+ * @param string $group Cache group. Eg 'bp_activity'.
+ * @return array|bool False if no cached values are found, otherwise an array of IDs.
+ */
+function bp_core_get_incremented_cache( $key, $group ) {
+       $cache_key = bp_core_get_incremented_cache_key( $key, $group );
+       return wp_cache_get( $cache_key, $group );
+}
+
+/**
+ * Caches a value using an incremented key.
+ *
+ * An "incremented key" is a cache key that is hashed with a unique incrementor,
+ * allowing for bulk invalidation.
+ *
+ * Use this method when caching data that should be invalidated whenever any
+ * object of a given type is created, updated, or deleted. This usually means
+ * data related to object queries, which can only reliably cached until the
+ * underlying set of objects has been modified. See, eg, BP_Activity_Activity::get().
+ *
+ * @since 2.7.0
+ *
+ * @param string $key   Unique key for the query. Usually a SQL string.
+ * @param string $group Cache group. Eg 'bp_activity'.
+ * @param array  $ids   Array of IDs.
+ * @return bool
+ */
+function bp_core_set_incremented_cache( $key, $group, $ids ) {
+       $cache_key = bp_core_get_incremented_cache_key( $key, $group );
+       return wp_cache_set( $cache_key, $ids, $group );
+}
+
+/**
+ * Gets the key to be used when caching a value using an incremented cache key.
+ *
+ * The $key is hashed with a component-specific incrementor, which is used to
+ * invalidate multiple caches at once.
+
+ * @since 2.7.0
+ *
+ * @param string $key   Unique key for the query. Usually a SQL string.
+ * @param string $group Cache group. Eg 'bp_activity'.
+ * @return string
+ */
+function bp_core_get_incremented_cache_key( $key, $group ) {
+       $incrementor = bp_core_get_incrementor( $group );
+       $cache_key = md5( $key . $incrementor );
+       return $cache_key;
+}
+
+/**
+ * Gets a group-specific cache incrementor.
+ *
+ * The incrementor is paired with query identifiers (like SQL strings) to
+ * create cache keys that can be invalidated en masse.
+ *
+ * If an incrementor does not yet exist for the given `$group`, one will
+ * be created.
+ *
+ * @since 2.7.0
+ *
+ * @param string $group Cache group. Eg 'bp_activity'.
+ * @return string
+ */
+function bp_core_get_incrementor( $group ) {
+       $incrementor = wp_cache_get( 'incrementor', $group );
+       if ( ! $incrementor ) {
+               $incrementor = microtime();
+               wp_cache_set( 'incrementor', $incrementor, $group );
+       }
+
+       return $incrementor;
+}
+
+/**
+ * Reset a group-specific cache incrementor.
+ *
+ * Call this function when all incrementor-based caches associated with a given
+ * cache group should be invalidated.
+ *
+ * @since 2.7.0
+ *
+ * @param string $group Cache group. Eg 'bp_activity'.
+ * @return bool True on success, false on failure.
+ */
+function bp_core_reset_incrementor( $group ) {
+       wp_cache_delete( 'incrementor', $group );
+}
</ins></span></pre>
</div>
</div>

</body>
</html>