wp/wp-admin/includes/ms.php
changeset 0 d970ebf37754
child 5 5e2f62d02dcd
equal deleted inserted replaced
-1:000000000000 0:d970ebf37754
       
     1 <?php
       
     2 /**
       
     3  * Multisite administration functions.
       
     4  *
       
     5  * @package WordPress
       
     6  * @subpackage Multisite
       
     7  * @since 3.0.0
       
     8  */
       
     9 
       
    10 /**
       
    11  * Determine if uploaded file exceeds space quota.
       
    12  *
       
    13  * @since 3.0.0
       
    14  *
       
    15  * @param array $file $_FILES array for a given file.
       
    16  * @return array $_FILES array with 'error' key set if file exceeds quota. 'error' is empty otherwise.
       
    17  */
       
    18 function check_upload_size( $file ) {
       
    19 	if ( get_site_option( 'upload_space_check_disabled' ) )
       
    20 		return $file;
       
    21 
       
    22 	if ( $file['error'] != '0' ) // there's already an error
       
    23 		return $file;
       
    24 
       
    25 	if ( defined( 'WP_IMPORTING' ) )
       
    26 		return $file;
       
    27 
       
    28 	$space_left = get_upload_space_available();
       
    29 
       
    30 	$file_size = filesize( $file['tmp_name'] );
       
    31 	if ( $space_left < $file_size )
       
    32 		$file['error'] = sprintf( __( 'Not enough space to upload. %1$s KB needed.' ), number_format( ($file_size - $space_left) /1024 ) );
       
    33 	if ( $file_size > ( 1024 * get_site_option( 'fileupload_maxk', 1500 ) ) )
       
    34 		$file['error'] = sprintf(__('This file is too big. Files must be less than %1$s KB in size.'), get_site_option( 'fileupload_maxk', 1500 ) );
       
    35 	if ( upload_is_user_over_quota( false ) ) {
       
    36 		$file['error'] = __( 'You have used your space quota. Please delete files before uploading.' );
       
    37 	}
       
    38 	if ( $file['error'] != '0' && !isset($_POST['html-upload']) )
       
    39 		wp_die( $file['error'] . ' <a href="javascript:history.go(-1)">' . __( 'Back' ) . '</a>' );
       
    40 
       
    41 	return $file;
       
    42 }
       
    43 add_filter( 'wp_handle_upload_prefilter', 'check_upload_size' );
       
    44 
       
    45 /**
       
    46  * Delete a blog
       
    47  *
       
    48  * @since 3.0.0
       
    49  *
       
    50  * @param int $blog_id Blog ID
       
    51  * @param bool $drop True if blog's table should be dropped. Default is false.
       
    52  * @return void
       
    53  */
       
    54 function wpmu_delete_blog( $blog_id, $drop = false ) {
       
    55 	global $wpdb, $current_site;
       
    56 
       
    57 	$switch = false;
       
    58 	if ( get_current_blog_id() != $blog_id ) {
       
    59 		$switch = true;
       
    60 		switch_to_blog( $blog_id );
       
    61 	}
       
    62 
       
    63 	$blog = get_blog_details( $blog_id );
       
    64 	/**
       
    65 	 * Fires before a blog is deleted.
       
    66 	 *
       
    67 	 * @since MU
       
    68 	 *
       
    69 	 * @param int  $blog_id The blog ID.
       
    70 	 * @param bool $drop    True if blog's table should be dropped. Default is false.
       
    71 	 */
       
    72 	do_action( 'delete_blog', $blog_id, $drop );
       
    73 
       
    74 	$users = get_users( array( 'blog_id' => $blog_id, 'fields' => 'ids' ) );
       
    75 
       
    76 	// Remove users from this blog.
       
    77 	if ( ! empty( $users ) ) {
       
    78 		foreach ( $users as $user_id ) {
       
    79 			remove_user_from_blog( $user_id, $blog_id );
       
    80 		}
       
    81 	}
       
    82 
       
    83 	update_blog_status( $blog_id, 'deleted', 1 );
       
    84 
       
    85 	// Don't destroy the initial, main, or root blog.
       
    86 	if ( $drop && ( 1 == $blog_id || is_main_site( $blog_id ) || ( $blog->path == $current_site->path && $blog->domain == $current_site->domain ) ) )
       
    87 		$drop = false;
       
    88 
       
    89 	if ( $drop ) {
       
    90 		$tables = $wpdb->tables( 'blog' );
       
    91 		/**
       
    92 		 * Filter the tables to drop when the blog is deleted.
       
    93 		 *
       
    94 		 * @since MU
       
    95 		 *
       
    96 		 * @param array $tables  The blog tables to be dropped.
       
    97 		 * @param int   $blog_id The ID of the blog to drop tables for.
       
    98 		 */
       
    99 		$drop_tables = apply_filters( 'wpmu_drop_tables', $tables, $blog_id );
       
   100 
       
   101 		foreach ( (array) $drop_tables as $table ) {
       
   102 			$wpdb->query( "DROP TABLE IF EXISTS `$table`" );
       
   103 		}
       
   104 
       
   105 		$wpdb->delete( $wpdb->blogs, array( 'blog_id' => $blog_id ) );
       
   106 
       
   107 		$uploads = wp_upload_dir();
       
   108 		/**
       
   109 		 * Filter the upload base directory to delete when the blog is deleted.
       
   110 		 *
       
   111 		 * @since MU
       
   112 		 *
       
   113 		 * @param string $uploads['basedir'] Uploads path without subdirectory. @see wp_upload_dir()
       
   114 		 * @param int    $blog_id            The blog ID.
       
   115 		 */
       
   116 		$dir = apply_filters( 'wpmu_delete_blog_upload_dir', $uploads['basedir'], $blog_id );
       
   117 		$dir = rtrim( $dir, DIRECTORY_SEPARATOR );
       
   118 		$top_dir = $dir;
       
   119 		$stack = array($dir);
       
   120 		$index = 0;
       
   121 
       
   122 		while ( $index < count( $stack ) ) {
       
   123 			# Get indexed directory from stack
       
   124 			$dir = $stack[$index];
       
   125 
       
   126 			$dh = @opendir( $dir );
       
   127 			if ( $dh ) {
       
   128 				while ( ( $file = @readdir( $dh ) ) !== false ) {
       
   129 					if ( $file == '.' || $file == '..' )
       
   130 						continue;
       
   131 
       
   132 					if ( @is_dir( $dir . DIRECTORY_SEPARATOR . $file ) )
       
   133 						$stack[] = $dir . DIRECTORY_SEPARATOR . $file;
       
   134 					else if ( @is_file( $dir . DIRECTORY_SEPARATOR . $file ) )
       
   135 						@unlink( $dir . DIRECTORY_SEPARATOR . $file );
       
   136 				}
       
   137 				@closedir( $dh );
       
   138 			}
       
   139 			$index++;
       
   140 		}
       
   141 
       
   142 		$stack = array_reverse( $stack ); // Last added dirs are deepest
       
   143 		foreach( (array) $stack as $dir ) {
       
   144 			if ( $dir != $top_dir)
       
   145 			@rmdir( $dir );
       
   146 		}
       
   147 
       
   148 		clean_blog_cache( $blog );
       
   149 	}
       
   150 
       
   151 	if ( $switch )
       
   152 		restore_current_blog();
       
   153 }
       
   154 
       
   155 // @todo Merge with wp_delete_user() ?
       
   156 function wpmu_delete_user( $id ) {
       
   157 	global $wpdb;
       
   158 
       
   159 	$id = (int) $id;
       
   160 	$user = new WP_User( $id );
       
   161 
       
   162 	if ( !$user->exists() )
       
   163 		return false;
       
   164 	/**
       
   165 	 * Fires before a user is deleted from the network.
       
   166 	 *
       
   167 	 * @since MU
       
   168 	 *
       
   169 	 * @param int $id ID of the user about to be deleted from the network.
       
   170 	 */
       
   171 	do_action( 'wpmu_delete_user', $id );
       
   172 
       
   173 	$blogs = get_blogs_of_user( $id );
       
   174 
       
   175 	if ( ! empty( $blogs ) ) {
       
   176 		foreach ( $blogs as $blog ) {
       
   177 			switch_to_blog( $blog->userblog_id );
       
   178 			remove_user_from_blog( $id, $blog->userblog_id );
       
   179 
       
   180 			$post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $id ) );
       
   181 			foreach ( (array) $post_ids as $post_id ) {
       
   182 				wp_delete_post( $post_id );
       
   183 			}
       
   184 
       
   185 			// Clean links
       
   186 			$link_ids = $wpdb->get_col( $wpdb->prepare( "SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $id ) );
       
   187 
       
   188 			if ( $link_ids ) {
       
   189 				foreach ( $link_ids as $link_id )
       
   190 					wp_delete_link( $link_id );
       
   191 			}
       
   192 
       
   193 			restore_current_blog();
       
   194 		}
       
   195 	}
       
   196 
       
   197 	$meta = $wpdb->get_col( $wpdb->prepare( "SELECT umeta_id FROM $wpdb->usermeta WHERE user_id = %d", $id ) );
       
   198 	foreach ( $meta as $mid )
       
   199 		delete_metadata_by_mid( 'user', $mid );
       
   200 
       
   201 	$wpdb->delete( $wpdb->users, array( 'ID' => $id ) );
       
   202 
       
   203 	clean_user_cache( $user );
       
   204 
       
   205 	/**
       
   206 	 * Fires after the user is deleted from the network.
       
   207 	 *
       
   208 	 * @since 2.8.0
       
   209 	 *
       
   210 	 * @param int $id ID of the user that was deleted from the network.
       
   211 	 */
       
   212 	do_action( 'deleted_user', $id );
       
   213 
       
   214 	return true;
       
   215 }
       
   216 
       
   217 function update_option_new_admin_email( $old_value, $value ) {
       
   218 	$email = get_option( 'admin_email' );
       
   219 	if ( $value == get_option( 'admin_email' ) || !is_email( $value ) )
       
   220 		return;
       
   221 
       
   222 	$hash = md5( $value. time() .mt_rand() );
       
   223 	$new_admin_email = array(
       
   224 		'hash' => $hash,
       
   225 		'newemail' => $value
       
   226 	);
       
   227 	update_option( 'adminhash', $new_admin_email );
       
   228 
       
   229 	$email_text = __( 'Dear user,
       
   230 
       
   231 You recently requested to have the administration email address on
       
   232 your site changed.
       
   233 If this is correct, please click on the following link to change it:
       
   234 ###ADMIN_URL###
       
   235 
       
   236 You can safely ignore and delete this email if you do not want to
       
   237 take this action.
       
   238 
       
   239 This email has been sent to ###EMAIL###
       
   240 
       
   241 Regards,
       
   242 All at ###SITENAME###
       
   243 ###SITEURL###' );
       
   244 
       
   245 	/**
       
   246 	 * Filter the email text sent when the site admin email is changed.
       
   247 	 *
       
   248 	 * The following strings have a special meaning and will get replaced dynamically:
       
   249 	 * ###ADMIN_URL### The link to click on to confirm the email change. Required otherwise this functunalty is will break.
       
   250 	 * ###EMAIL###     The new email.
       
   251 	 * ###SITENAME###  The name of the site.
       
   252 	 * ###SITEURL###   The URL to the site.
       
   253 	 *
       
   254 	 * @since MU
       
   255 	 *
       
   256 	 * @param string $email_text      Text in the email.
       
   257 	 * @param string $new_admin_email New admin email that the current administration email was changed to.
       
   258 	 */
       
   259 	$content = apply_filters( 'new_admin_email_content', $email_text, $new_admin_email );
       
   260 
       
   261 	$content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'options.php?adminhash='.$hash ) ), $content );
       
   262 	$content = str_replace( '###EMAIL###', $value, $content );
       
   263 	$content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content );
       
   264 	$content = str_replace( '###SITEURL###', network_home_url(), $content );
       
   265 
       
   266 	wp_mail( $value, sprintf( __( '[%s] New Admin Email Address' ), get_option( 'blogname' ) ), $content );
       
   267 }
       
   268 add_action( 'update_option_new_admin_email', 'update_option_new_admin_email', 10, 2 );
       
   269 add_action( 'add_option_new_admin_email', 'update_option_new_admin_email', 10, 2 );
       
   270 
       
   271 function send_confirmation_on_profile_email() {
       
   272 	global $errors, $wpdb;
       
   273 	$current_user = wp_get_current_user();
       
   274 	if ( ! is_object($errors) )
       
   275 		$errors = new WP_Error();
       
   276 
       
   277 	if ( $current_user->ID != $_POST['user_id'] )
       
   278 		return false;
       
   279 
       
   280 	if ( $current_user->user_email != $_POST['email'] ) {
       
   281 		if ( !is_email( $_POST['email'] ) ) {
       
   282 			$errors->add( 'user_email', __( "<strong>ERROR</strong>: The email address isn&#8217;t correct." ), array( 'form-field' => 'email' ) );
       
   283 			return;
       
   284 		}
       
   285 
       
   286 		if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_email FROM {$wpdb->users} WHERE user_email=%s", $_POST['email'] ) ) ) {
       
   287 			$errors->add( 'user_email', __( "<strong>ERROR</strong>: The email address is already used." ), array( 'form-field' => 'email' ) );
       
   288 			delete_option( $current_user->ID . '_new_email' );
       
   289 			return;
       
   290 		}
       
   291 
       
   292 		$hash = md5( $_POST['email'] . time() . mt_rand() );
       
   293 		$new_user_email = array(
       
   294 				'hash' => $hash,
       
   295 				'newemail' => $_POST['email']
       
   296 				);
       
   297 		update_option( $current_user->ID . '_new_email', $new_user_email );
       
   298 
       
   299 		$email_text = __( 'Dear user,
       
   300 
       
   301 You recently requested to have the email address on your account changed.
       
   302 If this is correct, please click on the following link to change it:
       
   303 ###ADMIN_URL###
       
   304 
       
   305 You can safely ignore and delete this email if you do not want to
       
   306 take this action.
       
   307 
       
   308 This email has been sent to ###EMAIL###
       
   309 
       
   310 Regards,
       
   311 All at ###SITENAME###
       
   312 ###SITEURL###' );
       
   313 
       
   314 		/**
       
   315 		 * Filter the email text sent when a user changes emails.
       
   316 		 *
       
   317 		 * The following strings have a special meaning and will get replaced dynamically:
       
   318 		 * ###ADMIN_URL### The link to click on to confirm the email change. Required otherwise this functunalty is will break.
       
   319 		 * ###EMAIL### The new email.
       
   320 		 * ###SITENAME### The name of the site.
       
   321 		 * ###SITEURL### The URL to the site.
       
   322 		 *
       
   323 		 * @since MU
       
   324 		 *
       
   325 		 * @param string $email_text     Text in the email.
       
   326 		 * @param string $new_user_email New user email that the current user has changed to.
       
   327 		 */
       
   328 		$content = apply_filters( 'new_user_email_content', $email_text, $new_user_email );
       
   329 
       
   330 		$content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'profile.php?newuseremail='.$hash ) ), $content );
       
   331 		$content = str_replace( '###EMAIL###', $_POST['email'], $content);
       
   332 		$content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content );
       
   333 		$content = str_replace( '###SITEURL###', network_home_url(), $content );
       
   334 
       
   335 		wp_mail( $_POST['email'], sprintf( __( '[%s] New Email Address' ), get_option( 'blogname' ) ), $content );
       
   336 		$_POST['email'] = $current_user->user_email;
       
   337 	}
       
   338 }
       
   339 add_action( 'personal_options_update', 'send_confirmation_on_profile_email' );
       
   340 
       
   341 function new_user_email_admin_notice() {
       
   342 	if ( strpos( $_SERVER['PHP_SELF'], 'profile.php' ) && isset( $_GET['updated'] ) && $email = get_option( get_current_user_id() . '_new_email' ) )
       
   343 		echo "<div class='update-nag'>" . sprintf( __( "Your email address has not been updated yet. Please check your inbox at %s for a confirmation email." ), $email['newemail'] ) . "</div>";
       
   344 }
       
   345 add_action( 'admin_notices', 'new_user_email_admin_notice' );
       
   346 
       
   347 /**
       
   348  * Check whether a blog has used its allotted upload space.
       
   349  *
       
   350  * @since MU
       
   351  *
       
   352  * @param bool $echo Optional. If $echo is set and the quota is exceeded, a warning message is echoed. Default is true.
       
   353  * @return int
       
   354  */
       
   355 function upload_is_user_over_quota( $echo = true ) {
       
   356 	if ( get_site_option( 'upload_space_check_disabled' ) )
       
   357 		return false;
       
   358 
       
   359 	$space_allowed = get_space_allowed();
       
   360 	if ( empty( $space_allowed ) || !is_numeric( $space_allowed ) )
       
   361 		$space_allowed = 10; // Default space allowed is 10 MB
       
   362 
       
   363 	$space_used = get_space_used();
       
   364 
       
   365 	if ( ( $space_allowed - $space_used ) < 0 ) {
       
   366 		if ( $echo )
       
   367 			_e( 'Sorry, you have used your space allocation. Please delete some files to upload more files.' );
       
   368 		return true;
       
   369 	} else {
       
   370 		return false;
       
   371 	}
       
   372 }
       
   373 
       
   374 /**
       
   375  * Displays the amount of disk space used by the current blog. Not used in core.
       
   376  *
       
   377  * @since MU
       
   378  */
       
   379 function display_space_usage() {
       
   380 	$space_allowed = get_space_allowed();
       
   381 	$space_used = get_space_used();
       
   382 
       
   383 	$percent_used = ( $space_used / $space_allowed ) * 100;
       
   384 
       
   385 	if ( $space_allowed > 1000 ) {
       
   386 		$space = number_format( $space_allowed / 1024 );
       
   387 		/* translators: Gigabytes */
       
   388 		$space .= __( 'GB' );
       
   389 	} else {
       
   390 		$space = number_format( $space_allowed );
       
   391 		/* translators: Megabytes */
       
   392 		$space .= __( 'MB' );
       
   393 	}
       
   394 	?>
       
   395 	<strong><?php printf( __( 'Used: %1$s%% of %2$s' ), number_format( $percent_used ), $space ); ?></strong>
       
   396 	<?php
       
   397 }
       
   398 
       
   399 /**
       
   400  * Get the remaining upload space for this blog.
       
   401  *
       
   402  * @since MU
       
   403  * @uses upload_is_user_over_quota()
       
   404  * @uses get_space_allowed()
       
   405  * @uses get_upload_space_available()
       
   406  *
       
   407  * @param int $size Current max size in bytes
       
   408  * @return int Max size in bytes
       
   409  */
       
   410 function fix_import_form_size( $size ) {
       
   411 	if ( upload_is_user_over_quota( false ) == true )
       
   412 		return 0;
       
   413 
       
   414 	$available = get_upload_space_available();
       
   415 	return min( $size, $available );
       
   416 }
       
   417 
       
   418 // Edit blog upload space setting on Edit Blog page
       
   419 function upload_space_setting( $id ) {
       
   420 	switch_to_blog( $id );
       
   421 	$quota = get_option( 'blog_upload_space' );
       
   422 	restore_current_blog();
       
   423 
       
   424 	if ( !$quota )
       
   425 		$quota = '';
       
   426 
       
   427 	?>
       
   428 	<tr>
       
   429 		<th><?php _e( 'Site Upload Space Quota '); ?></th>
       
   430 		<td><input type="number" step="1" min="0" style="width: 100px" name="option[blog_upload_space]" value="<?php echo $quota; ?>" /> <?php _e( 'MB (Leave blank for network default)' ); ?></td>
       
   431 	</tr>
       
   432 	<?php
       
   433 }
       
   434 add_action( 'wpmueditblogaction', 'upload_space_setting' );
       
   435 
       
   436 function update_user_status( $id, $pref, $value, $deprecated = null ) {
       
   437 	global $wpdb;
       
   438 
       
   439 	if ( null !== $deprecated )
       
   440 		_deprecated_argument( __FUNCTION__, '3.1' );
       
   441 
       
   442 	$wpdb->update( $wpdb->users, array( sanitize_key( $pref ) => $value ), array( 'ID' => $id ) );
       
   443 
       
   444 	$user = new WP_User( $id );
       
   445 	clean_user_cache( $user );
       
   446 
       
   447 	if ( $pref == 'spam' ) {
       
   448 		if ( $value == 1 ) {
       
   449 			/**
       
   450 			 * Fires after the user is marked as a SPAM user.
       
   451 			 *
       
   452 			 * @since 3.0.0
       
   453 			 *
       
   454 			 * @param int $id ID of the user marked as SPAM.
       
   455 			 */
       
   456 			do_action( 'make_spam_user', $id );
       
   457 		} else {
       
   458 			/**
       
   459 			 * Fires after the user is marked as a HAM user. Opposite of SPAM.
       
   460 			 *
       
   461 			 * @since 3.0.0
       
   462 			 *
       
   463 			 * @param int $id ID of the user marked as HAM.
       
   464 			 */
       
   465 			do_action( 'make_ham_user', $id );
       
   466 		}
       
   467 	}
       
   468 
       
   469 	return $value;
       
   470 }
       
   471 
       
   472 function refresh_user_details( $id ) {
       
   473 	$id = (int) $id;
       
   474 
       
   475 	if ( !$user = get_userdata( $id ) )
       
   476 		return false;
       
   477 
       
   478 	clean_user_cache( $user );
       
   479 
       
   480 	return $id;
       
   481 }
       
   482 
       
   483 function format_code_lang( $code = '' ) {
       
   484 	$code = strtolower( substr( $code, 0, 2 ) );
       
   485 	$lang_codes = array(
       
   486 		'aa' => 'Afar', 'ab' => 'Abkhazian', 'af' => 'Afrikaans', 'ak' => 'Akan', 'sq' => 'Albanian', 'am' => 'Amharic', 'ar' => 'Arabic', 'an' => 'Aragonese', 'hy' => 'Armenian', 'as' => 'Assamese', 'av' => 'Avaric', 'ae' => 'Avestan', 'ay' => 'Aymara', 'az' => 'Azerbaijani', 'ba' => 'Bashkir', 'bm' => 'Bambara', 'eu' => 'Basque', 'be' => 'Belarusian', 'bn' => 'Bengali',
       
   487 		'bh' => 'Bihari', 'bi' => 'Bislama', 'bs' => 'Bosnian', 'br' => 'Breton', 'bg' => 'Bulgarian', 'my' => 'Burmese', 'ca' => 'Catalan; Valencian', 'ch' => 'Chamorro', 'ce' => 'Chechen', 'zh' => 'Chinese', 'cu' => 'Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic', 'cv' => 'Chuvash', 'kw' => 'Cornish', 'co' => 'Corsican', 'cr' => 'Cree',
       
   488 		'cs' => 'Czech', 'da' => 'Danish', 'dv' => 'Divehi; Dhivehi; Maldivian', 'nl' => 'Dutch; Flemish', 'dz' => 'Dzongkha', 'en' => 'English', 'eo' => 'Esperanto', 'et' => 'Estonian', 'ee' => 'Ewe', 'fo' => 'Faroese', 'fj' => 'Fijjian', 'fi' => 'Finnish', 'fr' => 'French', 'fy' => 'Western Frisian', 'ff' => 'Fulah', 'ka' => 'Georgian', 'de' => 'German', 'gd' => 'Gaelic; Scottish Gaelic',
       
   489 		'ga' => 'Irish', 'gl' => 'Galician', 'gv' => 'Manx', 'el' => 'Greek, Modern', 'gn' => 'Guarani', 'gu' => 'Gujarati', 'ht' => 'Haitian; Haitian Creole', 'ha' => 'Hausa', 'he' => 'Hebrew', 'hz' => 'Herero', 'hi' => 'Hindi', 'ho' => 'Hiri Motu', 'hu' => 'Hungarian', 'ig' => 'Igbo', 'is' => 'Icelandic', 'io' => 'Ido', 'ii' => 'Sichuan Yi', 'iu' => 'Inuktitut', 'ie' => 'Interlingue',
       
   490 		'ia' => 'Interlingua (International Auxiliary Language Association)', 'id' => 'Indonesian', 'ik' => 'Inupiaq', 'it' => 'Italian', 'jv' => 'Javanese', 'ja' => 'Japanese', 'kl' => 'Kalaallisut; Greenlandic', 'kn' => 'Kannada', 'ks' => 'Kashmiri', 'kr' => 'Kanuri', 'kk' => 'Kazakh', 'km' => 'Central Khmer', 'ki' => 'Kikuyu; Gikuyu', 'rw' => 'Kinyarwanda', 'ky' => 'Kirghiz; Kyrgyz',
       
   491 		'kv' => 'Komi', 'kg' => 'Kongo', 'ko' => 'Korean', 'kj' => 'Kuanyama; Kwanyama', 'ku' => 'Kurdish', 'lo' => 'Lao', 'la' => 'Latin', 'lv' => 'Latvian', 'li' => 'Limburgan; Limburger; Limburgish', 'ln' => 'Lingala', 'lt' => 'Lithuanian', 'lb' => 'Luxembourgish; Letzeburgesch', 'lu' => 'Luba-Katanga', 'lg' => 'Ganda', 'mk' => 'Macedonian', 'mh' => 'Marshallese', 'ml' => 'Malayalam',
       
   492 		'mi' => 'Maori', 'mr' => 'Marathi', 'ms' => 'Malay', 'mg' => 'Malagasy', 'mt' => 'Maltese', 'mo' => 'Moldavian', 'mn' => 'Mongolian', 'na' => 'Nauru', 'nv' => 'Navajo; Navaho', 'nr' => 'Ndebele, South; South Ndebele', 'nd' => 'Ndebele, North; North Ndebele', 'ng' => 'Ndonga', 'ne' => 'Nepali', 'nn' => 'Norwegian Nynorsk; Nynorsk, Norwegian', 'nb' => 'Bokmål, Norwegian, Norwegian Bokmål',
       
   493 		'no' => 'Norwegian', 'ny' => 'Chichewa; Chewa; Nyanja', 'oc' => 'Occitan, Provençal', 'oj' => 'Ojibwa', 'or' => 'Oriya', 'om' => 'Oromo', 'os' => 'Ossetian; Ossetic', 'pa' => 'Panjabi; Punjabi', 'fa' => 'Persian', 'pi' => 'Pali', 'pl' => 'Polish', 'pt' => 'Portuguese', 'ps' => 'Pushto', 'qu' => 'Quechua', 'rm' => 'Romansh', 'ro' => 'Romanian', 'rn' => 'Rundi', 'ru' => 'Russian',
       
   494 		'sg' => 'Sango', 'sa' => 'Sanskrit', 'sr' => 'Serbian', 'hr' => 'Croatian', 'si' => 'Sinhala; Sinhalese', 'sk' => 'Slovak', 'sl' => 'Slovenian', 'se' => 'Northern Sami', 'sm' => 'Samoan', 'sn' => 'Shona', 'sd' => 'Sindhi', 'so' => 'Somali', 'st' => 'Sotho, Southern', 'es' => 'Spanish; Castilian', 'sc' => 'Sardinian', 'ss' => 'Swati', 'su' => 'Sundanese', 'sw' => 'Swahili',
       
   495 		'sv' => 'Swedish', 'ty' => 'Tahitian', 'ta' => 'Tamil', 'tt' => 'Tatar', 'te' => 'Telugu', 'tg' => 'Tajik', 'tl' => 'Tagalog', 'th' => 'Thai', 'bo' => 'Tibetan', 'ti' => 'Tigrinya', 'to' => 'Tonga (Tonga Islands)', 'tn' => 'Tswana', 'ts' => 'Tsonga', 'tk' => 'Turkmen', 'tr' => 'Turkish', 'tw' => 'Twi', 'ug' => 'Uighur; Uyghur', 'uk' => 'Ukrainian', 'ur' => 'Urdu', 'uz' => 'Uzbek',
       
   496 		've' => 'Venda', 'vi' => 'Vietnamese', 'vo' => 'Volapük', 'cy' => 'Welsh','wa' => 'Walloon','wo' => 'Wolof', 'xh' => 'Xhosa', 'yi' => 'Yiddish', 'yo' => 'Yoruba', 'za' => 'Zhuang; Chuang', 'zu' => 'Zulu' );
       
   497 
       
   498 	/**
       
   499 	 * Filter the language codes.
       
   500 	 *
       
   501 	 * @since MU
       
   502 	 *
       
   503 	 * @param array  $lang_codes Key/value pair of language codes where key is the short version.
       
   504 	 * @param string $code       A two-letter designation of the language.
       
   505 	 */
       
   506 	$lang_codes = apply_filters( 'lang_codes', $lang_codes, $code );
       
   507 	return strtr( $code, $lang_codes );
       
   508 }
       
   509 
       
   510 function sync_category_tag_slugs( $term, $taxonomy ) {
       
   511 	if ( global_terms_enabled() && ( $taxonomy == 'category' || $taxonomy == 'post_tag' ) ) {
       
   512 		if ( is_object( $term ) ) {
       
   513 			$term->slug = sanitize_title( $term->name );
       
   514 		} else {
       
   515 			$term['slug'] = sanitize_title( $term['name'] );
       
   516 		}
       
   517 	}
       
   518 	return $term;
       
   519 }
       
   520 add_filter( 'get_term', 'sync_category_tag_slugs', 10, 2 );
       
   521 
       
   522 function _access_denied_splash() {
       
   523 	if ( ! is_user_logged_in() || is_network_admin() )
       
   524 		return;
       
   525 
       
   526 	$blogs = get_blogs_of_user( get_current_user_id() );
       
   527 
       
   528 	if ( wp_list_filter( $blogs, array( 'userblog_id' => get_current_blog_id() ) ) )
       
   529 		return;
       
   530 
       
   531 	$blog_name = get_bloginfo( 'name' );
       
   532 
       
   533 	if ( empty( $blogs ) )
       
   534 		wp_die( sprintf( __( 'You attempted to access the "%1$s" dashboard, but you do not currently have privileges on this site. If you believe you should be able to access the "%1$s" dashboard, please contact your network administrator.' ), $blog_name ) );
       
   535 
       
   536 	$output = '<p>' . sprintf( __( 'You attempted to access the "%1$s" dashboard, but you do not currently have privileges on this site. If you believe you should be able to access the "%1$s" dashboard, please contact your network administrator.' ), $blog_name ) . '</p>';
       
   537 	$output .= '<p>' . __( 'If you reached this screen by accident and meant to visit one of your own sites, here are some shortcuts to help you find your way.' ) . '</p>';
       
   538 
       
   539 	$output .= '<h3>' . __('Your Sites') . '</h3>';
       
   540 	$output .= '<table>';
       
   541 
       
   542 	foreach ( $blogs as $blog ) {
       
   543 		$output .= "<tr>";
       
   544 		$output .= "<td valign='top'>";
       
   545 		$output .= "{$blog->blogname}";
       
   546 		$output .= "</td>";
       
   547 		$output .= "<td valign='top'>";
       
   548 		$output .= "<a href='" . esc_url( get_admin_url( $blog->userblog_id ) ) . "'>" . __( 'Visit Dashboard' ) . "</a> | <a href='" . esc_url( get_home_url( $blog->userblog_id ) ). "'>" . __( 'View Site' ) . "</a>" ;
       
   549 		$output .= "</td>";
       
   550 		$output .= "</tr>";
       
   551 	}
       
   552 	$output .= '</table>';
       
   553 
       
   554 	wp_die( $output );
       
   555 }
       
   556 add_action( 'admin_page_access_denied', '_access_denied_splash', 99 );
       
   557 
       
   558 function check_import_new_users( $permission ) {
       
   559 	if ( !is_super_admin() )
       
   560 		return false;
       
   561 	return true;
       
   562 }
       
   563 add_filter( 'import_allow_create_users', 'check_import_new_users' );
       
   564 // See "import_allow_fetch_attachments" and "import_attachment_size_limit" filters too.
       
   565 
       
   566 function mu_dropdown_languages( $lang_files = array(), $current = '' ) {
       
   567 	$flag = false;
       
   568 	$output = array();
       
   569 
       
   570 	foreach ( (array) $lang_files as $val ) {
       
   571 		$code_lang = basename( $val, '.mo' );
       
   572 
       
   573 		if ( $code_lang == 'en_US' ) { // American English
       
   574 			$flag = true;
       
   575 			$ae = __( 'American English' );
       
   576 			$output[$ae] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . $ae . '</option>';
       
   577 		} elseif ( $code_lang == 'en_GB' ) { // British English
       
   578 			$flag = true;
       
   579 			$be = __( 'British English' );
       
   580 			$output[$be] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . $be . '</option>';
       
   581 		} else {
       
   582 			$translated = format_code_lang( $code_lang );
       
   583 			$output[$translated] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . esc_html ( $translated ) . '</option>';
       
   584 		}
       
   585 
       
   586 	}
       
   587 
       
   588 	if ( $flag === false ) // WordPress english
       
   589 		$output[] = '<option value=""' . selected( $current, '', false ) . '>' . __( 'English' ) . "</option>";
       
   590 
       
   591 	// Order by name
       
   592 	uksort( $output, 'strnatcasecmp' );
       
   593 	/**
       
   594 	 * Filter the languages available in the dropdown.
       
   595 	 *
       
   596 	 * @since MU
       
   597 	 *
       
   598 	 * @param array $output     HTML output of the dropdown.
       
   599 	 * @param array $lang_files Available language files.
       
   600 	 * @param string $current   The current language code.
       
   601 	 */
       
   602 	$output = apply_filters( 'mu_dropdown_languages', $output, $lang_files, $current );
       
   603 	echo implode( "\n\t", $output );
       
   604 }
       
   605 
       
   606 function site_admin_notice() {
       
   607 	global $wp_db_version;
       
   608 	if ( !is_super_admin() )
       
   609 		return false;
       
   610 	if ( get_site_option( 'wpmu_upgrade_site' ) != $wp_db_version )
       
   611 		echo "<div class='update-nag'>" . sprintf( __( 'Thank you for Updating! Please visit the <a href="%s">Upgrade Network</a> page to update all your sites.' ), esc_url( network_admin_url( 'upgrade.php' ) ) ) . "</div>";
       
   612 }
       
   613 add_action( 'admin_notices', 'site_admin_notice' );
       
   614 add_action( 'network_admin_notices', 'site_admin_notice' );
       
   615 
       
   616 function avoid_blog_page_permalink_collision( $data, $postarr ) {
       
   617 	if ( is_subdomain_install() )
       
   618 		return $data;
       
   619 	if ( $data['post_type'] != 'page' )
       
   620 		return $data;
       
   621 	if ( !isset( $data['post_name'] ) || $data['post_name'] == '' )
       
   622 		return $data;
       
   623 	if ( !is_main_site() )
       
   624 		return $data;
       
   625 
       
   626 	$post_name = $data['post_name'];
       
   627 	$c = 0;
       
   628 	while( $c < 10 && get_id_from_blogname( $post_name ) ) {
       
   629 		$post_name .= mt_rand( 1, 10 );
       
   630 		$c ++;
       
   631 	}
       
   632 	if ( $post_name != $data['post_name'] ) {
       
   633 		$data['post_name'] = $post_name;
       
   634 	}
       
   635 	return $data;
       
   636 }
       
   637 add_filter( 'wp_insert_post_data', 'avoid_blog_page_permalink_collision', 10, 2 );
       
   638 
       
   639 function choose_primary_blog() {
       
   640 	?>
       
   641 	<table class="form-table">
       
   642 	<tr>
       
   643 	<?php /* translators: My sites label */ ?>
       
   644 		<th scope="row"><?php _e( 'Primary Site' ); ?></th>
       
   645 		<td>
       
   646 		<?php
       
   647 		$all_blogs = get_blogs_of_user( get_current_user_id() );
       
   648 		$primary_blog = get_user_meta( get_current_user_id(), 'primary_blog', true );
       
   649 		if ( count( $all_blogs ) > 1 ) {
       
   650 			$found = false;
       
   651 			?>
       
   652 			<select name="primary_blog">
       
   653 				<?php foreach( (array) $all_blogs as $blog ) {
       
   654 					if ( $primary_blog == $blog->userblog_id )
       
   655 						$found = true;
       
   656 					?><option value="<?php echo $blog->userblog_id ?>"<?php selected( $primary_blog, $blog->userblog_id ); ?>><?php echo esc_url( get_home_url( $blog->userblog_id ) ) ?></option><?php
       
   657 				} ?>
       
   658 			</select>
       
   659 			<?php
       
   660 			if ( !$found ) {
       
   661 				$blog = array_shift( $all_blogs );
       
   662 				update_user_meta( get_current_user_id(), 'primary_blog', $blog->userblog_id );
       
   663 			}
       
   664 		} elseif ( count( $all_blogs ) == 1 ) {
       
   665 			$blog = array_shift( $all_blogs );
       
   666 			echo $blog->domain;
       
   667 			if ( $primary_blog != $blog->userblog_id ) // Set the primary blog again if it's out of sync with blog list.
       
   668 				update_user_meta( get_current_user_id(), 'primary_blog', $blog->userblog_id );
       
   669 		} else {
       
   670 			echo "N/A";
       
   671 		}
       
   672 		?>
       
   673 		</td>
       
   674 	</tr>
       
   675 	<?php if ( in_array( get_site_option( 'registration' ), array( 'all', 'blog' ) ) ) : ?>
       
   676 		<tr>
       
   677 			<th scope="row" colspan="2" class="th-full">
       
   678 				<?php
       
   679 				$signup_url = network_site_url( 'wp-signup.php' );
       
   680 				/** This filter is documented in wp-login.php */
       
   681 				?>
       
   682 				<a href="<?php echo apply_filters( 'wp_signup_location', $signup_url ); ?>"><?php _e( 'Create a New Site' ); ?></a>
       
   683 			</th>
       
   684 		</tr>
       
   685 	<?php endif; ?>
       
   686 	</table>
       
   687 	<?php
       
   688 }
       
   689 
       
   690 /**
       
   691  * Grants Super Admin privileges.
       
   692  *
       
   693  * @since 3.0.0
       
   694  * @param int $user_id ID of the user to be granted Super Admin privileges.
       
   695  */
       
   696 function grant_super_admin( $user_id ) {
       
   697 	global $super_admins;
       
   698 
       
   699 	// If global super_admins override is defined, there is nothing to do here.
       
   700 	if ( isset( $super_admins ) )
       
   701 		return false;
       
   702 
       
   703 	/**
       
   704 	 * Fires before the user is granted Super Admin privileges.
       
   705 	 *
       
   706 	 * @since 3.0.0
       
   707 	 *
       
   708 	 * @param int $user_id ID of the user that is about to be granted Super Admin privileges.
       
   709 	 */
       
   710 	do_action( 'grant_super_admin', $user_id );
       
   711 
       
   712 	// Directly fetch site_admins instead of using get_super_admins()
       
   713 	$super_admins = get_site_option( 'site_admins', array( 'admin' ) );
       
   714 
       
   715 	$user = get_userdata( $user_id );
       
   716 	if ( $user && ! in_array( $user->user_login, $super_admins ) ) {
       
   717 		$super_admins[] = $user->user_login;
       
   718 		update_site_option( 'site_admins' , $super_admins );
       
   719 
       
   720 		/**
       
   721 		 * Fires after the user is granted Super Admin privileges.
       
   722 		 *
       
   723 		 * @since 3.0.0
       
   724 		 *
       
   725 		 * @param int $user_id ID of the user that was granted Super Admin privileges.
       
   726 		 */
       
   727 		do_action( 'granted_super_admin', $user_id );
       
   728 		return true;
       
   729 	}
       
   730 	return false;
       
   731 }
       
   732 
       
   733 /**
       
   734  * Revokes Super Admin privileges.
       
   735  *
       
   736  * @since 3.0.0
       
   737  * @param int $user_id ID of the user Super Admin privileges to be revoked from.
       
   738  */
       
   739 function revoke_super_admin( $user_id ) {
       
   740 	global $super_admins;
       
   741 
       
   742 	// If global super_admins override is defined, there is nothing to do here.
       
   743 	if ( isset( $super_admins ) )
       
   744 		return false;
       
   745 
       
   746 	/**
       
   747 	 * Fires before the user's Super Admin privileges are revoked.
       
   748 	 *
       
   749 	 * @since 3.0.0
       
   750 	 *
       
   751 	 * @param int $user_id ID of the user Super Admin privileges are being revoked from.
       
   752 	 */
       
   753 	do_action( 'revoke_super_admin', $user_id );
       
   754 
       
   755 	// Directly fetch site_admins instead of using get_super_admins()
       
   756 	$super_admins = get_site_option( 'site_admins', array( 'admin' ) );
       
   757 
       
   758 	$user = get_userdata( $user_id );
       
   759 	if ( $user && $user->user_email != get_site_option( 'admin_email' ) ) {
       
   760 		if ( false !== ( $key = array_search( $user->user_login, $super_admins ) ) ) {
       
   761 			unset( $super_admins[$key] );
       
   762 			update_site_option( 'site_admins', $super_admins );
       
   763 
       
   764 			/**
       
   765 			 * Fires after the user's Super Admin privileges are revoked.
       
   766 			 *
       
   767 			 * @since 3.0.0
       
   768 			 *
       
   769 			 * @param int $user_id ID of the user Super Admin privileges were revoked from.
       
   770 			 */
       
   771 			do_action( 'revoked_super_admin', $user_id );
       
   772 			return true;
       
   773 		}
       
   774 	}
       
   775 	return false;
       
   776 }
       
   777 
       
   778 /**
       
   779  * Whether or not we can edit this network from this page
       
   780  *
       
   781  * By default editing of network is restricted to the Network Admin for that site_id this allows for this to be overridden
       
   782  *
       
   783  * @since 3.1.0
       
   784  * @param integer $site_id The network/site ID to check.
       
   785  */
       
   786 function can_edit_network( $site_id ) {
       
   787 	global $wpdb;
       
   788 
       
   789 	if ( $site_id == $wpdb->siteid )
       
   790 		$result = true;
       
   791 	else
       
   792 		$result = false;
       
   793 
       
   794 	/**
       
   795 	 * Filter whether this network can be edited from this page.
       
   796 	 *
       
   797 	 * @since 3.1.0
       
   798 	 *
       
   799 	 * @param bool $result  Whether the network can be edited from this page.
       
   800 	 * @param int  $site_id The network/site ID to check.
       
   801 	 */
       
   802 	return apply_filters( 'can_edit_network', $result, $site_id );
       
   803 }
       
   804 
       
   805 /**
       
   806  * Thickbox image paths for Network Admin.
       
   807  *
       
   808  * @since 3.1.0
       
   809  * @access private
       
   810  */
       
   811 function _thickbox_path_admin_subfolder() {
       
   812 ?>
       
   813 <script type="text/javascript">
       
   814 //<![CDATA[
       
   815 var tb_pathToImage = "../../wp-includes/js/thickbox/loadingAnimation.gif";
       
   816 //]]>
       
   817 </script>
       
   818 <?php
       
   819 }