~canonical-sysadmins/wordpress/4.7.2

« back to all changes in this revision

Viewing changes to wp-admin/includes/ms.php

  • Committer: Jacek Nykis
  • Date: 2015-01-05 16:17:05 UTC
  • Revision ID: jacek.nykis@canonical.com-20150105161705-w544l1h5mcg7u4w9
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * Multisite administration functions.
 
4
 *
 
5
 * @package WordPress
 
6
 * @subpackage Multisite
 
7
 * @since 3.0.0
 
8
 */
 
9
 
 
10
/**
 
11
 * Determine if uploaded file exceeds space quota.
 
12
 *
 
13
 * @since 3.0.0
 
14
 *
 
15
 * @param array $file $_FILES array for a given file.
 
16
 * @return array $_FILES array with 'error' key set if file exceeds quota. 'error' is empty otherwise.
 
17
 */
 
18
function check_upload_size( $file ) {
 
19
        if ( get_site_option( 'upload_space_check_disabled' ) )
 
20
                return $file;
 
21
 
 
22
        if ( $file['error'] != '0' ) // there's already an error
 
23
                return $file;
 
24
 
 
25
        if ( defined( 'WP_IMPORTING' ) )
 
26
                return $file;
 
27
 
 
28
        $space_left = get_upload_space_available();
 
29
 
 
30
        $file_size = filesize( $file['tmp_name'] );
 
31
        if ( $space_left < $file_size )
 
32
                $file['error'] = sprintf( __( 'Not enough space to upload. %1$s KB needed.' ), number_format( ($file_size - $space_left) /1024 ) );
 
33
        if ( $file_size > ( 1024 * get_site_option( 'fileupload_maxk', 1500 ) ) )
 
34
                $file['error'] = sprintf(__('This file is too big. Files must be less than %1$s KB in size.'), get_site_option( 'fileupload_maxk', 1500 ) );
 
35
        if ( upload_is_user_over_quota( false ) ) {
 
36
                $file['error'] = __( 'You have used your space quota. Please delete files before uploading.' );
 
37
        }
 
38
        if ( $file['error'] != '0' && !isset($_POST['html-upload']) )
 
39
                wp_die( $file['error'] . ' <a href="javascript:history.go(-1)">' . __( 'Back' ) . '</a>' );
 
40
 
 
41
        return $file;
 
42
}
 
43
add_filter( 'wp_handle_upload_prefilter', 'check_upload_size' );
 
44
 
 
45
/**
 
46
 * Delete a blog
 
47
 *
 
48
 * @since 3.0.0
 
49
 *
 
50
 * @param int $blog_id Blog ID
 
51
 * @param bool $drop True if blog's table should be dropped. Default is false.
 
52
 * @return void
 
53
 */
 
54
function wpmu_delete_blog( $blog_id, $drop = false ) {
 
55
        global $wpdb;
 
56
 
 
57
        $switch = false;
 
58
        if ( get_current_blog_id() != $blog_id ) {
 
59
                $switch = true;
 
60
                switch_to_blog( $blog_id );
 
61
        }
 
62
 
 
63
        $blog = get_blog_details( $blog_id );
 
64
        /**
 
65
         * Fires before a blog is deleted.
 
66
         *
 
67
         * @since MU
 
68
         *
 
69
         * @param int  $blog_id The blog ID.
 
70
         * @param bool $drop    True if blog's table should be dropped. Default is false.
 
71
         */
 
72
        do_action( 'delete_blog', $blog_id, $drop );
 
73
 
 
74
        $users = get_users( array( 'blog_id' => $blog_id, 'fields' => 'ids' ) );
 
75
 
 
76
        // Remove users from this blog.
 
77
        if ( ! empty( $users ) ) {
 
78
                foreach ( $users as $user_id ) {
 
79
                        remove_user_from_blog( $user_id, $blog_id );
 
80
                }
 
81
        }
 
82
 
 
83
        update_blog_status( $blog_id, 'deleted', 1 );
 
84
 
 
85
        $current_site = get_current_site();
 
86
 
 
87
        // Don't destroy the initial, main, or root blog.
 
88
        if ( $drop && ( 1 == $blog_id || is_main_site( $blog_id ) || ( $blog->path == $current_site->path && $blog->domain == $current_site->domain ) ) )
 
89
                $drop = false;
 
90
 
 
91
        if ( $drop ) {
 
92
                $tables = $wpdb->tables( 'blog' );
 
93
                /**
 
94
                 * Filter the tables to drop when the blog is deleted.
 
95
                 *
 
96
                 * @since MU
 
97
                 *
 
98
                 * @param array $tables  The blog tables to be dropped.
 
99
                 * @param int   $blog_id The ID of the blog to drop tables for.
 
100
                 */
 
101
                $drop_tables = apply_filters( 'wpmu_drop_tables', $tables, $blog_id );
 
102
 
 
103
                foreach ( (array) $drop_tables as $table ) {
 
104
                        $wpdb->query( "DROP TABLE IF EXISTS `$table`" );
 
105
                }
 
106
 
 
107
                $wpdb->delete( $wpdb->blogs, array( 'blog_id' => $blog_id ) );
 
108
 
 
109
                $uploads = wp_upload_dir();
 
110
                /**
 
111
                 * Filter the upload base directory to delete when the blog is deleted.
 
112
                 *
 
113
                 * @since MU
 
114
                 *
 
115
                 * @param string $uploads['basedir'] Uploads path without subdirectory. @see wp_upload_dir()
 
116
                 * @param int    $blog_id            The blog ID.
 
117
                 */
 
118
                $dir = apply_filters( 'wpmu_delete_blog_upload_dir', $uploads['basedir'], $blog_id );
 
119
                $dir = rtrim( $dir, DIRECTORY_SEPARATOR );
 
120
                $top_dir = $dir;
 
121
                $stack = array($dir);
 
122
                $index = 0;
 
123
 
 
124
                while ( $index < count( $stack ) ) {
 
125
                        # Get indexed directory from stack
 
126
                        $dir = $stack[$index];
 
127
 
 
128
                        $dh = @opendir( $dir );
 
129
                        if ( $dh ) {
 
130
                                while ( ( $file = @readdir( $dh ) ) !== false ) {
 
131
                                        if ( $file == '.' || $file == '..' )
 
132
                                                continue;
 
133
 
 
134
                                        if ( @is_dir( $dir . DIRECTORY_SEPARATOR . $file ) )
 
135
                                                $stack[] = $dir . DIRECTORY_SEPARATOR . $file;
 
136
                                        else if ( @is_file( $dir . DIRECTORY_SEPARATOR . $file ) )
 
137
                                                @unlink( $dir . DIRECTORY_SEPARATOR . $file );
 
138
                                }
 
139
                                @closedir( $dh );
 
140
                        }
 
141
                        $index++;
 
142
                }
 
143
 
 
144
                $stack = array_reverse( $stack ); // Last added dirs are deepest
 
145
                foreach( (array) $stack as $dir ) {
 
146
                        if ( $dir != $top_dir)
 
147
                        @rmdir( $dir );
 
148
                }
 
149
 
 
150
                clean_blog_cache( $blog );
 
151
        }
 
152
 
 
153
        if ( $switch )
 
154
                restore_current_blog();
 
155
}
 
