WordPress 4.5
[autoinstalls/wordpress.git] / wp-includes / ms-blogs.php
1 <?php
2
3 /**
4  * Site/blog functions that work with the blogs table and related data.
5  *
6  * @package WordPress
7  * @subpackage Multisite
8  * @since MU
9  */
10
11 /**
12  * Update the last_updated field for the current site.
13  *
14  * @since MU
15  *
16  * @global wpdb $wpdb WordPress database abstraction object.
17  */
18 function wpmu_update_blogs_date() {
19         global $wpdb;
20
21         update_blog_details( $wpdb->blogid, array('last_updated' => current_time('mysql', true)) );
22         /**
23          * Fires after the blog details are updated.
24          *
25          * @since MU
26          *
27          * @param int $blog_id Site ID.
28          */
29         do_action( 'wpmu_blog_updated', $wpdb->blogid );
30 }
31
32 /**
33  * Get a full blog URL, given a blog id.
34  *
35  * @since MU
36  *
37  * @param int $blog_id Blog ID
38  * @return string Full URL of the blog if found. Empty string if not.
39  */
40 function get_blogaddress_by_id( $blog_id ) {
41         $bloginfo = get_blog_details( (int) $blog_id );
42
43         if ( empty( $bloginfo ) ) {
44                 return '';
45         }
46
47         $scheme = parse_url( $bloginfo->home, PHP_URL_SCHEME );
48         $scheme = empty( $scheme ) ? 'http' : $scheme;
49
50         return esc_url( $scheme . '://' . $bloginfo->domain . $bloginfo->path );
51 }
52
53 /**
54  * Get a full blog URL, given a blog name.
55  *
56  * @since MU
57  *
58  * @param string $blogname The (subdomain or directory) name
59  * @return string
60  */
61 function get_blogaddress_by_name( $blogname ) {
62         if ( is_subdomain_install() ) {
63                 if ( $blogname == 'main' )
64                         $blogname = 'www';
65                 $url = rtrim( network_home_url(), '/' );
66                 if ( !empty( $blogname ) )
67                         $url = preg_replace( '|^([^\.]+://)|', "\${1}" . $blogname . '.', $url );
68         } else {
69                 $url = network_home_url( $blogname );
70         }
71         return esc_url( $url . '/' );
72 }
73
74 /**
75  * Given a blog's (subdomain or directory) slug, retrieve its id.
76  *
77  * @since MU
78  *
79  * @global wpdb $wpdb WordPress database abstraction object.
80  *
81  * @param string $slug
82  * @return int A blog id
83  */
84 function get_id_from_blogname( $slug ) {
85         global $wpdb;
86
87         $current_site = get_current_site();
88         $slug = trim( $slug, '/' );
89
90         $blog_id = wp_cache_get( 'get_id_from_blogname_' . $slug, 'blog-details' );
91         if ( $blog_id )
92                 return $blog_id;
93
94         if ( is_subdomain_install() ) {
95                 $domain = $slug . '.' . $current_site->domain;
96                 $path = $current_site->path;
97         } else {
98                 $domain = $current_site->domain;
99                 $path = $current_site->path . $slug . '/';
100         }
101
102         $blog_id = $wpdb->get_var( $wpdb->prepare("SELECT blog_id FROM {$wpdb->blogs} WHERE domain = %s AND path = %s", $domain, $path) );
103         wp_cache_set( 'get_id_from_blogname_' . $slug, $blog_id, 'blog-details' );
104         return $blog_id;
105 }
106
107 /**
108  * Retrieve the details for a blog from the blogs table and blog options.
109  *
110  * @since MU
111  *
112  * @global wpdb $wpdb WordPress database abstraction object.
113  *
114  * @param int|string|array $fields  Optional. A blog ID, a blog slug, or an array of fields to query against.
115  *                                  If not specified the current blog ID is used.
116  * @param bool             $get_all Whether to retrieve all details or only the details in the blogs table.
117  *                                  Default is true.
118  * @return WP_Site|false Blog details on success. False on failure.
119  */
120 function get_blog_details( $fields = null, $get_all = true ) {
121         global $wpdb;
122
123         if ( is_array($fields ) ) {
124                 if ( isset($fields['blog_id']) ) {
125                         $blog_id = $fields['blog_id'];
126                 } elseif ( isset($fields['domain']) && isset($fields['path']) ) {
127                         $key = md5( $fields['domain'] . $fields['path'] );
128                         $blog = wp_cache_get($key, 'blog-lookup');
129                         if ( false !== $blog )
130                                 return $blog;
131                         if ( substr( $fields['domain'], 0, 4 ) == 'www.' ) {
132                                 $nowww = substr( $fields['domain'], 4 );
133                                 $blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE domain IN (%s,%s) AND path = %s ORDER BY CHAR_LENGTH(domain) DESC", $nowww, $fields['domain'], $fields['path'] ) );
134                         } else {
135                                 $blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE domain = %s AND path = %s", $fields['domain'], $fields['path'] ) );
136                         }
137                         if ( $blog ) {
138                                 wp_cache_set($blog->blog_id . 'short', $blog, 'blog-details');
139                                 $blog_id = $blog->blog_id;
140                         } else {
141                                 return false;
142                         }
143                 } elseif ( isset($fields['domain']) && is_subdomain_install() ) {
144                         $key = md5( $fields['domain'] );
145                         $blog = wp_cache_get($key, 'blog-lookup');
146                         if ( false !== $blog )
147                                 return $blog;
148                         if ( substr( $fields['domain'], 0, 4 ) == 'www.' ) {
149                                 $nowww = substr( $fields['domain'], 4 );
150                                 $blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE domain IN (%s,%s) ORDER BY CHAR_LENGTH(domain) DESC", $nowww, $fields['domain'] ) );
151                         } else {
152                                 $blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE domain = %s", $fields['domain'] ) );
153                         }
154                         if ( $blog ) {
155                                 wp_cache_set($blog->blog_id . 'short', $blog, 'blog-details');
156                                 $blog_id = $blog->blog_id;
157                         } else {
158                                 return false;
159                         }
160                 } else {
161                         return false;
162                 }
163         } else {
164                 if ( ! $fields )
165                         $blog_id = get_current_blog_id();
166                 elseif ( ! is_numeric( $fields ) )
167                         $blog_id = get_id_from_blogname( $fields );
168                 else
169                         $blog_id = $fields;
170         }
171
172         $blog_id = (int) $blog_id;
173
174         $all = $get_all == true ? '' : 'short';
175         $details = wp_cache_get( $blog_id . $all, 'blog-details' );
176
177         if ( $details ) {
178                 if ( ! is_object( $details ) ) {
179                         if ( $details == -1 ) {
180                                 return false;
181                         } else {
182                                 // Clear old pre-serialized objects. Cache clients do better with that.
183                                 wp_cache_delete( $blog_id . $all, 'blog-details' );
184                                 unset($details);
185                         }
186                 } else {
187                         return $details;
188                 }
189         }
190
191         // Try the other cache.
192         if ( $get_all ) {
193                 $details = wp_cache_get( $blog_id . 'short', 'blog-details' );
194         } else {
195                 $details = wp_cache_get( $blog_id, 'blog-details' );
196                 // If short was requested and full cache is set, we can return.
197                 if ( $details ) {
198                         if ( ! is_object( $details ) ) {
199                                 if ( $details == -1 ) {
200                                         return false;
201                                 } else {
202                                         // Clear old pre-serialized objects. Cache clients do better with that.
203                                         wp_cache_delete( $blog_id, 'blog-details' );
204                                         unset($details);
205                                 }
206                         } else {
207                                 return $details;
208                         }
209                 }
210         }
211
212         if ( empty($details) ) {
213                 $details = WP_Site::get_instance( $blog_id );
214                 if ( ! $details ) {
215                         // Set the full cache.
216                         wp_cache_set( $blog_id, -1, 'blog-details' );
217                         return false;
218                 }
219         }
220
221         if ( ! $details instanceof WP_Site ) {
222                 $details = new WP_Site( $details );
223         }
224
225         if ( ! $get_all ) {
226                 wp_cache_set( $blog_id . $all, $details, 'blog-details' );
227                 return $details;
228         }
229
230         switch_to_blog( $blog_id );
231         $details->blogname   = get_option( 'blogname' );
232         $details->siteurl    = get_option( 'siteurl' );
233         $details->post_count = get_option( 'post_count' );
234         $details->home       = get_option( 'home' );
235         restore_current_blog();
236
237         /**
238          * Filter a blog's details.
239          *
240          * @since MU
241          *
242          * @param object $details The blog details.
243          */
244         $details = apply_filters( 'blog_details', $details );
245
246         wp_cache_set( $blog_id . $all, $details, 'blog-details' );
247
248         $key = md5( $details->domain . $details->path );
249         wp_cache_set( $key, $details, 'blog-lookup' );
250
251         return $details;
252 }
253
254 /**
255  * Clear the blog details cache.
256  *
257  * @since MU
258  *
259  * @param int $blog_id Optional. Blog ID. Defaults to current blog.
260  */
261 function refresh_blog_details( $blog_id = 0 ) {
262         $blog_id = (int) $blog_id;
263         if ( ! $blog_id ) {
264                 $blog_id = get_current_blog_id();
265         }
266
267         $details = get_blog_details( $blog_id, false );
268         if ( ! $details ) {
269                 // Make sure clean_blog_cache() gets the blog ID
270                 // when the blog has been previously cached as
271                 // non-existent.
272                 $details = (object) array(
273                         'blog_id' => $blog_id,
274                         'domain' => null,
275                         'path' => null
276                 );
277         }
278
279         clean_blog_cache( $details );
280
281         /**
282          * Fires after the blog details cache is cleared.
283          *
284          * @since 3.4.0
285          *
286          * @param int $blog_id Blog ID.
287          */
288         do_action( 'refresh_blog_details', $blog_id );
289 }
290
291 /**
292  * Update the details for a blog. Updates the blogs table for a given blog id.
293  *
294  * @since MU
295  *
296  * @global wpdb $wpdb WordPress database abstraction object.
297  *
298  * @param int   $blog_id Blog ID
299  * @param array $details Array of details keyed by blogs table field names.
300  * @return bool True if update succeeds, false otherwise.
301  */
302 function update_blog_details( $blog_id, $details = array() ) {
303         global $wpdb;
304
305         if ( empty($details) )
306                 return false;
307
308         if ( is_object($details) )
309                 $details = get_object_vars($details);
310
311         $current_details = get_blog_details($blog_id, false);
312         if ( empty($current_details) )
313                 return false;
314
315         $current_details = get_object_vars($current_details);
316
317         $details = array_merge($current_details, $details);
318         $details['last_updated'] = current_time('mysql', true);
319
320         $update_details = array();
321         $fields = array( 'site_id', 'domain', 'path', 'registered', 'last_updated', 'public', 'archived', 'mature', 'spam', 'deleted', 'lang_id');
322         foreach ( array_intersect( array_keys( $details ), $fields ) as $field ) {
323                 if ( 'path' === $field ) {
324                         $details[ $field ] = trailingslashit( '/' . trim( $details[ $field ], '/' ) );
325                 }
326
327                 $update_details[ $field ] = $details[ $field ];
328         }
329
330         $result = $wpdb->update( $wpdb->blogs, $update_details, array('blog_id' => $blog_id) );
331
332         if ( false === $result )
333                 return false;
334
335         // If spam status changed, issue actions.
336         if ( $details['spam'] != $current_details['spam'] ) {
337                 if ( $details['spam'] == 1 ) {
338                         /**
339                          * Fires when the blog status is changed to 'spam'.
340                          *
341                          * @since MU
342                          *
343                          * @param int $blog_id Blog ID.
344                          */
345                         do_action( 'make_spam_blog', $blog_id );
346                 } else {
347                         /**
348                          * Fires when the blog status is changed to 'ham'.
349                          *
350                          * @since MU
351                          *
352                          * @param int $blog_id Blog ID.
353                          */
354                         do_action( 'make_ham_blog', $blog_id );
355                 }
356         }
357
358         // If mature status changed, issue actions.
359         if ( $details['mature'] != $current_details['mature'] ) {
360                 if ( $details['mature'] == 1 ) {
361                         /**
362                          * Fires when the blog status is changed to 'mature'.
363                          *
364                          * @since 3.1.0
365                          *
366                          * @param int $blog_id Blog ID.
367                          */
368                         do_action( 'mature_blog', $blog_id );
369                 } else {
370                         /**
371                          * Fires when the blog status is changed to 'unmature'.
372                          *
373                          * @since 3.1.0
374                          *
375                          * @param int $blog_id Blog ID.
376                          */
377                         do_action( 'unmature_blog', $blog_id );
378                 }
379         }
380
381         // If archived status changed, issue actions.
382         if ( $details['archived'] != $current_details['archived'] ) {
383                 if ( $details['archived'] == 1 ) {
384                         /**
385                          * Fires when the blog status is changed to 'archived'.
386                          *
387                          * @since MU
388                          *
389                          * @param int $blog_id Blog ID.
390                          */
391                         do_action( 'archive_blog', $blog_id );
392                 } else {
393                         /**
394                          * Fires when the blog status is changed to 'unarchived'.
395                          *
396                          * @since MU
397                          *
398                          * @param int $blog_id Blog ID.
399                          */
400                         do_action( 'unarchive_blog', $blog_id );
401                 }
402         }
403
404         // If deleted status changed, issue actions.
405         if ( $details['deleted'] != $current_details['deleted'] ) {
406                 if ( $details['deleted'] == 1 ) {
407                         /**
408                          * Fires when the blog status is changed to 'deleted'.
409                          *
410                          * @since 3.5.0
411                          *
412                          * @param int $blog_id Blog ID.
413                          */
414                         do_action( 'make_delete_blog', $blog_id );
415                 } else {
416                         /**
417                          * Fires when the blog status is changed to 'undeleted'.
418                          *
419                          * @since 3.5.0
420                          *
421                          * @param int $blog_id Blog ID.
422                          */
423                         do_action( 'make_undelete_blog', $blog_id );
424                 }
425         }
426
427         if ( isset( $details['public'] ) ) {
428                 switch_to_blog( $blog_id );
429                 update_option( 'blog_public', $details['public'] );
430                 restore_current_blog();
431         }
432
433         refresh_blog_details($blog_id);
434
435         return true;
436 }
437
438 /**
439  * Clean the blog cache
440  *
441  * @since 3.5.0
442  *
443  * @param WP_Site $blog The blog details as returned from get_blog_details()
444  */
445 function clean_blog_cache( $blog ) {
446         $blog_id = $blog->blog_id;
447         $domain_path_key = md5( $blog->domain . $blog->path );
448
449         wp_cache_delete( $blog_id, 'sites' );
450         wp_cache_delete( $blog_id , 'blog-details' );
451         wp_cache_delete( $blog_id . 'short' , 'blog-details' );
452         wp_cache_delete(  $domain_path_key, 'blog-lookup' );
453         wp_cache_delete( 'current_blog_' . $blog->domain, 'site-options' );
454         wp_cache_delete( 'current_blog_' . $blog->domain . $blog->path, 'site-options' );
455         wp_cache_delete( 'get_id_from_blogname_' . trim( $blog->path, '/' ), 'blog-details' );
456         wp_cache_delete( $domain_path_key, 'blog-id-cache' );
457 }
458
459 /**
460  * Retrieve option value for a given blog id based on name of option.
461  *
462  * If the option does not exist or does not have a value, then the return value
463  * will be false. This is useful to check whether you need to install an option
464  * and is commonly used during installation of plugin options and to test
465  * whether upgrading is required.
466  *
467  * If the option was serialized then it will be unserialized when it is returned.
468  *
469  * @since MU
470  *
471  * @param int    $id      A blog ID. Can be null to refer to the current blog.
472  * @param string $option  Name of option to retrieve. Expected to not be SQL-escaped.
473  * @param mixed  $default Optional. Default value to return if the option does not exist.
474  * @return mixed Value set for the option.
475  */
476 function get_blog_option( $id, $option, $default = false ) {
477         $id = (int) $id;
478
479         if ( empty( $id ) )
480                 $id = get_current_blog_id();
481
482         if ( get_current_blog_id() == $id )
483                 return get_option( $option, $default );
484
485         switch_to_blog( $id );
486         $value = get_option( $option, $default );
487         restore_current_blog();
488
489         /**
490          * Filter a blog option value.
491          *
492          * The dynamic portion of the hook name, `$option`, refers to the blog option name.
493          *
494          * @since 3.5.0
495          *
496          * @param string  $value The option value.
497          * @param int     $id    Blog ID.
498          */
499         return apply_filters( "blog_option_{$option}", $value, $id );
500 }
501
502 /**
503  * Add a new option for a given blog id.
504  *
505  * You do not need to serialize values. If the value needs to be serialized, then
506  * it will be serialized before it is inserted into the database. Remember,
507  * resources can not be serialized or added as an option.
508  *
509  * You can create options without values and then update the values later.
510  * Existing options will not be updated and checks are performed to ensure that you
511  * aren't adding a protected WordPress option. Care should be taken to not name
512  * options the same as the ones which are protected.
513  *
514  * @since MU
515  *
516  * @param int    $id     A blog ID. Can be null to refer to the current blog.
517  * @param string $option Name of option to add. Expected to not be SQL-escaped.
518  * @param mixed  $value  Optional. Option value, can be anything. Expected to not be SQL-escaped.
519  * @return bool False if option was not added and true if option was added.
520  */
521 function add_blog_option( $id, $option, $value ) {
522         $id = (int) $id;
523
524         if ( empty( $id ) )
525                 $id = get_current_blog_id();
526
527         if ( get_current_blog_id() == $id )
528                 return add_option( $option, $value );
529
530         switch_to_blog( $id );
531         $return = add_option( $option, $value );
532         restore_current_blog();
533
534         return $return;
535 }
536
537 /**
538  * Removes option by name for a given blog id. Prevents removal of protected WordPress options.
539  *
540  * @since MU
541  *
542  * @param int    $id     A blog ID. Can be null to refer to the current blog.
543  * @param string $option Name of option to remove. Expected to not be SQL-escaped.
544  * @return bool True, if option is successfully deleted. False on failure.
545  */
546 function delete_blog_option( $id, $option ) {
547         $id = (int) $id;
548
549         if ( empty( $id ) )
550                 $id = get_current_blog_id();
551
552         if ( get_current_blog_id() == $id )
553                 return delete_option( $option );
554
555         switch_to_blog( $id );
556         $return = delete_option( $option );
557         restore_current_blog();
558
559         return $return;
560 }
561
562 /**
563  * Update an option for a particular blog.
564  *
565  * @since MU
566  *
567  * @param int    $id         The blog id.
568  * @param string $option     The option key.
569  * @param mixed  $value      The option value.
570  * @param mixed  $deprecated Not used.
571  * @return bool True on success, false on failure.
572  */
573 function update_blog_option( $id, $option, $value, $deprecated = null ) {
574         $id = (int) $id;
575
576         if ( null !== $deprecated  )
577                 _deprecated_argument( __FUNCTION__, '3.1' );
578
579         if ( get_current_blog_id() == $id )
580                 return update_option( $option, $value );
581
582         switch_to_blog( $id );
583         $return = update_option( $option, $value );
584         restore_current_blog();
585
586         refresh_blog_details( $id );
587
588         return $return;
589 }
590
591 /**
592  * Switch the current blog.
593  *
594  * This function is useful if you need to pull posts, or other information,
595  * from other blogs. You can switch back afterwards using restore_current_blog().
596  *
597  * Things that aren't switched:
598  *  - autoloaded options. See #14992
599  *  - plugins. See #14941
600  *
601  * @see restore_current_blog()
602  * @since MU
603  *
604  * @global wpdb            $wpdb
605  * @global int             $blog_id
606  * @global array           $_wp_switched_stack
607  * @global bool            $switched
608  * @global string          $table_prefix
609  * @global WP_Object_Cache $wp_object_cache
610  *
611  * @param int  $new_blog   The id of the blog you want to switch to. Default: current blog
612  * @param bool $deprecated Deprecated argument
613  * @return true Always returns True.
614  */
615 function switch_to_blog( $new_blog, $deprecated = null ) {
616         global $wpdb;
617
618         if ( empty( $new_blog ) )
619                 $new_blog = $GLOBALS['blog_id'];
620
621         $GLOBALS['_wp_switched_stack'][] = $GLOBALS['blog_id'];
622
623         /*
624          * If we're switching to the same blog id that we're on,
625          * set the right vars, do the associated actions, but skip
626          * the extra unnecessary work
627          */
628         if ( $new_blog == $GLOBALS['blog_id'] ) {
629                 /**
630                  * Fires when the blog is switched.
631                  *
632                  * @since MU
633                  *
634                  * @param int $new_blog New blog ID.
635                  * @param int $new_blog Blog ID.
636                  */
637                 do_action( 'switch_blog', $new_blog, $new_blog );
638                 $GLOBALS['switched'] = true;
639                 return true;
640         }
641
642         $wpdb->set_blog_id( $new_blog );
643         $GLOBALS['table_prefix'] = $wpdb->get_blog_prefix();
644         $prev_blog_id = $GLOBALS['blog_id'];
645         $GLOBALS['blog_id'] = $new_blog;
646
647         if ( function_exists( 'wp_cache_switch_to_blog' ) ) {
648                 wp_cache_switch_to_blog( $new_blog );
649         } else {
650                 global $wp_object_cache;
651
652                 if ( is_object( $wp_object_cache ) && isset( $wp_object_cache->global_groups ) )
653                         $global_groups = $wp_object_cache->global_groups;
654                 else
655                         $global_groups = false;
656
657                 wp_cache_init();
658
659                 if ( function_exists( 'wp_cache_add_global_groups' ) ) {
660                         if ( is_array( $global_groups ) ) {
661                                 wp_cache_add_global_groups( $global_groups );
662                         } else {
663                                 wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites' ) );
664                         }
665                         wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) );
666                 }
667         }
668
669         if ( did_action( 'init' ) ) {
670                 wp_roles()->reinit();
671                 $current_user = wp_get_current_user();
672                 $current_user->for_blog( $new_blog );
673         }
674
675         /** This filter is documented in wp-includes/ms-blogs.php */
676         do_action( 'switch_blog', $new_blog, $prev_blog_id );
677         $GLOBALS['switched'] = true;
678
679         return true;
680 }
681
682 /**
683  * Restore the current blog, after calling switch_to_blog()
684  *
685  * @see switch_to_blog()
686  * @since MU
687  *
688  * @global wpdb            $wpdb
689  * @global array           $_wp_switched_stack
690  * @global int             $blog_id
691  * @global bool            $switched
692  * @global string          $table_prefix
693  * @global WP_Object_Cache $wp_object_cache
694  *
695  * @return bool True on success, false if we're already on the current blog
696  */
697 function restore_current_blog() {
698         global $wpdb;
699
700         if ( empty( $GLOBALS['_wp_switched_stack'] ) )
701                 return false;
702
703         $blog = array_pop( $GLOBALS['_wp_switched_stack'] );
704
705         if ( $GLOBALS['blog_id'] == $blog ) {
706                 /** This filter is documented in wp-includes/ms-blogs.php */
707                 do_action( 'switch_blog', $blog, $blog );
708                 // If we still have items in the switched stack, consider ourselves still 'switched'
709                 $GLOBALS['switched'] = ! empty( $GLOBALS['_wp_switched_stack'] );
710                 return true;
711         }
712
713         $wpdb->set_blog_id( $blog );
714         $prev_blog_id = $GLOBALS['blog_id'];
715         $GLOBALS['blog_id'] = $blog;
716         $GLOBALS['table_prefix'] = $wpdb->get_blog_prefix();
717
718         if ( function_exists( 'wp_cache_switch_to_blog' ) ) {
719                 wp_cache_switch_to_blog( $blog );
720         } else {
721                 global $wp_object_cache;
722
723                 if ( is_object( $wp_object_cache ) && isset( $wp_object_cache->global_groups ) )
724                         $global_groups = $wp_object_cache->global_groups;
725                 else
726                         $global_groups = false;
727
728                 wp_cache_init();
729
730                 if ( function_exists( 'wp_cache_add_global_groups' ) ) {
731                         if ( is_array( $global_groups ) ) {
732                                 wp_cache_add_global_groups( $global_groups );
733                         } else {
734                                 wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites' ) );
735                         }
736                         wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) );
737                 }
738         }
739
740         if ( did_action( 'init' ) ) {
741                 wp_roles()->reinit();
742                 $current_user = wp_get_current_user();
743                 $current_user->for_blog( $blog );
744         }
745
746         /** This filter is documented in wp-includes/ms-blogs.php */
747         do_action( 'switch_blog', $blog, $prev_blog_id );
748
749         // If we still have items in the switched stack, consider ourselves still 'switched'
750         $GLOBALS['switched'] = ! empty( $GLOBALS['_wp_switched_stack'] );
751
752         return true;
753 }
754
755 /**
756  * Determines if switch_to_blog() is in effect
757  *
758  * @since 3.5.0
759  *
760  * @global array $_wp_switched_stack
761  *
762  * @return bool True if switched, false otherwise.
763  */
764 function ms_is_switched() {
765         return ! empty( $GLOBALS['_wp_switched_stack'] );
766 }
767
768 /**
769  * Check if a particular blog is archived.
770  *
771  * @since MU
772  *
773  * @param int $id The blog id
774  * @return string Whether the blog is archived or not
775  */
776 function is_archived( $id ) {
777         return get_blog_status($id, 'archived');
778 }
779
780 /**
781  * Update the 'archived' status of a particular blog.
782  *
783  * @since MU
784  *
785  * @param int    $id       The blog id
786  * @param string $archived The new status
787  * @return string $archived
788  */
789 function update_archived( $id, $archived ) {
790         update_blog_status($id, 'archived', $archived);
791         return $archived;
792 }
793
794 /**
795  * Update a blog details field.
796  *
797  * @since MU
798  *
799  * @global wpdb $wpdb WordPress database abstraction object.
800  *
801  * @param int    $blog_id BLog ID
802  * @param string $pref    A field name
803  * @param string $value   Value for $pref
804  * @param null   $deprecated
805  * @return string|false $value
806  */
807 function update_blog_status( $blog_id, $pref, $value, $deprecated = null ) {
808         global $wpdb;
809
810         if ( null !== $deprecated  )
811                 _deprecated_argument( __FUNCTION__, '3.1' );
812
813         if ( ! in_array( $pref, array( 'site_id', 'domain', 'path', 'registered', 'last_updated', 'public', 'archived', 'mature', 'spam', 'deleted', 'lang_id') ) )
814                 return $value;
815
816         $result = $wpdb->update( $wpdb->blogs, array($pref => $value, 'last_updated' => current_time('mysql', true)), array('blog_id' => $blog_id) );
817
818         if ( false === $result )
819                 return false;
820
821         refresh_blog_details( $blog_id );
822
823         if ( 'spam' == $pref ) {
824                 if ( $value == 1 ) {
825                         /** This filter is documented in wp-includes/ms-blogs.php */
826                         do_action( 'make_spam_blog', $blog_id );
827                 } else {
828                         /** This filter is documented in wp-includes/ms-blogs.php */
829                         do_action( 'make_ham_blog', $blog_id );
830                 }
831         } elseif ( 'mature' == $pref ) {
832                 if ( $value == 1 ) {
833                         /** This filter is documented in wp-includes/ms-blogs.php */
834                         do_action( 'mature_blog', $blog_id );
835                 } else {
836                         /** This filter is documented in wp-includes/ms-blogs.php */
837                         do_action( 'unmature_blog', $blog_id );
838                 }
839         } elseif ( 'archived' == $pref ) {
840                 if ( $value == 1 ) {
841                         /** This filter is documented in wp-includes/ms-blogs.php */
842                         do_action( 'archive_blog', $blog_id );
843                 } else {
844                         /** This filter is documented in wp-includes/ms-blogs.php */
845                         do_action( 'unarchive_blog', $blog_id );
846                 }
847         } elseif ( 'deleted' == $pref ) {
848                 if ( $value == 1 ) {
849                         /** This filter is documented in wp-includes/ms-blogs.php */
850                         do_action( 'make_delete_blog', $blog_id );
851                 } else {
852                         /** This filter is documented in wp-includes/ms-blogs.php */
853                         do_action( 'make_undelete_blog', $blog_id );
854                 }
855         } elseif ( 'public' == $pref ) {
856                 /**
857                  * Fires after the current blog's 'public' setting is updated.
858                  *
859                  * @since MU
860                  *
861                  * @param int    $blog_id Blog ID.
862                  * @param string $value   The value of blog status.
863                  */
864                 do_action( 'update_blog_public', $blog_id, $value ); // Moved here from update_blog_public().
865         }
866
867         return $value;
868 }
869
870 /**
871  * Get a blog details field.
872  *
873  * @since MU
874  *
875  * @global wpdb $wpdb WordPress database abstraction object.
876  *
877  * @param int    $id   The blog id
878  * @param string $pref A field name
879  * @return bool|string|null $value
880  */
881 function get_blog_status( $id, $pref ) {
882         global $wpdb;
883
884         $details = get_blog_details( $id, false );
885         if ( $details )
886                 return $details->$pref;
887
888         return $wpdb->get_var( $wpdb->prepare("SELECT %s FROM {$wpdb->blogs} WHERE blog_id = %d", $pref, $id) );
889 }
890
891 /**
892  * Get a list of most recently updated blogs.
893  *
894  * @since MU
895  *
896  * @global wpdb $wpdb WordPress database abstraction object.
897  *
898  * @param mixed $deprecated Not used
899  * @param int   $start      The offset
900  * @param int   $quantity   The maximum number of blogs to retrieve. Default is 40.
901  * @return array The list of blogs
902  */
903 function get_last_updated( $deprecated = '', $start = 0, $quantity = 40 ) {
904         global $wpdb;
905
906         if ( ! empty( $deprecated ) )
907                 _deprecated_argument( __FUNCTION__, 'MU' ); // never used
908
909         return $wpdb->get_results( $wpdb->prepare("SELECT blog_id, domain, path FROM $wpdb->blogs WHERE site_id = %d AND public = '1' AND archived = '0' AND mature = '0' AND spam = '0' AND deleted = '0' AND last_updated != '0000-00-00 00:00:00' ORDER BY last_updated DESC limit %d, %d", $wpdb->siteid, $start, $quantity ) , ARRAY_A );
910 }
911
912 /**
913  * Handler for updating the blog date when a post is published or an already published post is changed.
914  *
915  * @since 3.3.0
916  *
917  * @param string $new_status The new post status
918  * @param string $old_status The old post status
919  * @param object $post       Post object
920  */
921 function _update_blog_date_on_post_publish( $new_status, $old_status, $post ) {
922         $post_type_obj = get_post_type_object( $post->post_type );
923         if ( ! $post_type_obj || ! $post_type_obj->public ) {
924                 return;
925         }
926
927         if ( 'publish' != $new_status && 'publish' != $old_status ) {
928                 return;
929         }
930
931         // Post was freshly published, published post was saved, or published post was unpublished.
932
933         wpmu_update_blogs_date();
934 }
935
936 /**
937  * Handler for updating the blog date when a published post is deleted.
938  *
939  * @since 3.4.0
940  *
941  * @param int $post_id Post ID
942  */
943 function _update_blog_date_on_post_delete( $post_id ) {
944         $post = get_post( $post_id );
945
946         $post_type_obj = get_post_type_object( $post->post_type );
947         if ( ! $post_type_obj || ! $post_type_obj->public ) {
948                 return;
949         }
950
951         if ( 'publish' != $post->post_status ) {
952                 return;
953         }
954
955         wpmu_update_blogs_date();
956 }
957
958 /**
959  * Handler for updating the blog posts count date when a post is deleted.
960  *
961  * @since 4.0.0
962  *
963  * @param int $post_id Post ID.
964  */
965 function _update_posts_count_on_delete( $post_id ) {
966         $post = get_post( $post_id );
967
968         if ( ! $post || 'publish' !== $post->post_status ) {
969                 return;
970         }
971
972         update_posts_count();
973 }
974
975 /**
976  * Handler for updating the blog posts count date when a post status changes.
977  *
978  * @since 4.0.0
979  *
980  * @param string $new_status The status the post is changing to.
981  * @param string $old_status The status the post is changing from.
982  */
983 function _update_posts_count_on_transition_post_status( $new_status, $old_status ) {
984         if ( $new_status === $old_status ) {
985                 return;
986         }
987
988         if ( 'publish' !== $new_status && 'publish' !== $old_status ) {
989                 return;
990         }
991
992         update_posts_count();
993 }