Wordpress 3.7
[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, $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 }