156
 
 
157
// @todo Merge with wp_delete_user() ?
 
158
function wpmu_delete_user( $id ) {
 
159
        global $wpdb;
 
160
 
 
161
        $id = (int) $id;
 
162
        $user = new WP_User( $id );
 
163
 
 
164
        if ( !$user->exists() )
 
165
                return false;
 
166
        /**
 
167
         * Fires before a user is deleted from the network.
 
168
         *
 
169
         * @since MU
 
170
         *
 
171
         * @param int $id ID of the user about to be deleted from the network.
 
172
         */
 
173
        do_action( 'wpmu_delete_user', $id );
 
174
 
 
175
        $blogs = get_blogs_of_user( $id );
 
176
 
 
177
        if ( ! empty( $blogs ) ) {
 
178
                foreach ( $blogs as $blog ) {
 
179
                        switch_to_blog( $blog->userblog_id );
 
180
                        remove_user_from_blog( $id, $blog->userblog_id );
 
181
 
 
182
                        $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $id ) );
 
183
                        foreach ( (array) $post_ids as $post_id ) {
 
184
                                wp_delete_post( $post_id );
 
185
                        }
 
186
 
 
187
                        // Clean links
 
188
                        $link_ids = $wpdb->get_col( $wpdb->prepare( "SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $id ) );
 
189
 
 
190
                        if ( $link_ids ) {
 
191
                                foreach ( $link_ids as $link_id )
 
192
                                        wp_delete_link( $link_id );
 
193
                        }
 
194
 
 
195
                        restore_current_blog();
 
196
                }
 
197
        }
 
198
 
 
199
        $meta = $wpdb->get_col( $wpdb->prepare( "SELECT umeta_id FROM $wpdb->usermeta WHERE user_id = %d", $id ) );
 
200
        foreach ( $meta as $mid )
 
201
                delete_metadata_by_mid( 'user', $mid );
 
202
 
 
203
        $wpdb->delete( $wpdb->users, array( 'ID' => $id ) );
 
204
 
 
205
        clean_user_cache( $user );
 
206
 
 
207
        /** This action is documented in wp-admin/includes/user.php */
 
208
        do_action( 'deleted_user', $id );
 
209
 
 
210
        return true;
 
211
}
 
212
 
 
213
function update_option_new_admin_email( $old_value, $value ) {
 
214
        if ( $value == get_option( 'admin_email' ) || !is_email( $value ) )
 
215
                return;
 
216
 
 
217
        $hash = md5( $value. time() .mt_rand() );
 
218
        $new_admin_email = array(
 
219
                'hash' => $hash,
 
220
                'newemail' => $value
 
221
        );
 
222
        update_option( 'adminhash', $new_admin_email );
 
223
 
 
224
        $email_text = __( 'Dear user,
 
225
 
 
226
You recently requested to have the administration email address on
 
227
your site changed.
 
228
If this is correct, please click on the following link to change it:
 
229
###ADMIN_URL###
 
230
 
 
231
You can safely ignore and delete this email if you do not want to
 
232
take this action.
 
233
 
 
234
This email has been sent to ###EMAIL###
 
235
 
 
236
Regards,
 
237
All at ###SITENAME###
 
238
###SITEURL###' );
 
239
 
 
240
        /**
 
241
         * Filter the email text sent when the site admin email is changed.
 
242
         *
 
243
         * The following strings have a special meaning and will get replaced dynamically:
 
244
         * ###ADMIN_URL### The link to click on to confirm the email change. Required otherwise this functunalty is will break.
 
245
         * ###EMAIL###     The new email.
 
246
         * ###SITENAME###  The name of the site.
 
247
         * ###SITEURL###   The URL to the site.
 
248
         *
 
249
         * @since MU
 
250
         *
 
251
         * @param string $email_text      Text in the email.
 
252
         * @param string $new_admin_email New admin email that the current administration email was changed to.
 
253
         */
 
254
        $content = apply_filters( 'new_admin_email_content', $email_text, $new_admin_email );
 
255
 
 
256
        $content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'options.php?adminhash='.$hash ) ), $content );
 
