~canonical-sysadmins/wordpress/4.7.2

« back to all changes in this revision

Viewing changes to wp-admin/includes/misc.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
 * Misc WordPress Administration API.
 
4
 *
 
5
 * @package WordPress
 
6
 * @subpackage Administration
 
7
 */
 
8
 
 
9
/**
 
10
 * Returns whether the server is running Apache with the mod_rewrite module loaded.
 
11
 *
 
12
 * @since 2.0.0
 
13
 *
 
14
 * @return bool
 
15
 */
 
16
function got_mod_rewrite() {
 
17
        $got_rewrite = apache_mod_loaded('mod_rewrite', true);
 
18
 
 
19
        /**
 
20
         * Filter whether Apache and mod_rewrite are present.
 
21
         *
 
22
         * This filter was previously used to force URL rewriting for other servers,
 
23
         * like nginx. Use the got_url_rewrite filter in got_url_rewrite() instead.
 
24
         *
 
25
         * @since 2.5.0
 
26
         *
 
27
         * @see got_url_rewrite()
 
28
         *
 
29
         * @param bool $got_rewrite Whether Apache and mod_rewrite are present.
 
30
         */
 
31
        return apply_filters( 'got_rewrite', $got_rewrite );
 
32
}
 
33
 
 
34
/**
 
35
 * Returns whether the server supports URL rewriting.
 
36
 *
 
37
 * Detects Apache's mod_rewrite, IIS 7.0+ permalink support, and nginx.
 
38
 *
 
39
 * @since 3.7.0
 
40
 *
 
41
 * @return bool Whether the server supports URL rewriting.
 
42
 */
 
43
function got_url_rewrite() {
 
44
        $got_url_rewrite = ( got_mod_rewrite() || $GLOBALS['is_nginx'] || iis7_supports_permalinks() );
 
45
 
 
46
        /**
 
47
         * Filter whether URL rewriting is available.
 
48
         *
 
49
         * @since 3.7.0
 
50
         *
 
51
         * @param bool $got_url_rewrite Whether URL rewriting is available.
 
52
         */
 
53
        return apply_filters( 'got_url_rewrite', $got_url_rewrite );
 
54
}
 
55
 
 
56
/**
 
57
 * {@internal Missing Short Description}}
 
58
 *
 
59
 * @since 1.5.0
 
60
 *
 
61
 * @param unknown_type $filename
 
62
 * @param unknown_type $marker
 
63
 * @return array An array of strings from a file (.htaccess ) from between BEGIN and END markers.
 
64
 */
 
65
function extract_from_markers( $filename, $marker ) {
 
66
        $result = array ();
 
67
 
 
68
        if (!file_exists( $filename ) ) {
 
69
                return $result;
 
70
        }
 
71
 
 
72
        if ( $markerdata = explode( "\n", implode( '', file( $filename ) ) ));
 
73
        {
 
74
                $state = false;
 
75
                foreach ( $markerdata as $markerline ) {
 
76
                        if (strpos($markerline, '# END ' . $marker) !== false)
 
77
                                $state = false;
 
78
                        if ( $state )
 
79
                                $result[] = $markerline;
 
80
                        if (strpos($markerline, '# BEGIN ' . $marker) !== false)
 
81
                                $state = true;
 
82
                }
 
83
        }
 
84
 
 
85
        return $result;
 
86
}
 
87
 
 
88
/**
 
89
 * {@internal Missing Short Description}}
 
90
 *
 
91
 * Inserts an array of strings into a file (.htaccess ), placing it between
 
92
 * BEGIN and END markers. Replaces existing marked info. Retains surrounding
 
93
 * data. Creates file if none exists.
 
94
 *
 
95
 * @since 1.5.0
 
96
 *
 
97
 * @param unknown_type $filename
 
98
 * @param unknown_type $marker
 
99
 * @param unknown_type $insertion
 
100
 * @return bool True on write success, false on failure.
 
101
 */
 
