<?php
if(!defined( 'WPINC' )){
die();
}
/**
* Object Cache API
*
* @link https://developer.wordpress.org/reference/classes/wp_object_cache/
*
* @package WordPress
* @subpackage Cache
*/
/** WP_Object_Cache class */
require_once $plugin_dir . '/main/objectcache.php';
function wp_cache_init() {
$GLOBALS['wp_object_cache'] = WP_Object_Cache::get_instance();
}
function wp_cache_add( $key, $data, $group = '', $expire = 0 ) {
global $wp_object_cache;
return $wp_object_cache->add( $key, $data, $group, (int) $expire );
}
function wp_cache_add_multiple( array $data, $group = '', $expire = 0 ) {
global $wp_object_cache;
return $wp_object_cache->add_multiple( $data, $group, $expire );
}
function wp_cache_replace( $key, $data, $group = '', $expire = 0 ) {
global $wp_object_cache;
return $wp_object_cache->replace( $key, $data, $group, (int) $expire );
}
function wp_cache_set( $key, $data, $group = '', $expire = 0 ) {
global $wp_object_cache;
return $wp_object_cache->set( $key, $data, $group, (int) $expire );
}
function wp_cache_set_multiple( array $data, $group = '', $expire = 0 ) {
global $wp_object_cache;
return $wp_object_cache->set_multiple( $data, $group, $expire );
}
function wp_cache_get( $key, $group = '', $force = false, &$found = null ) {
global $wp_object_cache;
return $wp_object_cache->get( $key, $group, $force, $found );
}
function wp_cache_get_multiple( $keys, $group = '', $force = false ) {
global $wp_object_cache;
return $wp_object_cache->get_multiple( $keys, $group, $force );
}
function wp_cache_delete( $key, $group = '' ) {
global $wp_object_cache;
return $wp_object_cache->delete( $key, $group );
}
function wp_cache_delete_multiple( array $keys, $group = '' ) {
global $wp_object_cache;
return $wp_object_cache->delete_multiple( $keys, $group );
}
function wp_cache_incr( $key, $offset = 1, $group = '' ) {
global $wp_object_cache;
return $wp_object_cache->incr( $key, $offset, $group );
}
function wp_cache_decr( $key, $offset = 1, $group = '' ) {
global $wp_object_cache;
return $wp_object_cache->decr( $key, $offset, $group );
}
function wp_cache_flush() {
global $wp_object_cache;
return $wp_object_cache->flush();
}
function wp_cache_flush_runtime() {
return wp_cache_flush();
}
function wp_cache_flush_group( $group ) {
global $wp_object_cache;
return $wp_object_cache->flush_group( $group );
}
function wp_cache_supports( $feature ) {
switch ( $feature ) {
case 'add_multiple':
case 'set_multiple':
case 'get_multiple':
case 'delete_multiple':
case 'flush_runtime':
case 'flush_group':
return true;
default:
return false;
}
}
function wp_cache_close() {
return true;
}
function wp_cache_add_global_groups( $groups ) {
global $wp_object_cache;
$wp_object_cache->add_global_groups( $groups );
}
function wp_cache_add_non_persistent_groups( $groups ) {
// Default cache doesn't persist so nothing to do here.
}
function wp_cache_switch_to_blog( $blog_id ) {
global $wp_object_cache;
$wp_object_cache->switch_to_blog( $blog_id );
}
function wp_cache_reset() {
_deprecated_function( __FUNCTION__, '3.5.0', 'wp_cache_switch_to_blog()' );
global $wp_object_cache;
$wp_object_cache->reset();
}
#[AllowDynamicProperties]
class WP_Object_Cache {
private $cache = array();
public $cache_hits = 0;
public $cache_misses = 0;
protected $global_groups = array();
private $blog_prefix;
private $multisite;
public $object_cache;
static $instance;
public function __construct() {
$this->object_cache = \SpeedyCache\ObjectCache::get_instance();
$this->multisite = is_multisite();
$this->blog_prefix = $this->multisite ? get_current_blog_id() . ':' : '';
}
static function get_instance(){
if(self::$instance){
return self::$instance;
}
self::$instance = new self;
return self::$instance;
}
public function __get( $name ) {
return $this->$name;
}
public function __set( $name, $value ) {
return $this->$name = $value;
}
public function __isset( $name ) {
return isset( $this->$name );
}
public function __unset( $name ) {
unset( $this->$name );
}
protected function is_valid_key( $key ) {
if ( is_int( $key ) ) {
return true;
}
if ( is_string( $key ) && trim( $key ) !== '' ) {
return true;
}
$type = gettype( $key );
if ( ! function_exists( '__' ) ) {
wp_load_translations_early();
}
$message = is_string( $key )
? __( 'Cache key must not be an empty string.' )
/* translators: %s: The type of the given cache key. */
: sprintf( __( 'Cache key must be integer or non-empty string, %s given.' ), $type );
_doing_it_wrong(
sprintf( '%s::%s', __CLASS__, debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 )[1]['function'] ),
$message,
'6.1.0'
);
return false;
}
protected function _exists( $key, $group ) {
if(!$id = $this->id($key, $group)){
return false;
}
return isset($this->cache[$group][$id]);
}
public function add( $key, $data, $group = 'default', $expire = 0 ) {
if(wp_suspend_cache_addition()){
return false;
}
if(! $this->is_valid_key($key)){
return false;
}
if($this->_exists($key, $group)){
return false;
}
return $this->set($key, $data, $group, (int) $expire);
}
public function add_multiple( array $data, $group = '', $expire = 0 ) {
$values = array();
foreach ( $data as $key => $value ) {
$values[ $key ] = $this->add( $key, $value, $group, $expire );
}
return $values;
}
public function replace( $key, $data, $group = 'default', $expire = 0 ) {
if ( ! $this->is_valid_key( $key ) ) {
return false;
}
if(!$id = $this->id($key, $group)){
return false;
}
if (!$this->_exists($key, $group)){
if(!$this->object_cache::exists($id)){
return false;
}
}
return $this->set( $key, $data, $group, (int) $expire );
}
public function set( $key, $data, $group = 'default', $expire = 0 ) {
if(! $this->is_valid_key($key)){
return false;
}
if(is_object($data)){
$data = clone $data;
}
if(!$id = $this->id($key, $group)){
return false;
}
if(!in_array($group, $this->object_cache::$non_cache_group)){
$this->object_cache::set($id, $data, (int) $expire);
}
$this->cache[$group][$id] = $data;
return true;
}
public function set_multiple( array $data, $group = '', $expire = 0 ) {
$values = array();
foreach ( $data as $key => $value ) {
$values[ $key ] = $this->set( $key, $value, $group, $expire );
}
return $values;
}
public function get( $key, $group = 'default', $force = false, &$found = null ) {
if ( ! $this->is_valid_key( $key ) ) {
return false;
}
if(!$id = $this->id($key, $group)){
$found = false;
$this->cache_misses += 1;
return false;
}
// In memory cache
if($this->_exists($key, $group)){
$found = true;
$this->cache_hits += 1;
return $this->cache[$group][$id];
}
// Non Cache Group check.
if(empty($this->object_cache) || in_array($group, $this->object_cache::$non_cache_group)){
$found = false;
$this->cache_misses += 1;
return false;
}
// Fetch cache from redis.
if($cache = $this->object_cache::get($id)){
$found = true;
$this->cache_hits += 1;
if(is_serialized($cache)){
$cache = maybe_unserialize($cache);
}
$this->cache[$group][$id] = $cache;
return $this->cache[$group][$id];
}
$found = false;
$this->cache_misses += 1;
return false;
}
public function get_multiple($keys, $group = 'default', $force = false) {
$values = array();
foreach($keys as $key){
$values[$key] = $this->get($key, $group, $force);
}
return $values;
}
public function delete($key, $group = 'default', $deprecated = false) {
if (! $this->is_valid_key($key)){
return false;
}
if(!$id = $this->id($key, $group)){
return false;
}
if(empty($this->cache[$group]) && empty($this->cache[$group][$id]) && !$this->object_cache::exists($id)) {
return false;
}
unset($this->cache[$group][$id]);
$this->object_cache::delete($id);
return true;
}
public function delete_multiple(array $keys, $group = ''){
$values = array();
foreach($keys as $key){
$values[$key] = $this->delete($key, $group);
}
return $values;
}
public function incr($key, $offset = 1, $group = 'default'){
return $this->incr_desr($key, $offset = 1, $group, true);
}
public function decr($key, $offset = 1, $group = 'default'){
return $this->incr_desr($key, $offset = 1, $group, false);
}
public function incr_desr($key, $offset = 1, $group = 'default', $incr = true){
if (! $this->is_valid_key($key)){
return false;
}
$cache_val = $this->get($key, $group);
if(false === $cache_val){
return false;
}
if(! is_numeric( $cache_val)){
$cache_val = 0;
}
$offset = (int) $offset;
if($incr){
$cache_val += $offset;
}
else {
$cache_val -= $offset;
}
if ( $cache_val < 0 ) {
$cache_val = 0;
}
$this->set($key, $cache_val, $group);
return $cache_val;
}
public function flush() {
$this->cache = array();
if(!empty($this->object_cache)){
$this->object_cache::flush_db();
}
return true;
}
public function flush_group($group) {
unset($this->cache[$group]);
return true;
}
public function add_global_groups($groups){
$groups = (array) $groups;
$groups = array_fill_keys($groups, true);
$this->global_groups = array_merge($this->global_groups, $groups);
}
public function is_global($group){
return in_array($group, $this->global_groups);
}
public function switch_to_blog($blog_id){
$blog_id = (int) $blog_id;
$this->blog_prefix = $this->multisite ? $blog_id . ':' : '';
}
public function reset(){
_deprecated_function(__FUNCTION__, '3.5.0', 'WP_Object_Cache::switch_to_blog()');
// Clear out non-global caches since the blog ID has changed.
foreach(array_keys($this->cache) as $group){
if(! isset( $this->global_groups[$group])){
unset($this->cache[$group]);
}
}
}
public function stats() {
echo '<p>';
echo "<strong>Cache Hits:</strong> {$this->cache_hits}<br />";
echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br />";
echo '</p>';
echo '<ul>';
foreach($this->cache as $group => $cache){
echo '<li><strong>Group:</strong> ' . esc_html($group) . ' - ( ' . number_format(strlen(serialize($cache)) / KB_IN_BYTES, 2 ) . 'k )</li>';
}
echo '</ul>';
}
public function id($key, $group){
$prefix = $this->is_global($group) ? '' : $this->blog_prefix;
if(empty($group)){
$group = 'default';
}
return $prefix . $group . '.' . $key;
}
}