]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-admin/includes/ms.php
Wordpress 3.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_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         global $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, $current_user;
315         if ( ! is_object($errors) )
316                 $errors = new WP_Error();
317
318         if ( $current_user->id != $_POST['user_id'] )
319                 return false;
320
321         if ( $current_user->user_email != $_POST['email'] ) {
322                 if ( !is_email( $_POST['email'] ) ) {
323                         $errors->add( 'user_email', __( "<strong>ERROR</strong>: The e-mail address isn't correct." ), array( 'form-field' => 'email' ) );
324                         return;
325                 }
326
327                 if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_email FROM {$wpdb->users} WHERE user_email=%s", $_POST['email'] ) ) ) {
328                         $errors->add( 'user_email', __( "<strong>ERROR</strong>: The e-mail address is already used." ), array( 'form-field' => 'email' ) );
329                         delete_option( $current_user->ID . '_new_email' );
330                         return;
331                 }
332
333                 $hash = md5( $_POST['email'] . time() . mt_rand() );
334                 $new_user_email = array(
335                                 'hash' => $hash,
336                                 'newemail' => $_POST['email']
337                                 );
338                 update_option( $current_user->ID . '_new_email', $new_user_email );
339
340                 $content = apply_filters( 'new_user_email_content', __( "Dear user,
341
342 You recently requested to have the email address on your account changed.
343 If this is correct, please click on the following link to change it:
344 ###ADMIN_URL###
345
346 You can safely ignore and delete this email if you do not want to
347 take this action.
348
349 This email has been sent to ###EMAIL###
350
351 Regards,
352 All at ###SITENAME###
353 ###SITEURL###" ), $new_user_email );
354
355                 $content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'profile.php?newuseremail='.$hash ) ), $content );
356                 $content = str_replace( '###EMAIL###', $_POST['email'], $content);
357                 $content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content );
358                 $content = str_replace( '###SITEURL###', network_home_url(), $content );
359
360                 wp_mail( $_POST['email'], sprintf( __( '[%s] New Email Address' ), get_option( 'blogname' ) ), $content );
361                 $_POST['email'] = $current_user->user_email;
362         }
363 }
364 add_action( 'personal_options_update', 'send_confirmation_on_profile_email' );
365
366 function new_user_email_admin_notice() {
367         global $current_user;
368         if ( strpos( $_SERVER['PHP_SELF'], 'profile.php' ) && isset( $_GET['updated'] ) && $email = get_option( $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         global $current_user;
602         $c = 0;
603         if ( isset( $_GET['c'] ) )
604                 $c = (int) $_GET['c'];
605
606         if ( $c >= 5 ) {
607                 wp_die( __( "You don&#8217;t have permission to view this site. Please contact the system administrator." ) );
608         }
609         $c ++;
610
611         $blog = get_active_blog_for_user( $current_user->ID );
612         $dashboard_blog = get_dashboard_blog();
613         if ( is_object( $blog ) ) {
614                 wp_redirect( get_admin_url( $blog->blog_id, '?c=' . $c ) ); // redirect and count to 5, "just in case"
615                 exit;
616         }
617
618         /*
619            If the user is a member of only 1 blog and the user's primary_blog isn't set to that blog,
620            then update the primary_blog record to match the user's blog
621          */
622         $blogs = get_blogs_of_user( $current_user->ID );
623
624         if ( !empty( $blogs ) ) {
625                 foreach( $blogs as $blogid => $blog ) {
626                         if ( $blogid != $dashboard_blog->blog_id && get_user_meta( $current_user->ID , 'primary_blog', true ) == $dashboard_blog->blog_id ) {
627                                 update_user_meta( $current_user->ID, 'primary_blog', $blogid );
628                                 continue;
629                         }
630                 }
631                 $blog = get_blog_details( get_user_meta( $current_user->ID, 'primary_blog', true ) );
632                         wp_redirect( get_admin_url( $blog->blog_id, '?c=' . $c ) );
633                 exit;
634         }
635         wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
636 }
637 add_action( 'admin_page_access_denied', 'redirect_user_to_blog', 99 );
638
639 function check_import_new_users( $permission ) {
640         if ( !is_super_admin() )
641                 return false;
642         return true;
643 }
644 add_filter( 'import_allow_create_users', 'check_import_new_users' );
645 // See "import_allow_fetch_attachments" and "import_attachment_size_limit" filters too.
646
647 function mu_dropdown_languages( $lang_files = array(), $current = '' ) {
648         $flag = false;
649         $output = array();
650
651         foreach ( (array) $lang_files as $val ) {
652                 $code_lang = basename( $val, '.mo' );
653
654                 if ( $code_lang == 'en_US' ) { // American English
655                         $flag = true;
656                         $ae = __( 'American English' );
657                         $output[$ae] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang ) . '> ' . $ae . '</option>';
658                 } elseif ( $code_lang == 'en_GB' ) { // British English
659                         $flag = true;
660                         $be = __( 'British English' );
661                         $output[$be] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang ) . '> ' . $be . '</option>';
662                 } else {
663                         $translated = format_code_lang( $code_lang );
664                         $output[$translated] =  '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang ) . '> ' . esc_html ( $translated ) . '</option>';
665                 }
666
667         }
668
669         if ( $flag === false ) // WordPress english
670                 $output[] = '<option value=""' . selected( $current, '' ) . '>' . __( 'English' ) . "</option>";
671
672         // Order by name
673         uksort( $output, 'strnatcasecmp' );
674
675         $output = apply_filters( 'mu_dropdown_languages', $output, $lang_files, $current );
676         echo implode( "\n\t", $output );
677 }
678
679 /* Warn the admin if SECRET SALT information is missing from wp-config.php */
680 function secret_salt_warning() {
681         if ( !is_super_admin() )
682                 return;
683         $secret_keys = array( 'AUTH_KEY', 'SECURE_AUTH_KEY', 'LOGGED_IN_KEY', 'NONCE_KEY', 'AUTH_SALT', 'SECURE_AUTH_SALT', 'LOGGED_IN_SALT', 'NONCE_SALT' );
684         $out = '';
685         foreach( $secret_keys as $key ) {
686                 if ( ! defined( $key ) )
687                         $out .= "define( '$key', '" . esc_html( wp_generate_password( 64, true, true ) ) . "' );<br />";
688         }
689         if ( $out != '' ) {
690                 $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.' );
691                 $msg .= '<br/>' . __( "Before the line <code>/* That's all, stop editing! Happy blogging. */</code> please add this code:" );
692                 $msg .= "<br/><br/><code>$out</code>";
693
694                 echo "<div class='update-nag'>$msg</div>";
695         }
696 }
697 add_action( 'admin_notices', 'secret_salt_warning' );
698
699 function admin_notice_feed() {
700         global $current_user, $current_screen;
701         if ( $current_screen->id != 'dashboard' )
702                 return;
703
704         if ( !empty( $_GET['feed_dismiss'] ) ) {
705                 update_user_option( $current_user->id, 'admin_feed_dismiss', $_GET['feed_dismiss'], true );
706                 return;
707         }
708
709         $url = get_site_option( 'admin_notice_feed' );
710         if ( empty( $url ) )
711                 return;
712
713         $rss = fetch_feed( $url );
714         if ( ! is_wp_error( $rss ) && $item = $rss->get_item() ) {
715                 $title = $item->get_title();
716                 if ( md5( $title ) == get_user_option( 'admin_feed_dismiss' ) )
717                         return;
718                 $msg = "<h3>" . esc_html( $title ) . "</h3>\n";
719                 $content = $item->get_description();
720                 $content = $content ? wp_html_excerpt( $content, 200 ) . ' &hellip; ' : '';
721                 $link = esc_url( strip_tags( $item->get_link() ) );
722                 $msg .= "<p>" . $content . "<a href='$link'>" . __( 'Read More' ) . "</a> <a href='index.php?feed_dismiss=" . md5( $title ) . "'>" . __( 'Dismiss' ) . "</a></p>";
723                 echo "<div class='updated'>$msg</div>";
724         } elseif ( is_super_admin() ) {
725                 printf( '<div class="update-nag">' . __( 'Your feed at %s is empty.' ) . '</div>', esc_html( $url ) );
726         }
727 }
728 add_action( 'admin_notices', 'admin_notice_feed' );
729
730 function site_admin_notice() {
731         global $current_user, $wp_db_version;
732         if ( !is_super_admin() )
733                 return false;
734         if ( get_site_option( 'wpmu_upgrade_site' ) != $wp_db_version )
735                 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>";
736 }
737 add_action( 'admin_notices', 'site_admin_notice' );
738
739 function avoid_blog_page_permalink_collision( $data, $postarr ) {
740         if ( is_subdomain_install() )
741                 return $data;
742         if ( $data['post_type'] != 'page' )
743                 return $data;
744         if ( !isset( $data['post_name'] ) || $data['post_name'] == '' )
745                 return $data;
746         if ( !is_main_site() )
747                 return $data;
748
749         $post_name = $data['post_name'];
750         $c = 0;
751         while( $c < 10 && get_id_from_blogname( $post_name ) ) {
752                 $post_name .= mt_rand( 1, 10 );
753                 $c ++;
754         }
755         if ( $post_name != $data['post_name'] ) {
756                 $data['post_name'] = $post_name;
757         }
758         return $data;
759 }
760 add_filter( 'wp_insert_post_data', 'avoid_blog_page_permalink_collision', 10, 2 );
761
762 function choose_primary_blog() {
763         global $current_user;
764         ?>
765         <table class="form-table">
766         <tr>
767         <?php /* translators: My sites label */ ?>
768                 <th scope="row"><?php _e( 'Primary Site' ); ?></th>
769                 <td>
770                 <?php
771                 $all_blogs = get_blogs_of_user( $current_user->ID );
772                 $primary_blog = get_user_meta( $current_user->ID, 'primary_blog', true );
773                 if ( count( $all_blogs ) > 1 ) {
774                         $found = false;
775                         ?>
776                         <select name="primary_blog">
777                                 <?php foreach( (array) $all_blogs as $blog ) {
778                                         if ( $primary_blog == $blog->userblog_id )
779                                                 $found = true;
780                                         ?><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
781                                 } ?>
782                         </select>
783                         <?php
784                         if ( !$found ) {
785                                 $blog = array_shift( $all_blogs );
786                                 update_user_meta( $current_user->ID, 'primary_blog', $blog->userblog_id );
787                         }
788                 } elseif ( count( $all_blogs ) == 1 ) {
789                         $blog = array_shift( $all_blogs );
790                         echo $blog->domain;
791                         if ( $primary_blog != $blog->userblog_id ) // Set the primary blog again if it's out of sync with blog list.
792                                 update_user_meta( $current_user->ID, 'primary_blog', $blog->userblog_id );
793                 } else {
794                         echo "N/A";
795                 }
796                 ?>
797                 </td>
798         </tr>
799         <?php if ( in_array( get_site_option( 'registration' ), array( 'all', 'blog' ) ) ) : ?>
800                 <tr>
801                         <th scope="row" colspan="2" class="th-full">
802                                 <a href="<?php echo apply_filters( 'wp_signup_location', network_home_url( 'wp-signup.php' ) ); ?>"><?php _e( 'Create a New Site' ); ?></a>
803                         </th>
804                 </tr>
805         <?php endif; ?>
806         </table>
807         <?php
808 }
809
810 function show_post_thumbnail_warning() {
811         if ( ! is_super_admin() )
812                 return;
813         $mu_media_buttons = get_site_option( 'mu_media_buttons', array() );
814         if ( empty($mu_media_buttons['image']) && current_theme_supports( 'post-thumbnails' ) ) {
815                 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>";
816         }
817 }
818 add_action( 'admin_notices', 'show_post_thumbnail_warning' );
819
820 function ms_deprecated_blogs_file() {
821         if ( ! is_super_admin() )
822                 return;
823         if ( ! file_exists( WP_CONTENT_DIR . '/blogs.php' ) )
824                 return;
825         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>';
826 }
827 add_action( 'admin_notices', 'ms_deprecated_blogs_file' );
828
829 /**
830  * Outputs the notice message for multisite regarding activation of plugin page.
831  *
832  * @since 3.0.0
833  * @return none
834  */
835 function _admin_notice_multisite_activate_plugins_page() {
836         $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>' );
837         echo "<div class='error'><p>$message</p></div>";
838 }
839
840 /**
841  * Grants super admin privileges.
842  *
843  * @since 3.0.0
844  * @param $user_id
845  */
846 function grant_super_admin( $user_id ) {
847         global $super_admins;
848
849         // If global super_admins override is defined, there is nothing to do here.
850         if ( isset($super_admins) )
851                 return false;
852
853         do_action( 'grant_super_admin', $user_id );
854
855         // Directly fetch site_admins instead of using get_super_admins()
856         $super_admins = get_site_option( 'site_admins', array( 'admin' ) );
857
858         $user = new WP_User( $user_id );
859         if ( ! in_array( $user->user_login, $super_admins ) ) {
860                 $super_admins[] = $user->user_login;
861                 update_site_option( 'site_admins' , $super_admins );
862                 do_action( 'granted_super_admin', $user_id );
863                 return true;
864         }
865         return false;
866 }
867
868 /**
869  * Revokes super admin privileges.
870  *
871  * @since 3.0.0
872  * @param $user_id
873  */
874 function revoke_super_admin( $user_id ) {
875         global $super_admins;
876
877         // If global super_admins override is defined, there is nothing to do here.
878         if ( isset($super_admins) )
879                 return false;
880
881         do_action( 'revoke_super_admin', $user_id );
882
883         // Directly fetch site_admins instead of using get_super_admins()
884         $super_admins = get_site_option( 'site_admins', array( 'admin' ) );
885
886         $user = new WP_User( $user_id );
887         if ( $user->user_email != get_site_option( 'admin_email' ) ) {
888                 if ( false !== ( $key = array_search( $user->user_login, $super_admins ) ) ) {
889                         unset( $super_admins[$key] );
890                         update_site_option( 'site_admins', $super_admins );
891                         do_action( 'revoked_super_admin', $user_id );
892                         return true;
893                 }
894         }
895         return false;
896 }
897 ?>