102
function insert_with_markers( $filename, $marker, $insertion ) {
 
103
        if (!file_exists( $filename ) || is_writeable( $filename ) ) {
 
104
                if (!file_exists( $filename ) ) {
 
105
                        $markerdata = '';
 
106
                } else {
 
107
                        $markerdata = explode( "\n", implode( '', file( $filename ) ) );
 
108
                }
 
109
 
 
110
                if ( !$f = @fopen( $filename, 'w' ) )
 
111
                        return false;
 
112
 
 
113
                $foundit = false;
 
114
                if ( $markerdata ) {
 
115
                        $state = true;
 
116
                        foreach ( $markerdata as $n => $markerline ) {
 
117
                                if (strpos($markerline, '# BEGIN ' . $marker) !== false)
 
118
                                        $state = false;
 
119
                                if ( $state ) {
 
120
                                        if ( $n + 1 < count( $markerdata ) )
 
121
                                                fwrite( $f, "{$markerline}\n" );
 
122
                                        else
 
123
                                                fwrite( $f, "{$markerline}" );
 
124
                                }
 
125
                                if (strpos($markerline, '# END ' . $marker) !== false) {
 
126
                                        fwrite( $f, "# BEGIN {$marker}\n" );
 
127
                                        if ( is_array( $insertion ))
 
128
                                                foreach ( $insertion as $insertline )
 
129
                                                        fwrite( $f, "{$insertline}\n" );
 
130
                                        fwrite( $f, "# END {$marker}\n" );
 
131
                                        $state = true;
 
132
                                        $foundit = true;
 
133
                                }
 
134
                        }
 
135
                }
 
136
                if (!$foundit) {
 
137
                        fwrite( $f, "\n# BEGIN {$marker}\n" );
 
138
                        foreach ( $insertion as $insertline )
 
139
                                fwrite( $f, "{$insertline}\n" );
 
140
                        fwrite( $f, "# END {$marker}\n" );
 
141
                }
 
142
                fclose( $f );
 
143
                return true;
 
144
        } else {
 
145
                return false;
 
146
        }
 
147
}
 
148
 
 
149
/**
 
150
 * Updates the htaccess file with the current rules if it is writable.
 
151
 *
 
152
 * Always writes to the file if it exists and is writable to ensure that we
 
153
 * blank out old rules.
 
154
 *
 
155
 * @since 1.5.0
 
156
 */
 
157
function save_mod_rewrite_rules() {
 
158
        if ( is_multisite() )
 
159
                return;
 
160
 
 
161
        global $wp_rewrite;
 
162
 
 
163
        $home_path = get_home_path();
 
164
        $htaccess_file = $home_path.'.htaccess';
 
165
 
 
166
        /*
 
167
         * If the file doesn't already exist check for write access to the directory
 
168
         * and whether we have some rules. Else check for write access to the file.
 
169
         */
 
170
        if ((!file_exists($htaccess_file) && is_writable($home_path) && $wp_rewrite->using_mod_rewrite_permalinks()) || is_writable($htaccess_file)) {
 
171
                if ( got_mod_rewrite() ) {
 
172
                        $rules = explode( "\n", $wp_rewrite->mod_rewrite_rules() );
 
173
                        return insert_with_markers( $htaccess_file, 'WordPress', $rules );
 
174
                }
 
175
        }
 
176
 
 
177
        return false;
 
178
}
 
179
 
 
180
/**
 
181
 * Updates the IIS web.config file with the current rules if it is writable.
 
182
 * If the permalinks do not require rewrite rules then the rules are deleted from the web.config file.
 
183
 *
 
184
 * @since 2.8.0
 
185
 *
 
186
 * @return bool True if web.config was updated successfully
 
187
 */
 
188
function iis7_save_url_rewrite_rules(){
 
189
        if ( is_multisite() )
 
190
                return;
 
191
 
 
192
        global $wp_rewrite;
 
193
 
 
194
        $home_path = get_home_path();
 
195
        $web_config_file = $home_path . 'web.config';
 
196
 
 
197
        // Using win_is_writable() instead of is_writable() because of a bug in Windows PHP
 
198
        if ( iis7_supports_permalinks() && ( ( ! file_exists($web_config_file) && win_is_writable($home_path) && $wp_rewrite->using_mod_rewrite_permalinks() ) || win_is_writable($web_config_file) ) ) {
 
199
                $rule = $wp_rewrite->iis7_url_rewrite_rules(false, '', '');
 
200
                if ( ! empty($rule) ) {
 
201
                        return iis7_add_rewrite_rule($web_config_file, $rule);
 
202
                } else {
 
203
                        return iis7_delete_rewrite_rule($web_config_file);
 
204
                }
 
205
        }
 
206
        return false;
 
207
}
 
208
 
 
209
/**
 
210
 * {@internal Missing Short Description}}
 
211
 *
 
212
 * @since 1.5.0
 
213
 *
 
214
 * @param unknown_type $file
 
215
 */
 
216
function update_recently_edited( $file ) {
 
217
        $oldfiles = (array ) get_option( 'recently_edited' );
 
218
        if ( $oldfiles ) {
 
219
                $oldfiles = array_reverse( $oldfiles );
 
220
                $oldfiles[] = $file;
 
221
                $oldfiles = array_reverse( $oldfiles );
 
222
                $oldfiles = array_unique( $oldfiles );
 
223
                if ( 5 < count( $oldfiles ))
 
224
                        array_pop( $oldfiles );
 
225
        } else {
 
226
                $oldfiles[] = $file;
 
227
        }
 
228
        update_option( 'recently_edited', $oldfiles );
 
229
}
 
