angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

ms-blogs.php (25174B)


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