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