230
 
 
231
/**
 
232
 * If siteurl, home or page_on_front changed, flush rewrite rules.
 
233
 *
 
234
 * @since 2.1.0
 
235
 *
 
236
 * @param string $old_value
 
237
 * @param string $value
 
238
 */
 
239
function update_home_siteurl( $old_value, $value ) {
 
240
        if ( defined( "WP_INSTALLING" ) )
 
241
                return;
 
242
 
 
243
        // If home changed, write rewrite rules to new location.
 
244
        flush_rewrite_rules();
 
245
}
 
246
 
 
247
add_action( 'update_option_home', 'update_home_siteurl', 10, 2 );
 
248
add_action( 'update_option_siteurl', 'update_home_siteurl', 10, 2 );
 
249
add_action( 'update_option_page_on_front', 'update_home_siteurl', 10, 2 );
 
250
 
 
251
/**
 
252
 * Shorten an URL, to be used as link text
 
253
 *
 
254
 * @since 1.2.0
 
255
 *
 
256
 * @param string $url
 
257
 * @return string
 
258
 */
 
259
function url_shorten( $url ) {
 
260
        $short_url = str_replace( array( 'http://', 'www.' ), '', $url );
 
261
        $short_url = untrailingslashit( $short_url );
 
262
        if ( strlen( $short_url ) > 35 )
 
263
                $short_url = substr( $short_url, 0, 32 ) . '&hellip;';
 
264
        return $short_url;
 
265
}
 
266
 
 
267
/**
 
268
 * Resets global variables based on $_GET and $_POST
 
269
 *
 
270
 * This function resets global variables based on the names passed
 
271
 * in the $vars array to the value of $_POST[$var] or $_GET[$var] or ''
 
272
 * if neither is defined.
 
273
 *
 
274
 * @since 2.0.0
 
275
 *
 
276
 * @param array $vars An array of globals to reset.
 
277
 */
 
278
function wp_reset_vars( $vars ) {
 
279
        foreach ( $vars as $var ) {
 
280
                if ( empty( $_POST[ $var ] ) ) {
 
281
                        if ( empty( $_GET[ $var ] ) ) {
 
282
                                $GLOBALS[ $var ] = '';
 
283
                        } else {
 
284
                                $GLOBALS[ $var ] = $_GET[ $var ];
 
285
                        }
 
286
                } else {
 
287
                        $GLOBALS[ $var ] = $_POST[ $var ];
 
288
                }
 
289
        }
 
290
}
 
291
 
 
292
/**
 
293
 * {@internal Missing Short Description}}
 
294
 *
 
295
 * @since 2.1.0
 
296
 *
 
297
 * @param unknown_type $message
 
298
 */
 
299
function show_message($message) {
 
300
        if ( is_wp_error($message) ){
 
301
                if ( $message->get_error_data() && is_string( $message->get_error_data() ) )
 
302
                        $message = $message->get_error_message() . ': ' . $message->get_error_data();
 
303
                else
 
304
                        $message = $message->get_error_message();
 
305
        }
 
306
        echo "<p>$message</p>\n";
 
307
        wp_ob_end_flush_all();
 
308
        flush();
 
309
}
 
310
 
 
311
function wp_doc_link_parse( $content ) {
 
312
        if ( !is_string( $content ) || empty( $content ) )
 
313
                return array();
 
314
 
 
315
        if ( !function_exists('token_get_all') )
 
316
                return array();
 
317
 
 
318
        $tokens = token_get_all( $content );
 
319
        $count = count( $tokens );
 
320
        $functions = array();
 
321
        $ignore_functions = array();
 
322
        for ( $t = 0; $t < $count - 2; $t++ ) {
 
323
                if ( ! is_array( $tokens[ $t ] ) ) {
 
324
                        continue;
 
325
                }
 
326
 
 
327
                if ( T_STRING == $tokens[ $t ][0] && ( '(' == $tokens[ $t + 1 ] || '(' == $tokens[ $t + 2 ] ) ) {
 
328
                        // If it's a function or class defined locally, there's not going to be any docs available
 
329
                        if ( ( isset( $tokens[ $t - 2 ][1] ) && in_array( $tokens[ $t - 2 ][1], array( 'function', 'class' ) ) ) || ( isset( $tokens[ $t - 2 ][0] ) && T_OBJECT_OPERATOR == $tokens[ $t - 1 ][0] ) ) {
 
330
                                $ignore_functions[] = $tokens[$t][1];
 
331
                        }
 
332
                        // Add this to our stack of unique references
 
333
                        $functions[] = $tokens[$t][1];
 
334
                }
 
335
        }
 
336
 
 
337
        $functions = array_unique( $functions );
 
338
        sort( $functions );
 
339
 
 
340
        /**
 
341
         * Filter the list of functions and classes to be ignored from the documentation lookup.
 
342
         *
 
343
         * @since 2.8.0
 
344
         *
 
345
         * @param array $ignore_functions Functions and classes to be ignored.
 
346
         */
 
347
        $ignore_functions = apply_filters( 'documentation_ignore_functions', $ignore_functions );
 
348
 
 
349
        $ignore_functions = array_unique( $ignore_functions );
 
350
 
 
351
        $out = array();
 
352
        foreach ( $functions as $function ) {
 
353
                if ( in_array( $function, $ignore_functions ) )
 
354
                        continue;
 
355
                $out[] = $function;
 
356
        }
 
357
 
 
358
        return $out;
 
359
}
 
