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