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