257
        $content = str_replace( '###EMAIL###', $value, $content );
 
258
        $content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content );
 
259
        $content = str_replace( '###SITEURL###', network_home_url(), $content );
 
260
 
 
261
        wp_mail( $value, sprintf( __( '[%s] New Admin Email Address' ), wp_specialchars_decode( get_option( 'blogname' ) ) ), $content );
 
262
}
 
263
add_action( 'update_option_new_admin_email', 'update_option_new_admin_email', 10, 2 );
 
264
add_action( 'add_option_new_admin_email', 'update_option_new_admin_email', 10, 2 );
 
265
 
 
266
function send_confirmation_on_profile_email() {
 
267
        global $errors, $wpdb;
 
268
        $current_user = wp_get_current_user();
 
269
        if ( ! is_object($errors) )
 
270
                $errors = new WP_Error();
 
271
 
 
272
        if ( $current_user->ID != $_POST['user_id'] )
 
273
                return false;
 
274
 
 
275
        if ( $current_user->user_email != $_POST['email'] ) {
 
276
                if ( !is_email( $_POST['email'] ) ) {
 
277
                        $errors->add( 'user_email', __( "<strong>ERROR</strong>: The email address isn&#8217;t correct." ), array( 'form-field' => 'email' ) );
 
278
                        return;
 
279
                }
 
280
 
 
281
                if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_email FROM {$wpdb->users} WHERE user_email=%s", $_POST['email'] ) ) ) {
 
282
                        $errors->add( 'user_email', __( "<strong>ERROR</strong>: The email address is already used." ), array( 'form-field' => 'email' ) );
 
283
                        delete_option( $current_user->ID . '_new_email' );
 
284
                        return;
 
285
                }
 
286
 
 
287
                $hash = md5( $_POST['email'] . time() . mt_rand() );
 
288
                $new_user_email = array(
 
289
                                'hash' => $hash,
 
290
                                'newemail' => $_POST['email']
 
291
                                );
 
292
                update_option( $current_user->ID . '_new_email', $new_user_email );
 
293
 
 
294
                $email_text = __( 'Dear user,
 
295
 
 
296
You recently requested to have the email address on your account changed.
 
297
If this is correct, please click on the following link to change it:
 
298
###ADMIN_URL###
 
299
 
 
300
You can safely ignore and delete this email if you do not want to
 
301
take this action.
 
302
 
 
303
This email has been sent to ###EMAIL###
 
304
 
 
305
Regards,
 
306
All at ###SITENAME###
 
307
###SITEURL###' );
 
308
 
 
309
                /**
 
310
                 * Filter the email text sent when a user changes emails.
 
311
                 *
 
312
                 * The following strings have a special meaning and will get replaced dynamically:
 
313
                 * ###ADMIN_URL### The link to click on to confirm the email change. Required otherwise this functunalty is will break.
 
314
                 * ###EMAIL### The new email.
 
315
                 * ###SITENAME### The name of the site.
 
316
                 * ###SITEURL### The URL to the site.
 
317
                 *
 
318
                 * @since MU
 
319
                 *
 
320
                 * @param string $email_text     Text in the email.
 
321
                 * @param string $new_user_email New user email that the current user has changed to.
 
322
                 */
 
323
                $content = apply_filters( 'new_user_email_content', $email_text, $new_user_email );
 
324
 
 
325
                $content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'profile.php?newuseremail='.$hash ) ), $content );
 
326
                $content = str_replace( '###EMAIL###', $_POST['email'], $content);
 
327
                $content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content );
 
328
                $content = str_replace( '###SITEURL###', network_home_url(), $content );
 
329
 
 
330
                wp_mail( $_POST['email'], sprintf( __( '[%s] New Email Address' ), wp_specialchars_decode( get_option( 'blogname' ) ) ), $content );
 
331
                $_POST['email'] = $current_user->user_email;
 
332
        }
 
333
}
 
334
add_action( 'personal_options_update', 'send_confirmation_on_profile_email' );
 
335
 
 
336
function new_user_email_admin_notice() {
 
337
        if ( strpos( $_SERVER['PHP_SELF'], 'profile.php' ) && isset( $_GET['updated'] ) && $email = get_option( get_current_user_id() . '_new_email' ) )
 
338
                echo "<div class='update-nag'>" . sprintf( __( "Your email address has not been updated yet. Please check your inbox at %s for a confirmation email." ), $email['newemail'] ) . "</div>";
 
339
}
 
340
add_action( 'admin_notices', 'new_user_email_admin_notice' );
 
341
 
 
342
/**
 
343
 * Check whether a blog has used its allotted upload space.
 
344
 *
 
345
 * @since MU
 
346
 *
 
347
 * @param bool $echo Optional. If $echo is set and the quota is exceeded, a warning message is echoed. Default is true.
 
348
 * @return int
 
349
 */
 
