WordPress 4.4.2
[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 blog.
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 Blog 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 object|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 = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE blog_id = %d /* get_blog_details */", $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 ( ! $get_all ) {
222                 wp_cache_set( $blog_id . $all, $details, 'blog-details' );
223                 return $details;
224         }
225
226         switch_to_blog( $blog_id );
227         $details->blogname   = get_option( 'blogname' );
228         $details->siteurl    = get_option( 'siteurl' );
229         $details->post_count = get_option( 'post_count' );
230         $details->home       = get_option( 'home' );
231         restore_current_blog();
232
233         /**
234          * Filter a blog's details.
235          *
236          * @since MU
237          *
238          * @param object $details The blog details.
239          */
240         $details = apply_filters( 'blog_details', $details );
241
242         wp_cache_set( $blog_id . $all, $details, 'blog-details' );
243
244         $key = md5( $details->domain . $details->path );
245         wp_cache_set( $key, $details, 'blog-lookup' );
246
247         return $details;
248 }
249
250 /**
251  * Clear the blog details cache.
252  *
253  * @since MU
254  *
255  * @param int $blog_id Optional. Blog ID. Defaults to current blog.
256  */
257 function refresh_blog_details( $blog_id = 0 ) {
258         $blog_id = (int) $blog_id;
259         if ( ! $blog_id ) {
260                 $blog_id = get_current_blog_id();
261         }
262
263         $details = get_blog_details( $blog_id, false );
264         if ( ! $details ) {
265                 // Make sure clean_blog_cache() gets the blog ID
266                 // when the blog has been previously cached as
267                 // non-existent.
268                 $details = (object) array(
269                         'blog_id' => $blog_id,
270                         'domain' => null,
271                         'path' => null
272                 );
273         }
274
275         clean_blog_cache( $details );
276
277         /**
278          * Fires after the blog details cache is cleared.
279          *
280          * @since 3.4.0
281          *
282          * @param int $blog_id Blog ID.
283          */
284         do_action( 'refresh_blog_details', $blog_id );
285 }
286
287 /**
288  * Update the details for a blog. Updates the blogs table for a given blog id.
289  *
290  * @since MU
291  *
292  * @global wpdb $wpdb WordPress database abstraction object.
293  *
294  * @param int   $blog_id Blog ID
295  * @param array $details Array of details keyed by blogs table field names.
296  * @return bool True if update succeeds, false otherwise.
297  */
298 function update_blog_details( $blog_id, $details = array() ) {
299         global $wpdb;
300
301         if ( empty($details) )
302                 return false;
303
304         if ( is_object($details) )
305                 $details = get_object_vars($details);
306
307         $current_details = get_blog_details($blog_id, false);
308         if ( empty($current_details) )
309                 return false;
310
311         $current_details = get_object_vars($current_details);
312
313         $details = array_merge($current_details, $details);
314         $details['last_updated'] = current_time('mysql', true);
315
316         $update_details = array();
317         $fields = array( 'site_id', 'domain', 'path', 'registered', 'last_updated', 'public', 'archived', 'mature', 'spam', 'deleted', 'lang_id');
318         foreach ( array_intersect( array_keys( $details ), $fields ) as $field ) {
319                 if ( 'path' === $field ) {
320                         $details[ $field ] = trailingslashit( '/' . trim( $details[ $field ], '/' ) );
321                 }
322
323                 $update_details[ $field ] = $details[ $field ];
324         }
325
326         $result = $wpdb->update( $wpdb->blogs, $update_details, array('blog_id' => $blog_id) );
327
328         if ( false === $result )
329                 return false;
330
331         // If spam status changed, issue actions.
332         if ( $details['spam'] != $current_details['spam'] ) {
333                 if ( $details['spam'] == 1 ) {
334                         /**
335                          * Fires when the blog status is changed to 'spam'.
336                          *
337                          * @since MU
338                          *
339                          * @param int $blog_id Blog ID.
340                          */
341                         do_action( 'make_spam_blog', $blog_id );
342                 } else {
343                         /**
344                          * Fires when the blog status is changed to 'ham'.
345                          *
346                          * @since MU
347                          *
348                          * @param int $blog_id Blog ID.
349                          */
350                         do_action( 'make_ham_blog', $blog_id );
351                 }
352         }
353
354         // If mature status changed, issue actions.
355         if ( $details['mature'] != $current_details['mature'] ) {
356                 if ( $details['mature'] == 1 ) {
357                         /**
358                          * Fires when the blog status is changed to 'mature'.
359                          *
360                          * @since 3.1.0
361                          *
362                          * @param int $blog_id Blog ID.
363                          */
364                         do_action( 'mature_blog', $blog_id );
365                 } else {
366                         /**
367                          * Fires when the blog status is changed to 'unmature'.
368                          *
369                          * @since 3.1.0
370                          *
371                          * @param int $blog_id Blog ID.
372                          */
373                         do_action( 'unmature_blog', $blog_id );
374                 }
375         }
376
377         // If archived status changed, issue actions.
378         if ( $details['archived'] != $current_details['archived'] ) {
379                 if ( $details['archived'] == 1 ) {
380                         /**
381                          * Fires when the blog status is changed to 'archived'.
382                          *
383                          * @since MU
384                          *
385                          * @param int $blog_id Blog ID.
386                          */
387                         do_action( 'archive_blog', $blog_id );
388                 } else {
389                         /**
390                          * Fires when the blog status is changed to 'unarchived'.
391                          *
392                          * @since MU
393                          *
394                          * @param int $blog_id Blog ID.
395                          */
396                         do_action( 'unarchive_blog', $blog_id );
397                 }
398         }
399
400         // If deleted status changed, issue actions.
401         if ( $details['deleted'] != $current_details['deleted'] ) {
402                 if ( $details['deleted'] == 1 ) {
403                         /**
404                          * Fires when the blog status is changed to 'deleted'.
405                          *
406                          * @since 3.5.0
407                          *
408                          * @param int $blog_id Blog ID.
409                          */
410                         do_action( 'make_delete_blog', $blog_id );
411                 } else {
412                         /**
413                          * Fires when the blog status is changed to 'undeleted'.
414                          *
415                          * @since 3.5.0
416                          *
417                          * @param int $blog_id Blog ID.
418                          */
419                         do_action( 'make_undelete_blog', $blog_id );
420                 }
421         }
422
423         if ( isset( $details['public'] ) ) {
424                 switch_to_blog( $blog_id );
425                 update_option( 'blog_public', $details['public'] );
426                 restore_current_blog();
427         }
428
429         refresh_blog_details($blog_id);
430
431         return true;
432 }
433
434 /**
435  * Clean the blog cache
436  *
437  * @since 3.5.0
438  *
439  * @param stdClass $blog The blog details as returned from get_blog_details()
440  */
441 function clean_blog_cache( $blog ) {
442         $blog_id = $blog->blog_id;
443         $domain_path_key = md5( $blog->domain . $blog->path );
444
445         wp_cache_delete( $blog_id , 'blog-details' );
446         wp_cache_delete( $blog_id . 'short' , 'blog-details' );
447         wp_cache_delete(  $domain_path_key, 'blog-lookup' );
448         wp_cache_delete( 'current_blog_' . $blog->domain, 'site-options' );
449         wp_cache_delete( 'current_blog_' . $blog->domain . $blog->path, 'site-options' );
450         wp_cache_delete( 'get_id_from_blogname_' . trim( $blog->path, '/' ), 'blog-details' );
451         wp_cache_delete( $domain_path_key, 'blog-id-cache' );
452 }
453
454 /**
455  * Retrieve option value for a given blog id based on name of option.
456  *
457  * If the option does not exist or does not have a value, then the return value
458  * will be false. This is useful to check whether you need to install an option
459  * and is commonly used during installation of plugin options and to test
460  * whether upgrading is required.
461  *
462  * If the option was serialized then it will be unserialized when it is returned.
463  *
464  * @since MU
465  *
466  * @param int    $id      A blog ID. Can be null to refer to the current blog.
467  * @param string $option  Name of option to retrieve. Expected to not be SQL-escaped.
468  * @param mixed  $default Optional. Default value to return if the option does not exist.
469  * @return mixed Value set for the option.
470  */
471 function get_blog_option( $id, $option, $default = false ) {
472         $id = (int) $id;
473
474         if ( empty( $id ) )
475                 $id = get_current_blog_id();
476
477         if ( get_current_blog_id() == $id )
478                 return get_option( $option, $default );
479
480         switch_to_blog( $id );
481         $value = get_option( $option, $default );
482         restore_current_blog();
483
484         /**
485          * Filter a blog option value.
486          *
487          * The dynamic portion of the hook name, `$option`, refers to the blog option name.
488          *
489          * @since 3.5.0
490          *
491          * @param string  $value The option value.
492          * @param int     $id    Blog ID.
493          */
494         return apply_filters( "blog_option_{$option}", $value, $id );
495 }
496
497 /**
498  * Add a new option for a given blog id.
499  *
500  * You do not need to serialize values. If the value needs to be serialized, then
501  * it will be serialized before it is inserted into the database. Remember,
502  * resources can not be serialized or added as an option.
503  *
504  * You can create options without values and then update the values later.
505  * Existing options will not be updated and checks are performed to ensure that you
506  * aren't adding a protected WordPress option. Care should be taken to not name
507  * options the same as the ones which are protected.
508  *
509  * @since MU
510  *
511  * @param int    $id     A blog ID. Can be null to refer to the current blog.
512  * @param string $option Name of option to add. Expected to not be SQL-escaped.
513  * @param mixed  $value  Optional. Option value, can be anything. Expected to not be SQL-escaped.
514  * @return bool False if option was not added and true if option was added.
515  */
516 function add_blog_option( $id, $option, $value ) {
517         $id = (int) $id;
518
519         if ( empty( $id ) )
520                 $id = get_current_blog_id();
521
522         if ( get_current_blog_id() == $id )
523                 return add_option( $option, $value );
524
525         switch_to_blog( $id );
526         $return = add_option( $option, $value );
527         restore_current_blog();
528
529         return $return;
530 }
531
532 /**
533  * Removes option by name for a given blog id. Prevents removal of protected WordPress options.
534  *
535  * @since MU
536  *
537  * @param int    $id     A blog ID. Can be null to refer to the current blog.
538  * @param string $option Name of option to remove. Expected to not be SQL-escaped.
539  * @return bool True, if option is successfully deleted. False on failure.
540  */
541 function delete_blog_option( $id, $option ) {
542         $id = (int) $id;
543
544         if ( empty( $id ) )
545                 $id = get_current_blog_id();
546
547         if ( get_current_blog_id() == $id )
548                 return delete_option( $option );
549
550         switch_to_blog( $id );
551         $return = delete_option( $option );
552         restore_current_blog();
553
554         return $return;
555 }
556
557 /**
558  * Update an option for a particular blog.
559  *
560  * @since MU
561  *
562  * @param int    $id     The blog id
563  * @param string $option The option key
564  * @param mixed  $value  The option value
565  * @return bool True on success, false on failure.
566  */
567 function update_blog_option( $id, $option, $value, $deprecated = null ) {
568         $id = (int) $id;
569
570         if ( null !== $deprecated  )
571                 _deprecated_argument( __FUNCTION__, '3.1' );
572
573         if ( get_current_blog_id() == $id )
574                 return update_option( $option, $value );
575
576         switch_to_blog( $id );
577         $return = update_option( $option, $value );
578         restore_current_blog();
579
580         refresh_blog_details( $id );
581
582         return $return;
583 }
584
585 /**
586  * Switch the current blog.
587  *
588  * This function is useful if you need to pull posts, or other information,
589  * from other blogs. You can switch back afterwards using restore_current_blog().
590  *
591  * Things that aren't switched:
592  *  - autoloaded options. See #14992
593  *  - plugins. See #14941
594  *
595  * @see restore_current_blog()
596  * @since MU
597  *
598  * @global wpdb            $wpdb
599  * @global int             $blog_id
600  * @global array           $_wp_switched_stack
601  * @global bool            $switched
602  * @global string          $table_prefix
603  * @global WP_Object_Cache $wp_object_cache
604  *
605  * @param int  $new_blog   The id of the blog you want to switch to. Default: current blog
606  * @param bool $deprecated Deprecated argument
607  * @return true Always returns True.
608  */
609 function switch_to_blog( $new_blog, $deprecated = null ) {
610         global $wpdb;
611
612         if ( empty( $new_blog ) )
613                 $new_blog = $GLOBALS['blog_id'];
614
615         $GLOBALS['_wp_switched_stack'][] = $GLOBALS['blog_id'];
616
617         /*
618          * If we're switching to the same blog id that we're on,
619          * set the right vars, do the associated actions, but skip
620          * the extra unnecessary work
621          */
622         if ( $new_blog == $GLOBALS['blog_id'] ) {
623                 /**
624                  * Fires when the blog is switched.
625                  *
626                  * @since MU
627                  *
628                  * @param int $new_blog New blog ID.
629                  * @param int $new_blog Blog ID.
630                  */
631                 do_action( 'switch_blog', $new_blog, $new_blog );
632                 $GLOBALS['switched'] = true;
633                 return true;
634         }
635
636         $wpdb->set_blog_id( $new_blog );
637         $GLOBALS['table_prefix'] = $wpdb->get_blog_prefix();
638         $prev_blog_id = $GLOBALS['blog_id'];
639         $GLOBALS['blog_id'] = $new_blog;
640
641         if ( function_exists( 'wp_cache_switch_to_blog' ) ) {
642                 wp_cache_switch_to_blog( $new_blog );
643         } else {
644                 global $wp_object_cache;
645
646                 if ( is_object( $wp_object_cache ) && isset( $wp_object_cache->global_groups ) )
647                         $global_groups = $wp_object_cache->global_groups;
648                 else
649                         $global_groups = false;
650
651                 wp_cache_init();
652
653                 if ( function_exists( 'wp_cache_add_global_groups' ) ) {
654                         if ( is_array( $global_groups ) ) {
655                                 wp_cache_add_global_groups( $global_groups );
656                         } else {
657                                 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' ) );
658                         }
659                         wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) );
660                 }
661         }
662
663         if ( did_action( 'init' ) ) {
664                 wp_roles()->reinit();
665                 $current_user = wp_get_current_user();
666                 $current_user->for_blog( $new_blog );
667         }
668
669         /** This filter is documented in wp-includes/ms-blogs.php */
670         do_action( 'switch_blog', $new_blog, $prev_blog_id );
671         $GLOBALS['switched'] = true;
672
673         return true;
674 }
675
676 /**
677  * Restore the current blog, after calling switch_to_blog()
678  *
679  * @see switch_to_blog()
680  * @since MU
681  *
682  * @global wpdb            $wpdb
683  * @global array           $_wp_switched_stack
684  * @global int             $blog_id
685  * @global bool            $switched
686  * @global string          $table_prefix
687  * @global WP_Object_Cache $wp_object_cache
688  *
689  * @return bool True on success, false if we're already on the current blog
690  */
691 function restore_current_blog() {
692         global $wpdb;
693
694         if ( empty( $GLOBALS['_wp_switched_stack'] ) )
695                 return false;
696
697         $blog = array_pop( $GLOBALS['_wp_switched_stack'] );
698
699         if ( $GLOBALS['blog_id'] == $blog ) {
700                 /** This filter is documented in wp-includes/ms-blogs.php */
701                 do_action( 'switch_blog', $blog, $blog );
702                 // If we still have items in the switched stack, consider ourselves still 'switched'
703                 $GLOBALS['switched'] = ! empty( $GLOBALS['_wp_switched_stack'] );
704                 return true;
705         }
706
707         $wpdb->set_blog_id( $blog );
708         $prev_blog_id = $GLOBALS['blog_id'];
709         $GLOBALS['blog_id'] = $blog;
710         $GLOBALS['table_prefix'] = $wpdb->get_blog_prefix();
711
712         if ( function_exists( 'wp_cache_switch_to_blog' ) ) {
713                 wp_cache_switch_to_blog( $blog );
714         } else {
715                 global $wp_object_cache;
716
717                 if ( is_object( $wp_object_cache ) && isset( $wp_object_cache->global_groups ) )
718                         $global_groups = $wp_object_cache->global_groups;
719                 else
720                         $global_groups = false;
721
722                 wp_cache_init();
723
724                 if ( function_exists( 'wp_cache_add_global_groups' ) ) {
725                         if ( is_array( $global_groups ) ) {
726                                 wp_cache_add_global_groups( $global_groups );
727                         } else {
728                                 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' ) );
729                         }
730                         wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) );
731                 }
732         }
733
734         if ( did_action( 'init' ) ) {
735                 wp_roles()->reinit();
736                 $current_user = wp_get_current_user();
737                 $current_user->for_blog( $blog );
738         }
739
740         /** This filter is documented in wp-includes/ms-blogs.php */
741         do_action( 'switch_blog', $blog, $prev_blog_id );
742
743         // If we still have items in the switched stack, consider ourselves still 'switched'
744         $GLOBALS['switched'] = ! empty( $GLOBALS['_wp_switched_stack'] );
745
746         return true;
747 }
748
749 /**
750  * Determines if switch_to_blog() is in effect
751  *
752  * @since 3.5.0
753  *
754  * @global array $_wp_switched_stack
755  *
756  * @return bool True if switched, false otherwise.
757  */
758 function ms_is_switched() {
759         return ! empty( $GLOBALS['_wp_switched_stack'] );
760 }
761
762 /**
763  * Check if a particular blog is archived.
764  *
765  * @since MU
766  *
767  * @param int $id The blog id
768  * @return string Whether the blog is archived or not
769  */
770 function is_archived( $id ) {
771         return get_blog_status($id, 'archived');
772 }
773
774 /**
775  * Update the 'archived' status of a particular blog.
776  *
777  * @since MU
778  *
779  * @param int    $id       The blog id
780  * @param string $archived The new status
781  * @return string $archived
782  */
783 function update_archived( $id, $archived ) {
784         update_blog_status($id, 'archived', $archived);
785         return $archived;
786 }
787
788 /**
789  * Update a blog details field.
790  *
791  * @since MU
792  *
793  * @global wpdb $wpdb WordPress database abstraction object.
794  *
795  * @param int    $blog_id BLog ID
796  * @param string $pref    A field name
797  * @param string $value   Value for $pref
798  * @param null   $deprecated
799  * @return string|false $value
800  */
801 function update_blog_status( $blog_id, $pref, $value, $deprecated = null ) {
802         global $wpdb;
803
804         if ( null !== $deprecated  )
805                 _deprecated_argument( __FUNCTION__, '3.1' );
806
807         if ( ! in_array( $pref, array( 'site_id', 'domain', 'path', 'registered', 'last_updated', 'public', 'archived', 'mature', 'spam', 'deleted', 'lang_id') ) )
808                 return $value;
809
810         $result = $wpdb->update( $wpdb->blogs, array($pref => $value, 'last_updated' => current_time('mysql', true)), array('blog_id' => $blog_id) );
811
812         if ( false === $result )
813                 return false;
814
815         refresh_blog_details( $blog_id );
816
817         if ( 'spam' == $pref ) {
818                 if ( $value == 1 ) {
819                         /** This filter is documented in wp-includes/ms-blogs.php */
820                         do_action( 'make_spam_blog', $blog_id );
821                 } else {
822                         /** This filter is documented in wp-includes/ms-blogs.php */
823                         do_action( 'make_ham_blog', $blog_id );
824                 }
825         } elseif ( 'mature' == $pref ) {
826                 if ( $value == 1 ) {
827                         /** This filter is documented in wp-includes/ms-blogs.php */
828                         do_action( 'mature_blog', $blog_id );
829                 } else {
830                         /** This filter is documented in wp-includes/ms-blogs.php */
831                         do_action( 'unmature_blog', $blog_id );
832                 }
833         } elseif ( 'archived' == $pref ) {
834                 if ( $value == 1 ) {
835                         /** This filter is documented in wp-includes/ms-blogs.php */
836                         do_action( 'archive_blog', $blog_id );
837                 } else {
838                         /** This filter is documented in wp-includes/ms-blogs.php */
839                         do_action( 'unarchive_blog', $blog_id );
840                 }
841         } elseif ( 'deleted' == $pref ) {
842                 if ( $value == 1 ) {
843                         /** This filter is documented in wp-includes/ms-blogs.php */
844                         do_action( 'make_delete_blog', $blog_id );
845                 } else {
846                         /** This filter is documented in wp-includes/ms-blogs.php */
847                         do_action( 'make_undelete_blog', $blog_id );
848                 }
849         } elseif ( 'public' == $pref ) {
850                 /**
851                  * Fires after the current blog's 'public' setting is updated.
852                  *
853                  * @since MU
854                  *
855                  * @param int    $blog_id Blog ID.
856                  * @param string $value   The value of blog status.
857                  */
858                 do_action( 'update_blog_public', $blog_id, $value ); // Moved here from update_blog_public().
859         }
860
861         return $value;
862 }
863
864 /**
865  * Get a blog details field.
866  *
867  * @since MU
868  *
869  * @global wpdb $wpdb WordPress database abstraction object.
870  *
871  * @param int    $id   The blog id
872  * @param string $pref A field name
873  * @return bool|string|null $value
874  */
875 function get_blog_status( $id, $pref ) {
876         global $wpdb;
877
878         $details = get_blog_details( $id, false );
879         if ( $details )
880                 return $details->$pref;
881
882         return $wpdb->get_var( $wpdb->prepare("SELECT %s FROM {$wpdb->blogs} WHERE blog_id = %d", $pref, $id) );
883 }
884
885 /**
886  * Get a list of most recently updated blogs.
887  *
888  * @since MU
889  *
890  * @global wpdb $wpdb WordPress database abstraction object.
891  *
892  * @param mixed $deprecated Not used
893  * @param int   $start      The offset
894  * @param int   $quantity   The maximum number of blogs to retrieve. Default is 40.
895  * @return array The list of blogs
896  */
897 function get_last_updated( $deprecated = '', $start = 0, $quantity = 40 ) {
898         global $wpdb;
899
900         if ( ! empty( $deprecated ) )
901                 _deprecated_argument( __FUNCTION__, 'MU' ); // never used
902
903         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 );
904 }
905
906 /**
907  * Handler for updating the blog date when a post is published or an already published post is changed.
908  *
909  * @since 3.3.0
910  *
911  * @param string $new_status The new post status
912  * @param string $old_status The old post status
913  * @param object $post       Post object
914  */
915 function _update_blog_date_on_post_publish( $new_status, $old_status, $post ) {
916         $post_type_obj = get_post_type_object( $post->post_type );
917         if ( ! $post_type_obj || ! $post_type_obj->public ) {
918                 return;
919         }
920
921         if ( 'publish' != $new_status && 'publish' != $old_status ) {
922                 return;
923         }
924
925         // Post was freshly published, published post was saved, or published post was unpublished.
926
927         wpmu_update_blogs_date();
928 }
929
930 /**
931  * Handler for updating the blog date when a published post is deleted.
932  *
933  * @since 3.4.0
934  *
935  * @param int $post_id Post ID
936  */
937 function _update_blog_date_on_post_delete( $post_id ) {
938         $post = get_post( $post_id );
939
940         $post_type_obj = get_post_type_object( $post->post_type );
941         if ( ! $post_type_obj || ! $post_type_obj->public ) {
942                 return;
943         }
944
945         if ( 'publish' != $post->post_status ) {
946                 return;
947         }
948
949         wpmu_update_blogs_date();
950 }
951
952 /**
953  * Handler for updating the blog posts count date when a post is deleted.
954  *
955  * @since 4.0.0
956  *
957  * @param int $post_id Post ID.
958  */
959 function _update_posts_count_on_delete( $post_id ) {
960         $post = get_post( $post_id );
961
962         if ( ! $post || 'publish' !== $post->post_status ) {
963                 return;
964         }
965
966         update_posts_count();
967 }
968
969 /**
970  * Handler for updating the blog posts count date when a post status changes.
971  *
972  * @since 4.0.0
973  *
974  * @param string $new_status The status the post is changing to.
975  * @param string $old_status The status the post is changing from.
976  */
977 function _update_posts_count_on_transition_post_status( $new_status, $old_status ) {
978         if ( $new_status === $old_status ) {
979                 return;
980         }
981
982         if ( 'publish' !== $new_status && 'publish' !== $old_status ) {
983                 return;
984         }
985
986         update_posts_count();
987 }
988