[ 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       * @phpstan-param false $deprecated
 425       */
 426  	public function delete( $key, $group = 'default', $deprecated = false ) {
 427          if ( ! $this->is_valid_key( $key ) ) {
 428              return false;
 429          }
 430  
 431          if ( empty( $group ) ) {
 432              $group = 'default';
 433          }
 434  
 435          if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
 436              $key = $this->blog_prefix . $key;
 437          }
 438  
 439          if ( ! $this->_exists( $key, $group ) ) {
 440              return false;
 441          }
 442  
 443          unset( $this->cache[ $group ][ $key ] );
 444          return true;
 445      }
 446  
 447      /**
 448       * Deletes multiple values from the cache in one call.
 449       *
 450       * @since 6.0.0
 451       *
 452       * @param array  $keys  Array of keys to be deleted.
 453       * @param string $group Optional. Where the cache contents are grouped. Default empty.
 454       * @return bool[] Array of return values, grouped by key. Each value is either
 455       *                true on success, or false if the contents were not deleted.
 456       */
 457  	public function delete_multiple( array $keys, $group = '' ) {
 458          $values = array();
 459  
 460          foreach ( $keys as $key ) {
 461              $values[ $key ] = $this->delete( $key, $group );
 462          }
 463  
 464          return $values;
 465      }
 466  
 467      /**
 468       * Increments numeric cache item's value.
 469       *
 470       * @since 3.3.0
 471       *
 472       * @param int|string $key    The cache key to increment.
 473       * @param int        $offset Optional. The amount by which to increment the item's value.
 474       *                           Default 1.
 475       * @param string     $group  Optional. The group the key is in. Default 'default'.
 476       * @return int|false The item's new value on success, false on failure.
 477       */
 478  	public function incr( $key, $offset = 1, $group = 'default' ) {
 479          if ( ! $this->is_valid_key( $key ) ) {
 480              return false;
 481          }
 482  
 483          if ( empty( $group ) ) {
 484              $group = 'default';
 485          }
 486  
 487          if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
 488              $key = $this->blog_prefix . $key;
 489          }
 490  
 491          if ( ! $this->_exists( $key, $group ) ) {
 492              return false;
 493          }
 494  
 495          if ( ! is_numeric( $this->cache[ $group ][ $key ] ) ) {
 496              $this->cache[ $group ][ $key ] = 0;
 497          }
 498  
 499          $offset = (int) $offset;
 500  
 501          $this->cache[ $group ][ $key ] += $offset;
 502  
 503          if ( $this->cache[ $group ][ $key ] < 0 ) {
 504              $this->cache[ $group ][ $key ] = 0;
 505          }
 506  
 507          return $this->cache[ $group ][ $key ];
 508      }
 509  
 510      /**
 511       * Decrements numeric cache item's value.
 512       *
 513       * @since 3.3.0
 514       *
 515       * @param int|string $key    The cache key to decrement.
 516       * @param int        $offset Optional. The amount by which to decrement the item's value.
 517       *                           Default 1.
 518       * @param string     $group  Optional. The group the key is in. Default 'default'.
 519       * @return int|false The item's new value on success, false on failure.
 520       */
 521  	public function decr( $key, $offset = 1, $group = 'default' ) {
 522          if ( ! $this->is_valid_key( $key ) ) {
 523              return false;
 524          }
 525  
 526          if ( empty( $group ) ) {
 527              $group = 'default';
 528          }
 529  
 530          if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
 531              $key = $this->blog_prefix . $key;
 532          }
 533  
 534          if ( ! $this->_exists( $key, $group ) ) {
 535              return false;
 536          }
 537  
 538          if ( ! is_numeric( $this->cache[ $group ][ $key ] ) ) {
 539              $this->cache[ $group ][ $key ] = 0;
 540          }
 541  
 542          $offset = (int) $offset;
 543  
 544          $this->cache[ $group ][ $key ] -= $offset;
 545  
 546          if ( $this->cache[ $group ][ $key ] < 0 ) {
 547              $this->cache[ $group ][ $key ] = 0;
 548          }
 549  
 550          return $this->cache[ $group ][ $key ];
 551      }
 552  
 553      /**
 554       * Clears the object cache of all data.
 555       *
 556       * @since 2.0.0
 557       *
 558       * @return true Always returns true.
 559       */
 560  	public function flush() {
 561          $this->cache = array();
 562  
 563          return true;
 564      }
 565  
 566      /**
 567       * Removes all cache items in a group.
 568       *
 569       * @since 6.1.0
 570       *
 571       * @param string $group Name of group to remove from cache.
 572       * @return true Always returns true.
 573       */
 574  	public function flush_group( $group ) {
 575          unset( $this->cache[ $group ] );
 576  
 577          return true;
 578      }
 579  
 580      /**
 581       * Sets the list of global cache groups.
 582       *
 583       * @since 3.0.0
 584       *
 585       * @param string|string[] $groups List of groups that are global.
 586       */
 587  	public function add_global_groups( $groups ) {
 588          $groups = (array) $groups;
 589  
 590          $groups              = array_fill_keys( $groups, true );
 591          $this->global_groups = array_merge( $this->global_groups, $groups );
 592      }
 593  
 594      /**
 595       * Switches the internal blog ID.
 596       *
 597       * This changes the blog ID used to create keys in blog specific groups.
 598       *
 599       * @since 3.5.0
 600       *
 601       * @param int $blog_id Blog ID.
 602       */
 603  	public function switch_to_blog( $blog_id ) {
 604          $blog_id           = (int) $blog_id;
 605          $this->blog_prefix = $this->multisite ? $blog_id . ':' : '';
 606      }
 607  
 608      /**
 609       * Resets cache keys.
 610       *
 611       * @since 3.0.0
 612       *
 613       * @deprecated 3.5.0 Use WP_Object_Cache::switch_to_blog()
 614       * @see switch_to_blog()
 615       */
 616  	public function reset() {
 617          _deprecated_function( __FUNCTION__, '3.5.0', 'WP_Object_Cache::switch_to_blog()' );
 618  
 619          // Clear out non-global caches since the blog ID has changed.
 620          foreach ( array_keys( $this->cache ) as $group ) {
 621              if ( ! isset( $this->global_groups[ $group ] ) ) {
 622                  unset( $this->cache[ $group ] );
 623              }
 624          }
 625      }
 626  
 627      /**
 628       * Echoes the stats of the caching.
 629       *
 630       * Gives the cache hits, and cache misses. Also prints every cached group,
 631       * key and the data.
 632       *
 633       * @since 2.0.0
 634       */
 635  	public function stats() {
 636          echo '<p>';
 637          echo "<strong>Cache Hits:</strong> {$this->cache_hits}<br />";
 638          echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br />";
 639          echo '</p>';
 640          echo '<ul>';
 641          foreach ( $this->cache as $group => $cache ) {
 642              echo '<li><strong>Group:</strong> ' . esc_html( $group ) . ' - ( ' . number_format( strlen( serialize( $cache ) ) / KB_IN_BYTES, 2 ) . 'k )</li>';
 643          }
 644          echo '</ul>';
 645      }
 646  }


Generated : Thu Oct 15 08:20:32 2026 Cross-referenced by PHPXref