350
function upload_is_user_over_quota( $echo = true ) {
 
351
        if ( get_site_option( 'upload_space_check_disabled' ) )
 
352
                return false;
 
353
 
 
354
        $space_allowed = get_space_allowed();
 
355
        if ( empty( $space_allowed ) || !is_numeric( $space_allowed ) )
 
356
                $space_allowed = 10; // Default space allowed is 10 MB
 
357
 
 
358
        $space_used = get_space_used();
 
359
 
 
360
        if ( ( $space_allowed - $space_used ) < 0 ) {
 
361
                if ( $echo )
 
362
                        _e( 'Sorry, you have used your space allocation. Please delete some files to upload more files.' );
 
363
                return true;
 
364
        } else {
 
365
                return false;
 
366
        }
 
367
}
 
368
 
 
369
/**
 
370
 * Displays the amount of disk space used by the current blog. Not used in core.
 
371
 *
 
372
 * @since MU
 
373
 */
 
374
function display_space_usage() {
 
375
        $space_allowed = get_space_allowed();
 
376
        $space_used = get_space_used();
 
377
 
 
378
        $percent_used = ( $space_used / $space_allowed ) * 100;
 
379
 
 
380
        if ( $space_allowed > 1000 ) {
 
381
                $space = number_format( $space_allowed / 1024 );
 
382
                /* translators: Gigabytes */
 
383
                $space .= __( 'GB' );
 
384
        } else {
 
385
                $space = number_format( $space_allowed );
 
386
                /* translators: Megabytes */
 
387
                $space .= __( 'MB' );
 
388
        }
 
389
        ?>
 
390
        <strong><?php printf( __( 'Used: %1$s%% of %2$s' ), number_format( $percent_used ), $space ); ?></strong>
 
391
        <?php
 
392
}
 
393
 
 
394
/**
 
395
 * Get the remaining upload space for this blog.
 
396
 *
 
397
 * @since MU
 
398
 * @uses upload_is_user_over_quota()
 
399
 * @uses get_space_allowed()
 
400
 * @uses get_upload_space_available()
 
401
 *
 
402
 * @param int $size Current max size in bytes
 
403
 * @return int Max size in bytes
 
404
 */
 
405
function fix_import_form_size( $size ) {
 
406
        if ( upload_is_user_over_quota( false ) == true )
 
407
                return 0;
 
408
 
 
409
        $available = get_upload_space_available();
 
410
        return min( $size, $available );
 
411
}
 
412
 
 
413
// Edit blog upload space setting on Edit Blog page
 
414
function upload_space_setting( $id ) {
 
415
        switch_to_blog( $id );
 
416
        $quota = get_option( 'blog_upload_space' );
 
417
        restore_current_blog();
 
418
 
 
419
        if ( !$quota )
 
420
                $quota = '';
 
421
 
 
422
        ?>
 
423
        <tr>
 
424
                <th><?php _e( 'Site Upload Space Quota '); ?></th>
 
425
                <td><input type="number" step="1" min="0" style="width: 100px" name="option[blog_upload_space]" value="<?php echo $quota; ?>" /> <?php _e( 'MB (Leave blank for network default)' ); ?></td>
 
426
        </tr>
 
427
        <?php
 
428
}
 
429
add_action( 'wpmueditblogaction', 'upload_space_setting' );
 
430
 
 
431
function update_user_status( $id, $pref, $value, $deprecated = null ) {
 
432
        global $wpdb;
 
433
 
 
434
        if ( null !== $deprecated )
 
435
                _deprecated_argument( __FUNCTION__, '3.1' );
 
436
 
 
437
        $wpdb->update( $wpdb->users, array( sanitize_key( $pref ) => $value ), array( 'ID' => $id ) );
 
438
 
 
439
        $user = new WP_User( $id );
 
440
        clean_user_cache( $user );
 
441
 
 
442
        if ( $pref == 'spam' ) {
 
443
                if ( $value == 1 ) {
 
444
                        /**
 
445
                         * Fires after the user is marked as a SPAM user.
 
446
                         *
 
447
                         * @since 3.0.0
 
448
                         *
 
449
                         * @param int $id ID of the user marked as SPAM.
 
450
                         */
 
451
                        do_action( 'make_spam_user', $id );
 
452
                } else {
 
453
                        /**
 
454
                         * Fires after the user is marked as a HAM user. Opposite of SPAM.
 
455
                         *
 
456
                         * @since 3.0.0
 
457
                         *
 
458
                         * @param int $id ID of the user marked as HAM.
 
459
                         */
 
460
                        do_action( 'make_ham_user', $id );
 
461
                }
 
462
        }
 
463
 
 
464
        return $value;
 
465
}
 
466
 
 
467
function refresh_user_details( $id ) {
 
468
        $id = (int) $id;
 
469
 
 
470
        if ( !$user = get_userdata( $id ) )
 
471
                return false;
 
472
 
 
473
        clean_user_cache( $user );
 
474
 
 
475
        return $id;
 
476
}
 