360
 
 
361
/**
 
362
 * Saves option for number of rows when listing posts, pages, comments, etc.
 
363
 *
 
364
 * @since 2.8.0
 
365
 */
 
366
function set_screen_options() {
 
367
 
 
368
        if ( isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options']) ) {
 
369
                check_admin_referer( 'screen-options-nonce', 'screenoptionnonce' );
 
370
 
 
371
                if ( !$user = wp_get_current_user() )
 
372
                        return;
 
373
                $option = $_POST['wp_screen_options']['option'];
 
374
                $value = $_POST['wp_screen_options']['value'];
 
375
 
 
376
                if ( $option != sanitize_key( $option ) )
 
377
                        return;
 
378
 
 
379
                $map_option = $option;
 
380
                $type = str_replace('edit_', '', $map_option);
 
381
                $type = str_replace('_per_page', '', $type);
 
382
                if ( in_array( $type, get_taxonomies() ) )
 
383
                        $map_option = 'edit_tags_per_page';
 
384
                elseif ( in_array( $type, get_post_types() ) )
 
385
                        $map_option = 'edit_per_page';
 
386
                else
 
387
                        $option = str_replace('-', '_', $option);
 
388
 
 
389
                switch ( $map_option ) {
 
390
                        case 'edit_per_page':
 
391
                        case 'users_per_page':
 
392
                        case 'edit_comments_per_page':
 
393
                        case 'upload_per_page':
 
394
                        case 'edit_tags_per_page':
 
395
                        case 'plugins_per_page':
 
396
                        // Network admin
 
397
                        case 'sites_network_per_page':
 
398
                        case 'users_network_per_page':
 
399
                        case 'site_users_network_per_page':
 
400
                        case 'plugins_network_per_page':
 
401
                        case 'themes_network_per_page':
 
402
                        case 'site_themes_network_per_page':
 
403
                                $value = (int) $value;
 
404
                                if ( $value < 1 || $value > 999 )
 
405
                                        return;
 
406
                                break;
 
407
                        default:
 
408
 
 
409
                                /**
 
410
                                 * Filter a screen option value before it is set.
 
411
                                 *
 
412
                                 * The filter can also be used to modify non-standard [items]_per_page
 
413
                                 * settings. See the parent function for a full list of standard options.
 
414
                                 *
 
415
                                 * Returning false to the filter will skip saving the current option.
 
416
                                 *
 
417
                                 * @since 2.8.0
 
418
                                 *
 
419
                                 * @see set_screen_options()
 
420
                                 *
 
421
                                 * @param bool|int $value  Screen option value. Default false to skip.
 
422
                                 * @param string   $option The option name.
 
423
                                 * @param int      $value  The number of rows to use.
 
424
                                 */
 
425
                                $value = apply_filters( 'set-screen-option', false, $option, $value );
 
426
 
 
427
                                if ( false === $value )
 
428
                                        return;
 
429
                                break;
 
430
                }
 
431
 
 
432
                update_user_meta($user->ID, $option, $value);
 
433
                wp_safe_redirect( remove_query_arg( array('pagenum', 'apage', 'paged'), wp_get_referer() ) );
 
434
                exit;
 
435
        }
 
436
}
 
437
 
 
438
/**
 
439
 * Check if rewrite rule for WordPress already exists in the IIS 7+ configuration file
 
440
 *
 
441
 * @since 2.8.0
 
442
 *
 
443
 * @return bool
 
444
 * @param string $filename The file path to the configuration file
 
445
 */
 
