[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> class-wp-object-cache.php (source)

   1  <?php
   2  /**
   3   * Object Cache API: WP_Object_Cache class
   4   *
   5   * @package WordPress
   6   * @subpackage Cache
   7   * @since 5.4.0
   8   */
   9  
  10  /**
  11   * Core class that implements an object cache.
  12   *
  13   * The WordPress Object Cache is used to save on trips to the database. The
  14   * Object Cache stores all of the cache data to memory and makes the cache
  15   * contents available by using a key, which is used to name and later retrieve
  16   * the cache contents.
  17   *
  18   * The Object Cache can be replaced by other caching mechanisms by placing files
  19   * in the wp-content folder which is looked at in wp-settings. If that file
  20   * exists, then this file will not be included.
  21   *
  22   * @since 2.0.0
  23   */
  24  #[AllowDynamicProperties]
  25  class WP_Object_Cache {
  26  
  27      /**
  28       * Holds the cached objects.
  29       *
  30       * @since 2.0.0
  31       * @var array
  32       */
  33      private $cache = array();
  34  
  35      /**
  36       * The amount of times the cache data was already stored in the cache.
  37       *
  38       * @since 2.5.0
  39       * @var int
  40       */
  41      public $cache_hits = 0;
  42  
  43      /**
  44       * Amount of times the cache did not have the request in cache.
  45       *
  46       * @since 2.0.0
  47       * @var int
  48       */
  49      public $cache_misses = 0;
  50  
  51      /**
  52       * List of global cache groups.
  53       *
  54       * @since 3.0.0
  55       * @var string[]
  56       */
  57      protected $global_groups = array();
  58  
  59      /**
  60       * The blog prefix to prepend to keys in non-global groups.
  61       *
  62       * @since 3.5.0
  63       * @var string
  64       */
  65      private $blog_prefix;
  66  
  67      /**
  68       * Holds the value of is_multisite().
  69       *
  70       * @since 3.5.0
  71       * @var bool
  72       */
  73      private $multisite;
  74  
  75      /**
  76       * Sets up object properties.
  77       *
  78       * @since 2.0.8
  79       */
  80  	public function __construct() {
  81          $this->multisite   = is_multisite();
  82          $this->blog_prefix = $this->multisite ? get_current_blog_id() . ':' : '';
  83      }
  84  
  85      /**
  86       * Makes private properties readable for backward compatibility.
  87       *
  88       * @since 4.0.0
  89       *
  90       * @param string $name Property to get.
  91       * @return mixed Property.
  92       */
  93  	public function __get( $name ) {
  94          return $this->$name;
  95      }
  96  
  97      /**
  98       * Makes private properties settable for backward compatibility.
  99       *
 100       * @since 4.0.0
 101       *
 102       * @param string $name  Property to set.
 103       * @param mixed  $value Property value.
 104       */
 105  	public function __set( $name, $value ) {
 106          $this->$name = $value;
 107      }
 108  
 109      /**
 110       * Makes private properties checkable for backward compatibility.
 111       *
 112       * @since 4.0.0
 113       *
 114       * @param string $name Property to check if set.
 115       * @return bool Whether the property is set.
 116       */
 117  	public function __isset( $name ) {
 118          return isset( $this->$name );
 119      }
 120  
 121      /**
 122       * Makes private properties un-settable for backward compatibility.
 123       *
 124       * @since 4.0.0
 125       *
 126       * @param string $name Property to unset.
 127       */
 128  	public function __unset( $name ) {
 129          unset( $this->$name );
 130      }
 131  
 132      /**
 133       * Serves as a utility function to determine whether a key is valid.
 134       *
 135       * @since 6.1.0
 136       *
 137       * @param int|string $key Cache key to check for validity.
 138       * @return bool Whether the key is valid.
 139       */
 140  	protected function is_valid_key( $key ) {
 141          if ( is_int( $key ) ) {
 142              return true;
 143          }
 144  
 145          if ( is_string( $key ) && trim( $key ) !== '' ) {
 146              return true;
 147          }
 148  
 149          $type = gettype( $key );
 150  
 151          if ( ! function_exists( '__' ) ) {
 152              wp_load_translations_early();
 153          }
 154  
 155          $message = is_string( $key )
 156              ? __( 'Cache key must not be an empty string.' )
 157              /* translators: %s: The type of the given cache key. */
 158              : sprintf( __( 'Cache key must be an integer or a non-empty string, %s given.' ), $type );
 159  
 160          _doing_it_wrong(
 161              sprintf( '%s::%s', __CLASS__, debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 )[1]['function'] ),
 162              $message,
 163              '6.1.0'
 164          );
 165  
 166          return false;
 167      }
 168  
 169      /**
 170       * Serves as a utility function to determine whether a key exists in the cache.
 171       *
 172       * @since 3.4.0
 173       *
 174       * @param int|string $key   Cache key to check for existence.
 175       * @param string     $group Cache group for the key existence check.
 176       * @return bool Whether the key exists in the cache for the given group.
 177       */
 178  	protected function _exists( $key, $group ) {
 179          return isset( $this->cache[ $group ] ) && ( isset( $this->cache[ $group ][ $key ] ) || array_key_exists( $key, $this->cache[ $group ] ) );
 180      }
 181  
 182      /**
 183       * Adds data to the cache if it doesn't already exist.
 184       *
 185       * @since 2.0.0
 186       *
 187       * @uses WP_Object_Cache::_exists() Checks to see if the cache already has data.
 188       * @uses WP_Object_Cache::set()     Sets the data after the checking the cache
 189       *                                  contents existence.
 190       *
 191       * @param int|string $key    What to call the contents in the cache.
 192       * @param mixed      $data   The contents to store in the cache.
 193       * @param string     $group  Optional. Where to group the cache contents. Default 'default'.
 194       * @param int        $expire Optional. When to expire the cache contents, in seconds.
 195       *                           Default 0 (no expiration).
 196       * @return bool True on success, false if cache key and group already exist.
 197       */
 198  	public function add( $key, $data, $group = 'default', $expire = 0 ) {
 199          if ( wp_suspend_cache_addition() ) {
 200              return false;
 201          }
 202  
 203          if ( ! $this->is_valid_key( $key ) ) {
 204              return false;
 205          }
 206  
 207          if ( empty( $group ) ) {
 208              $group = 'default';
 209          }
 210  
 211          $id = $key;
 212          if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
 213              $id = $this->blog_prefix . $key;
 214          }
 215  
 216          if ( $this->_exists( $id, $group ) ) {
 217              return false;
 218          }
 219  
 220          return $this->set( $key, $data, $group, (int) $expire );
 221      }
 222  
 223      /**
 224       * Adds multiple values to the cache in one call.
 225       *
 226       * @since 6.0.0
 227       *
 228       * @param array  $data   Array of keys and values to be added.
 229       * @param string $group  Optional. Where the cache contents are grouped. Default empty.
 230       * @param int    $expire Optional. When to expire the cache contents, in seconds.
 231       *                       Default 0 (no expiration).
 232       * @return bool[] Array of return values, grouped by key. Each value is either
 233       *                true on success, or false if cache key and group already exist.
 234       */
 235  	public function add_multiple( array $data, $group = '', $expire = 0 ) {
 236          $values = array();
 237  
 238          foreach ( $data as $key => $value ) {
 239              $values[ $key ] = $this->add( $key, $value, $group, $expire );
 240          }
 241  
 242          return $values;
 243      }
 244  
 245      /**
 246       * Replaces the contents in the cache, if contents already exist.
 247       *
 248       * @since 2.0.0
 249       *
 250       * @see WP_Object_Cache::set()
 251       *
 252       * @param int|string $key    What to call the contents in the cache.
 253       * @param mixed      $data   The contents to store in the cache.
 254       * @param string     $group  Optional. Where to group the cache contents. Default 'default'.
 255       * @param int        $expire Optional. When to expire the cache contents, in seconds.
 256       *                           Default 0 (no expiration).
 257       * @return bool True if contents were replaced, false if original value does not exist.
 258       */
 259  	public function replace( $key, $data, $group = 'default', $expire = 0 ) {
 260          if ( ! $this->is_valid_key( $key ) ) {
 261              return false;
 262          }
 263  
 264          if ( empty( $group ) ) {
 265              $group = 'default';
 266          }
 267  
 268          $id = $key;
 269          if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
 270              $id = $this->blog_prefix . $key;
 271          }
 272  
 273          if ( ! $this->_exists( $id, $group ) ) {
 274              return false;
 275          }
 276  
 277          return $this->set( $key, $data, $group, (int) $expire );
 278      }
 279  
 280      /**
 281       * Sets the data contents into the cache.
 282       *
 283       * The cache contents are grouped by the $group parameter followed by the
 284       * $key. This allows for duplicate IDs in unique groups. Therefore, naming of
 285       * the group should be used with care and should follow normal function
 286       * naming guidelines outside of core WordPress usage.
 287       *
 288       * The $expire parameter is not used, because the cache will automatically
 289       * expire for each time a page is accessed and PHP finishes. The method is
 290       * more for cache plugins which use files.
 291       *
 292       * @since 2.0.0
 293       * @since 6.1.0 Returns false if cache key is invalid.
 294       *
 295       * @param int|string $key    What to call the contents in the cache.
 296       * @param mixed      $data   The contents to store in the cache.
 297       * @param string     $group  Optional. Where to group the cache contents. Default 'default'.
 298       * @param int        $expire Optional. Not used.
 299       * @return bool True if contents were set, false if key is invalid.
 300       */
 301  	public function set( $key, $data, $group = 'default', $expire = 0 ) {
 302          if ( ! $this->is_valid_key( $key ) ) {
 303              return false;
 304          }
 305  
 306          if ( empty( $group ) ) {
 307              $group = 'default';
 308          }
 309  
 310          if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
 311              $key = $this->blog_prefix . $key;
 312          }
 313  
 314          if ( is_object( $data ) ) {
 315              $data = clone $data;
 316          }
 317  
 318          $this->cache[ $group ][ $key ] = $data;
 319          return true;
 320      }
 321  
 322      /**
 323       * Sets multiple values to the cache in one call.
 324       *
 325       * @since 6.0.0
 326       *
 327       * @param array  $data   Array of key and value to be set.
 328       * @param string $group  Optional. Where the cache contents are grouped. Default empty.
 329       * @param int    $expire Optional. When to expire the cache contents, in seconds.
 330       *                       Default 0 (no expiration).
 331       * @return bool[] Array of return values, grouped by key. Each value is always true.
 332       */
 333  	public function set_multiple( array $data, $group = '', $expire = 0 ) {
 334          $values = array();
 335  
 336          foreach ( $data as $key => $value ) {
 337              $values[ $key ] = $this->set( $key, $value, $group, $expire );
 338          }
 339  
 340          return $values;
 341      }
 342  
 343      /**
 344       * Retrieves the cache contents, if it exists.
 345       *
 346       * The contents will be first attempted to be retrieved by searching by the
 347       * key in the cache group. If the cache is hit (success) then the contents
 348       * are returned.
 349       *
 350       * On failure, the number of cache misses will be incremented.
 351       *
 352       * @since 2.0.0
 353       *
 354       * @param int|string $key   The key under which the cache contents are stored.
 355       * @param string     $group Optional. Where the cache contents are grouped. Default 'default'.
 356       * @param bool       $force Optional. Unused. Whether to force an update of the local cache
 357       *                          from the persistent cache. Default false.
 358       * @param bool|null  $found Optional. Whether the key was found in the cache (passed by reference).
 359       *                          Disambiguates a return of false, a storable value. Default null.
 360       * @return mixed|false The cache contents on success, false on failure to retrieve contents.
 361       */
 362  	public function get( $key, $group = 'default', $force = false, &$found = null ) {
 363          if ( ! $this->is_valid_key( $key ) ) {
 364              return false;
 365          }
 366  
 367          if ( empty( $group ) ) {
 368              $group = 'default';
 369          }
 370  
 371          if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
 372              $key = $this->blog_prefix . $key;
 373          }
 374  
 375          if ( $this->_exists( $key, $group ) ) {
 376              $found             = true;
 377              $this->cache_hits += 1;
 378              if ( is_object( $this->cache[ $group ][ $key ] ) ) {
 379                  return clone $this->cache[ $group ][ $key ];
 380              } else {
 381                  return $this->cache[ $group ][ $key ];
 382              }
 383          }
 384  
 385          $found               = false;
 386          $this->cache_misses += 1;
 387          return false;
 388      }
 389  
 390      /**
 391       * Retrieves multiple values from the cache in one call.
 392       *
 393       * @since 5.5.0
 394       *
 395       * @param array  $keys  Array of keys under which the cache contents are stored.
 396       * @param string $group Optional. Where the cache contents are grouped. Default 'default'.
 397       * @param bool   $force Optional. Whether to force an update of the local cache
 398       *                      from the persistent cache. Default false.
 399       * @return array Array of return values, grouped by key. Each value is either
 400       *               the cache contents on success, or false on failure.
 401       */
 402  	public function get_multiple( $keys, $group = 'default', $force = false ) {
 403          $values = array();
 404  
 405          foreach ( $keys as $key ) {
 406              $values[ $key ] = $this->get( $key, $group, $force );
 407          }
 408  
 409          return $values;
 410      }
 411  
 412      /**
 413       * Removes the contents of the cache key in the group.
 414       *
 415       * If the cache key does not exist in the group, then nothing will happen.
 416       *
 417       * @since 2.0.0
 418       *
 419       * @param int|string $key        What the contents in the cache are called.
 420       * @param string     $group      Optional. Where the cache contents are grouped. Default 'default'.
 421       * @param bool       $deprecated Optional. Unused. Default false.
 422       * @return bool True on success, false if the contents were not deleted.
 423       */
 424  	public function delete( $key, $group = 'default', $deprecated = false ) {
 425          if ( ! $this->is_valid_key( $key ) ) {
 426              return false;
 427          }
 428  
 429          if ( empty( $group ) ) {
 430              $group = 'default';
 431          }
 432  
 433          if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
 434              $key = $this->blog_prefix . $key;
 435          }
 436  
 437          if ( ! $this->_exists( $key, $group ) ) {
 438              return false;
 439          }
 440  
 441          unset( $this->cache[ $group ][ $key ] );
 442          return true;
 443      }
 444  
 445      /**
 446       * Deletes multiple values from the cache in one call.
 447       *
 448       * @since 6.0.0
 449       *
 450       * @param array  $keys  Array of keys to be deleted.
 451       * @param string $group Optional. Where the cache contents are grouped. Default empty.
 452       * @return bool[] Array of return values, grouped by key. Each value is either
 453       *                true on success, or false if the contents were not deleted.
 454       */
 455  	public function delete_multiple( array $keys, $group = '' ) {
 456          $values = array();
 457  
 458          foreach ( $keys as $key ) {
 459              $values[ $key ] = $this->delete( $key, $group );
 460          }
 461  
 462          return $values;
 463      }
 464  
 465      /**
 466       * Increments numeric cache item's value.
 467       *
 468       * @since 3.3.0
 469       *
 470       * @param int|string $key    The cache key to increment.
 471       * @param int        $offset Optional. The amount by which to increment the item's value.
 472       *                           Default 1.
 473       * @param string     $group  Optional. The group the key is in. Default 'default'.
 474       * @return int|false The item's new value on success, false on failure.
 475       */
 476  	public function incr( $key, $offset = 1, $group = 'default' ) {
 477          if ( ! $this->is_valid_key( $key ) ) {
 478              return false;
 479          }
 480  
 481          if ( empty( $group ) ) {
 482              $group = 'default';
 483          }
 484  
 485          if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
 486              $key = $this->blog_prefix . $key;
 487          }
 488  
 489          if ( ! $this->_exists( $key, $group ) ) {
 490              return false;
 491          }
 492  
 493          if ( ! is_numeric( $this->cache[ $group ][ $key ] ) ) {
 494              $this->cache[ $group ][ $key ] = 0;
 495          }
 496  
 497          $offset = (int) $offset;
 498  
 499          $this->cache[ $group ][ $key ] += $offset;
 500  
 501          if ( $this->cache[ $group ][ $key ] < 0 ) {
 502              $this->cache[ $group ][ $key ] = 0;
 503          }
 504  
 505          return $this->cache[ $group ][ $key ];
 506      }
 507  
 508      /**
 509       * Decrements numeric cache item's value.
 510       *
 511       * @since 3.3.0
 512       *
 513       * @param int|string $key    The cache key to decrement.
 514       * @param int        $offset Optional. The amount by which to decrement the item's value.
 515       *                           Default 1.
 516       * @param string     $group  Optional. The group the key is in. Default 'default'.
 517       * @return int|false The item's new value on success, false on failure.
 518       */
 519  	public function decr( $key, $offset = 1, $group = 'default' ) {
 520          if ( ! $this->is_valid_key( $key ) ) {
 521              return false;
 522          }
 523  
 524          if ( empty( $group ) ) {
 525              $group = 'default';
 526          }
 527  
 528          if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
 529              $key = $this->blog_prefix . $key;
 530          }
 531  
 532          if ( ! $this->_exists( $key, $group ) ) {
 533              return false;
 534          }
 535  
 536          if ( ! is_numeric( $this->cache[ $group ][ $key ] ) ) {
 537              $this->cache[ $group ][ $key ] = 0;
 538          }
 539  
 540          $offset = (int) $offset;
 541  
 542          $this->cache[ $group ][ $key ] -= $offset;
 543  
 544          if ( $this->cache[ $group ][ $key ] < 0 ) {
 545              $this->cache[ $group ][ $key ] = 0;
 546          }
 547  
 548          return $this->cache[ $group ][ $key ];
 549      }
 550  
 551      /**
 552       * Clears the object cache of all data.
 553       *
 554       * @since 2.0.0
 555       *
 556       * @return true Always returns true.
 557       */
 558  	public function flush() {
 559          $this->cache = array();
 560  
 561          return true;
 562      }
 563  
 564      /**
 565       * Removes all cache items in a group.
 566       *
 567       * @since 6.1.0
 568       *
 569       * @param string $group Name of group to remove from cache.
 570       * @return true Always returns true.
 571       */
 572  	public function flush_group( $group ) {
 573          unset( $this->cache[ $group ] );
 574  
 575          return true;
 576      }
 577  
 578      /**
 579       * Sets the list of global cache groups.
 580       *
 581       * @since 3.0.0
 582       *
 583       * @param string|string[] $groups List of groups that are global.
 584       */
 585  	public function add_global_groups( $groups ) {
 586          $groups = (array) $groups;
 587  
 588          $groups              = array_fill_keys( $groups, true );
 589          $this->global_groups = array_merge( $this->global_groups, $groups );
 590      }
 591  
 592      /**
 593       * Switches the internal blog ID.
 594       *
 595       * This changes the blog ID used to create keys in blog specific groups.
 596       *
 597       * @since 3.5.0
 598       *
 599       * @param int $blog_id Blog ID.
 600       */
 601  	public function switch_to_blog( $blog_id ) {
 602          $blog_id           = (int) $blog_id;
 603          $this->blog_prefix = $this->multisite ? $blog_id . ':' : '';
 604      }
 605  
 606      /**
 607       * Resets cache keys.
 608       *
 609       * @since 3.0.0
 610       *
 611       * @deprecated 3.5.0 Use WP_Object_Cache::switch_to_blog()
 612       * @see switch_to_blog()
 613       */
 614  	public function reset() {
 615          _deprecated_function( __FUNCTION__, '3.5.0', 'WP_Object_Cache::switch_to_blog()' );
 616  
 617          // Clear out non-global caches since the blog ID has changed.
 618          foreach ( array_keys( $this->cache ) as $group ) {
 619              if ( ! isset( $this->global_groups[ $group ] ) ) {
 620                  unset( $this->cache[ $group ] );
 621              }
 622          }
 623      }
 624  
 625      /**
 626       * Echoes the stats of the caching.
 627       *
 628       * Gives the cache hits, and cache misses. Also prints every cached group,
 629       * key and the data.
 630       *
 631       * @since 2.0.0
 632       */
 633  	public function stats() {
 634          echo '<p>';
 635          echo "<strong>Cache Hits:</strong> {$this->cache_hits}<br />";
 636          echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br />";
 637          echo '</p>';
 638          echo '<ul>';
 639          foreach ( $this->cache as $group => $cache ) {
 640              echo '<li><strong>Group:</strong> ' . esc_html( $group ) . ' - ( ' . number_format( strlen( serialize( $cache ) ) / KB_IN_BYTES, 2 ) . 'k )</li>';
 641          }
 642          echo '</ul>';
 643      }
 644  }


Generated : Wed Jun 24 08:20:11 2026 Cross-referenced by PHPXref