477
 
 
478
function format_code_lang( $code = '' ) {
 
479
        $code = strtolower( substr( $code, 0, 2 ) );
 
480
        $lang_codes = array(
 
481
                'aa' => 'Afar', 'ab' => 'Abkhazian', 'af' => 'Afrikaans', 'ak' => 'Akan', 'sq' => 'Albanian', 'am' => 'Amharic', 'ar' => 'Arabic', 'an' => 'Aragonese', 'hy' => 'Armenian', 'as' => 'Assamese', 'av' => 'Avaric', 'ae' => 'Avestan', 'ay' => 'Aymara', 'az' => 'Azerbaijani', 'ba' => 'Bashkir', 'bm' => 'Bambara', 'eu' => 'Basque', 'be' => 'Belarusian', 'bn' => 'Bengali',
 
482
                'bh' => 'Bihari', 'bi' => 'Bislama', 'bs' => 'Bosnian', 'br' => 'Breton', 'bg' => 'Bulgarian', 'my' => 'Burmese', 'ca' => 'Catalan; Valencian', 'ch' => 'Chamorro', 'ce' => 'Chechen', 'zh' => 'Chinese', 'cu' => 'Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic', 'cv' => 'Chuvash', 'kw' => 'Cornish', 'co' => 'Corsican', 'cr' => 'Cree',
 
483
                'cs' => 'Czech', 'da' => 'Danish', 'dv' => 'Divehi; Dhivehi; Maldivian', 'nl' => 'Dutch; Flemish', 'dz' => 'Dzongkha', 'en' => 'English', 'eo' => 'Esperanto', 'et' => 'Estonian', 'ee' => 'Ewe', 'fo' => 'Faroese', 'fj' => 'Fijjian', 'fi' => 'Finnish', 'fr' => 'French', 'fy' => 'Western Frisian', 'ff' => 'Fulah', 'ka' => 'Georgian', 'de' => 'German', 'gd' => 'Gaelic; Scottish Gaelic',
 
484
                'ga' => 'Irish', 'gl' => 'Galician', 'gv' => 'Manx', 'el' => 'Greek, Modern', 'gn' => 'Guarani', 'gu' => 'Gujarati', 'ht' => 'Haitian; Haitian Creole', 'ha' => 'Hausa', 'he' => 'Hebrew', 'hz' => 'Herero', 'hi' => 'Hindi', 'ho' => 'Hiri Motu', 'hu' => 'Hungarian', 'ig' => 'Igbo', 'is' => 'Icelandic', 'io' => 'Ido', 'ii' => 'Sichuan Yi', 'iu' => 'Inuktitut', 'ie' => 'Interlingue',
 
485
                'ia' => 'Interlingua (International Auxiliary Language Association)', 'id' => 'Indonesian', 'ik' => 'Inupiaq', 'it' => 'Italian', 'jv' => 'Javanese', 'ja' => 'Japanese', 'kl' => 'Kalaallisut; Greenlandic', 'kn' => 'Kannada', 'ks' => 'Kashmiri', 'kr' => 'Kanuri', 'kk' => 'Kazakh', 'km' => 'Central Khmer', 'ki' => 'Kikuyu; Gikuyu', 'rw' => 'Kinyarwanda', 'ky' => 'Kirghiz; Kyrgyz',
 
486
                'kv' => 'Komi', 'kg' => 'Kongo', 'ko' => 'Korean', 'kj' => 'Kuanyama; Kwanyama', 'ku' => 'Kurdish', 'lo' => 'Lao', 'la' => 'Latin', 'lv' => 'Latvian', 'li' => 'Limburgan; Limburger; Limburgish', 'ln' => 'Lingala', 'lt' => 'Lithuanian', 'lb' => 'Luxembourgish; Letzeburgesch', 'lu' => 'Luba-Katanga', 'lg' => 'Ganda', 'mk' => 'Macedonian', 'mh' => 'Marshallese', 'ml' => 'Malayalam',
 
487
                'mi' => 'Maori', 'mr' => 'Marathi', 'ms' => 'Malay', 'mg' => 'Malagasy', 'mt' => 'Maltese', 'mo' => 'Moldavian', 'mn' => 'Mongolian', 'na' => 'Nauru', 'nv' => 'Navajo; Navaho', 'nr' => 'Ndebele, South; South Ndebele', 'nd' => 'Ndebele, North; North Ndebele', 'ng' => 'Ndonga', 'ne' => 'Nepali', 'nn' => 'Norwegian Nynorsk; Nynorsk, Norwegian', 'nb' => 'Bokmål, Norwegian, Norwegian Bokmål',
 
488
                'no' => 'Norwegian', 'ny' => 'Chichewa; Chewa; Nyanja', 'oc' => 'Occitan, Provençal', 'oj' => 'Ojibwa', 'or' => 'Oriya', 'om' => 'Oromo', 'os' => 'Ossetian; Ossetic', 'pa' => 'Panjabi; Punjabi', 'fa' => 'Persian', 'pi' => 'Pali', 'pl' => 'Polish', 'pt' => 'Portuguese', 'ps' => 'Pushto', 'qu' => 'Quechua', 'rm' => 'Romansh', 'ro' => 'Romanian', 'rn' => 'Rundi', 'ru' => 'Russian',
 
489
                'sg' => 'Sango', 'sa' => 'Sanskrit', 'sr' => 'Serbian', 'hr' => 'Croatian', 'si' => 'Sinhala; Sinhalese', 'sk' => 'Slovak', 'sl' => 'Slovenian', 'se' => 'Northern Sami', 'sm' => 'Samoan', 'sn' => 'Shona', 'sd' => 'Sindhi', 'so' => 'Somali', 'st' => 'Sotho, Southern', 'es' => 'Spanish; Castilian', 'sc' => 'Sardinian', 'ss' => 'Swati', 'su' => 'Sundanese', 'sw' => 'Swahili',
 
490
                'sv' => 'Swedish', 'ty' => 'Tahitian', 'ta' => 'Tamil', 'tt' => 'Tatar', 'te' => 'Telugu', 'tg' => 'Tajik', 'tl' => 'Tagalog', 'th' => 'Thai', 'bo' => 'Tibetan', 'ti' => 'Tigrinya', 'to' => 'Tonga (Tonga Islands)', 'tn' => 'Tswana', 'ts' => 'Tsonga', 'tk' => 'Turkmen', 'tr' => 'Turkish', 'tw' => 'Twi', 'ug' => 'Uighur; Uyghur', 'uk' => 'Ukrainian', 'ur' => 'Urdu', 'uz' => 'Uzbek',
 
491
                've' => 'Venda', 'vi' => 'Vietnamese', 'vo' => 'Volapük', 'cy' => 'Welsh','wa' => 'Walloon','wo' => 'Wolof', 'xh' => 'Xhosa', 'yi' => 'Yiddish', 'yo' => 'Yoruba', 'za' => 'Zhuang; Chuang', 'zu' => 'Zulu' );
 
492
 
 
493
        /**
 
494
         * Filter the language codes.
 
495
         *
 
496
         * @since MU
 
497
         *
 
498
         * @param array  $lang_codes Key/value pair of language codes where key is the short version.
 
499
         * @param string $code       A two-letter designation of the language.
 
500
         */
 
501
        $lang_codes = apply_filters( 'lang_codes', $lang_codes, $code );
 
502
        return strtr( $code, $lang_codes );
 
503
}
 
