* Multisite administration functions.
* Determine if uploaded file exceeds space quota.
* @param array $file $_FILES array for a given file.
* @return array $_FILES array with 'error' key set if file exceeds quota. 'error' is empty otherwise.
function check_upload_size( $file ) {
if ( get_site_option( 'upload_space_check_disabled' ) ) {
if ( '0' != $file['error'] ) { // There's already an error.
if ( defined( 'WP_IMPORTING' ) ) {
$space_left = get_upload_space_available();
$file_size = filesize( $file['tmp_name'] );
if ( $space_left < $file_size ) {
/* translators: %s: Required disk space in kilobytes. */
$file['error'] = sprintf( __( 'Not enough space to upload. %s KB needed.' ), number_format( ( $file_size - $space_left ) / KB_IN_BYTES ) );
if ( $file_size > ( KB_IN_BYTES * get_site_option( 'fileupload_maxk', 1500 ) ) ) {
/* translators: %s: Maximum allowed file size in kilobytes. */
$file['error'] = sprintf( __( 'This file is too big. Files must be less than %s KB in size.' ), get_site_option( 'fileupload_maxk', 1500 ) );
if ( upload_is_user_over_quota( false ) ) {
$file['error'] = __( 'You have used your space quota. Please delete files before uploading.' );
if ( '0' != $file['error'] && ! isset( $_POST['html-upload'] ) && ! wp_doing_ajax() ) {
wp_die( $file['error'] . ' <a href="javascript:history.go(-1)">' . __( 'Back' ) . '</a>' );
* @since 5.1.0 Use wp_delete_site() internally to delete the site row from the database.
* @global wpdb $wpdb WordPress database abstraction object.
* @param int $blog_id Site ID.
* @param bool $drop True if site's database tables should be dropped. Default false.
function wpmu_delete_blog( $blog_id, $drop = false ) {
if ( get_current_blog_id() != $blog_id ) {
switch_to_blog( $blog_id );
$blog = get_site( $blog_id );
$current_network = get_network();
// If a full blog object is not available, do not destroy anything.
if ( $drop && ! $blog ) {
// Don't destroy the initial, main, or root blog.
if ( $drop && ( 1 == $blog_id || is_main_site( $blog_id ) || ( $blog->path == $current_network->path && $blog->domain == $current_network->domain ) ) ) {
$upload_path = trim( get_option( 'upload_path' ) );
// If ms_files_rewriting is enabled and upload_path is empty, wp_upload_dir is not reliable.
if ( $drop && get_site_option( 'ms_files_rewriting' ) && empty( $upload_path ) ) {
wp_delete_site( $blog_id );
/** This action is documented in wp-includes/ms-blogs.php */
do_action_deprecated( 'delete_blog', array( $blog_id, false ), '5.1.0' );
// Remove users from this blog.
if ( ! empty( $users ) ) {
foreach ( $users as $user_id ) {
remove_user_from_blog( $user_id, $blog_id );
update_blog_status( $blog_id, 'deleted', 1 );
/** This action is documented in wp-includes/ms-blogs.php */
do_action_deprecated( 'deleted_blog', array( $blog_id, false ), '5.1.0' );
* Delete a user from the network and remove from all sites.
* @todo Merge with wp_delete_user()?
* @global wpdb $wpdb WordPress database abstraction object.
* @param int $id The user ID.
* @return bool True if the user was deleted, otherwise false.
function wpmu_delete_user( $id ) {
if ( ! is_numeric( $id ) ) {
$user = new WP_User( $id );
if ( ! $user->exists() ) {
// Global super-administrators are protected, and cannot be deleted.
$_super_admins = get_super_admins();
if ( in_array( $user->user_login, $_super_admins, true ) ) {
* Fires before a user is deleted from the network.
* @since 5.5.0 Added the `$user` parameter.
* @param int $id ID of the user about to be deleted from the network.
* @param WP_User $user WP_User object of the user about to be deleted from the network.
do_action( 'wpmu_delete_user', $id, $user );
$blogs = get_blogs_of_user( $id );
if ( ! empty( $blogs ) ) {
foreach ( $blogs as $blog ) {
switch_to_blog( $blog->userblog_id );
remove_user_from_blog( $id, $blog->userblog_id );
$post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $id ) );
foreach ( (array) $post_ids as $post_id ) {
wp_delete_post( $post_id );
$link_ids = $wpdb->get_col( $wpdb->prepare( "SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $id ) );
foreach ( $link_ids as $link_id ) {
wp_delete_link( $link_id );
$meta = $wpdb->get_col( $wpdb->prepare( "SELECT umeta_id FROM $wpdb->usermeta WHERE user_id = %d", $id ) );
foreach ( $meta as $mid ) {
delete_metadata_by_mid( 'user', $mid );
$wpdb->delete( $wpdb->users, array( 'ID' => $id ) );
clean_user_cache( $user );
/** This action is documented in wp-admin/includes/user.php */
do_action( 'deleted_user', $id, null, $user );
* Check whether a site has used its allotted upload space.
* @param bool $echo Optional. If $echo is set and the quota is exceeded, a warning message is echoed. Default is true.
* @return bool True if user is over upload space quota, otherwise false.
function upload_is_user_over_quota( $echo = true ) {
if ( get_site_option( 'upload_space_check_disabled' ) ) {
$space_allowed = get_space_allowed();
if ( ! is_numeric( $space_allowed ) ) {
$space_allowed = 10; // Default space allowed is 10 MB.
$space_used = get_space_used();
if ( ( $space_allowed - $space_used ) < 0 ) {
/* translators: %s: Allowed space allocation. */
__( 'Sorry, you have used your space allocation of %s. Please delete some files to upload more files.' ),
size_format( $space_allowed * MB_IN_BYTES )
* Displays the amount of disk space used by the current site. Not used in core.
function display_space_usage() {
$space_allowed = get_space_allowed();
$space_used = get_space_used();
$percent_used = ( $space_used / $space_allowed ) * 100;
$space = size_format( $space_allowed * MB_IN_BYTES );
/* translators: Storage space that's been used. 1: Percentage of used space, 2: Total space allowed in megabytes or gigabytes. */
printf( __( 'Used: %1$s%% of %2$s' ), number_format( $percent_used ), $space );
* Get the remaining upload space for this site.
* @param int $size Current max size in bytes
* @return int Max size in bytes
function fix_import_form_size( $size ) {
if ( upload_is_user_over_quota( false ) ) {
$available = get_upload_space_available();
return min( $size, $available );
* Displays the site upload space quota setting form on the Edit Site Settings screen.
* @param int $id The ID of the site to display the setting for.
function upload_space_setting( $id ) {
$quota = get_option( 'blog_upload_space' );
<th><label for="blog-upload-space-number"><?php _e( 'Site Upload Space Quota' ); ?></label></th>
<input type="number" step="1" min="0" style="width: 100px" name="option[blog_upload_space]" id="blog-upload-space-number" aria-describedby="blog-upload-space-desc" value="<?php echo $quota; ?>" />
<span id="blog-upload-space-desc"><span class="screen-reader-text"><?php _e( 'Size in megabytes' ); ?></span> <?php _e( 'MB (Leave blank for network default)' ); ?></span>
* Cleans the user cache for a specific user.
* @param int $id The user ID.
* @return int|false The ID of the refreshed user or false if the user does not exist.
function refresh_user_details( $id ) {
$user = get_userdata( $id );
clean_user_cache( $user );
* Returns the language for a language code.
* @param string $code Optional. The two-letter language code. Default empty.
* @return string The language corresponding to $code if it exists. If it does not exist,
* then the first two letters of $code is returned.
function format_code_lang( $code = '' ) {
$code = strtolower( substr( $code, 0, 2 ) );
'ca' => 'Catalan; Valencian',
'cu' => 'Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic',
'dv' => 'Divehi; Dhivehi; Maldivian',
'nl' => 'Dutch; Flemish',
'fy' => 'Western Frisian',
'gd' => 'Gaelic; Scottish Gaelic',
'ht' => 'Haitian; Haitian Creole',
'ia' => 'Interlingua (International Auxiliary Language Association)',
'kl' => 'Kalaallisut; Greenlandic',
'ki' => 'Kikuyu; Gikuyu',
'ky' => 'Kirghiz; Kyrgyz',
'kj' => 'Kuanyama; Kwanyama',
'li' => 'Limburgan; Limburger; Limburgish',
'lb' => 'Luxembourgish; Letzeburgesch',
'nv' => 'Navajo; Navaho',
'nr' => 'Ndebele, South; South Ndebele',
'nd' => 'Ndebele, North; North Ndebele',
'nn' => 'Norwegian Nynorsk; Nynorsk, Norwegian',
'nb' => 'Bokmål, Norwegian, Norwegian Bokmål',
'ny' => 'Chichewa; Chewa; Nyanja',
'oc' => 'Occitan, Provençal',
'os' => 'Ossetian; Ossetic',
'pa' => 'Panjabi; Punjabi',
'si' => 'Sinhala; Sinhalese',
'st' => 'Sotho, Southern',
'es' => 'Spanish; Castilian',