PageRenderTime 41ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/wp-includes/class-wp-object-cache.php

https://gitlab.com/campus-academy/krowkaramel
PHP | 496 lines | 182 code | 61 blank | 253 comment | 38 complexity | cd6ecca924a6b3b89b9695a6082f5617 MD5 | raw file
  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. * Core class that implements an object cache.
  11. *
  12. * The WordPress Object Cache is used to save on trips to the database. The
  13. * Object Cache stores all of the cache data to memory and makes the cache
  14. * contents available by using a key, which is used to name and later retrieve
  15. * the cache contents.
  16. *
  17. * The Object Cache can be replaced by other caching mechanisms by placing files
  18. * in the wp-content folder which is looked at in wp-settings. If that file
  19. * exists, then this file will not be included.
  20. *
  21. * @since 2.0.0
  22. */
  23. class WP_Object_Cache {
  24. /**
  25. * Holds the cached objects.
  26. *
  27. * @since 2.0.0
  28. * @var array
  29. */
  30. private $cache = array();
  31. /**
  32. * The amount of times the cache data was already stored in the cache.
  33. *
  34. * @since 2.5.0
  35. * @var int
  36. */
  37. public $cache_hits = 0;
  38. /**
  39. * Amount of times the cache did not have the request in cache.
  40. *
  41. * @since 2.0.0
  42. * @var int
  43. */
  44. public $cache_misses = 0;
  45. /**
  46. * List of global cache groups.
  47. *
  48. * @since 3.0.0
  49. * @var array
  50. */
  51. protected $global_groups = array();
  52. /**
  53. * The blog prefix to prepend to keys in non-global groups.
  54. *
  55. * @since 3.5.0
  56. * @var string
  57. */
  58. private $blog_prefix;
  59. /**
  60. * Holds the value of is_multisite().
  61. *
  62. * @since 3.5.0
  63. * @var bool
  64. */
  65. private $multisite;
  66. /**
  67. * Sets up object properties; PHP 5 style constructor.
  68. *
  69. * @since 2.0.8
  70. */
  71. public function __construct() {
  72. $this->multisite = is_multisite();
  73. $this->blog_prefix = $this->multisite ? get_current_blog_id() . ':' : '';
  74. }
  75. /**
  76. * Makes private properties readable for backward compatibility.
  77. *
  78. * @since 4.0.0
  79. *
  80. * @param string $name Property to get.
  81. * @return mixed Property.
  82. */
  83. public function __get( $name ) {
  84. return $this->$name;
  85. }
  86. /**
  87. * Makes private properties settable for backward compatibility.
  88. *
  89. * @since 4.0.0
  90. *
  91. * @param string $name Property to set.
  92. * @param mixed $value Property value.
  93. * @return mixed Newly-set property.
  94. */
  95. public function __set( $name, $value ) {
  96. return $this->$name = $value;
  97. }
  98. /**
  99. * Makes private properties checkable for backward compatibility.
  100. *
  101. * @since 4.0.0
  102. *
  103. * @param string $name Property to check if set.
  104. * @return bool Whether the property is set.
  105. */
  106. public function __isset( $name ) {
  107. return isset( $this->$name );
  108. }
  109. /**
  110. * Makes private properties un-settable for backward compatibility.
  111. *
  112. * @since 4.0.0
  113. *
  114. * @param string $name Property to unset.
  115. */
  116. public function __unset( $name ) {
  117. unset( $this->$name );
  118. }
  119. /**
  120. * Adds data to the cache if it doesn't already exist.
  121. *
  122. * @since 2.0.0
  123. *
  124. * @uses WP_Object_Cache::_exists() Checks to see if the cache already has data.
  125. * @uses WP_Object_Cache::set() Sets the data after the checking the cache
  126. * contents existence.
  127. *
  128. * @param int|string $key What to call the contents in the cache.
  129. * @param mixed $data The contents to store in the cache.
  130. * @param string $group Optional. Where to group the cache contents. Default 'default'.
  131. * @param int $expire Optional. When to expire the cache contents. Default 0 (no expiration).
  132. * @return bool True on success, false if cache key and group already exist.
  133. */
  134. public function add( $key, $data, $group = 'default', $expire = 0 ) {
  135. if ( wp_suspend_cache_addition() ) {
  136. return false;
  137. }
  138. if ( empty( $group ) ) {
  139. $group = 'default';
  140. }
  141. $id = $key;
  142. if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
  143. $id = $this->blog_prefix . $key;
  144. }
  145. if ( $this->_exists( $id, $group ) ) {
  146. return false;
  147. }
  148. return $this->set( $key, $data, $group, (int) $expire );
  149. }
  150. /**
  151. * Sets the list of global cache groups.
  152. *
  153. * @since 3.0.0
  154. *
  155. * @param string|string[] $groups List of groups that are global.
  156. */
  157. public function add_global_groups( $groups ) {
  158. $groups = (array) $groups;
  159. $groups = array_fill_keys( $groups, true );
  160. $this->global_groups = array_merge( $this->global_groups, $groups );
  161. }
  162. /**
  163. * Decrements numeric cache item's value.
  164. *
  165. * @since 3.3.0
  166. *
  167. * @param int|string $key The cache key to decrement.
  168. * @param int $offset Optional. The amount by which to decrement the item's value. Default 1.
  169. * @param string $group Optional. The group the key is in. Default 'default'.
  170. * @return int|false The item's new value on success, false on failure.
  171. */
  172. public function decr( $key, $offset = 1, $group = 'default' ) {
  173. if ( empty( $group ) ) {
  174. $group = 'default';
  175. }
  176. if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
  177. $key = $this->blog_prefix . $key;
  178. }
  179. if ( ! $this->_exists( $key, $group ) ) {
  180. return false;
  181. }
  182. if ( ! is_numeric( $this->cache[ $group ][ $key ] ) ) {
  183. $this->cache[ $group ][ $key ] = 0;
  184. }
  185. $offset = (int) $offset;
  186. $this->cache[ $group ][ $key ] -= $offset;
  187. if ( $this->cache[ $group ][ $key ] < 0 ) {
  188. $this->cache[ $group ][ $key ] = 0;
  189. }
  190. return $this->cache[ $group ][ $key ];
  191. }
  192. /**
  193. * Removes the contents of the cache key in the group.
  194. *
  195. * If the cache key does not exist in the group, then nothing will happen.
  196. *
  197. * @since 2.0.0
  198. *
  199. * @param int|string $key What the contents in the cache are called.
  200. * @param string $group Optional. Where the cache contents are grouped. Default 'default'.
  201. * @param bool $deprecated Optional. Unused. Default false.
  202. * @return bool False if the contents weren't deleted and true on success.
  203. */
  204. public function delete( $key, $group = 'default', $deprecated = false ) {
  205. if ( empty( $group ) ) {
  206. $group = 'default';
  207. }
  208. if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
  209. $key = $this->blog_prefix . $key;
  210. }
  211. if ( ! $this->_exists( $key, $group ) ) {
  212. return false;
  213. }
  214. unset( $this->cache[ $group ][ $key ] );
  215. return true;
  216. }
  217. /**
  218. * Clears the object cache of all data.
  219. *
  220. * @since 2.0.0
  221. *
  222. * @return true Always returns true.
  223. */
  224. public function flush() {
  225. $this->cache = array();
  226. return true;
  227. }
  228. /**
  229. * Retrieves the cache contents, if it exists.
  230. *
  231. * The contents will be first attempted to be retrieved by searching by the
  232. * key in the cache group. If the cache is hit (success) then the contents
  233. * are returned.
  234. *
  235. * On failure, the number of cache misses will be incremented.
  236. *
  237. * @since 2.0.0
  238. *
  239. * @param int|string $key The key under which the cache contents are stored.
  240. * @param string $group Optional. Where the cache contents are grouped. Default 'default'.
  241. * @param bool $force Optional. Unused. Whether to force an update of the local cache
  242. * from the persistent cache. Default false.
  243. * @param bool $found Optional. Whether the key was found in the cache (passed by reference).
  244. * Disambiguates a return of false, a storable value. Default null.
  245. * @return mixed|false The cache contents on success, false on failure to retrieve contents.
  246. */
  247. public function get( $key, $group = 'default', $force = false, &$found = null ) {
  248. if ( empty( $group ) ) {
  249. $group = 'default';
  250. }
  251. if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
  252. $key = $this->blog_prefix . $key;
  253. }
  254. if ( $this->_exists( $key, $group ) ) {
  255. $found = true;
  256. $this->cache_hits += 1;
  257. if ( is_object( $this->cache[ $group ][ $key ] ) ) {
  258. return clone $this->cache[ $group ][ $key ];
  259. } else {
  260. return $this->cache[ $group ][ $key ];
  261. }
  262. }
  263. $found = false;
  264. $this->cache_misses += 1;
  265. return false;
  266. }
  267. /**
  268. * Retrieves multiple values from the cache in one call.
  269. *
  270. * @since 5.5.0
  271. *
  272. * @param array $keys Array of keys under which the cache contents are stored.
  273. * @param string $group Optional. Where the cache contents are grouped. Default 'default'.
  274. * @param bool $force Optional. Whether to force an update of the local cache
  275. * from the persistent cache. Default false.
  276. * @return array Array of values organized into groups.
  277. */
  278. public function get_multiple( $keys, $group = 'default', $force = false ) {
  279. $values = array();
  280. foreach ( $keys as $key ) {
  281. $values[ $key ] = $this->get( $key, $group, $force );
  282. }
  283. return $values;
  284. }
  285. /**
  286. * Increments numeric cache item's value.
  287. *
  288. * @since 3.3.0
  289. *
  290. * @param int|string $key The cache key to increment
  291. * @param int $offset Optional. The amount by which to increment the item's value. Default 1.
  292. * @param string $group Optional. The group the key is in. Default 'default'.
  293. * @return int|false The item's new value on success, false on failure.
  294. */
  295. public function incr( $key, $offset = 1, $group = 'default' ) {
  296. if ( empty( $group ) ) {
  297. $group = 'default';
  298. }
  299. if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
  300. $key = $this->blog_prefix . $key;
  301. }
  302. if ( ! $this->_exists( $key, $group ) ) {
  303. return false;
  304. }
  305. if ( ! is_numeric( $this->cache[ $group ][ $key ] ) ) {
  306. $this->cache[ $group ][ $key ] = 0;
  307. }
  308. $offset = (int) $offset;
  309. $this->cache[ $group ][ $key ] += $offset;
  310. if ( $this->cache[ $group ][ $key ] < 0 ) {
  311. $this->cache[ $group ][ $key ] = 0;
  312. }
  313. return $this->cache[ $group ][ $key ];
  314. }
  315. /**
  316. * Replaces the contents in the cache, if contents already exist.
  317. *
  318. * @since 2.0.0
  319. *
  320. * @see WP_Object_Cache::set()
  321. *
  322. * @param int|string $key What to call the contents in the cache.
  323. * @param mixed $data The contents to store in the cache.
  324. * @param string $group Optional. Where to group the cache contents. Default 'default'.
  325. * @param int $expire Optional. When to expire the cache contents. Default 0 (no expiration).
  326. * @return bool False if not exists, true if contents were replaced.
  327. */
  328. public function replace( $key, $data, $group = 'default', $expire = 0 ) {
  329. if ( empty( $group ) ) {
  330. $group = 'default';
  331. }
  332. $id = $key;
  333. if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
  334. $id = $this->blog_prefix . $key;
  335. }
  336. if ( ! $this->_exists( $id, $group ) ) {
  337. return false;
  338. }
  339. return $this->set( $key, $data, $group, (int) $expire );
  340. }
  341. /**
  342. * Resets cache keys.
  343. *
  344. * @since 3.0.0
  345. *
  346. * @deprecated 3.5.0 Use switch_to_blog()
  347. * @see switch_to_blog()
  348. */
  349. public function reset() {
  350. _deprecated_function( __FUNCTION__, '3.5.0', 'switch_to_blog()' );
  351. // Clear out non-global caches since the blog ID has changed.
  352. foreach ( array_keys( $this->cache ) as $group ) {
  353. if ( ! isset( $this->global_groups[ $group ] ) ) {
  354. unset( $this->cache[ $group ] );
  355. }
  356. }
  357. }
  358. /**
  359. * Sets the data contents into the cache.
  360. *
  361. * The cache contents are grouped by the $group parameter followed by the
  362. * $key. This allows for duplicate IDs in unique groups. Therefore, naming of
  363. * the group should be used with care and should follow normal function
  364. * naming guidelines outside of core WordPress usage.
  365. *
  366. * The $expire parameter is not used, because the cache will automatically
  367. * expire for each time a page is accessed and PHP finishes. The method is
  368. * more for cache plugins which use files.
  369. *
  370. * @since 2.0.0
  371. *
  372. * @param int|string $key What to call the contents in the cache.
  373. * @param mixed $data The contents to store in the cache.
  374. * @param string $group Optional. Where to group the cache contents. Default 'default'.
  375. * @param int $expire Not Used.
  376. * @return true Always returns true.
  377. */
  378. public function set( $key, $data, $group = 'default', $expire = 0 ) {
  379. if ( empty( $group ) ) {
  380. $group = 'default';
  381. }
  382. if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
  383. $key = $this->blog_prefix . $key;
  384. }
  385. if ( is_object( $data ) ) {
  386. $data = clone $data;
  387. }
  388. $this->cache[ $group ][ $key ] = $data;
  389. return true;
  390. }
  391. /**
  392. * Echoes the stats of the caching.
  393. *
  394. * Gives the cache hits, and cache misses. Also prints every cached group,
  395. * key and the data.
  396. *
  397. * @since 2.0.0
  398. */
  399. public function stats() {
  400. echo '<p>';
  401. echo "<strong>Cache Hits:</strong> {$this->cache_hits}<br />";
  402. echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br />";
  403. echo '</p>';
  404. echo '<ul>';
  405. foreach ( $this->cache as $group => $cache ) {
  406. echo '<li><strong>Group:</strong> ' . esc_html( $group ) . ' - ( ' . number_format( strlen( serialize( $cache ) ) / KB_IN_BYTES, 2 ) . 'k )</li>';
  407. }
  408. echo '</ul>';
  409. }
  410. /**
  411. * Switches the internal blog ID.
  412. *
  413. * This changes the blog ID used to create keys in blog specific groups.
  414. *
  415. * @since 3.5.0
  416. *
  417. * @param int $blog_id Blog ID.
  418. */
  419. public function switch_to_blog( $blog_id ) {
  420. $blog_id = (int) $blog_id;
  421. $this->blog_prefix = $this->multisite ? $blog_id . ':' : '';
  422. }
  423. /**
  424. * Serves as a utility function to determine whether a key exists in the cache.
  425. *
  426. * @since 3.4.0
  427. *
  428. * @param int|string $key Cache key to check for existence.
  429. * @param string $group Cache group for the key existence check.
  430. * @return bool Whether the key exists in the cache for the given group.
  431. */
  432. protected function _exists( $key, $group ) {
  433. return isset( $this->cache[ $group ] ) && ( isset( $this->cache[ $group ][ $key ] ) || array_key_exists( $key, $this->cache[ $group ] ) );
  434. }
  435. }