504
 
 
505
function sync_category_tag_slugs( $term, $taxonomy ) {
 
506
        if ( global_terms_enabled() && ( $taxonomy == 'category' || $taxonomy == 'post_tag' ) ) {
 
507
                if ( is_object( $term ) ) {
 
508
                        $term->slug = sanitize_title( $term->name );
 
509
                } else {
 
510
                        $term['slug'] = sanitize_title( $term['name'] );
 
511
                }
 
512
        }
 
513
        return $term;
 
514
}
 
515
add_filter( 'get_term', 'sync_category_tag_slugs', 10, 2 );
 
516
 
 
517
function _access_denied_splash() {
 
518
        if ( ! is_user_logged_in() || is_network_admin() )
 
519
                return;
 
520
 
 
521
        $blogs = get_blogs_of_user( get_current_user_id() );
 
522
 
 
523
        if ( wp_list_filter( $blogs, array( 'userblog_id' => get_current_blog_id() ) ) )
 
524
                return;
 
525
 
 
526
        $blog_name = get_bloginfo( 'name' );
 
527
 
 
528
        if ( empty( $blogs ) )
 
529
                wp_die( sprintf( __( 'You attempted to access the "%1$s" dashboard, but you do not currently have privileges on this site. If you believe you should be able to access the "%1$s" dashboard, please contact your network administrator.' ), $blog_name ) );
 
530
 
 
531
        $output = '<p>' . sprintf( __( 'You attempted to access the "%1$s" dashboard, but you do not currently have privileges on this site. If you believe you should be able to access the "%1$s" dashboard, please contact your network administrator.' ), $blog_name ) . '</p>';
 
532
        $output .= '<p>' . __( 'If you reached this screen by accident and meant to visit one of your own sites, here are some shortcuts to help you find your way.' ) . '</p>';
 
533
 
 
534
        $output .= '<h3>' . __('Your Sites') . '</h3>';
 
535
        $output .= '<table>';
 
536
 
 
537
        foreach ( $blogs as $blog ) {
 
538
                $output .= '<tr>';
 
539
                $output .= "<td>{$blog->blogname}</td>";
 
540
                $output .= '<td><a href="' . esc_url( get_admin_url( $blog->userblog_id ) ) . '">' . __( 'Visit Dashboard' ) . '</a> | ' .
 
541
                        '<a href="' . esc_url( get_home_url( $blog->userblog_id ) ). '">' . __( 'View Site' ) . '</a></td>';
 
542
                $output .= '</tr>';
 
543
        }
 
544
 
 
545
        $output .= '</table>';
 
546
 
 
547
        wp_die( $output );
 
548
}
 
549
add_action( 'admin_page_access_denied', '_access_denied_splash', 99 );
 
550
 
 
551
function check_import_new_users( $permission ) {
 
552
        if ( !is_super_admin() )
 
553
                return false;
 
554
        return true;
 
555
}
 
556
add_filter( 'import_allow_create_users', 'check_import_new_users' );
 
557
// See "import_allow_fetch_attachments" and "import_attachment_size_limit" filters too.
 
