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


Generated : Wed Nov 4 08:20:38 2026 Cross-referenced by PHPXref