WordPress 4.0
[autoinstalls/wordpress.git] / wp-admin / includes / ms.php
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;
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         $current_site = get_current_site();
86
87         // Don't destroy the initial, main, or root blog.
88         if ( $drop && ( 1 == $blog_id || is_main_site( $blog_id ) || ( $blog->path == $current_site->path && $blog->domain == $current_site->domain ) ) )
89                 $drop = false;
90
91         if ( $drop ) {
92                 $tables = $wpdb->tables( 'blog' );
93                 /**
94                  * Filter the tables to drop when the blog is deleted.
95                  *
96                  * @since MU
97                  *
98                  * @param array $tables  The blog tables to be dropped.
99                  * @param int   $blog_id The ID of the blog to drop tables for.
100                  */
101                 $drop_tables = apply_filters( 'wpmu_drop_tables', $tables, $blog_id );
102
103                 foreach ( (array) $drop_tables as $table ) {
104                         $wpdb->query( "DROP TABLE IF EXISTS `$table`" );
105                 }
106
107                 $wpdb->delete( $wpdb->blogs, array( 'blog_id' => $blog_id ) );
108
109                 $uploads = wp_upload_dir();
110                 /**
111                  * Filter the upload base directory to delete when the blog is deleted.
112                  *
113                  * @since MU
114                  *
115                  * @param string $uploads['basedir'] Uploads path without subdirectory. @see wp_upload_dir()
116                  * @param int    $blog_id            The blog ID.
117                  */
118                 $dir = apply_filters( 'wpmu_delete_blog_upload_dir', $uploads['basedir'], $blog_id );
119                 $dir = rtrim( $dir, DIRECTORY_SEPARATOR );
120                 $top_dir = $dir;
121                 $stack = array($dir);
122                 $index = 0;
123
124                 while ( $index < count( $stack ) ) {
125                         # Get indexed directory from stack
126                         $dir = $stack[$index];
127
128                         $dh = @opendir( $dir );
129                         if ( $dh ) {
130                                 while ( ( $file = @readdir( $dh ) ) !== false ) {
131                                         if ( $file == '.' || $file == '..' )
132                                                 continue;
133
134                                         if ( @is_dir( $dir . DIRECTORY_SEPARATOR . $file ) )
135                                                 $stack[] = $dir . DIRECTORY_SEPARATOR . $file;
136                                         else if ( @is_file( $dir . DIRECTORY_SEPARATOR . $file ) )
137                                                 @unlink( $dir . DIRECTORY_SEPARATOR . $file );
138                                 }
139                                 @closedir( $dh );
140                         }
141                         $index++;
142                 }
143
144                 $stack = array_reverse( $stack ); // Last added dirs are deepest
145                 foreach( (array) $stack as $dir ) {
146                         if ( $dir != $top_dir)
147                         @rmdir( $dir );
148                 }
149
150                 clean_blog_cache( $blog );
151         }
152
153         if ( $switch )
154                 restore_current_blog();
155 }
156
157 // @todo Merge with wp_delete_user() ?
158 function wpmu_delete_user( $id ) {
159         global $wpdb;
160
161         $id = (int) $id;
162         $user = new WP_User( $id );
163
164         if ( !$user->exists() )
165                 return false;
166         /**
167          * Fires before a user is deleted from the network.
168          *
169          * @since MU
170          *
171          * @param int $id ID of the user about to be deleted from the network.
172          */
173         do_action( 'wpmu_delete_user', $id );
174
175         $blogs = get_blogs_of_user( $id );
176
177         if ( ! empty( $blogs ) ) {
178                 foreach ( $blogs as $blog ) {
179                         switch_to_blog( $blog->userblog_id );
180                         remove_user_from_blog( $id, $blog->userblog_id );
181
182                         $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $id ) );
183                         foreach ( (array) $post_ids as $post_id ) {
184                                 wp_delete_post( $post_id );
185                         }
186
187                         // Clean links
188                         $link_ids = $wpdb->get_col( $wpdb->prepare( "SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $id ) );
189
190                         if ( $link_ids ) {
191                                 foreach ( $link_ids as $link_id )
192                                         wp_delete_link( $link_id );
193                         }
194
195                         restore_current_blog();
196                 }
197         }
198
199         $meta = $wpdb->get_col( $wpdb->prepare( "SELECT umeta_id FROM $wpdb->usermeta WHERE user_id = %d", $id ) );
200         foreach ( $meta as $mid )
201                 delete_metadata_by_mid( 'user', $mid );
202
203         $wpdb->delete( $wpdb->users, array( 'ID' => $id ) );
204
205         clean_user_cache( $user );
206
207         /** This action is documented in wp-admin/includes/user.php */
208         do_action( 'deleted_user', $id );
209
210         return true;
211 }
212
213 function update_option_new_admin_email( $old_value, $value ) {
214         if ( $value == get_option( 'admin_email' ) || !is_email( $value ) )
215                 return;
216
217         $hash = md5( $value. time() .mt_rand() );
218         $new_admin_email = array(
219                 'hash' => $hash,
220                 'newemail' => $value
221         );
222         update_option( 'adminhash', $new_admin_email );
223
224         $email_text = __( 'Dear user,
225
226 You recently requested to have the administration email address on
227 your site changed.
228 If this is correct, please click on the following link to change it:
229 ###ADMIN_URL###
230
231 You can safely ignore and delete this email if you do not want to
232 take this action.
233
234 This email has been sent to ###EMAIL###
235
236 Regards,
237 All at ###SITENAME###
238 ###SITEURL###' );
239
240         /**
241          * Filter the email text sent when the site admin email is changed.
242          *
243          * The following strings have a special meaning and will get replaced dynamically:
244          * ###ADMIN_URL### The link to click on to confirm the email change. Required otherwise this functunalty is will break.
245          * ###EMAIL###     The new email.
246          * ###SITENAME###  The name of the site.
247          * ###SITEURL###   The URL to the site.
248          *
249          * @since MU
250          *
251          * @param string $email_text      Text in the email.
252          * @param string $new_admin_email New admin email that the current administration email was changed to.
253          */
254         $content = apply_filters( 'new_admin_email_content', $email_text, $new_admin_email );
255
256         $content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'options.php?adminhash='.$hash ) ), $content );
257         $content = str_replace( '###EMAIL###', $value, $content );
258         $content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content );
259         $content = str_replace( '###SITEURL###', network_home_url(), $content );
260
261         wp_mail( $value, sprintf( __( '[%s] New Admin Email Address' ), wp_specialchars_decode( get_option( 'blogname' ) ) ), $content );
262 }
263 add_action( 'update_option_new_admin_email', 'update_option_new_admin_email', 10, 2 );
264 add_action( 'add_option_new_admin_email', 'update_option_new_admin_email', 10, 2 );
265
266 function send_confirmation_on_profile_email() {
267         global $errors, $wpdb;
268         $current_user = wp_get_current_user();
269         if ( ! is_object($errors) )
270                 $errors = new WP_Error();
271
272         if ( $current_user->ID != $_POST['user_id'] )
273                 return false;
274
275         if ( $current_user->user_email != $_POST['email'] ) {
276                 if ( !is_email( $_POST['email'] ) ) {
277                         $errors->add( 'user_email', __( "<strong>ERROR</strong>: The email address isn&#8217;t correct." ), array( 'form-field' => 'email' ) );
278                         return;
279                 }
280
281                 if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_email FROM {$wpdb->users} WHERE user_email=%s", $_POST['email'] ) ) ) {
282                         $errors->add( 'user_email', __( "<strong>ERROR</strong>: The email address is already used." ), array( 'form-field' => 'email' ) );
283                         delete_option( $current_user->ID . '_new_email' );
284                         return;
285                 }
286
287                 $hash = md5( $_POST['email'] . time() . mt_rand() );
288                 $new_user_email = array(
289                                 'hash' => $hash,
290                                 'newemail' => $_POST['email']
291                                 );
292                 update_option( $current_user->ID . '_new_email', $new_user_email );
293
294                 $email_text = __( 'Dear user,
295
296 You recently requested to have the email address on your account changed.
297 If this is correct, please click on the following link to change it:
298 ###ADMIN_URL###
299
300 You can safely ignore and delete this email if you do not want to
301 take this action.
302
303 This email has been sent to ###EMAIL###
304
305 Regards,
306 All at ###SITENAME###
307 ###SITEURL###' );
308
309                 /**
310                  * Filter the email text sent when a user changes emails.
311                  *
312                  * The following strings have a special meaning and will get replaced dynamically:
313                  * ###ADMIN_URL### The link to click on to confirm the email change. Required otherwise this functunalty is will break.
314                  * ###EMAIL### The new email.
315                  * ###SITENAME### The name of the site.
316                  * ###SITEURL### The URL to the site.
317                  *
318                  * @since MU
319                  *
320                  * @param string $email_text     Text in the email.
321                  * @param string $new_user_email New user email that the current user has changed to.
322                  */
323                 $content = apply_filters( 'new_user_email_content', $email_text, $new_user_email );
324
325                 $content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'profile.php?newuseremail='.$hash ) ), $content );
326                 $content = str_replace( '###EMAIL###', $_POST['email'], $content);
327                 $content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content );
328                 $content = str_replace( '###SITEURL###', network_home_url(), $content );
329
330                 wp_mail( $_POST['email'], sprintf( __( '[%s] New Email Address' ), wp_specialchars_decode( get_option( 'blogname' ) ) ), $content );
331                 $_POST['email'] = $current_user->user_email;
332         }
333 }
334 add_action( 'personal_options_update', 'send_confirmation_on_profile_email' );
335
336 function new_user_email_admin_notice() {
337         if ( strpos( $_SERVER['PHP_SELF'], 'profile.php' ) && isset( $_GET['updated'] ) && $email = get_option( get_current_user_id() . '_new_email' ) )
338                 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>";
339 }
340 add_action( 'admin_notices', 'new_user_email_admin_notice' );
341
342 /**
343  * Check whether a blog has used its allotted upload space.
344  *
345  * @since MU
346  *
347  * @param bool $echo Optional. If $echo is set and the quota is exceeded, a warning message is echoed. Default is true.
348  * @return int
349  */
350 function upload_is_user_over_quota( $echo = true ) {
351         if ( get_site_option( 'upload_space_check_disabled' ) )
352                 return false;
353
354         $space_allowed = get_space_allowed();
355         if ( empty( $space_allowed ) || !is_numeric( $space_allowed ) )
356                 $space_allowed = 10; // Default space allowed is 10 MB
357
358         $space_used = get_space_used();
359
360         if ( ( $space_allowed - $space_used ) < 0 ) {
361                 if ( $echo )
362                         _e( 'Sorry, you have used your space allocation. Please delete some files to upload more files.' );
363                 return true;
364         } else {
365                 return false;
366         }
367 }
368
369 /**
370  * Displays the amount of disk space used by the current blog. Not used in core.
371  *
372  * @since MU
373  */
374 function display_space_usage() {
375         $space_allowed = get_space_allowed();
376         $space_used = get_space_used();
377
378         $percent_used = ( $space_used / $space_allowed ) * 100;
379
380         if ( $space_allowed > 1000 ) {
381                 $space = number_format( $space_allowed / 1024 );
382                 /* translators: Gigabytes */
383                 $space .= __( 'GB' );
384         } else {
385                 $space = number_format( $space_allowed );
386                 /* translators: Megabytes */
387                 $space .= __( 'MB' );
388         }
389         ?>
390         <strong><?php printf( __( 'Used: %1$s%% of %2$s' ), number_format( $percent_used ), $space ); ?></strong>
391         <?php
392 }
393
394 /**
395  * Get the remaining upload space for this blog.
396  *
397  * @since MU
398  * @uses upload_is_user_over_quota()
399  * @uses get_space_allowed()
400  * @uses get_upload_space_available()
401  *
402  * @param int $size Current max size in bytes
403  * @return int Max size in bytes
404  */
405 function fix_import_form_size( $size ) {
406         if ( upload_is_user_over_quota( false ) == true )
407                 return 0;
408
409         $available = get_upload_space_available();
410         return min( $size, $available );
411 }
412
413 // Edit blog upload space setting on Edit Blog page
414 function upload_space_setting( $id ) {
415         switch_to_blog( $id );
416         $quota = get_option( 'blog_upload_space' );
417         restore_current_blog();
418
419         if ( !$quota )
420                 $quota = '';
421
422         ?>
423         <tr>
424                 <th><?php _e( 'Site Upload Space Quota '); ?></th>
425                 <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>
426         </tr>
427         <?php
428 }
429 add_action( 'wpmueditblogaction', 'upload_space_setting' );
430
431 function update_user_status( $id, $pref, $value, $deprecated = null ) {
432         global $wpdb;
433
434         if ( null !== $deprecated )
435                 _deprecated_argument( __FUNCTION__, '3.1' );
436
437         $wpdb->update( $wpdb->users, array( sanitize_key( $pref ) => $value ), array( 'ID' => $id ) );
438
439         $user = new WP_User( $id );
440         clean_user_cache( $user );
441
442         if ( $pref == 'spam' ) {
443                 if ( $value == 1 ) {
444                         /**
445                          * Fires after the user is marked as a SPAM user.
446                          *
447                          * @since 3.0.0
448                          *
449                          * @param int $id ID of the user marked as SPAM.
450                          */
451                         do_action( 'make_spam_user', $id );
452                 } else {
453                         /**
454                          * Fires after the user is marked as a HAM user. Opposite of SPAM.
455                          *
456                          * @since 3.0.0
457                          *
458                          * @param int $id ID of the user marked as HAM.
459                          */
460                         do_action( 'make_ham_user', $id );
461                 }
462         }
463
464         return $value;
465 }
466
467 function refresh_user_details( $id ) {
468         $id = (int) $id;
469
470         if ( !$user = get_userdata( $id ) )
471                 return false;
472
473         clean_user_cache( $user );
474
475         return $id;
476 }
477
478 function format_code_lang( $code = '' ) {
479         $code = strtolower( substr( $code, 0, 2 ) );
480         $lang_codes = array(
481                 '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',
482                 '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',
483                 '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',
484                 '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',
485                 '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',
486                 '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',
487                 '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',
488                 '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',
489                 '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',
490                 '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',
491                 've' => 'Venda', 'vi' => 'Vietnamese', 'vo' => 'Volapük', 'cy' => 'Welsh','wa' => 'Walloon','wo' => 'Wolof', 'xh' => 'Xhosa', 'yi' => 'Yiddish', 'yo' => 'Yoruba', 'za' => 'Zhuang; Chuang', 'zu' => 'Zulu' );
492
493         /**
494          * Filter the language codes.
495          *
496          * @since MU
497          *
498          * @param array  $lang_codes Key/value pair of language codes where key is the short version.
499          * @param string $code       A two-letter designation of the language.
500          */
501         $lang_codes = apply_filters( 'lang_codes', $lang_codes, $code );
502         return strtr( $code, $lang_codes );
503 }
504
505 function sync_category_tag_slugs( $term, $taxonomy ) {
506         if ( global_terms_enabled() && ( $taxonomy == 'category' || $taxonomy == 'post_tag' ) ) {
507                 if ( is_object( $term ) ) {
508                         $term->slug = sanitize_title( $term->name );
509                 } else {
510                         $term['slug'] = sanitize_title( $term['name'] );
511                 }
512         }
513         return $term;
514 }
515 add_filter( 'get_term', 'sync_category_tag_slugs', 10, 2 );
516
517 function _access_denied_splash() {
518         if ( ! is_user_logged_in() || is_network_admin() )
519                 return;
520
521         $blogs = get_blogs_of_user( get_current_user_id() );
522
523         if ( wp_list_filter( $blogs, array( 'userblog_id' => get_current_blog_id() ) ) )
524                 return;
525
526         $blog_name = get_bloginfo( 'name' );
527
528         if ( empty( $blogs ) )
529                 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 ) );
530
531         $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>';
532         $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>';
533
534         $output .= '<h3>' . __('Your Sites') . '</h3>';
535         $output .= '<table>';
536
537         foreach ( $blogs as $blog ) {
538                 $output .= '<tr>';
539                 $output .= "<td>{$blog->blogname}</td>";
540                 $output .= '<td><a href="' . esc_url( get_admin_url( $blog->userblog_id ) ) . '">' . __( 'Visit Dashboard' ) . '</a> | ' .
541                         '<a href="' . esc_url( get_home_url( $blog->userblog_id ) ). '">' . __( 'View Site' ) . '</a></td>';
542                 $output .= '</tr>';
543         }
544
545         $output .= '</table>';
546
547         wp_die( $output );
548 }
549 add_action( 'admin_page_access_denied', '_access_denied_splash', 99 );
550
551 function check_import_new_users( $permission ) {
552         if ( !is_super_admin() )
553                 return false;
554         return true;
555 }
556 add_filter( 'import_allow_create_users', 'check_import_new_users' );
557 // See "import_allow_fetch_attachments" and "import_attachment_size_limit" filters too.
558
559 function mu_dropdown_languages( $lang_files = array(), $current = '' ) {
560         $flag = false;
561         $output = array();
562
563         foreach ( (array) $lang_files as $val ) {
564                 $code_lang = basename( $val, '.mo' );
565
566                 if ( $code_lang == 'en_US' ) { // American English
567                         $flag = true;
568                         $ae = __( 'American English' );
569                         $output[$ae] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . $ae . '</option>';
570                 } elseif ( $code_lang == 'en_GB' ) { // British English
571                         $flag = true;
572                         $be = __( 'British English' );
573                         $output[$be] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . $be . '</option>';
574                 } else {
575                         $translated = format_code_lang( $code_lang );
576                         $output[$translated] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . esc_html ( $translated ) . '</option>';
577                 }
578
579         }
580
581         if ( $flag === false ) // WordPress english
582                 $output[] = '<option value=""' . selected( $current, '', false ) . '>' . __( 'English' ) . "</option>";
583
584         // Order by name
585         uksort( $output, 'strnatcasecmp' );
586         /**
587          * Filter the languages available in the dropdown.
588          *
589          * @since MU
590          *
591          * @param array $output     HTML output of the dropdown.
592          * @param array $lang_files Available language files.
593          * @param string $current   The current language code.
594          */
595         $output = apply_filters( 'mu_dropdown_languages', $output, $lang_files, $current );
596         echo implode( "\n\t", $output );
597 }
598
599 function site_admin_notice() {
600         global $wp_db_version;
601         if ( !is_super_admin() )
602                 return false;
603         if ( get_site_option( 'wpmu_upgrade_site' ) != $wp_db_version )
604                 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>";
605 }
606 add_action( 'admin_notices', 'site_admin_notice' );
607 add_action( 'network_admin_notices', 'site_admin_notice' );
608
609 function avoid_blog_page_permalink_collision( $data, $postarr ) {
610         if ( is_subdomain_install() )
611                 return $data;
612         if ( $data['post_type'] != 'page' )
613                 return $data;
614         if ( !isset( $data['post_name'] ) || $data['post_name'] == '' )
615                 return $data;
616         if ( !is_main_site() )
617                 return $data;
618
619         $post_name = $data['post_name'];
620         $c = 0;
621         while( $c < 10 && get_id_from_blogname( $post_name ) ) {
622                 $post_name .= mt_rand( 1, 10 );
623                 $c ++;
624         }
625         if ( $post_name != $data['post_name'] ) {
626                 $data['post_name'] = $post_name;
627         }
628         return $data;
629 }
630 add_filter( 'wp_insert_post_data', 'avoid_blog_page_permalink_collision', 10, 2 );
631
632 function choose_primary_blog() {
633         ?>
634         <table class="form-table">
635         <tr>
636         <?php /* translators: My sites label */ ?>
637                 <th scope="row"><?php _e( 'Primary Site' ); ?></th>
638                 <td>
639                 <?php
640                 $all_blogs = get_blogs_of_user( get_current_user_id() );
641                 $primary_blog = get_user_meta( get_current_user_id(), 'primary_blog', true );
642                 if ( count( $all_blogs ) > 1 ) {
643                         $found = false;
644                         ?>
645                         <select name="primary_blog">
646                                 <?php foreach( (array) $all_blogs as $blog ) {
647                                         if ( $primary_blog == $blog->userblog_id )
648                                                 $found = true;
649                                         ?><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
650                                 } ?>
651                         </select>
652                         <?php
653                         if ( !$found ) {
654                                 $blog = array_shift( $all_blogs );
655                                 update_user_meta( get_current_user_id(), 'primary_blog', $blog->userblog_id );
656                         }
657                 } elseif ( count( $all_blogs ) == 1 ) {
658                         $blog = array_shift( $all_blogs );
659                         echo $blog->domain;
660                         if ( $primary_blog != $blog->userblog_id ) // Set the primary blog again if it's out of sync with blog list.
661                                 update_user_meta( get_current_user_id(), 'primary_blog', $blog->userblog_id );
662                 } else {
663                         echo "N/A";
664                 }
665                 ?>
666                 </td>
667         </tr>
668         <?php if ( in_array( get_site_option( 'registration' ), array( 'all', 'blog' ) ) ) : ?>
669                 <tr>
670                         <th scope="row" colspan="2" class="th-full">
671                                 <?php
672                                 /** This filter is documented in wp-login.php */
673                                 $sign_up_url = apply_filters( 'wp_signup_location', network_site_url( 'wp-signup.php' ) );
674                                 ?>
675                                 <a href="<?php echo esc_url( $sign_up_url ); ?>"><?php _e( 'Create a New Site' ); ?></a>
676                         </th>
677                 </tr>
678         <?php endif; ?>
679         </table>
680         <?php
681 }
682
683 /**
684  * Grants Super Admin privileges.
685  *
686  * @since 3.0.0
687  * @param int $user_id ID of the user to be granted Super Admin privileges.
688  * @return bool True on success, false on failure. This can fail when the user is
689  *              already a super admin or when the $super_admins global is defined.
690  */
691 function grant_super_admin( $user_id ) {
692         // If global super_admins override is defined, there is nothing to do here.
693         if ( isset( $GLOBALS['super_admins'] ) ) {
694                 return false;
695         }
696
697         /**
698          * Fires before the user is granted Super Admin privileges.
699          *
700          * @since 3.0.0
701          *
702          * @param int $user_id ID of the user that is about to be granted Super Admin privileges.
703          */
704         do_action( 'grant_super_admin', $user_id );
705
706         // Directly fetch site_admins instead of using get_super_admins()
707         $super_admins = get_site_option( 'site_admins', array( 'admin' ) );
708
709         $user = get_userdata( $user_id );
710         if ( $user && ! in_array( $user->user_login, $super_admins ) ) {
711                 $super_admins[] = $user->user_login;
712                 update_site_option( 'site_admins' , $super_admins );
713
714                 /**
715                  * Fires after the user is granted Super Admin privileges.
716                  *
717                  * @since 3.0.0
718                  *
719                  * @param int $user_id ID of the user that was granted Super Admin privileges.
720                  */
721                 do_action( 'granted_super_admin', $user_id );
722                 return true;
723         }
724         return false;
725 }
726
727 /**
728  * Revokes Super Admin privileges.
729  *
730  * @since 3.0.0
731  * @param int $user_id ID of the user Super Admin privileges to be revoked from.
732  * @return bool True on success, false on failure. This can fail when the user's email
733  *              is the network admin email or when the $super_admins global is defined.
734  */
735 function revoke_super_admin( $user_id ) {
736         // If global super_admins override is defined, there is nothing to do here.
737         if ( isset( $GLOBALS['super_admins'] ) ) {
738                 return false;
739         }
740
741         /**
742          * Fires before the user's Super Admin privileges are revoked.
743          *
744          * @since 3.0.0
745          *
746          * @param int $user_id ID of the user Super Admin privileges are being revoked from.
747          */
748         do_action( 'revoke_super_admin', $user_id );
749
750         // Directly fetch site_admins instead of using get_super_admins()
751         $super_admins = get_site_option( 'site_admins', array( 'admin' ) );
752
753         $user = get_userdata( $user_id );
754         if ( $user && 0 !== strcasecmp( $user->user_email, get_site_option( 'admin_email' ) ) ) {
755                 if ( false !== ( $key = array_search( $user->user_login, $super_admins ) ) ) {
756                         unset( $super_admins[$key] );
757                         update_site_option( 'site_admins', $super_admins );
758
759                         /**
760                          * Fires after the user's Super Admin privileges are revoked.
761                          *
762                          * @since 3.0.0
763                          *
764                          * @param int $user_id ID of the user Super Admin privileges were revoked from.
765                          */
766                         do_action( 'revoked_super_admin', $user_id );
767                         return true;
768                 }
769         }
770         return false;
771 }
772
773 /**
774  * Whether or not we can edit this network from this page
775  *
776  * By default editing of network is restricted to the Network Admin for that site_id this allows for this to be overridden
777  *
778  * @since 3.1.0
779  * @param integer $site_id The network/site ID to check.
780  */
781 function can_edit_network( $site_id ) {
782         global $wpdb;
783
784         if ( $site_id == $wpdb->siteid )
785                 $result = true;
786         else
787                 $result = false;
788
789         /**
790          * Filter whether this network can be edited from this page.
791          *
792          * @since 3.1.0
793          *
794          * @param bool $result  Whether the network can be edited from this page.
795          * @param int  $site_id The network/site ID to check.
796          */
797         return apply_filters( 'can_edit_network', $result, $site_id );
798 }
799
800 /**
801  * Thickbox image paths for Network Admin.
802  *
803  * @since 3.1.0
804  * @access private
805  */
806 function _thickbox_path_admin_subfolder() {
807 ?>
808 <script type="text/javascript">
809 //<![CDATA[
810 var tb_pathToImage = "../../wp-includes/js/thickbox/loadingAnimation.gif";
811 //]]>
812 </script>
813 <?php
814 }