* Site/blog functions that work with the blogs table and related data.
require_once ABSPATH . WPINC . '/ms-site.php';
require_once ABSPATH . WPINC . '/ms-network.php';
* Update the last_updated field for the current site.
function wpmu_update_blogs_date() {
$site_id = get_current_blog_id();
update_blog_details( $site_id, array( 'last_updated' => current_time( 'mysql', true ) ) );
* Fires after the blog details are updated.
* @param int $blog_id Site ID.
do_action( 'wpmu_blog_updated', $site_id );
* Get a full blog URL, given a blog ID.
* @param int $blog_id Blog ID.
* @return string Full URL of the blog if found. Empty string if not.
function get_blogaddress_by_id( $blog_id ) {
$bloginfo = get_site( (int) $blog_id );
if ( empty( $bloginfo ) ) {
$scheme = parse_url( $bloginfo->home, PHP_URL_SCHEME );
$scheme = empty( $scheme ) ? 'http' : $scheme;
return esc_url( $scheme . '://' . $bloginfo->domain . $bloginfo->path );
* Get a full blog URL, given a blog name.
* @param string $blogname The (subdomain or directory) name
function get_blogaddress_by_name( $blogname ) {
if ( is_subdomain_install() ) {
if ( 'main' === $blogname ) {
$url = rtrim( network_home_url(), '/' );
if ( ! empty( $blogname ) ) {
$url = preg_replace( '|^([^\.]+://)|', '${1}' . $blogname . '.', $url );
$url = network_home_url( $blogname );
return esc_url( $url . '/' );
* Retrieves a sites ID given its (subdomain or directory) slug.
* @since 4.7.0 Converted to use `get_sites()`.
* @param string $slug A site's slug.
* @return int|null The site ID, or null if no site is found for the given slug.
function get_id_from_blogname( $slug ) {
$current_network = get_network();
$slug = trim( $slug, '/' );
if ( is_subdomain_install() ) {
$domain = $slug . '.' . preg_replace( '|^www\.|', '', $current_network->domain );
$path = $current_network->path;
$domain = $current_network->domain;
$path = $current_network->path . $slug . '/';
'update_site_meta_cache' => false,
if ( empty( $site_ids ) ) {
return array_shift( $site_ids );
* Retrieve the details for a blog from the blogs table and blog options.
* @global wpdb $wpdb WordPress database abstraction object.
* @param int|string|array $fields Optional. A blog ID, a blog slug, or an array of fields to query against.
* If not specified the current blog ID is used.
* @param bool $get_all Whether to retrieve all details or only the details in the blogs table.
* @return WP_Site|false Blog details on success. False on failure.
function get_blog_details( $fields = null, $get_all = true ) {
if ( is_array( $fields ) ) {
if ( isset( $fields['blog_id'] ) ) {
$blog_id = $fields['blog_id'];
} elseif ( isset( $fields['domain'] ) && isset( $fields['path'] ) ) {
$key = md5( $fields['domain'] . $fields['path'] );
$blog = wp_cache_get( $key, 'blog-lookup' );
if ( 'www.' === substr( $fields['domain'], 0, 4 ) ) {
$nowww = substr( $fields['domain'], 4 );
$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'] ) );
$blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE domain = %s AND path = %s", $fields['domain'], $fields['path'] ) );
wp_cache_set( $blog->blog_id . 'short', $blog, 'blog-details' );
$blog_id = $blog->blog_id;
} elseif ( isset( $fields['domain'] ) && is_subdomain_install() ) {
$key = md5( $fields['domain'] );
$blog = wp_cache_get( $key, 'blog-lookup' );
if ( 'www.' === substr( $fields['domain'], 0, 4 ) ) {
$nowww = substr( $fields['domain'], 4 );
$blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE domain IN (%s,%s) ORDER BY CHAR_LENGTH(domain) DESC", $nowww, $fields['domain'] ) );
$blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE domain = %s", $fields['domain'] ) );
wp_cache_set( $blog->blog_id . 'short', $blog, 'blog-details' );
$blog_id = $blog->blog_id;
$blog_id = get_current_blog_id();
} elseif ( ! is_numeric( $fields ) ) {
$blog_id = get_id_from_blogname( $fields );
$blog_id = (int) $blog_id;
$all = $get_all ? '' : 'short';
$details = wp_cache_get( $blog_id . $all, 'blog-details' );
if ( ! is_object( $details ) ) {
// Clear old pre-serialized objects. Cache clients do better with that.
wp_cache_delete( $blog_id . $all, 'blog-details' );
$details = wp_cache_get( $blog_id . 'short', 'blog-details' );
$details = wp_cache_get( $blog_id, 'blog-details' );
// If short was requested and full cache is set, we can return.
if ( ! is_object( $details ) ) {
// Clear old pre-serialized objects. Cache clients do better with that.
wp_cache_delete( $blog_id, 'blog-details' );
if ( empty( $details ) ) {
$details = WP_Site::get_instance( $blog_id );
wp_cache_set( $blog_id, -1, 'blog-details' );
if ( ! $details instanceof WP_Site ) {
$details = new WP_Site( $details );
wp_cache_set( $blog_id . $all, $details, 'blog-details' );
if ( get_current_blog_id() !== $blog_id ) {
switch_to_blog( $blog_id );
$details->blogname = get_option( 'blogname' );
$details->siteurl = get_option( 'siteurl' );
$details->post_count = get_option( 'post_count' );
$details->home = get_option( 'home' );
* Filters a blog's details.
* @deprecated 4.7.0 Use {@see 'site_details'} instead.
* @param WP_Site $details The blog details.
$details = apply_filters_deprecated( 'blog_details', array( $details ), '4.7.0', 'site_details' );
wp_cache_set( $blog_id . $all, $details, 'blog-details' );
$key = md5( $details->domain . $details->path );
wp_cache_set( $key, $details, 'blog-lookup' );
* Clear the blog details cache.
* @param int $blog_id Optional. Blog ID. Defaults to current blog.
function refresh_blog_details( $blog_id = 0 ) {
$blog_id = (int) $blog_id;
$blog_id = get_current_blog_id();
clean_blog_cache( $blog_id );
* Update the details for a blog. Updates the blogs table for a given blog ID.
* @global wpdb $wpdb WordPress database abstraction object.
* @param int $blog_id Blog ID.
* @param array $details Array of details keyed by blogs table field names.
* @return bool True if update succeeds, false otherwise.
function update_blog_details( $blog_id, $details = array() ) {
if ( empty( $details ) ) {
if ( is_object( $details ) ) {
$details = get_object_vars( $details );
$site = wp_update_site( $blog_id, $details );
if ( is_wp_error( $site ) ) {
* Cleans the site details cache for a site.
* @param int $site_id Optional. Site ID. Default is the current site ID.
function clean_site_details_cache( $site_id = 0 ) {
$site_id = (int) $site_id;
$site_id = get_current_blog_id();
wp_cache_delete( $site_id, 'site-details' );
wp_cache_delete( $site_id, 'blog-details' );
* Retrieve option value for a given blog id based on name of option.
* If the option does not exist or does not have a value, then the return value
* will be false. This is useful to check whether you need to install an option
* and is commonly used during installation of plugin options and to test
* whether upgrading is required.
* If the option was serialized then it will be unserialized when it is returned.
* @param int $id A blog ID. Can be null to refer to the current blog.
* @param string $option Name of option to retrieve. Expected to not be SQL-escaped.
* @param mixed $default Optional. Default value to return if the option does not exist.
* @return mixed Value set for the option.
function get_blog_option( $id, $option, $default = false ) {
$id = get_current_blog_id();
if ( get_current_blog_id() == $id ) {
return get_option( $option, $default );
$value = get_option( $option, $default );
* Filters a blog option value.
* The dynamic portion of the hook name, `$option`, refers to the blog option name.
* @param string $value The option value.
* @param int $id Blog ID.
return apply_filters( "blog_option_{$option}", $value, $id );
* Add a new option for a given blog ID.
* You do not need to serialize values. If the value needs to be serialized, then
* it will be serialized before it is inserted into the database. Remember,
* resources can not be serialized or added as an option.
* You can create options without values and then update the values later.
* Existing options will not be updated and checks are performed to ensure that you
* aren't adding a protected WordPress option. Care should be taken to not name
* options the same as the ones which are protected.
* @param int $id A blog ID. Can be null to refer to the current blog.
* @param string $option Name of option to add. Expected to not be SQL-escaped.
* @param mixed $value Optional. Option value, can be anything. Expected to not be SQL-escaped.
* @return bool True if the option was added, false otherwise.
function add_blog_option( $id, $option, $value ) {
$id = get_current_blog_id();
if ( get_current_blog_id() == $id ) {
return add_option( $option, $value );
$return = add_option( $option, $value );
* Removes option by name for a given blog ID. Prevents removal of protected WordPress options.
* @param int $id A blog ID. Can be null to refer to the current blog.
* @param string $option Name of option to remove. Expected to not be SQL-escaped.
* @return bool True if the option was deleted, false otherwise.
function delete_blog_option( $id, $option ) {
$id = get_current_blog_id();
if ( get_current_blog_id() == $id ) {
return delete_option( $option );
$return = delete_option( $option );
* Update an option for a particular blog.
* @param int $id The blog ID.
* @param string $option The option key.
* @param mixed $value The option value.
* @param mixed $deprecated Not used.
* @return bool True if the value was updated, false otherwise.
function update_blog_option( $id, $option, $value, $deprecated = null ) {
if ( null !== $deprecated ) {
_deprecated_argument( __FUNCTION__, '3.1.0' );
if ( get_current_blog_id() == $id ) {
return update_option( $option, $value );
$return = update_option( $option, $value );
* Switch the current blog.
* This function is useful if you need to pull posts, or other information,
* from other blogs. You can switch back afterwards using restore_current_blog().
* Things that aren't switched:
* @see restore_current_blog()
* @global wpdb $wpdb WordPress database abstraction object.
* @global array $_wp_switched_stack
* @global string $table_prefix
* @global WP_Object_Cache $wp_object_cache
* @param int $new_blog_id The ID of the blog to switch to. Default: current blog.
* @param bool $deprecated Not used.
* @return true Always returns true.
function switch_to_blog( $new_blog_id, $deprecated = null ) {