558
 
 
559
function mu_dropdown_languages( $lang_files = array(), $current = '' ) {
 
560
        $flag = false;
 
561
        $output = array();
 
562
 
 
563
        foreach ( (array) $lang_files as $val ) {
 
564
                $code_lang = basename( $val, '.mo' );
 
565
 
 
566
                if ( $code_lang == 'en_US' ) { // American English
 
567
                        $flag = true;
 
568
                        $ae = __( 'American English' );
 
569
                        $output[$ae] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . $ae . '</option>';
 
570
                } elseif ( $code_lang == 'en_GB' ) { // British English
 
571
                        $flag = true;
 
572
                        $be = __( 'British English' );
 
573
                        $output[$be] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . $be . '</option>';
 
574
                } else {
 
575
                        $translated = format_code_lang( $code_lang );
 
576
                        $output[$translated] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . esc_html ( $translated ) . '</option>';
 
577
                }
 
578
 
 
579
        }
 
580
 
 
581
        if ( $flag === false ) // WordPress english
 
582
                $output[] = '<option value=""' . selected( $current, '', false ) . '>' . __( 'English' ) . "</option>";
 
583
 
 
584
        // Order by name
 
585
        uksort( $output, 'strnatcasecmp' );
 
586
        /**
 
587
         * Filter the languages available in the dropdown.
 
588
         *
 
589
         * @since MU
 
590
         *
 
591
         * @param array $output     HTML output of the dropdown.
 
592
         * @param array $lang_files Available language files.
 
593
         * @param string $current   The current language code.
 
594
         */
 
595
        $output = apply_filters( 'mu_dropdown_languages', $output, $lang_files, $current );
 
596
        echo implode( "\n\t", $output );
 
597
}
 
598
 
 
599
function site_admin_notice() {
 
600
        global $wp_db_version;
 
601
        if ( !is_super_admin() )
 
602
                return false;
 
603
        if ( get_site_option( 'wpmu_upgrade_site' ) != $wp_db_version )
 
604
                echo "<div class='update-nag'>" . sprintf( __( 'Thank you for Updating! Please visit the <a href="%s">Upgrade Network</a> page to update all your sites.' ), esc_url( network_admin_url( 'upgrade.php' ) ) ) . "</div>";
 
605
}
 
606
add_action( 'admin_notices', 'site_admin_notice' );
 
607
add_action( 'network_admin_notices', 'site_admin_notice' );
 
608
 
 
609
function avoid_blog_page_permalink_collision( $data, $postarr ) {
 
610
        if ( is_subdomain_install() )
 
611
                return $data;
 
612
        if ( $data['post_type'] != 'page' )
 
613
                return $data;
 
614
        if ( !isset( $data['post_name'] ) || $data['post_name'] == '' )
 
615
                return $data;
 
616
        if ( !is_main_site() )
 
617
                return $data;
 
618
 
 
619
        $post_name = $data['post_name'];
 
620
        $c = 0;
 
621
        while( $c < 10 && get_id_from_blogname( $post_name ) ) {
 
622
                $post_name .= mt_rand( 1, 10 );
 
623
                $c ++;
 
624
        }
 
625
        if ( $post_name != $data['post_name'] ) {
 
626
                $data['post_name'] = $post_name;
 
627
        }
 
628
        return $data;
 
629
}
 
630
add_filter( 'wp_insert_post_data', 'avoid_blog_page_permalink_collision', 10, 2 );
 
631
 
 
632
function choose_primary_blog() {
 
633
        ?>
 
634
        <table class="form-table">
 
635
        <tr>
 
636
        <?php /* translators: My sites label */ ?>
 
637
                <th scope="row"><?php _e( 'Primary Site' ); ?></th>
 
638
                <td>
 
639
                <?php
 
640
                $all_blogs = get_blogs_of_user( get_current_user_id() );
 
641
                $primary_blog = get_user_meta( get_current_user_id(), 'primary_blog', true );
 
642
                if ( count( $all_blogs ) > 1 ) {
 
643
                        $found = false;
 
644
                        ?>
 
645
                        <select name="primary_blog">
 
646
                                <?php foreach( (array) $all_blogs as $blog ) {
 
647
                                        if ( $primary_blog == $blog->userblog_id )
 
648
                                                $found = true;
 
649
                                        ?><option value="<?php echo $blog->userblog_id ?>"<?php selected( $primary_blog, $blog->userblog_id ); ?>><?php echo esc_url( get_home_url( $blog->userblog_id ) ) ?></option><?php
 
650
                                } ?>
 
651
                        </select>
 
652
                        <?php
 
653
                        if ( !$found ) {
 
654
                                $blog = array_shift( $all_blogs );
 
655
                                update_user_meta( get_current_user_id(), 'primary_blog', $blog->userblog_id );
 
656
                        }
 
657
                } elseif ( count( $all_blogs ) == 1 ) {
 
658
                        $blog = array_shift( $all_blogs );
 
659
                        echo $blog->domain;
 
660
                        if ( $primary_blog != $blog->userblog_id ) // Set the primary blog again if it's out of sync with blog list.
 
661
                                update_user_meta( get_current_user_id(), 'primary_blog', $blog->userblog_id );
 
662
                } else {
 
663
                        echo "N/A";
 
664
                }
 
665
                ?>
 
666
                </td>
 
667
        </tr>
 
668
        <?php if ( in_array( get_site_option( 'registration' ), array( 'all', 'blog' ) ) ) : ?>
 
669
                <tr>
 
670
                        <th scope="row" colspan="2" class="th-full">
 
671
                                <?php
 
672
                                /** This filter is documented in wp-login.php */
 
673
                                $sign_up_url = apply_filters( 'wp_signup_location', network_site_url( 'wp-signup.php' ) );
 
674
                                ?>
 
675
                                <a href="<?php echo esc_url( $sign_up_url ); ?>"><?php _e( 'Create a New Site' ); ?></a>
 
676
                        </th>
 
677
                </tr>
 
678
        <?php endif; ?>
 
679
        </table>
 
680
        <?php
 
681
}
 
