Wordpress 3.0.6
[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_allowed = 1048576 * get_space_allowed();
29         $space_used = get_dirsize( BLOGUPLOADDIR );
30         $space_left = $space_allowed - $space_used;
31         $file_size = filesize( $file['tmp_name'] );
32         if ( $space_left < $file_size )
33                 $file['error'] = sprintf( __( 'Not enough space to upload. %1$s KB needed.' ), number_format( ($file_size - $space_left) /1024 ) );
34         if ( $file_size > ( 1024 * get_site_option( 'fileupload_maxk', 1500 ) ) )
35                 $file['error'] = sprintf(__('This file is too big. Files must be less than %1$s KB in size.'), get_site_option( 'fileupload_maxk', 1500 ) );
36         if ( upload_is_user_over_quota( false ) ) {
37                 $file['error'] = __( 'You have used your space quota. Please delete files before uploading.' );
38         }
39         if ( $file['error'] != '0' && !isset($_POST['html-upload']) )
40                 wp_die( $file['error'] . ' <a href="javascript:history.go(-1)">' . __( 'Back' ) . '</a>' );
41
42         return $file;
43 }
44 add_filter( 'wp_handle_upload_prefilter', 'check_upload_size' );
45
46 /**
47  * Delete a blog
48  *
49  * @since 3.0.0
50  *
51  * @param int $blog_id Blog ID
52  * @param bool $drop True if blog's table should be dropped.  Default is false.
53  * @return void
54  */
55 function wpmu_delete_blog( $blog_id, $drop = false ) {
56         global $wpdb;
57
58         $switch = false;
59         if ( $blog_id != $wpdb->blogid ) {
60                 $switch = true;
61                 switch_to_blog( $blog_id );
62         }
63
64         $blog_prefix = $wpdb->get_blog_prefix( $blog_id );
65
66         do_action( 'delete_blog', $blog_id, $drop );
67
68         $users = get_users_of_blog( $blog_id );
69
70         // Remove users from this blog.
71         if ( ! empty( $users ) ) {
72                 foreach ( $users as $user ) {
73                         remove_user_from_blog( $user->user_id, $blog_id) ;
74                 }
75         }
76
77         update_blog_status( $blog_id, 'deleted', 1 );
78
79         if ( $drop ) {
80                 if ( substr( $blog_prefix, -1 ) == '_' )
81                         $blog_prefix =  substr( $blog_prefix, 0, -1 ) . '\_';
82
83                 $drop_tables = $wpdb->get_results( "SHOW TABLES LIKE '{$blog_prefix}%'", ARRAY_A );
84                 $drop_tables = apply_filters( 'wpmu_drop_tables', $drop_tables );
85
86                 reset( $drop_tables );
87                 foreach ( (array) $drop_tables as $drop_table) {
88                         $wpdb->query( "DROP TABLE IF EXISTS ". current( $drop_table ) ."" );
89                 }
90                 $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->blogs WHERE blog_id = %d", $blog_id ) );
91                 $dir = apply_filters( 'wpmu_delete_blog_upload_dir', WP_CONTENT_DIR . "/blogs.dir/{$blog_id}/files/", $blog_id );
92                 $dir = rtrim( $dir, DIRECTORY_SEPARATOR );
93                 $top_dir = $dir;
94                 $stack = array($dir);
95                 $index = 0;
96
97                 while ( $index < count( $stack ) ) {
98                         # Get indexed directory from stack
99                         $dir = $stack[$index];
100
101                         $dh = @opendir( $dir );
102                         if ( $dh ) {
103                                 while ( ( $file = @readdir( $dh ) ) !== false ) {
104                                         if ( $file == '.' || $file == '..' )
105                                                 continue;
106
107                                         if ( @is_dir( $dir . DIRECTORY_SEPARATOR . $file ) )
108                                                 $stack[] = $dir . DIRECTORY_SEPARATOR . $file;
109                                         else if ( @is_file( $dir . DIRECTORY_SEPARATOR . $file ) )
110                                                 @unlink( $dir . DIRECTORY_SEPARATOR . $file );
111                                 }
112                         }
113                         $index++;
114                 }
115
116                 $stack = array_reverse( $stack );  // Last added dirs are deepest
117                 foreach( (array) $stack as $dir ) {
118                         if ( $dir != $top_dir)
119                         @rmdir( $dir );
120                 }
121         }
122
123         $wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key = '{$blog_prefix}autosave_draft_ids'" );
124         $blogs = get_site_option( 'blog_list' );
125         if ( is_array( $blogs ) ) {
126                 foreach ( $blogs as $n => $blog ) {
127                         if ( $blog['blog_id'] == $blog_id )
128                                 unset( $blogs[$n] );
129                 }
130                 update_site_option( 'blog_list', $blogs );
131         }
132
133         if ( $switch === true )
134                 restore_current_blog();
135 }
136
137 // @todo Merge with wp_delete_user() ?
138 function wpmu_delete_user( $id ) {
139         global $wpdb;
140
141         $id = (int) $id;
142
143         do_action( 'wpmu_delete_user', $id );
144
145         $blogs = get_blogs_of_user( $id );
146
147         if ( ! empty( $blogs ) ) {
148                 foreach ( $blogs as $blog ) {
149                         switch_to_blog( $blog->userblog_id );
150                         remove_user_from_blog( $id, $blog->userblog_id );
151
152                         $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $id ) );
153                         foreach ( (array) $post_ids as $post_id ) {
154                                 wp_delete_post( $post_id );
155                         }
156
157                         // Clean links
158                         $link_ids = $wpdb->get_col( $wpdb->prepare( "SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $id ) );
159
160                         if ( $link_ids ) {
161                                 foreach ( $link_ids as $link_id )
162                                         wp_delete_link( $link_id );
163                         }
164
165                         restore_current_blog();
166                 }
167         }
168
169         $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->users WHERE ID = %d", $id ) );
170         $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->usermeta WHERE user_id = %d", $id ) );
171
172         clean_user_cache( $id );
173
174         // allow for commit transaction
175         do_action( 'deleted_user', $id );
176
177         return true;
178 }
179
180 function confirm_delete_users( $users ) {
181         $current_user = wp_get_current_user();
182         if ( !is_array( $users ) )
183                 return false;
184
185         screen_icon();
186         ?>
187         <h2><?php esc_html_e( 'Users' ); ?></h2>
188         <p><?php _e( 'Transfer or delete posts and links before deleting users.' ); ?></p>
189         <form action="ms-edit.php?action=dodelete" method="post">
190         <input type="hidden" name="dodelete" />
191         <?php
192         wp_nonce_field( 'ms-users-delete' );
193         $site_admins = get_super_admins();
194         $admin_out = "<option value='$current_user->ID'>$current_user->user_login</option>";
195
196         foreach ( ( $allusers = (array) $_POST['allusers'] ) as $key => $val ) {
197                 if ( $val != '' && $val != '0' ) {
198                         $delete_user = new WP_User( $val );
199
200                         if ( in_array( $delete_user->user_login, $site_admins ) )
201                                 wp_die( sprintf( __( 'Warning! User cannot be deleted. The user %s is a network admnistrator.' ), $delete_user->user_login ) );
202
203                         echo "<input type='hidden' name='user[]' value='{$val}'/>\n";
204                         $blogs = get_blogs_of_user( $val, true );
205
206                         if ( !empty( $blogs ) ) {
207                                 ?>
208                                 <br /><fieldset><p><legend><?php printf( __( "What should be done with posts and links owned by <em>%s</em>?" ), $delete_user->user_login ); ?></legend></p>
209                                 <?php
210                                 foreach ( (array) $blogs as $key => $details ) {
211                                         $blog_users = get_users_of_blog( $details->userblog_id );
212                                         if ( is_array( $blog_users ) && !empty( $blog_users ) ) {
213                                                 $user_site = "<a href='" . esc_url( get_home_url( $details->userblog_id ) ) . "'>{$details->blogname}</a>";
214                                                 $user_dropdown = "<select name='blog[$val][{$key}]'>";
215                                                 $user_list = '';
216                                                 foreach ( $blog_users as $user ) {
217                                                         if ( $user->user_id != $val && !in_array( $user->user_id, $allusers ) )
218                                                                 $user_list .= "<option value='{$user->user_id}'>{$user->user_login}</option>";
219                                                 }
220                                                 if ( '' == $user_list )
221                                                         $user_list = $admin_out;
222                                                 $user_dropdown .= $user_list;
223                                                 $user_dropdown .= "</select>\n";
224                                                 ?>
225                                                 <ul style="list-style:none;">
226                                                         <li><?php printf( __( 'Site: %s' ), $user_site ); ?></li>
227                                                         <li><label><input type="radio" id="delete_option0" name="delete[<?php echo $details->userblog_id . '][' . $delete_user->ID ?>]" value="delete" checked="checked" />
228                                                         <?php _e( 'Delete all posts and links.' ); ?></label></li>
229                                                         <li><label><input type="radio" id="delete_option1" name="delete[<?php echo $details->userblog_id . '][' . $delete_user->ID ?>]" value="reassign" />
230                                                         <?php echo __( 'Attribute all posts and links to:' ) . '</label>' . $user_dropdown; ?></li>
231                                                 </ul>
232                                                 <?php
233                                         }
234                                 }
235                                 echo "</fieldset>";
236                         }
237                 }
238         }
239         ?>
240         <p class="submit"><input type="submit" class="button-secondary delete" value="<?php esc_attr_e( 'Confirm Deletion' ); ?>" /></p>
241         </form>
242     <?php
243         return true;
244 }
245
246 function wpmu_get_blog_allowedthemes( $blog_id = 0 ) {
247         $themes = get_themes();
248
249         if ( $blog_id != 0 )
250                 switch_to_blog( $blog_id );
251
252         $blog_allowed_themes = get_option( 'allowedthemes' );
253         if ( !is_array( $blog_allowed_themes ) || empty( $blog_allowed_themes ) ) { // convert old allowed_themes to new allowedthemes
254                 $blog_allowed_themes = get_option( 'allowed_themes' );
255
256                 if ( is_array( $blog_allowed_themes ) ) {
257                         foreach( (array) $themes as $key => $theme ) {
258                                 $theme_key = esc_html( $theme['Stylesheet'] );
259                                 if ( isset( $blog_allowed_themes[$key] ) == true ) {
260                                         $blog_allowedthemes[$theme_key] = 1;
261                                 }
262                         }
263                         $blog_allowed_themes = $blog_allowedthemes;
264                         add_option( 'allowedthemes', $blog_allowed_themes );
265                         delete_option( 'allowed_themes' );
266                 }
267         }
268
269         if ( $blog_id != 0 )
270                 restore_current_blog();
271
272         return $blog_allowed_themes;
273 }
274
275 function update_option_new_admin_email( $old_value, $value ) {
276         $email = get_option( 'admin_email' );
277         if ( $value == get_option( 'admin_email' ) || !is_email( $value ) )
278                 return;
279
280         $hash = md5( $value. time() .mt_rand() );
281         $new_admin_email = array(
282                 'hash' => $hash,
283                 'newemail' => $value
284         );
285         update_option( 'adminhash', $new_admin_email );
286
287         $content = apply_filters( 'new_admin_email_content', __( "Dear user,
288
289 You recently requested to have the administration email address on
290 your site changed.
291 If this is correct, please click on the following link to change it:
292 ###ADMIN_URL###
293
294 You can safely ignore and delete this email if you do not want to
295 take this action.
296
297 This email has been sent to ###EMAIL###
298
299 Regards,
300 All at ###SITENAME###
301 ###SITEURL### "), $new_admin_email );
302
303         $content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'options.php?adminhash='.$hash ) ), $content );
304         $content = str_replace( '###EMAIL###', $value, $content );
305         $content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content );
306         $content = str_replace( '###SITEURL###', network_home_url(), $content );
307
308         wp_mail( $value, sprintf( __( '[%s] New Admin Email Address' ), get_option( 'blogname' ) ), $content );
309 }
310 add_action( 'update_option_new_admin_email', 'update_option_new_admin_email', 10, 2 );
311 add_action( 'add_option_new_admin_email', 'update_option_new_admin_email', 10, 2 );
312
313 function send_confirmation_on_profile_email() {
314         global $errors, $wpdb;
315         $current_user = wp_get_current_user();
316         if ( ! is_object($errors) )
317                 $errors = new WP_Error();
318
319         if ( $current_user->id != $_POST['user_id'] )
320                 return false;
321
322         if ( $current_user->user_email != $_POST['email'] ) {
323                 if ( !is_email( $_POST['email'] ) ) {
324                         $errors->add( 'user_email', __( "<strong>ERROR</strong>: The e-mail address isn't correct." ), array( 'form-field' => 'email' ) );
325                         return;
326                 }
327
328                 if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_email FROM {$wpdb->users} WHERE user_email=%s", $_POST['email'] ) ) ) {
329                         $errors->add( 'user_email', __( "<strong>ERROR</strong>: The e-mail address is already used." ), array( 'form-field' => 'email' ) );
330                         delete_option( $current_user->ID . '_new_email' );
331                         return;
332                 }
333
334                 $hash = md5( $_POST['email'] . time() . mt_rand() );
335                 $new_user_email = array(
336                                 'hash' => $hash,
337                                 'newemail' => $_POST['email']
338                                 );
339                 update_option( $current_user->ID . '_new_email', $new_user_email );
340
341                 $content = apply_filters( 'new_user_email_content', __( "Dear user,
342
343 You recently requested to have the email address on your account changed.
344 If this is correct, please click on the following link to change it:
345 ###ADMIN_URL###
346
347 You can safely ignore and delete this email if you do not want to
348 take this action.
349
350 This email has been sent to ###EMAIL###
351
352 Regards,
353 All at ###SITENAME###
354 ###SITEURL###" ), $new_user_email );
355
356                 $content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'profile.php?newuseremail='.$hash ) ), $content );
357                 $content = str_replace( '###EMAIL###', $_POST['email'], $content);
358                 $content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content );
359                 $content = str_replace( '###SITEURL###', network_home_url(), $content );
360
361                 wp_mail( $_POST['email'], sprintf( __( '[%s] New Email Address' ), get_option( 'blogname' ) ), $content );
362                 $_POST['email'] = $current_user->user_email;
363         }
364 }
365 add_action( 'personal_options_update', 'send_confirmation_on_profile_email' );
366
367 function new_user_email_admin_notice() {
368         if ( strpos( $_SERVER['PHP_SELF'], 'profile.php' ) && isset( $_GET['updated'] ) && $email = get_option( get_current_user_id() . '_new_email' ) )
369                 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>";
370 }
371 add_action( 'admin_notices', 'new_user_email_admin_notice' );
372
373 function get_site_allowed_themes() {
374         $themes = get_themes();
375         $allowed_themes = get_site_option( 'allowedthemes' );
376         if ( !is_array( $allowed_themes ) || empty( $allowed_themes ) ) {
377                 $allowed_themes = get_site_option( 'allowed_themes' ); // convert old allowed_themes format
378                 if ( !is_array( $allowed_themes ) ) {
379                         $allowed_themes = array();
380                 } else {
381                         foreach( (array) $themes as $key => $theme ) {
382                                 $theme_key = esc_html( $theme['Stylesheet'] );
383                                 if ( isset( $allowed_themes[ $key ] ) == true ) {
384                                         $allowedthemes[ $theme_key ] = 1;
385                                 }
386                         }
387                         $allowed_themes = $allowedthemes;
388                 }
389         }
390         return $allowed_themes;
391 }
392
393 /**
394  * Determines if there is any upload space left in the current blog's quota.
395  *
396  * @since 3.0.0
397  * @return bool True if space is available, false otherwise.
398  */
399 function is_upload_space_available() {
400         if ( get_site_option( 'upload_space_check_disabled' ) )
401                 return true;
402
403         if ( !( $space_allowed = get_upload_space_available() ) )
404                 return false;
405
406         return true;
407 }
408
409 /*
410  * @since 3.0.0
411  *
412  * @return int of upload size limit in bytes
413  */
414 function upload_size_limit_filter( $size ) {
415         $fileupload_maxk = 1024 * get_site_option( 'fileupload_maxk', 1500 );
416         return min( $size, $fileupload_maxk, get_upload_space_available() );
417 }
418 /**
419  * Determines if there is any upload space left in the current blog's quota.
420  *
421  * @return int of upload space available in bytes
422  */
423 function get_upload_space_available() {
424         $space_allowed = get_space_allowed() * 1024 * 1024;
425         if ( get_site_option( 'upload_space_check_disabled' ) )
426                 return $space_allowed;
427
428         $dir_name = trailingslashit( BLOGUPLOADDIR );
429         if ( !( is_dir( $dir_name) && is_readable( $dir_name ) ) )
430                 return $space_allowed;
431
432         $dir = dir( $dir_name );
433         $size = 0;
434
435         while ( $file = $dir->read() ) {
436                 if ( $file != '.' && $file != '..' ) {
437                         if ( is_dir( $dir_name . $file) ) {
438                                 $size += get_dirsize( $dir_name . $file );
439                         } else {
440                                 $size += filesize( $dir_name . $file );
441                         }
442                 }
443         }
444         $dir->close();
445
446         if ( ( $space_allowed - $size ) <= 0 )
447                 return 0;
448
449         return $space_allowed - $size;
450 }
451
452 /**
453  * Returns the upload quota for the current blog.
454  *
455  * @return int Quota
456  */
457 function get_space_allowed() {
458         $space_allowed = get_option( 'blog_upload_space' );
459         if ( $space_allowed == false )
460                 $space_allowed = get_site_option( 'blog_upload_space' );
461         if ( empty( $space_allowed ) || !is_numeric( $space_allowed ) )
462                 $space_allowed = 50;
463
464         return $space_allowed;
465 }
466
467 function display_space_usage() {
468         $space = get_space_allowed();
469         $used = get_dirsize( BLOGUPLOADDIR ) / 1024 / 1024;
470
471         $percentused = ( $used / $space ) * 100;
472
473         if ( $space > 1000 ) {
474                 $space = number_format( $space / 1024 );
475                 /* translators: Gigabytes */
476                 $space .= __( 'GB' );
477         } else {
478                 /* translators: Megabytes */
479                 $space .= __( 'MB' );
480         }
481         ?>
482         <strong><?php printf( __( 'Used: %1s%% of %2s' ), number_format( $percentused ), $space ); ?></strong>
483         <?php
484 }
485
486 // Display File upload quota on dashboard
487 function dashboard_quota() {
488         if ( get_site_option( 'upload_space_check_disabled' ) )
489                 return true;
490
491         $quota = get_space_allowed();
492         $used = get_dirsize( BLOGUPLOADDIR ) / 1024 / 1024;
493
494         if ( $used > $quota )
495                 $percentused = '100';
496         else
497                 $percentused = ( $used / $quota ) * 100;
498         $used_color = ( $percentused < 70 ) ? ( ( $percentused >= 40 ) ? 'waiting' : 'approved' ) : 'spam';
499         $used = round( $used, 2 );
500         $percentused = number_format( $percentused );
501
502         ?>
503         <p class="sub musub"><?php _e( 'Storage Space' ); ?></p>
504         <div class="table table_content musubtable">
505         <table>
506                 <tr class="first">
507                         <td class="first b b-posts"><?php printf( __( '<a href="%1$s" title="Manage Uploads" class="musublink">%2$sMB</a>' ), esc_url( admin_url( 'upload.php' ) ), $quota ); ?></td>
508                         <td class="t posts"><?php _e( 'Space Allowed' ); ?></td>
509                 </tr>
510         </table>
511         </div>
512         <div class="table table_discussion musubtable">
513         <table>
514                 <tr class="first">
515                         <td class="b b-comments"><?php printf( __( '<a href="%1$s" title="Manage Uploads" class="musublink">%2$sMB (%3$s%%)</a>' ), esc_url( admin_url( 'upload.php' ) ), $used, $percentused ); ?></td>
516                         <td class="last t comments <?php echo $used_color;?>"><?php _e( 'Space Used' );?></td>
517                 </tr>
518         </table>
519         </div>
520         <br class="clear" />
521         <?php
522 }
523 if ( current_user_can( 'edit_posts' ) )
524         add_action( 'activity_box_end', 'dashboard_quota' );
525
526 // Edit blog upload space setting on Edit Blog page
527 function upload_space_setting( $id ) {
528         $quota = get_blog_option( $id, 'blog_upload_space' );
529         if ( !$quota )
530                 $quota = '';
531
532         ?>
533         <tr>
534                 <th><?php _e( 'Site Upload Space Quota '); ?></th>
535                 <td><input type="text" size="3" name="option[blog_upload_space]" value="<?php echo $quota; ?>" /> <?php _e( 'MB (Leave blank for network default)' ); ?></td>
536         </tr>
537         <?php
538 }
539 add_action( 'wpmueditblogaction', 'upload_space_setting' );
540
541 function update_user_status( $id, $pref, $value, $refresh = 1 ) {
542         global $wpdb;
543
544         $wpdb->update( $wpdb->users, array( $pref => $value ), array( 'ID' => $id ) );
545
546         if ( $refresh == 1 )
547                 refresh_user_details( $id );
548
549         if ( $pref == 'spam' ) {
550                 if ( $value == 1 )
551                         do_action( 'make_spam_user', $id );
552                 else
553                         do_action( 'make_ham_user', $id );
554         }
555
556         return $value;
557 }
558
559 function refresh_user_details( $id ) {
560         $id = (int) $id;
561
562         if ( !$user = get_userdata( $id ) )
563                 return false;
564
565         clean_user_cache( $id );
566
567         return $id;
568 }
569
570 function format_code_lang( $code = '' ) {
571         $code = strtolower( substr( $code, 0, 2 ) );
572         $lang_codes = array(
573                 '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',
574                 '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',
575                 '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',
576                 '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',
577                 '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',
578                 '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',
579                 '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',
580                 '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',
581                 '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',
582                 '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',
583                 've' => 'Venda', 'vi' => 'Vietnamese', 'vo' => 'Volapük', 'cy' => 'Welsh','wa' => 'Walloon','wo' => 'Wolof', 'xh' => 'Xhosa', 'yi' => 'Yiddish', 'yo' => 'Yoruba', 'za' => 'Zhuang; Chuang', 'zu' => 'Zulu' );
584         $lang_codes = apply_filters( 'lang_codes', $lang_codes, $code );
585         return strtr( $code, $lang_codes );
586 }
587
588 function sync_category_tag_slugs( $term, $taxonomy ) {
589         if ( global_terms_enabled() && ( $taxonomy == 'category' || $taxonomy == 'post_tag' ) ) {
590                 if ( is_object( $term ) ) {
591                         $term->slug = sanitize_title( $term->name );
592                 } else {
593                         $term['slug'] = sanitize_title( $term['name'] );
594                 }
595         }
596         return $term;
597 }
598 add_filter( 'get_term', 'sync_category_tag_slugs', 10, 2 );
599
600 function redirect_user_to_blog() {
601         $c = 0;
602         if ( isset( $_GET['c'] ) )
603                 $c = (int) $_GET['c'];
604
605         if ( $c >= 5 ) {
606                 wp_die( __( "You don&#8217;t have permission to view this site. Please contact the system administrator." ) );
607         }
608         $c ++;
609
610         $blog = get_active_blog_for_user( get_current_user_id() );
611         $dashboard_blog = get_dashboard_blog();
612         if ( is_object( $blog ) ) {
613                 wp_redirect( get_admin_url( $blog->blog_id, '?c=' . $c ) ); // redirect and count to 5, "just in case"
614                 exit;
615         }
616
617         /*
618            If the user is a member of only 1 blog and the user's primary_blog isn't set to that blog,
619            then update the primary_blog record to match the user's blog
620          */
621         $blogs = get_blogs_of_user( get_current_user_id() );
622
623         if ( !empty( $blogs ) ) {
624                 foreach( $blogs as $blogid => $blog ) {
625                         if ( $blogid != $dashboard_blog->blog_id && get_user_meta( get_current_user_id() , 'primary_blog', true ) == $dashboard_blog->blog_id ) {
626                                 update_user_meta( get_current_user_id(), 'primary_blog', $blogid );
627                                 continue;
628                         }
629                 }
630                 $blog = get_blog_details( get_user_meta( get_current_user_id(), 'primary_blog', true ) );
631                         wp_redirect( get_admin_url( $blog->blog_id, '?c=' . $c ) );
632                 exit;
633         }
634         wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
635 }
636 add_action( 'admin_page_access_denied', 'redirect_user_to_blog', 99 );
637
638 function check_import_new_users( $permission ) {
639         if ( !is_super_admin() )
640                 return false;
641         return true;
642 }
643 add_filter( 'import_allow_create_users', 'check_import_new_users' );
644 // See "import_allow_fetch_attachments" and "import_attachment_size_limit" filters too.
645
646 function mu_dropdown_languages( $lang_files = array(), $current = '' ) {
647         $flag = false;
648         $output = array();
649
650         foreach ( (array) $lang_files as $val ) {
651                 $code_lang = basename( $val, '.mo' );
652
653                 if ( $code_lang == 'en_US' ) { // American English
654                         $flag = true;
655                         $ae = __( 'American English' );
656                         $output[$ae] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . $ae . '</option>';
657                 } elseif ( $code_lang == 'en_GB' ) { // British English
658                         $flag = true;
659                         $be = __( 'British English' );
660                         $output[$be] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . $be . '</option>';
661                 } else {
662                         $translated = format_code_lang( $code_lang );
663                         $output[$translated] =  '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . esc_html ( $translated ) . '</option>';
664                 }
665
666         }
667
668         if ( $flag === false ) // WordPress english
669                 $output[] = '<option value=""' . selected( $current, '', false ) . '>' . __( 'English' ) . "</option>";
670
671         // Order by name
672         uksort( $output, 'strnatcasecmp' );
673
674         $output = apply_filters( 'mu_dropdown_languages', $output, $lang_files, $current );
675         echo implode( "\n\t", $output );
676 }
677
678 /* Warn the admin if SECRET SALT information is missing from wp-config.php */
679 function secret_salt_warning() {
680         if ( !is_super_admin() )
681                 return;
682         $secret_keys = array( 'AUTH_KEY', 'SECURE_AUTH_KEY', 'LOGGED_IN_KEY', 'NONCE_KEY', 'AUTH_SALT', 'SECURE_AUTH_SALT', 'LOGGED_IN_SALT', 'NONCE_SALT' );
683         $out = '';
684         foreach( $secret_keys as $key ) {
685                 if ( ! defined( $key ) )
686                         $out .= "define( '$key', '" . esc_html( wp_generate_password( 64, true, true ) ) . "' );<br />";
687         }
688         if ( $out != '' ) {
689                 $msg  = __( 'Warning! WordPress encrypts user cookies, but you must add the following lines to <strong>wp-config.php</strong> for it to be more secure.' );
690                 $msg .= '<br/>' . __( "Before the line <code>/* That's all, stop editing! Happy blogging. */</code> please add this code:" );
691                 $msg .= "<br/><br/><code>$out</code>";
692
693                 echo "<div class='update-nag'>$msg</div>";
694         }
695 }
696 add_action( 'admin_notices', 'secret_salt_warning' );
697
698 function admin_notice_feed() {
699         global $current_screen;
700         if ( $current_screen->id != 'dashboard' )
701                 return;
702
703         if ( !empty( $_GET['feed_dismiss'] ) ) {
704                 update_user_option( get_current_user_id(), 'admin_feed_dismiss', $_GET['feed_dismiss'], true );
705                 return;
706         }
707
708         $url = get_site_option( 'admin_notice_feed' );
709         if ( empty( $url ) )
710                 return;
711
712         $rss = fetch_feed( $url );
713         if ( ! is_wp_error( $rss ) && $item = $rss->get_item() ) {
714                 $title = $item->get_title();
715                 if ( md5( $title ) == get_user_option( 'admin_feed_dismiss' ) )
716                         return;
717                 $msg = "<h3>" . esc_html( $title ) . "</h3>\n";
718                 $content = $item->get_description();
719                 $content = $content ? wp_html_excerpt( $content, 200 ) . ' &hellip; ' : '';
720                 $link = esc_url( strip_tags( $item->get_link() ) );
721                 $msg .= "<p>" . $content . "<a href='$link'>" . __( 'Read More' ) . "</a> <a href='index.php?feed_dismiss=" . md5( $title ) . "'>" . __( 'Dismiss' ) . "</a></p>";
722                 echo "<div class='updated'>$msg</div>";
723         } elseif ( is_super_admin() ) {
724                 printf( '<div class="update-nag">' . __( 'Your feed at %s is empty.' ) . '</div>', esc_html( $url ) );
725         }
726 }
727 add_action( 'admin_notices', 'admin_notice_feed' );
728
729 function site_admin_notice() {
730         global $wp_db_version;
731         if ( !is_super_admin() )
732                 return false;
733         if ( get_site_option( 'wpmu_upgrade_site' ) != $wp_db_version )
734                 echo "<div class='update-nag'>" . sprintf( __( 'Thank you for Updating! Please visit the <a href="%s">Update Network</a> page to update all your sites.' ), esc_url( admin_url( 'ms-upgrade-network.php' ) ) ) . "</div>";
735 }
736 add_action( 'admin_notices', 'site_admin_notice' );
737
738 function avoid_blog_page_permalink_collision( $data, $postarr ) {
739         if ( is_subdomain_install() )
740                 return $data;
741         if ( $data['post_type'] != 'page' )
742                 return $data;
743         if ( !isset( $data['post_name'] ) || $data['post_name'] == '' )
744                 return $data;
745         if ( !is_main_site() )
746                 return $data;
747
748         $post_name = $data['post_name'];
749         $c = 0;
750         while( $c < 10 && get_id_from_blogname( $post_name ) ) {
751                 $post_name .= mt_rand( 1, 10 );
752                 $c ++;
753         }
754         if ( $post_name != $data['post_name'] ) {
755                 $data['post_name'] = $post_name;
756         }
757         return $data;
758 }
759 add_filter( 'wp_insert_post_data', 'avoid_blog_page_permalink_collision', 10, 2 );
760
761 function choose_primary_blog() {
762         ?>
763         <table class="form-table">
764         <tr>
765         <?php /* translators: My sites label */ ?>
766                 <th scope="row"><?php _e( 'Primary Site' ); ?></th>
767                 <td>
768                 <?php
769                 $all_blogs = get_blogs_of_user( get_current_user_id() );
770                 $primary_blog = get_user_meta( get_current_user_id(), 'primary_blog', true );
771                 if ( count( $all_blogs ) > 1 ) {
772                         $found = false;
773                         ?>
774                         <select name="primary_blog">
775                                 <?php foreach( (array) $all_blogs as $blog ) {
776                                         if ( $primary_blog == $blog->userblog_id )
777                                                 $found = true;
778                                         ?><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
779                                 } ?>
780                         </select>
781                         <?php
782                         if ( !$found ) {
783                                 $blog = array_shift( $all_blogs );
784                                 update_user_meta( get_current_user_id(), 'primary_blog', $blog->userblog_id );
785                         }
786                 } elseif ( count( $all_blogs ) == 1 ) {
787                         $blog = array_shift( $all_blogs );
788                         echo $blog->domain;
789                         if ( $primary_blog != $blog->userblog_id ) // Set the primary blog again if it's out of sync with blog list.
790                                 update_user_meta( get_current_user_id(), 'primary_blog', $blog->userblog_id );
791                 } else {
792                         echo "N/A";
793                 }
794                 ?>
795                 </td>
796         </tr>
797         <?php if ( in_array( get_site_option( 'registration' ), array( 'all', 'blog' ) ) ) : ?>
798                 <tr>
799                         <th scope="row" colspan="2" class="th-full">
800                                 <a href="<?php echo apply_filters( 'wp_signup_location', network_home_url( 'wp-signup.php' ) ); ?>"><?php _e( 'Create a New Site' ); ?></a>
801                         </th>
802                 </tr>
803         <?php endif; ?>
804         </table>
805         <?php
806 }
807
808 function show_post_thumbnail_warning() {
809         if ( ! is_super_admin() )
810                 return;
811         $mu_media_buttons = get_site_option( 'mu_media_buttons', array() );
812         if ( empty($mu_media_buttons['image']) && current_theme_supports( 'post-thumbnails' ) ) {
813                 echo "<div class='update-nag'>" . sprintf( __( "Warning! The current theme supports Featured Images. You must enable image uploads on <a href='%s'>the options page</a> for it to work." ), esc_url( admin_url( 'ms-options.php' ) ) ) . "</div>";
814         }
815 }
816 add_action( 'admin_notices', 'show_post_thumbnail_warning' );
817
818 function ms_deprecated_blogs_file() {
819         if ( ! is_super_admin() )
820                 return;
821         if ( ! file_exists( WP_CONTENT_DIR . '/blogs.php' ) )
822                 return;
823         echo '<div class="update-nag">' . sprintf( __( 'The <code>%1$s</code> file is deprecated. Please remove it and update your server rewrite rules to use <code>%2$s</code> instead.' ), 'wp-content/blogs.php', 'wp-includes/ms-files.php' ) . '</div>';
824 }
825 add_action( 'admin_notices', 'ms_deprecated_blogs_file' );
826
827 /**
828  * Outputs the notice message for multisite regarding activation of plugin page.
829  *
830  * @since 3.0.0
831  * @return none
832  */
833 function _admin_notice_multisite_activate_plugins_page() {
834         $message = sprintf( __( 'The plugins page is not visible to normal users. It must be activated first. %s' ), '<a href="' . esc_url( admin_url( 'ms-options.php#menu' ) ) . '">' . __( 'Activate' ) . '</a>' );
835         echo "<div class='error'><p>$message</p></div>";
836 }
837
838 /**
839  * Grants super admin privileges.
840  *
841  * @since 3.0.0
842  * @param $user_id
843  */
844 function grant_super_admin( $user_id ) {
845         global $super_admins;
846
847         // If global super_admins override is defined, there is nothing to do here.
848         if ( isset($super_admins) )
849                 return false;
850
851         do_action( 'grant_super_admin', $user_id );
852
853         // Directly fetch site_admins instead of using get_super_admins()
854         $super_admins = get_site_option( 'site_admins', array( 'admin' ) );
855
856         $user = new WP_User( $user_id );
857         if ( ! in_array( $user->user_login, $super_admins ) ) {
858                 $super_admins[] = $user->user_login;
859                 update_site_option( 'site_admins' , $super_admins );
860                 do_action( 'granted_super_admin', $user_id );
861                 return true;
862         }
863         return false;
864 }
865
866 /**
867  * Revokes super admin privileges.
868  *
869  * @since 3.0.0
870  * @param $user_id
871  */
872 function revoke_super_admin( $user_id ) {
873         global $super_admins;
874
875         // If global super_admins override is defined, there is nothing to do here.
876         if ( isset($super_admins) )
877                 return false;
878
879         do_action( 'revoke_super_admin', $user_id );
880
881         // Directly fetch site_admins instead of using get_super_admins()
882         $super_admins = get_site_option( 'site_admins', array( 'admin' ) );
883
884         $user = new WP_User( $user_id );
885         if ( $user->user_email != get_site_option( 'admin_email' ) ) {
886                 if ( false !== ( $key = array_search( $user->user_login, $super_admins ) ) ) {
887                         unset( $super_admins[$key] );
888                         update_site_option( 'site_admins', $super_admins );
889                         do_action( 'revoked_super_admin', $user_id );
890                         return true;
891                 }
892         }
893         return false;
894 }
895 ?>