446
function iis7_rewrite_rule_exists($filename) {
 
447
        if ( ! file_exists($filename) )
 
448
                return false;
 
449
        if ( ! class_exists('DOMDocument') )
 
450
                return false;
 
451
 
 
452
        $doc = new DOMDocument();
 
453
        if ( $doc->load($filename) === false )
 
454
                return false;
 
455
        $xpath = new DOMXPath($doc);
 
456
        $rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')]');
 
457
        if ( $rules->length == 0 )
 
458
                return false;
 
459
        else
 
460
                return true;
 
461
}
 
462
 
 
463
/**
 
464
 * Delete WordPress rewrite rule from web.config file if it exists there
 
465
 *
 
466
 * @since 2.8.0
 
467
 *
 
468
 * @param string $filename Name of the configuration file
 
469
 * @return bool
 
470
 */
 
471
function iis7_delete_rewrite_rule($filename) {
 
472
        // If configuration file does not exist then rules also do not exist so there is nothing to delete
 
473
        if ( ! file_exists($filename) )
 
474
                return true;
 
475
 
 
476
        if ( ! class_exists('DOMDocument') )
 
477
                return false;
 
478
 
 
479
        $doc = new DOMDocument();
 
480
        $doc->preserveWhiteSpace = false;
 
481
 
 
482
        if ( $doc -> load($filename) === false )
 
483
                return false;
 
484
        $xpath = new DOMXPath($doc);
 
485
        $rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')]');
 
486
        if ( $rules->length > 0 ) {
 
487
                $child = $rules->item(0);
 
488
                $parent = $child->parentNode;
 
489
                $parent->removeChild($child);
 
490
                $doc->formatOutput = true;
 
491
                saveDomDocument($doc, $filename);
 
492
        }
 
493
        return true;
 
494
}
 
495
 
 
496
/**
 
497
 * Add WordPress rewrite rule to the IIS 7+ configuration file.
 
498
 *
 
499
 * @since 2.8.0
 
500
 *
 
501
 * @param string $filename The file path to the configuration file
 
502
 * @param string $rewrite_rule The XML fragment with URL Rewrite rule
 
503
 * @return bool
 
504
 */
 
505
function iis7_add_rewrite_rule($filename, $rewrite_rule) {
 
506
        if ( ! class_exists('DOMDocument') )
 
507
                return false;
 
508
 
 
509
        // If configuration file does not exist then we create one.
 
510
        if ( ! file_exists($filename) ) {
 
511
                $fp = fopen( $filename, 'w');
 
512
                fwrite($fp, '<configuration/>');
 
513
                fclose($fp);
 
514
        }
 
515
 
 
516
        $doc = new DOMDocument();
 
517
        $doc->preserveWhiteSpace = false;
 
518
 
 
519
        if ( $doc->load($filename) === false )
 
520
                return false;
 
521
 
 
522
        $xpath = new DOMXPath($doc);
 
523
 
 
524
        // First check if the rule already exists as in that case there is no need to re-add it
 
525
        $wordpress_rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')]');
 
526
        if ( $wordpress_rules->length > 0 )
 
527
                return true;
 
528
 
 
529
        // Check the XPath to the rewrite rule and create XML nodes if they do not exist
 
530
        $xmlnodes = $xpath->query('/configuration/system.webServer/rewrite/rules');
 
531
        if ( $xmlnodes->length > 0 ) {
 
532
                $rules_node = $xmlnodes->item(0);
 
533
        } else {
 
534
                $rules_node = $doc->createElement('rules');
 
535
 
 
536
                $xmlnodes = $xpath->query('/configuration/system.webServer/rewrite');
 
537
                if ( $xmlnodes->length > 0 ) {
 
538
                        $rewrite_node = $xmlnodes->item(0);
 
539
                        $rewrite_node->appendChild($rules_node);
 
540
                } else {
 
541
                        $rewrite_node = $doc->createElement('rewrite');
 
542
                        $rewrite_node->appendChild($rules_node);
 
543
 
 
544
                        $xmlnodes = $xpath->query('/configuration/system.webServer');
 
545
                        if ( $xmlnodes->length > 0 ) {
 
546
                                $system_webServer_node = $xmlnodes->item(0);
 
547
                                $system_webServer_node->appendChild($rewrite_node);
 
548
                        } else {
 
549
                                $system_webServer_node = $doc->createElement('system.webServer');
 
550
                                $system_webServer_node->appendChild($rewrite_node);
 
551
 
 
552
                                $xmlnodes = $xpath->query('/configuration');
 
553
                                if ( $xmlnodes->length > 0 ) {
 
554
                                        $config_node = $xmlnodes->item(0);
 
555
                                        $config_node->appendChild($system_webServer_node);
 
556
                                } else {
 
557
                                        $config_node = $doc->createElement('configuration');
 
558
                                        $doc->appendChild($config_node);
 
559
                                        $config_node->appendChild($system_webServer_node);
 
560
                                }
 
561
                        }
 
562
                }
 
563
        }
 