682
 
 
683
/**
 
684
 * Grants Super Admin privileges.
 
685
 *
 
686
 * @since 3.0.0
 
687
 * @param int $user_id ID of the user to be granted Super Admin privileges.
 
688
 * @return bool True on success, false on failure. This can fail when the user is
 
689
 *              already a super admin or when the $super_admins global is defined.
 
690
 */
 
691
function grant_super_admin( $user_id ) {
 
692
        // If global super_admins override is defined, there is nothing to do here.
 
693
        if ( isset( $GLOBALS['super_admins'] ) ) {
 
694
                return false;
 
695
        }
 
696
 
 
697
        /**
 
698
         * Fires before the user is granted Super Admin privileges.
 
699
         *
 
700
         * @since 3.0.0
 
701
         *
 
702
         * @param int $user_id ID of the user that is about to be granted Super Admin privileges.
 
703
         */
 
704
        do_action( 'grant_super_admin', $user_id );
 
705
 
 
706
        // Directly fetch site_admins instead of using get_super_admins()
 
707
        $super_admins = get_site_option( 'site_admins', array( 'admin' ) );
 
708
 
 
709
        $user = get_userdata( $user_id );
 
710
        if ( $user && ! in_array( $user->user_login, $super_admins ) ) {
 
711
                $super_admins[] = $user->user_login;
 
712
                update_site_option( 'site_admins' , $super_admins );
 
713
 
 
714
                /**
 
715
                 * Fires after the user is granted Super Admin privileges.
 
716
                 *
 
717
                 * @since 3.0.0
 
718
                 *
 
719
                 * @param int $user_id ID of the user that was granted Super Admin privileges.
 
720
                 */
 
721
                do_action( 'granted_super_admin', $user_id );
 
722
                return true;
 
723
        }
 
724
        return false;
 
725
}
 
726
 
 
727
/**
 
728
 * Revokes Super Admin privileges.
 
729
 *
 
730
 * @since 3.0.0
 
731
 * @param int $user_id ID of the user Super Admin privileges to be revoked from.
 
732
 * @return bool True on success, false on failure. This can fail when the user's email
 
733
 *              is the network admin email or when the $super_admins global is defined.
 
734
 */
 
735
function revoke_super_admin( $user_id ) {
 
736
        // If global super_admins override is defined, there is nothing to do here.
 
737
        if ( isset( $GLOBALS['super_admins'] ) ) {
 
738
                return false;
 
739
        }
 
740
 
 
741
        /**
 
742
         * Fires before the user's Super Admin privileges are revoked.
 
743
         *
 
744
         * @since 3.0.0
 
745
         *
 
746
         * @param int $user_id ID of the user Super Admin privileges are being revoked from.
 
747
         */
 
748
        do_action( 'revoke_super_admin', $user_id );
 
749
 
 
750
        // Directly fetch site_admins instead of using get_super_admins()
 
751
        $super_admins = get_site_option( 'site_admins', array( 'admin' ) );
 
752
 
 
753
        $user = get_userdata( $user_id );
 
754
        if ( $user && 0 !== strcasecmp( $user->user_email, get_site_option( 'admin_email' ) ) ) {
 
755
                if ( false !== ( $key = array_search( $user->user_login, $super_admins ) ) ) {
 
756
                        unset( $super_admins[$key] );
 
757
                        update_site_option( 'site_admins', $super_admins );
 
758
 
 
759
                        /**
 
760
                         * Fires after the user's Super Admin privileges are revoked.
 
761
                         *
 
762
                         * @since 3.0.0
 
763
                         *
 
764
                         * @param int $user_id ID of the user Super Admin privileges were revoked from.
 
765
                         */
 
766
                        do_action( 'revoked_super_admin', $user_id );
 
767
                        return true;
 
768
                }
 
769
        }
 
770
        return false;
 
771
}
 
772
 
 
773
/**
 
774
 * Whether or not we can edit this network from this page
 
775
 *
 
776
 * By default editing of network is restricted to the Network Admin for that site_id this allows for this to be overridden
 
777
 *
 
778
 * @since 3.1.0
 
779
 * @param integer $site_id The network/site ID to check.
 
780
 */
 
781
function can_edit_network( $site_id ) {
 
782
        global $wpdb;
 
783
 
 
784
        if ( $site_id == $wpdb->siteid )
 
785
                $result = true;
 
786
        else
 
787
                $result = false;
 
788
 
 
789
        /**
 
790
         * Filter whether this network can be edited from this page.
 
791
         *
 
792
         * @since 3.1.0
 
793
         *
 
794
         * @param bool $result  Whether the network can be edited from this page.
 
795
         * @param int  $site_id The network/site ID to check.
 
796
         */
 
797
        return apply_filters( 'can_edit_network', $result, $site_id );
 
798
}
 
799
 
 
800
/**
 
801
 * Thickbox image paths for Network Admin.
 
802
 *
 
803
 * @since 3.1.0
 
804
 * @access private
 
805
 */
 
806
function _thickbox_path_admin_subfolder() {
 
807
?>
 
808
<script type="text/javascript">
 
809
//<![CDATA[
 
810
var tb_pathToImage = "../../wp-includes/js/thickbox/loadingAnimation.gif";
 
811
//]]>
 
812
</script>
 
813
<?php
 
814
}