You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

758 lines
22 KiB

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