564
 
 
565
        $rule_fragment = $doc->createDocumentFragment();
 
566
        $rule_fragment->appendXML($rewrite_rule);
 
567
        $rules_node->appendChild($rule_fragment);
 
568
 
 
569
        $doc->encoding = "UTF-8";
 
570
        $doc->formatOutput = true;
 
571
        saveDomDocument($doc, $filename);
 
572
 
 
573
        return true;
 
574
}
 
575
 
 
576
/**
 
577
 * Saves the XML document into a file
 
578
 *
 
579
 * @since 2.8.0
 
580
 *
 
581
 * @param DOMDocument $doc
 
582
 * @param string $filename
 
583
 */
 
584
function saveDomDocument($doc, $filename) {
 
585
        $config = $doc->saveXML();
 
586
        $config = preg_replace("/([^\r])\n/", "$1\r\n", $config);
 
587
        $fp = fopen($filename, 'w');
 
588
        fwrite($fp, $config);
 
589
        fclose($fp);
 
590
}
 
591
 
 
592
/**
 
593
 * Display the default admin color scheme picker (Used in user-edit.php)
 
594
 *
 
595
 * @since 3.0.0
 
596
 */
 
597
function admin_color_scheme_picker( $user_id ) {
 
598
        global $_wp_admin_css_colors;
 
599
 
 
600
        ksort( $_wp_admin_css_colors );
 
601
 
 
602
        if ( isset( $_wp_admin_css_colors['fresh'] ) ) {
 
603
                // Set Default ('fresh') and Light should go first.
 
604
                $_wp_admin_css_colors = array_filter( array_merge( array( 'fresh' => '', 'light' => '' ), $_wp_admin_css_colors ) );
 
605
        }
 
606
 
 
607
        $current_color = get_user_option( 'admin_color', $user_id );
 
608
 
 
609
        if ( empty( $current_color ) || ! isset( $_wp_admin_css_colors[ $current_color ] ) ) {
 
610
                $current_color = 'fresh';
 
611
        }
 
612
 
 
613
        ?>
 
614
        <fieldset id="color-picker" class="scheme-list">
 
615
                <legend class="screen-reader-text"><span><?php _e( 'Admin Color Scheme' ); ?></span></legend>
 
616
                <?php
 
617
                wp_nonce_field( 'save-color-scheme', 'color-nonce', false );
 
618
                foreach ( $_wp_admin_css_colors as $color => $color_info ) :
 
619
 
 
620
                        ?>
 
621
                        <div class="color-option <?php echo ( $color == $current_color ) ? 'selected' : ''; ?>">
 
622
                                <input name="admin_color" id="admin_color_<?php echo esc_attr( $color ); ?>" type="radio" value="<?php echo esc_attr( $color ); ?>" class="tog" <?php checked( $color, $current_color ); ?> />
 
623
                                <input type="hidden" class="css_url" value="<?php echo esc_url( $color_info->url ); ?>" />
 
624
                                <input type="hidden" class="icon_colors" value="<?php echo esc_attr( json_encode( array( 'icons' => $color_info->icon_colors ) ) ); ?>" />
 
625
                                <label for="admin_color_<?php echo esc_attr( $color ); ?>"><?php echo esc_html( $color_info->name ); ?></label>
 
626
                                <table class="color-palette">
 
627
                                        <tr>
 
628
                                        <?php
 
629
 
 
630
                                        foreach ( $color_info->colors as $html_color ) {
 
631
                                                ?>
 
632
                                                <td style="background-color: <?php echo esc_attr( $html_color ); ?>">&nbsp;</td>
 
633
                                                <?php
 
634
                                        }
 
635
 
 
636
                                        ?>
 
637
                                        </tr>
 
638
                                </table>
 
639
                        </div>
 
640
                        <?php
 
641
 
 
642
                endforeach;
 
643
 
 
644
        ?>
 
645
        </fieldset>
 
646
        <?php
 
647
}
 
648
 
 
649
function wp_color_scheme_settings() {
 
650
        global $_wp_admin_css_colors;
 
651
 
 
652
        $color_scheme = get_user_option( 'admin_color' );
 
653
 
 
654
        // It's possible to have a color scheme set that is no longer registered.
 
655
        if ( empty( $_wp_admin_css_colors[ $color_scheme ] ) ) {
 
656
                $color_scheme = 'fresh';
 
657
        }
 
658
 
 
659
        if ( ! empty( $_wp_admin_css_colors[ $color_scheme ]->icon_colors ) ) {
 
660
                $icon_colors = $_wp_admin_css_colors[ $color_scheme ]->icon_colors;
 
661
        } elseif ( ! empty( $_wp_admin_css_colors['fresh']->icon_colors ) ) {
 
662
                $icon_colors = $_wp_admin_css_colors['fresh']->icon_colors;
 
663
        } else {
 
664
                // Fall back to the default set of icon colors if the default scheme is missing.
 
665
                $icon_colors = array( 'base' => '#999', 'focus' => '#2ea2cc', 'current' => '#fff' );
 
666
        }
 
667
 
 
668
        echo '<script type="text/javascript">var _wpColorScheme = ' . json_encode( array( 'icons' => $icon_colors ) ) . ";</script>\n";
 
669
}
 
670
add_action( 'admin_head', 'wp_color_scheme_settings' );
 
671
 
 
672
function _ipad_meta() {
 
673
        if ( wp_is_mobile() ) {
 
674
                ?>
 
675
                <meta name="viewport" id="viewport-meta" content="width=device-width, initial-scale=1">
 
676
                <?php
 
677
        }
 
678
}
 
679
add_action('admin_head', '_ipad_meta');
 
680
 
 
681
/**
 
682
 * Check lock status for posts displayed on the Posts screen
 
683
 *
 
684
 * @since 3.6.0
 
685
 */
 
686
function wp_check_locked_posts( $response, $data, $screen_id ) {
 
687
        $checked = array();
 
688
 
 
689
        if ( array_key_exists( 'wp-check-locked-posts', $data ) && is_array( $data['wp-check-locked-posts'] ) ) {
 
690
                foreach ( $data['wp-check-locked-posts'] as $key ) {
 
691
                        if ( ! $post_id = absint( substr( $key, 5 ) ) )
 
692
                                continue;
 
693
 
 
694
                        if ( ( $user_id = wp_check_post_lock( $post_id ) ) && ( $user = get_userdata( $user_id ) ) && current_user_can( 'edit_post', $post_id ) ) {
 
695
                                $send = array( 'text' => sprintf( __( '%s is currently editing' ), $user->display_name ) );
 
696
 
 
697
                                if ( ( $avatar = get_avatar( $user->ID, 18 ) ) && preg_match( "|src='([^']+)'|", $avatar, $matches ) )
 
698
                                        $send['avatar_src'] = $matches[1];
 
699
 
 
700
                                $checked[$key] = $send;
 
701
                        }
 
702
                }
 
703
        }
 
704
 
 
705
        if ( ! empty( $checked ) )
 
706
                $response['wp-check-locked-posts'] = $checked;
 
707
 
 
708
        return $response;
 
709
}
 
710
add_filter( 'heartbeat_received', 'wp_check_locked_posts', 10, 3 );
 
711
 
 
712
/**
 
713
 * Check lock status on the New/Edit Post screen and refresh the lock
 
714
 *
 
715
 * @since 3.6.0
 
716
 */
 
717
function wp_refresh_post_lock( $response, $data, $screen_id ) {
 
718
        if ( array_key_exists( 'wp-refresh-post-lock', $data ) ) {
 
719
                $received = $data['wp-refresh-post-lock'];
 
720
                $send = array();
 
721
 
 
722
                if ( ! $post_id = absint( $received['post_id'] ) )
 
723
                        return $response;
 
724
 
 
725
                if ( ! current_user_can('edit_post', $post_id) )
 
726
                        return $response;
 
727
 
 
728
                if ( ( $user_id = wp_check_post_lock( $post_id ) ) && ( $user = get_userdata( $user_id ) ) ) {
 
729
                        $error = array(
 
730
                                'text' => sprintf( __( '%s has taken over and is currently editing.' ), $user->display_name )
 
731
                        );
 
732
 
 
733
                        if ( $avatar = get_avatar( $user->ID, 64 ) ) {
 
734
                                if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) )
 
735
                                        $error['avatar_src'] = $matches[1];
 
736
                        }
 
737
 
 
738
                        $send['lock_error'] = $error;
 
739
                } else {
 
740
                        if ( $new_lock = wp_set_post_lock( $post_id ) )
 
741
                                $send['new_lock'] = implode( ':', $new_lock );
 
742
                }
 
743
 
 
744
                $response['wp-refresh-post-lock'] = $send;
 
745
        }
 
746
 
 
747
        return $response;
 
748
}
 
749
add_filter( 'heartbeat_received', 'wp_refresh_post_lock', 10, 3 );
 
750
 
 
751
/**
 
752
 * Check nonce expiration on the New/Edit Post screen and refresh if needed
 
753
 *
 
754
 * @since 3.6.0
 
755
 */
 
756
function wp_refresh_post_nonces( $response, $data, $screen_id ) {
 
757
        if ( array_key_exists( 'wp-refresh-post-nonces', $data ) ) {
 
758
                $received = $data['wp-refresh-post-nonces'];
 
759
                $response['wp-refresh-post-nonces'] = array( 'check' => 1 );
 
760
 
 
761
                if ( ! $post_id = absint( $received['post_id'] ) )
 
762
                        return $response;
 
763
 
 
764
                if ( ! current_user_can( 'edit_post', $post_id ) || empty( $received['post_nonce'] ) )
 
765
                        return $response;
 
766
 
 
767
                if ( 2 === wp_verify_nonce( $received['post_nonce'], 'update-post_' . $post_id ) ) {
 
768
                        $response['wp-refresh-post-nonces'] = array(
 
769
                                'replace' => array(
 
770
                                        'getpermalinknonce' => wp_create_nonce('getpermalink'),
 
771
                                        'samplepermalinknonce' => wp_create_nonce('samplepermalink'),
 
772
                                        'closedpostboxesnonce' => wp_create_nonce('closedpostboxes'),
 
773
                                        '_ajax_linking_nonce' => wp_create_nonce( 'internal-linking' ),
 
774
                                        '_wpnonce' => wp_create_nonce( 'update-post_' . $post_id ),
 
775
                                ),
 
776
                                'heartbeatNonce' => wp_create_nonce( 'heartbeat-nonce' ),
 
777
                        );
 
778
                }
 
779
        }
 
780
 
 
781
        return $response;
 
782
}
 
783
add_filter( 'heartbeat_received', 'wp_refresh_post_nonces', 10, 3 );
 
784
 
 
785
/**
 
786
 * Disable suspension of Heartbeat on the Add/Edit Post screens.
 
787
 *
 
788
 * @since 3.8.0
 
789
 *
 
790
 * @param array $settings An array of Heartbeat settings.
 
791
 * @return array Filtered Heartbeat settings.
 
792
 */
 
793
function wp_heartbeat_set_suspension( $settings ) {
 
794
        global $pagenow;
 
795
 
 
796
        if ( 'post.php' === $pagenow || 'post-new.php' === $pagenow ) {
 
797
                $settings['suspension'] = 'disable';
 
798
        }
 
799
 
 
800
        return $settings;
 
801
}
 
802
add_filter( 'heartbeat_settings', 'wp_heartbeat_set_suspension' );
 
803
 
 
804
/**
 
805
 * Autosave with heartbeat
 
806
 *
 
807
 * @since 3.9.0
 
808
 */
 
809
function heartbeat_autosave( $response, $data ) {
 
810
        if ( ! empty( $data['wp_autosave'] ) ) {
 
811
                $saved = wp_autosave( $data['wp_autosave'] );
 
812
 
 
813
                if ( is_wp_error( $saved ) ) {
 
814
                        $response['wp_autosave'] = array( 'success' => false, 'message' => $saved->get_error_message() );
 
815
                } elseif ( empty( $saved ) ) {
 
816
                        $response['wp_autosave'] = array( 'success' => false, 'message' => __( 'Error while saving.' ) );
 
817
                } else {
 
818
                        /* translators: draft saved date format, see http://php.net/date */
 
819
                        $draft_saved_date_format = __( 'g:i:s a' );
 
820
                        /* translators: %s: date and time */
 
821
                        $response['wp_autosave'] = array( 'success' => true, 'message' => sprintf( __( 'Draft saved at %s.' ), date_i18n( $draft_saved_date_format ) ) );
 
822
                }
 
823
        }
 
824
 
 
825
        return $response;
 
826
}
 
827
// Run later as we have to set DOING_AUTOSAVE for back-compat
 
828
add_filter( 'heartbeat_received', 'heartbeat_autosave', 500, 2 );
 
829
 
 
830
/**
 
831
 * Disables autocomplete on the 'post' form (Add/Edit Post screens) for WebKit browsers,
 
832
 * as they disregard the autocomplete setting on the editor textarea. That can break the editor
 
833
 * when the user navigates to it with the browser's Back button. See #28037
 
834
 *
 
835
 * @since 4.0
 
836
 */
 
837
function post_form_autocomplete_off() {
 
838
        global $is_safari, $is_chrome;
 
839
 
 
840
        if ( $is_safari || $is_chrome ) {
 
841
                echo ' autocomplete="off"';
 
842
        }
 
843
}
 
844
 
 
845
add_action( 'post_edit_form_tag', 'post_form_autocomplete_off' );