[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
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 Whether the server is running Apache with the mod_rewrite module loaded. 15 */ 16 function got_mod_rewrite() { 17 $got_rewrite = apache_mod_loaded( 'mod_rewrite', true ); 18 19 /** 20 * Filters 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 {@see '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 * @global bool $is_nginx 42 * 43 * @return bool Whether the server supports URL rewriting. 44 */ 45 function got_url_rewrite() { 46 $got_url_rewrite = ( got_mod_rewrite() || $GLOBALS['is_nginx'] || iis7_supports_permalinks() ); 47 48 /** 49 * Filters whether URL rewriting is available. 50 * 51 * @since 3.7.0 52 * 53 * @param bool $got_url_rewrite Whether URL rewriting is available. 54 */ 55 return apply_filters( 'got_url_rewrite', $got_url_rewrite ); 56 } 57 58 /** 59 * Extracts strings from between the BEGIN and END markers in the .htaccess file. 60 * 61 * @since 1.5.0 62 * 63 * @param string $filename Filename to extract the strings from. 64 * @param string $marker The marker to extract the strings from. 65 * @return string[] An array of strings from a file (.htaccess) from between BEGIN and END markers. 66 */ 67 function extract_from_markers( $filename, $marker ) { 68 $result = array(); 69 70 if ( ! file_exists( $filename ) ) { 71 return $result; 72 } 73 74 $markerdata = explode( "\n", implode( '', file( $filename ) ) ); 75 76 $state = false; 77 foreach ( $markerdata as $markerline ) { 78 if ( false !== strpos( $markerline, '# END ' . $marker ) ) { 79 $state = false; 80 } 81 if ( $state ) { 82 if ( '#' === substr( $markerline, 0, 1 ) ) { 83 continue; 84 } 85 $result[] = $markerline; 86 } 87 if ( false !== strpos( $markerline, '# BEGIN ' . $marker ) ) { 88 $state = true; 89 } 90 } 91 92 return $result; 93 } 94 95 /** 96 * Inserts an array of strings into a file (.htaccess), placing it between 97 * BEGIN and END markers. 98 * 99 * Replaces existing marked info. Retains surrounding 100 * data. Creates file if none exists. 101 * 102 * @since 1.5.0 103 * 104 * @param string $filename Filename to alter. 105 * @param string $marker The marker to alter. 106 * @param array|string $insertion The new content to insert. 107 * @return bool True on write success, false on failure. 108 */ 109 function insert_with_markers( $filename, $marker, $insertion ) { 110 if ( ! file_exists( $filename ) ) { 111 if ( ! is_writable( dirname( $filename ) ) ) { 112 return false; 113 } 114 115 if ( ! touch( $filename ) ) { 116 return false; 117 } 118 119 // Make sure the file is created with a minimum set of permissions. 120 $perms = fileperms( $filename ); 121 if ( $perms ) { 122 chmod( $filename, $perms | 0644 ); 123 } 124 } elseif ( ! is_writable( $filename ) ) { 125 return false; 126 } 127 128 if ( ! is_array( $insertion ) ) { 129 $insertion = explode( "\n", $insertion ); 130 } 131 132 $switched_locale = switch_to_locale( get_locale() ); 133 134 $instructions = sprintf( 135 /* translators: 1: Marker. */ 136 __( 137 'The directives (lines) between "BEGIN %1$s" and "END %1$s" are 138 dynamically generated, and should only be modified via WordPress filters. 139 Any changes to the directives between these markers will be overwritten.' 140 ), 141 $marker 142 ); 143 144 $instructions = explode( "\n", $instructions ); 145 foreach ( $instructions as $line => $text ) { 146 $instructions[ $line ] = '# ' . $text; 147 } 148 149 /** 150 * Filters the inline instructions inserted before the dynamically generated content. 151 * 152 * @since 5.3.0 153 * 154 * @param string[] $instructions Array of lines with inline instructions. 155 * @param string $marker The marker being inserted. 156 */ 157 $instructions = apply_filters( 'insert_with_markers_inline_instructions', $instructions, $marker ); 158 159 if ( $switched_locale ) { 160 restore_previous_locale(); 161 } 162 163 $insertion = array_merge( $instructions, $insertion ); 164 165 $start_marker = "# BEGIN {$marker}"; 166 $end_marker = "# END {$marker}"; 167 168 $fp = fopen( $filename, 'r+' ); 169 if ( ! $fp ) { 170 return false; 171 } 172 173 // Attempt to get a lock. If the filesystem supports locking, this will block until the lock is acquired. 174 flock( $fp, LOCK_EX ); 175 176 $lines = array(); 177 while ( ! feof( $fp ) ) { 178 $lines[] = rtrim( fgets( $fp ), "\r\n" ); 179 } 180 181 // Split out the existing file into the preceding lines, and those that appear after the marker. 182 $pre_lines = array(); 183 $post_lines = array(); 184 $existing_lines = array(); 185 $found_marker = false; 186 $found_end_marker = false; 187 foreach ( $lines as $line ) { 188 if ( ! $found_marker && false !== strpos( $line, $start_marker ) ) { 189 $found_marker = true; 190 continue; 191 } elseif ( ! $found_end_marker && false !== strpos( $line, $end_marker ) ) { 192 $found_end_marker = true; 193 continue; 194 } 195 if ( ! $found_marker ) { 196 $pre_lines[] = $line; 197 } elseif ( $found_marker && $found_end_marker ) { 198 $post_lines[] = $line; 199 } else { 200 $existing_lines[] = $line; 201 } 202 } 203 204 // Check to see if there was a change. 205 if ( $existing_lines === $insertion ) { 206 flock( $fp, LOCK_UN ); 207 fclose( $fp ); 208 209 return true; 210 } 211 212 // Generate the new file data. 213 $new_file_data = implode( 214 "\n", 215 array_merge( 216 $pre_lines, 217 array( $start_marker ), 218 $insertion, 219 array( $end_marker ), 220 $post_lines 221 ) 222 ); 223 224 // Write to the start of the file, and truncate it to that length. 225 fseek( $fp, 0 ); 226 $bytes = fwrite( $fp, $new_file_data ); 227 if ( $bytes ) { 228 ftruncate( $fp, ftell( $fp ) ); 229 } 230 fflush( $fp ); 231 flock( $fp, LOCK_UN ); 232 fclose( $fp ); 233 234 return (bool) $bytes; 235 } 236 237 /** 238 * Updates the htaccess file with the current rules if it is writable. 239 * 240 * Always writes to the file if it exists and is writable to ensure that we 241 * blank out old rules. 242 * 243 * @since 1.5.0 244 * 245 * @global WP_Rewrite $wp_rewrite WordPress rewrite component. 246 * 247 * @return bool|null True on write success, false on failure. Null in multisite. 248 */ 249 function save_mod_rewrite_rules() { 250 if ( is_multisite() ) { 251 return; 252 } 253 254 global $wp_rewrite; 255 256 // Ensure get_home_path() is declared. 257 require_once ABSPATH . 'wp-admin/includes/file.php'; 258 259 $home_path = get_home_path(); 260 $htaccess_file = $home_path . '.htaccess'; 261 262 /* 263 * If the file doesn't already exist check for write access to the directory 264 * and whether we have some rules. Else check for write access to the file. 265 */ 266 if ( ( ! file_exists( $htaccess_file ) && is_writable( $home_path ) && $wp_rewrite->using_mod_rewrite_permalinks() ) || is_writable( $htaccess_file ) ) { 267 if ( got_mod_rewrite() ) { 268 $rules = explode( "\n", $wp_rewrite->mod_rewrite_rules() ); 269 return insert_with_markers( $htaccess_file, 'WordPress', $rules ); 270 } 271 } 272 273 return false; 274 } 275 276 /** 277 * Updates the IIS web.config file with the current rules if it is writable. 278 * If the permalinks do not require rewrite rules then the rules are deleted from the web.config file. 279 * 280 * @since 2.8.0 281 * 282 * @global WP_Rewrite $wp_rewrite WordPress rewrite component. 283 * 284 * @return bool|null True on write success, false on failure. Null in multisite. 285 */ 286 function iis7_save_url_rewrite_rules() { 287 if ( is_multisite() ) { 288 return; 289 } 290 291 global $wp_rewrite; 292 293 // Ensure get_home_path() is declared. 294 require_once ABSPATH . 'wp-admin/includes/file.php'; 295 296 $home_path = get_home_path(); 297 $web_config_file = $home_path . 'web.config'; 298 299 // Using win_is_writable() instead of is_writable() because of a bug in Windows PHP. 300 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 ) ) ) { 301 $rule = $wp_rewrite->iis7_url_rewrite_rules( false ); 302 if ( ! empty( $rule ) ) { 303 return iis7_add_rewrite_rule( $web_config_file, $rule ); 304 } else { 305 return iis7_delete_rewrite_rule( $web_config_file ); 306 } 307 } 308 return false; 309 } 310 311 /** 312 * Update the "recently-edited" file for the plugin or theme editor. 313 * 314 * @since 1.5.0 315 * 316 * @param string $file 317 */ 318 function update_recently_edited( $file ) { 319 $oldfiles = (array) get_option( 'recently_edited' ); 320 if ( $oldfiles ) { 321 $oldfiles = array_reverse( $oldfiles ); 322 $oldfiles[] = $file; 323 $oldfiles = array_reverse( $oldfiles ); 324 $oldfiles = array_unique( $oldfiles ); 325 if ( 5 < count( $oldfiles ) ) { 326 array_pop( $oldfiles ); 327 } 328 } else { 329 $oldfiles[] = $file; 330 } 331 update_option( 'recently_edited', $oldfiles ); 332 } 333 334 /** 335 * Makes a tree structure for the theme editor's file list. 336 * 337 * @since 4.9.0 338 * @access private 339 * 340 * @param array $allowed_files List of theme file paths. 341 * @return array Tree structure for listing theme files. 342 */ 343 function wp_make_theme_file_tree( $allowed_files ) { 344 $tree_list = array(); 345 foreach ( $allowed_files as $file_name => $absolute_filename ) { 346 $list = explode( '/', $file_name ); 347 $last_dir = &$tree_list; 348 foreach ( $list as $dir ) { 349 $last_dir =& $last_dir[ $dir ]; 350 } 351 $last_dir = $file_name; 352 } 353 return $tree_list; 354 } 355 356 /** 357 * Outputs the formatted file list for the theme editor. 358 * 359 * @since 4.9.0 360 * @access private 361 * 362 * @global string $relative_file Name of the file being edited relative to the 363 * theme directory. 364 * @global string $stylesheet The stylesheet name of the theme being edited. 365 * 366 * @param array|string $tree List of file/folder paths, or filename. 367 * @param int $level The aria-level for the current iteration. 368 * @param int $size The aria-setsize for the current iteration. 369 * @param int $index The aria-posinset for the current iteration. 370 */ 371 function wp_print_theme_file_tree( $tree, $level = 2, $size = 1, $index = 1 ) { 372 global $relative_file, $stylesheet; 373 374 if ( is_array( $tree ) ) { 375 $index = 0; 376 $size = count( $tree ); 377 foreach ( $tree as $label => $theme_file ) : 378 $index++; 379 if ( ! is_array( $theme_file ) ) { 380 wp_print_theme_file_tree( $theme_file, $level, $index, $size ); 381 continue; 382 } 383 ?> 384 <li role="treeitem" aria-expanded="true" tabindex="-1" 385 aria-level="<?php echo esc_attr( $level ); ?>" 386 aria-setsize="<?php echo esc_attr( $size ); ?>" 387 aria-posinset="<?php echo esc_attr( $index ); ?>"> 388 <span class="folder-label"><?php echo esc_html( $label ); ?> <span class="screen-reader-text"><?php _e( 'folder' ); ?></span><span aria-hidden="true" class="icon"></span></span> 389 <ul role="group" class="tree-folder"><?php wp_print_theme_file_tree( $theme_file, $level + 1, $index, $size ); ?></ul> 390 </li> 391 <?php 392 endforeach; 393 } else { 394 $filename = $tree; 395 $url = add_query_arg( 396 array( 397 'file' => rawurlencode( $tree ), 398 'theme' => rawurlencode( $stylesheet ), 399 ), 400 self_admin_url( 'theme-editor.php' ) 401 ); 402 ?> 403 <li role="none" class="<?php echo esc_attr( $relative_file === $filename ? 'current-file' : '' ); ?>"> 404 <a role="treeitem" tabindex="<?php echo esc_attr( $relative_file === $filename ? '0' : '-1' ); ?>" 405 href="<?php echo esc_url( $url ); ?>" 406 aria-level="<?php echo esc_attr( $level ); ?>" 407 aria-setsize="<?php echo esc_attr( $size ); ?>" 408 aria-posinset="<?php echo esc_attr( $index ); ?>"> 409 <?php 410 $file_description = esc_html( get_file_description( $filename ) ); 411 if ( $file_description !== $filename && wp_basename( $filename ) !== $file_description ) { 412 $file_description .= '<br /><span class="nonessential">(' . esc_html( $filename ) . ')</span>'; 413 } 414 415 if ( $relative_file === $filename ) { 416 echo '<span class="notice notice-info">' . $file_description . '</span>'; 417 } else { 418 echo $file_description; 419 } 420 ?> 421 </a> 422 </li> 423 <?php 424 } 425 } 426 427 /** 428 * Makes a tree structure for the plugin editor's file list. 429 * 430 * @since 4.9.0 431 * @access private 432 * 433 * @param array $plugin_editable_files List of plugin file paths. 434 * @return array Tree structure for listing plugin files. 435 */ 436 function wp_make_plugin_file_tree( $plugin_editable_files ) { 437 $tree_list = array(); 438 foreach ( $plugin_editable_files as $plugin_file ) { 439 $list = explode( '/', preg_replace( '#^.+?/#', '', $plugin_file ) ); 440 $last_dir = &$tree_list; 441 foreach ( $list as $dir ) { 442 $last_dir =& $last_dir[ $dir ]; 443 } 444 $last_dir = $plugin_file; 445 } 446 return $tree_list; 447 } 448 449 /** 450 * Outputs the formatted file list for the plugin editor. 451 * 452 * @since 4.9.0 453 * @access private 454 * 455 * @param array|string $tree List of file/folder paths, or filename. 456 * @param string $label Name of file or folder to print. 457 * @param int $level The aria-level for the current iteration. 458 * @param int $size The aria-setsize for the current iteration. 459 * @param int $index The aria-posinset for the current iteration. 460 */ 461 function wp_print_plugin_file_tree( $tree, $label = '', $level = 2, $size = 1, $index = 1 ) { 462 global $file, $plugin; 463 if ( is_array( $tree ) ) { 464 $index = 0; 465 $size = count( $tree ); 466 foreach ( $tree as $label => $plugin_file ) : 467 $index++; 468 if ( ! is_array( $plugin_file ) ) { 469 wp_print_plugin_file_tree( $plugin_file, $label, $level, $index, $size ); 470 continue; 471 } 472 ?> 473 <li role="treeitem" aria-expanded="true" tabindex="-1" 474 aria-level="<?php echo esc_attr( $level ); ?>" 475 aria-setsize="<?php echo esc_attr( $size ); ?>" 476 aria-posinset="<?php echo esc_attr( $index ); ?>"> 477 <span class="folder-label"><?php echo esc_html( $label ); ?> <span class="screen-reader-text"><?php _e( 'folder' ); ?></span><span aria-hidden="true" class="icon"></span></span> 478 <ul role="group" class="tree-folder"><?php wp_print_plugin_file_tree( $plugin_file, '', $level + 1, $index, $size ); ?></ul> 479 </li> 480 <?php 481 endforeach; 482 } else { 483 $url = add_query_arg( 484 array( 485 'file' => rawurlencode( $tree ), 486 'plugin' => rawurlencode( $plugin ), 487 ), 488 self_admin_url( 'plugin-editor.php' ) 489 ); 490 ?> 491 <li role="none" class="<?php echo esc_attr( $file === $tree ? 'current-file' : '' ); ?>"> 492 <a role="treeitem" tabindex="<?php echo esc_attr( $file === $tree ? '0' : '-1' ); ?>" 493 href="<?php echo esc_url( $url ); ?>" 494 aria-level="<?php echo esc_attr( $level ); ?>" 495 aria-setsize="<?php echo esc_attr( $size ); ?>" 496 aria-posinset="<?php echo esc_attr( $index ); ?>"> 497 <?php 498 if ( $file === $tree ) { 499 echo '<span class="notice notice-info">' . esc_html( $label ) . '</span>'; 500 } else { 501 echo esc_html( $label ); 502 } 503 ?> 504 </a> 505 </li> 506 <?php 507 } 508 } 509 510 /** 511 * Flushes rewrite rules if siteurl, home or page_on_front changed. 512 * 513 * @since 2.1.0 514 * 515 * @param string $old_value 516 * @param string $value 517 */ 518 function update_home_siteurl( $old_value, $value ) { 519 if ( wp_installing() ) { 520 return; 521 } 522 523 if ( is_multisite() && ms_is_switched() ) { 524 delete_option( 'rewrite_rules' ); 525 } else { 526 flush_rewrite_rules(); 527 } 528 } 529 530 531 /** 532 * Resets global variables based on $_GET and $_POST 533 * 534 * This function resets global variables based on the names passed 535 * in the $vars array to the value of $_POST[$var] or $_GET[$var] or '' 536 * if neither is defined. 537 * 538 * @since 2.0.0 539 * 540 * @param array $vars An array of globals to reset. 541 */ 542 function wp_reset_vars( $vars ) { 543 foreach ( $vars as $var ) { 544 if ( empty( $_POST[ $var ] ) ) { 545 if ( empty( $_GET[ $var ] ) ) { 546 $GLOBALS[ $var ] = ''; 547 } else { 548 $GLOBALS[ $var ] = $_GET[ $var ]; 549 } 550 } else { 551 $GLOBALS[ $var ] = $_POST[ $var ]; 552 } 553 } 554 } 555 556 /** 557 * Displays the given administration message. 558 * 559 * @since 2.1.0 560 * 561 * @param string|WP_Error $message 562 */ 563 function show_message( $message ) { 564 if ( is_wp_error( $message ) ) { 565 if ( $message->get_error_data() && is_string( $message->get_error_data() ) ) { 566 $message = $message->get_error_message() . ': ' . $message->get_error_data(); 567 } else { 568 $message = $message->get_error_message(); 569 } 570 } 571 echo "<p>$message</p>\n"; 572 wp_ob_end_flush_all(); 573 flush(); 574 } 575 576 /** 577 * @since 2.8.0 578 * 579 * @param string $content 580 * @return array 581 */ 582 function wp_doc_link_parse( $content ) { 583 if ( ! is_string( $content ) || empty( $content ) ) { 584 return array(); 585 } 586 587 if ( ! function_exists( 'token_get_all' ) ) { 588 return array(); 589 } 590 591 $tokens = token_get_all( $content ); 592 $count = count( $tokens ); 593 $functions = array(); 594 $ignore_functions = array(); 595 for ( $t = 0; $t < $count - 2; $t++ ) { 596 if ( ! is_array( $tokens[ $t ] ) ) { 597 continue; 598 } 599 600 if ( T_STRING == $tokens[ $t ][0] && ( '(' === $tokens[ $t + 1 ] || '(' === $tokens[ $t + 2 ] ) ) { 601 // If it's a function or class defined locally, there's not going to be any docs available. 602 if ( ( isset( $tokens[ $t - 2 ][1] ) && in_array( $tokens[ $t - 2 ][1], array( 'function', 'class' ), true ) ) 603 || ( isset( $tokens[ $t - 2 ][0] ) && T_OBJECT_OPERATOR == $tokens[ $t - 1 ][0] ) 604 ) { 605 $ignore_functions[] = $tokens[ $t ][1]; 606 } 607 // Add this to our stack of unique references. 608 $functions[] = $tokens[ $t ][1]; 609 } 610 } 611 612 $functions = array_unique( $functions ); 613 sort( $functions ); 614 615 /** 616 * Filters the list of functions and classes to be ignored from the documentation lookup. 617 * 618 * @since 2.8.0 619 * 620 * @param string[] $ignore_functions Array of names of functions and classes to be ignored. 621 */ 622 $ignore_functions = apply_filters( 'documentation_ignore_functions', $ignore_functions ); 623 624 $ignore_functions = array_unique( $ignore_functions ); 625 626 $out = array(); 627 foreach ( $functions as $function ) { 628 if ( in_array( $function, $ignore_functions, true ) ) { 629 continue; 630 } 631 $out[] = $function; 632 } 633 634 return $out; 635 } 636 637 /** 638 * Saves option for number of rows when listing posts, pages, comments, etc. 639 * 640 * @since 2.8.0 641 */ 642 function set_screen_options() { 643 644 if ( isset( $_POST['wp_screen_options'] ) && is_array( $_POST['wp_screen_options'] ) ) { 645 check_admin_referer( 'screen-options-nonce', 'screenoptionnonce' ); 646 647 $user = wp_get_current_user(); 648 if ( ! $user ) { 649 return; 650 } 651 $option = $_POST['wp_screen_options']['option']; 652 $value = $_POST['wp_screen_options']['value']; 653 654 if ( sanitize_key( $option ) != $option ) { 655 return; 656 } 657 658 $map_option = $option; 659 $type = str_replace( 'edit_', '', $map_option ); 660 $type = str_replace( '_per_page', '', $type ); 661 if ( in_array( $type, get_taxonomies(), true ) ) { 662 $map_option = 'edit_tags_per_page'; 663 } elseif ( in_array( $type, get_post_types(), true ) ) { 664 $map_option = 'edit_per_page'; 665 } else { 666 $option = str_replace( '-', '_', $option ); 667 } 668 669 switch ( $map_option ) { 670 case 'edit_per_page': 671 case 'users_per_page': 672 case 'edit_comments_per_page': 673 case 'upload_per_page': 674 case 'edit_tags_per_page': 675 case 'plugins_per_page': 676 case 'export_personal_data_requests_per_page': 677 case 'remove_personal_data_requests_per_page': 678 // Network admin. 679 case 'sites_network_per_page': 680 case 'users_network_per_page': 681 case 'site_users_network_per_page': 682 case 'plugins_network_per_page': 683 case 'themes_network_per_page': 684 case 'site_themes_network_per_page': 685 $value = (int) $value; 686 if ( $value < 1 || $value > 999 ) { 687 return; 688 } 689 break; 690 default: 691 $screen_option = false; 692 693 if ( '_page' === substr( $option, -5 ) || 'layout_columns' === $option ) { 694 /** 695 * Filters a screen option value before it is set. 696 * 697 * The filter can also be used to modify non-standard [items]_per_page 698 * settings. See the parent function for a full list of standard options. 699 * 700 * Returning false from the filter will skip saving the current option. 701 * 702 * @since 2.8.0 703 * @since 5.4.2 Only applied to options ending with '_page', 704 * or the 'layout_columns' option. 705 * 706 * @see set_screen_options() 707 * 708 * @param mixed $screen_option The value to save instead of the option value. 709 * Default false (to skip saving the current option). 710 * @param string $option The option name. 711 * @param int $value The option value. 712 */ 713 $screen_option = apply_filters( 'set-screen-option', $screen_option, $option, $value ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores 714 } 715 716 /** 717 * Filters a screen option value before it is set. 718 * 719 * The dynamic portion of the hook, `$option`, refers to the option name. 720 * 721 * Returning false from the filter will skip saving the current option. 722 * 723 * @since 5.4.2 724 * 725 * @see set_screen_options() 726 * 727 * @param mixed $screen_option The value to save instead of the option value. 728 * Default false (to skip saving the current option). 729 * @param string $option The option name. 730 * @param int $value The option value. 731 */ 732 $value = apply_filters( "set_screen_option_{$option}", $screen_option, $option, $value ); 733 734 if ( false === $value ) { 735 return; 736 } 737 break; 738 } 739 740 update_user_meta( $user->ID, $option, $value ); 741 742 $url = remove_query_arg( array( 'pagenum', 'apage', 'paged' ), wp_get_referer() ); 743 if ( isset( $_POST['mode'] ) ) { 744 $url = add_query_arg( array( 'mode' => $_POST['mode'] ), $url ); 745 } 746 747 wp_safe_redirect( $url ); 748 exit; 749 } 750 } 751 752 /** 753 * Check if rewrite rule for WordPress already exists in the IIS 7+ configuration file 754 * 755 * @since 2.8.0 756 * 757 * @return bool 758 * @param string $filename The file path to the configuration file 759 */ 760 function iis7_rewrite_rule_exists( $filename ) { 761 if ( ! file_exists( $filename ) ) { 762 return false; 763 } 764 if ( ! class_exists( 'DOMDocument', false ) ) { 765 return false; 766 } 767 768 $doc = new DOMDocument(); 769 if ( $doc->load( $filename ) === false ) { 770 return false; 771 } 772 $xpath = new DOMXPath( $doc ); 773 $rules = $xpath->query( '/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]' ); 774 if ( 0 == $rules->length ) { 775 return false; 776 } else { 777 return true; 778 } 779 } 780 781 /** 782 * Delete WordPress rewrite rule from web.config file if it exists there 783 * 784 * @since 2.8.0 785 * 786 * @param string $filename Name of the configuration file 787 * @return bool 788 */ 789 function iis7_delete_rewrite_rule( $filename ) { 790 // If configuration file does not exist then rules also do not exist, so there is nothing to delete. 791 if ( ! file_exists( $filename ) ) { 792 return true; 793 } 794 795 if ( ! class_exists( 'DOMDocument', false ) ) { 796 return false; 797 } 798 799 $doc = new DOMDocument(); 800 $doc->preserveWhiteSpace = false; 801 802 if ( $doc->load( $filename ) === false ) { 803 return false; 804 } 805 $xpath = new DOMXPath( $doc ); 806 $rules = $xpath->query( '/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]' ); 807 if ( $rules->length > 0 ) { 808 $child = $rules->item( 0 ); 809 $parent = $child->parentNode; 810 $parent->removeChild( $child ); 811 $doc->formatOutput = true; 812 saveDomDocument( $doc, $filename ); 813 } 814 return true; 815 } 816 817 /** 818 * Add WordPress rewrite rule to the IIS 7+ configuration file. 819 * 820 * @since 2.8.0 821 * 822 * @param string $filename The file path to the configuration file 823 * @param string $rewrite_rule The XML fragment with URL Rewrite rule 824 * @return bool 825 */ 826 function iis7_add_rewrite_rule( $filename, $rewrite_rule ) { 827 if ( ! class_exists( 'DOMDocument', false ) ) { 828 return false; 829 } 830 831 // If configuration file does not exist then we create one. 832 if ( ! file_exists( $filename ) ) { 833 $fp = fopen( $filename, 'w' ); 834 fwrite( $fp, '<configuration/>' ); 835 fclose( $fp ); 836 } 837 838 $doc = new DOMDocument(); 839 $doc->preserveWhiteSpace = false; 840 841 if ( $doc->load( $filename ) === false ) { 842 return false; 843 } 844 845 $xpath = new DOMXPath( $doc ); 846 847 // First check if the rule already exists as in that case there is no need to re-add it. 848 $wordpress_rules = $xpath->query( '/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]' ); 849 if ( $wordpress_rules->length > 0 ) { 850 return true; 851 } 852 853 // Check the XPath to the rewrite rule and create XML nodes if they do not exist. 854 $xmlnodes = $xpath->query( '/configuration/system.webServer/rewrite/rules' ); 855 if ( $xmlnodes->length > 0 ) { 856 $rules_node = $xmlnodes->item( 0 ); 857 } else { 858 $rules_node = $doc->createElement( 'rules' ); 859 860 $xmlnodes = $xpath->query( '/configuration/system.webServer/rewrite' ); 861 if ( $xmlnodes->length > 0 ) { 862 $rewrite_node = $xmlnodes->item( 0 ); 863 $rewrite_node->appendChild( $rules_node ); 864 } else { 865 $rewrite_node = $doc->createElement( 'rewrite' ); 866 $rewrite_node->appendChild( $rules_node ); 867 868 $xmlnodes = $xpath->query( '/configuration/system.webServer' ); 869 if ( $xmlnodes->length > 0 ) { 870 $system_webServer_node = $xmlnodes->item( 0 ); 871 $system_webServer_node->appendChild( $rewrite_node ); 872 } else { 873 $system_webServer_node = $doc->createElement( 'system.webServer' ); 874 $system_webServer_node->appendChild( $rewrite_node ); 875 876 $xmlnodes = $xpath->query( '/configuration' ); 877 if ( $xmlnodes->length > 0 ) { 878 $config_node = $xmlnodes->item( 0 ); 879 $config_node->appendChild( $system_webServer_node ); 880 } else { 881 $config_node = $doc->createElement( 'configuration' ); 882 $doc->appendChild( $config_node ); 883 $config_node->appendChild( $system_webServer_node ); 884 } 885 } 886 } 887 } 888 889 $rule_fragment = $doc->createDocumentFragment(); 890 $rule_fragment->appendXML( $rewrite_rule ); 891 $rules_node->appendChild( $rule_fragment ); 892 893 $doc->encoding = 'UTF-8'; 894 $doc->formatOutput = true; 895 saveDomDocument( $doc, $filename ); 896 897 return true; 898 } 899 900 /** 901 * Saves the XML document into a file 902 * 903 * @since 2.8.0 904 * 905 * @param DOMDocument $doc 906 * @param string $filename 907 */ 908 function saveDomDocument( $doc, $filename ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid 909 $config = $doc->saveXML(); 910 $config = preg_replace( "/([^\r])\n/", "$1\r\n", $config ); 911 $fp = fopen( $filename, 'w' ); 912 fwrite( $fp, $config ); 913 fclose( $fp ); 914 } 915 916 /** 917 * Display the default admin color scheme picker (Used in user-edit.php) 918 * 919 * @since 3.0.0 920 * 921 * @global array $_wp_admin_css_colors 922 * 923 * @param int $user_id User ID. 924 */ 925 function admin_color_scheme_picker( $user_id ) { 926 global $_wp_admin_css_colors; 927 928 ksort( $_wp_admin_css_colors ); 929 930 if ( isset( $_wp_admin_css_colors['fresh'] ) ) { 931 // Set Default ('fresh') and Light should go first. 932 $_wp_admin_css_colors = array_filter( 933 array_merge( 934 array( 935 'fresh' => '', 936 'light' => '', 937 'modern' => '', 938 ), 939 $_wp_admin_css_colors 940 ) 941 ); 942 } 943 944 $current_color = get_user_option( 'admin_color', $user_id ); 945 946 if ( empty( $current_color ) || ! isset( $_wp_admin_css_colors[ $current_color ] ) ) { 947 $current_color = 'fresh'; 948 } 949 950 ?> 951 <fieldset id="color-picker" class="scheme-list"> 952 <legend class="screen-reader-text"><span><?php _e( 'Admin Color Scheme' ); ?></span></legend> 953 <?php 954 wp_nonce_field( 'save-color-scheme', 'color-nonce', false ); 955 foreach ( $_wp_admin_css_colors as $color => $color_info ) : 956 957 ?> 958 <div class="color-option <?php echo ( $color == $current_color ) ? 'selected' : ''; ?>"> 959 <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 ); ?> /> 960 <input type="hidden" class="css_url" value="<?php echo esc_url( $color_info->url ); ?>" /> 961 <input type="hidden" class="icon_colors" value="<?php echo esc_attr( wp_json_encode( array( 'icons' => $color_info->icon_colors ) ) ); ?>" /> 962 <label for="admin_color_<?php echo esc_attr( $color ); ?>"><?php echo esc_html( $color_info->name ); ?></label> 963 <table class="color-palette"> 964 <tr> 965 <?php 966 967 foreach ( $color_info->colors as $html_color ) { 968 ?> 969 <td style="background-color: <?php echo esc_attr( $html_color ); ?>"> </td> 970 <?php 971 } 972 973 ?> 974 </tr> 975 </table> 976 </div> 977 <?php 978 979 endforeach; 980 981 ?> 982 </fieldset> 983 <?php 984 } 985 986 /** 987 * 988 * @global array $_wp_admin_css_colors 989 */ 990 function wp_color_scheme_settings() { 991 global $_wp_admin_css_colors; 992 993 $color_scheme = get_user_option( 'admin_color' ); 994 995 // It's possible to have a color scheme set that is no longer registered. 996 if ( empty( $_wp_admin_css_colors[ $color_scheme ] ) ) { 997 $color_scheme = 'fresh'; 998 } 999 1000 if ( ! empty( $_wp_admin_css_colors[ $color_scheme ]->icon_colors ) ) { 1001 $icon_colors = $_wp_admin_css_colors[ $color_scheme ]->icon_colors; 1002 } elseif ( ! empty( $_wp_admin_css_colors['fresh']->icon_colors ) ) { 1003 $icon_colors = $_wp_admin_css_colors['fresh']->icon_colors; 1004 } else { 1005 // Fall back to the default set of icon colors if the default scheme is missing. 1006 $icon_colors = array( 1007 'base' => '#a7aaad', 1008 'focus' => '#72aee6', 1009 'current' => '#fff', 1010 ); 1011 } 1012 1013 echo '<script type="text/javascript">var _wpColorScheme = ' . wp_json_encode( array( 'icons' => $icon_colors ) ) . ";</script>\n"; 1014 } 1015 1016 /** 1017 * Displays the viewport meta in the admin. 1018 * 1019 * @since 5.5.0 1020 */ 1021 function wp_admin_viewport_meta() { 1022 /** 1023 * Filters the viewport meta in the admin. 1024 * 1025 * @since 5.5.0 1026 * 1027 * @param string $viewport_meta The viewport meta. 1028 */ 1029 $viewport_meta = apply_filters( 'admin_viewport_meta', 'width=device-width,initial-scale=1.0' ); 1030 1031 if ( empty( $viewport_meta ) ) { 1032 return; 1033 } 1034 1035 echo '<meta name="viewport" content="' . esc_attr( $viewport_meta ) . '">'; 1036 } 1037 1038 /** 1039 * Adds viewport meta for mobile in Customizer. 1040 * 1041 * Hooked to the {@see 'admin_viewport_meta'} filter. 1042 * 1043 * @since 5.5.0 1044 * 1045 * @param string $viewport_meta The viewport meta. 1046 * @return string Filtered viewport meta. 1047 */ 1048 function _customizer_mobile_viewport_meta( $viewport_meta ) { 1049 return trim( $viewport_meta, ',' ) . ',minimum-scale=0.5,maximum-scale=1.2'; 1050 } 1051 1052 /** 1053 * Check lock status for posts displayed on the Posts screen 1054 * 1055 * @since 3.6.0 1056 * 1057 * @param array $response The Heartbeat response. 1058 * @param array $data The $_POST data sent. 1059 * @param string $screen_id The screen ID. 1060 * @return array The Heartbeat response. 1061 */ 1062 function wp_check_locked_posts( $response, $data, $screen_id ) { 1063 $checked = array(); 1064 1065 if ( array_key_exists( 'wp-check-locked-posts', $data ) && is_array( $data['wp-check-locked-posts'] ) ) { 1066 foreach ( $data['wp-check-locked-posts'] as $key ) { 1067 $post_id = absint( substr( $key, 5 ) ); 1068 if ( ! $post_id ) { 1069 continue; 1070 } 1071 1072 $user_id = wp_check_post_lock( $post_id ); 1073 if ( $user_id ) { 1074 $user = get_userdata( $user_id ); 1075 if ( $user && current_user_can( 'edit_post', $post_id ) ) { 1076 $send = array( 1077 /* translators: %s: User's display name. */ 1078 'text' => sprintf( __( '%s is currently editing' ), $user->display_name ), 1079 ); 1080 1081 if ( get_option( 'show_avatars' ) ) { 1082 $send['avatar_src'] = get_avatar_url( $user->ID, array( 'size' => 18 ) ); 1083 $send['avatar_src_2x'] = get_avatar_url( $user->ID, array( 'size' => 36 ) ); 1084 } 1085 1086 $checked[ $key ] = $send; 1087 } 1088 } 1089 } 1090 } 1091 1092 if ( ! empty( $checked ) ) { 1093 $response['wp-check-locked-posts'] = $checked; 1094 } 1095 1096 return $response; 1097 } 1098 1099 /** 1100 * Check lock status on the New/Edit Post screen and refresh the lock 1101 * 1102 * @since 3.6.0 1103 * 1104 * @param array $response The Heartbeat response. 1105 * @param array $data The $_POST data sent. 1106 * @param string $screen_id The screen ID. 1107 * @return array The Heartbeat response. 1108 */ 1109 function wp_refresh_post_lock( $response, $data, $screen_id ) { 1110 if ( array_key_exists( 'wp-refresh-post-lock', $data ) ) { 1111 $received = $data['wp-refresh-post-lock']; 1112 $send = array(); 1113 1114 $post_id = absint( $received['post_id'] ); 1115 if ( ! $post_id ) { 1116 return $response; 1117 } 1118 1119 if ( ! current_user_can( 'edit_post', $post_id ) ) { 1120 return $response; 1121 } 1122 1123 $user_id = wp_check_post_lock( $post_id ); 1124 $user = get_userdata( $user_id ); 1125 if ( $user ) { 1126 $error = array( 1127 /* translators: %s: User's display name. */ 1128 'text' => sprintf( __( '%s has taken over and is currently editing.' ), $user->display_name ), 1129 ); 1130 1131 if ( get_option( 'show_avatars' ) ) { 1132 $error['avatar_src'] = get_avatar_url( $user->ID, array( 'size' => 64 ) ); 1133 $error['avatar_src_2x'] = get_avatar_url( $user->ID, array( 'size' => 128 ) ); 1134 } 1135 1136 $send['lock_error'] = $error; 1137 } else { 1138 $new_lock = wp_set_post_lock( $post_id ); 1139 if ( $new_lock ) { 1140 $send['new_lock'] = implode( ':', $new_lock ); 1141 } 1142 } 1143 1144 $response['wp-refresh-post-lock'] = $send; 1145 } 1146 1147 return $response; 1148 } 1149 1150 /** 1151 * Check nonce expiration on the New/Edit Post screen and refresh if needed 1152 * 1153 * @since 3.6.0 1154 * 1155 * @param array $response The Heartbeat response. 1156 * @param array $data The $_POST data sent. 1157 * @param string $screen_id The screen ID. 1158 * @return array The Heartbeat response. 1159 */ 1160 function wp_refresh_post_nonces( $response, $data, $screen_id ) { 1161 if ( array_key_exists( 'wp-refresh-post-nonces', $data ) ) { 1162 $received = $data['wp-refresh-post-nonces']; 1163 $response['wp-refresh-post-nonces'] = array( 'check' => 1 ); 1164 1165 $post_id = absint( $received['post_id'] ); 1166 if ( ! $post_id ) { 1167 return $response; 1168 } 1169 1170 if ( ! current_user_can( 'edit_post', $post_id ) ) { 1171 return $response; 1172 } 1173 1174 $response['wp-refresh-post-nonces'] = array( 1175 'replace' => array( 1176 'getpermalinknonce' => wp_create_nonce( 'getpermalink' ), 1177 'samplepermalinknonce' => wp_create_nonce( 'samplepermalink' ), 1178 'closedpostboxesnonce' => wp_create_nonce( 'closedpostboxes' ), 1179 '_ajax_linking_nonce' => wp_create_nonce( 'internal-linking' ), 1180 '_wpnonce' => wp_create_nonce( 'update-post_' . $post_id ), 1181 ), 1182 ); 1183 } 1184 1185 return $response; 1186 } 1187 1188 /** 1189 * Add the latest Heartbeat and REST-API nonce to the Heartbeat response. 1190 * 1191 * @since 5.0.0 1192 * 1193 * @param array $response The Heartbeat response. 1194 * @return array The Heartbeat response. 1195 */ 1196 function wp_refresh_heartbeat_nonces( $response ) { 1197 // Refresh the Rest API nonce. 1198 $response['rest_nonce'] = wp_create_nonce( 'wp_rest' ); 1199 1200 // Refresh the Heartbeat nonce. 1201 $response['heartbeat_nonce'] = wp_create_nonce( 'heartbeat-nonce' ); 1202 return $response; 1203 } 1204 1205 /** 1206 * Disable suspension of Heartbeat on the Add/Edit Post screens. 1207 * 1208 * @since 3.8.0 1209 * 1210 * @global string $pagenow 1211 * 1212 * @param array $settings An array of Heartbeat settings. 1213 * @return array Filtered Heartbeat settings. 1214 */ 1215 function wp_heartbeat_set_suspension( $settings ) { 1216 global $pagenow; 1217 1218 if ( 'post.php' === $pagenow || 'post-new.php' === $pagenow ) { 1219 $settings['suspension'] = 'disable'; 1220 } 1221 1222 return $settings; 1223 } 1224 1225 /** 1226 * Autosave with heartbeat 1227 * 1228 * @since 3.9.0 1229 * 1230 * @param array $response The Heartbeat response. 1231 * @param array $data The $_POST data sent. 1232 * @return array The Heartbeat response. 1233 */ 1234 function heartbeat_autosave( $response, $data ) { 1235 if ( ! empty( $data['wp_autosave'] ) ) { 1236 $saved = wp_autosave( $data['wp_autosave'] ); 1237 1238 if ( is_wp_error( $saved ) ) { 1239 $response['wp_autosave'] = array( 1240 'success' => false, 1241 'message' => $saved->get_error_message(), 1242 ); 1243 } elseif ( empty( $saved ) ) { 1244 $response['wp_autosave'] = array( 1245 'success' => false, 1246 'message' => __( 'Error while saving.' ), 1247 ); 1248 } else { 1249 /* translators: Draft saved date format, see https://www.php.net/manual/datetime.format.php */ 1250 $draft_saved_date_format = __( 'g:i:s a' ); 1251 $response['wp_autosave'] = array( 1252 'success' => true, 1253 /* translators: %s: Date and time. */ 1254 'message' => sprintf( __( 'Draft saved at %s.' ), date_i18n( $draft_saved_date_format ) ), 1255 ); 1256 } 1257 } 1258 1259 return $response; 1260 } 1261 1262 /** 1263 * Remove single-use URL parameters and create canonical link based on new URL. 1264 * 1265 * Remove specific query string parameters from a URL, create the canonical link, 1266 * put it in the admin header, and change the current URL to match. 1267 * 1268 * @since 4.2.0 1269 */ 1270 function wp_admin_canonical_url() { 1271 $removable_query_args = wp_removable_query_args(); 1272 1273 if ( empty( $removable_query_args ) ) { 1274 return; 1275 } 1276 1277 // Ensure we're using an absolute URL. 1278 $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); 1279 $filtered_url = remove_query_arg( $removable_query_args, $current_url ); 1280 ?> 1281 <link id="wp-admin-canonical" rel="canonical" href="<?php echo esc_url( $filtered_url ); ?>" /> 1282 <script> 1283 if ( window.history.replaceState ) { 1284 window.history.replaceState( null, null, document.getElementById( 'wp-admin-canonical' ).href + window.location.hash ); 1285 } 1286 </script> 1287 <?php 1288 } 1289 1290 /** 1291 * Send a referrer policy header so referrers are not sent externally from administration screens. 1292 * 1293 * @since 4.9.0 1294 */ 1295 function wp_admin_headers() { 1296 $policy = 'strict-origin-when-cross-origin'; 1297 1298 /** 1299 * Filters the admin referrer policy header value. 1300 * 1301 * @since 4.9.0 1302 * @since 4.9.5 The default value was changed to 'strict-origin-when-cross-origin'. 1303 * 1304 * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy 1305 * 1306 * @param string $policy The admin referrer policy header value. Default 'strict-origin-when-cross-origin'. 1307 */ 1308 $policy = apply_filters( 'admin_referrer_policy', $policy ); 1309 1310 header( sprintf( 'Referrer-Policy: %s', $policy ) ); 1311 } 1312 1313 /** 1314 * Outputs JS that reloads the page if the user navigated to it with the Back or Forward button. 1315 * 1316 * Used on the Edit Post and Add New Post screens. Needed to ensure the page is not loaded from browser cache, 1317 * so the post title and editor content are the last saved versions. Ideally this script should run first in the head. 1318 * 1319 * @since 4.6.0 1320 */ 1321 function wp_page_reload_on_back_button_js() { 1322 ?> 1323 <script> 1324 if ( typeof performance !== 'undefined' && performance.navigation && performance.navigation.type === 2 ) { 1325 document.location.reload( true ); 1326 } 1327 </script> 1328 <?php 1329 } 1330 1331 /** 1332 * Send a confirmation request email when a change of site admin email address is attempted. 1333 * 1334 * The new site admin address will not become active until confirmed. 1335 * 1336 * @since 3.0.0 1337 * @since 4.9.0 This function was moved from wp-admin/includes/ms.php so it's no longer Multisite specific. 1338 * 1339 * @param string $old_value The old site admin email address. 1340 * @param string $value The proposed new site admin email address. 1341 */ 1342 function update_option_new_admin_email( $old_value, $value ) { 1343 if ( get_option( 'admin_email' ) === $value || ! is_email( $value ) ) { 1344 return; 1345 } 1346 1347 $hash = md5( $value . time() . wp_rand() ); 1348 $new_admin_email = array( 1349 'hash' => $hash, 1350 'newemail' => $value, 1351 ); 1352 update_option( 'adminhash', $new_admin_email ); 1353 1354 $switched_locale = switch_to_locale( get_user_locale() ); 1355 1356 /* translators: Do not translate USERNAME, ADMIN_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */ 1357 $email_text = __( 1358 'Howdy ###USERNAME###, 1359 1360 You recently requested to have the administration email address on 1361 your site changed. 1362 1363 If this is correct, please click on the following link to change it: 1364 ###ADMIN_URL### 1365 1366 You can safely ignore and delete this email if you do not want to 1367 take this action. 1368 1369 This email has been sent to ###EMAIL### 1370 1371 Regards, 1372 All at ###SITENAME### 1373 ###SITEURL###' 1374 ); 1375 1376 /** 1377 * Filters the text of the email sent when a change of site admin email address is attempted. 1378 * 1379 * The following strings have a special meaning and will get replaced dynamically: 1380 * ###USERNAME### The current user's username. 1381 * ###ADMIN_URL### The link to click on to confirm the email change. 1382 * ###EMAIL### The proposed new site admin email address. 1383 * ###SITENAME### The name of the site. 1384 * ###SITEURL### The URL to the site. 1385 * 1386 * @since MU (3.0.0) 1387 * @since 4.9.0 This filter is no longer Multisite specific. 1388 * 1389 * @param string $email_text Text in the email. 1390 * @param array $new_admin_email { 1391 * Data relating to the new site admin email address. 1392 * 1393 * @type string $hash The secure hash used in the confirmation link URL. 1394 * @type string $newemail The proposed new site admin email address. 1395 * } 1396 */ 1397 $content = apply_filters( 'new_admin_email_content', $email_text, $new_admin_email ); 1398 1399 $current_user = wp_get_current_user(); 1400 $content = str_replace( '###USERNAME###', $current_user->user_login, $content ); 1401 $content = str_replace( '###ADMIN_URL###', esc_url( self_admin_url( 'options.php?adminhash=' . $hash ) ), $content ); 1402 $content = str_replace( '###EMAIL###', $value, $content ); 1403 $content = str_replace( '###SITENAME###', wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), $content ); 1404 $content = str_replace( '###SITEURL###', home_url(), $content ); 1405 1406 wp_mail( 1407 $value, 1408 sprintf( 1409 /* translators: New admin email address notification email subject. %s: Site title. */ 1410 __( '[%s] New Admin Email Address' ), 1411 wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ) 1412 ), 1413 $content 1414 ); 1415 1416 if ( $switched_locale ) { 1417 restore_previous_locale(); 1418 } 1419 } 1420 1421 /** 1422 * Appends '(Draft)' to draft page titles in the privacy page dropdown 1423 * so that unpublished content is obvious. 1424 * 1425 * @since 4.9.8 1426 * @access private 1427 * 1428 * @param string $title Page title. 1429 * @param WP_Post $page Page data object. 1430 * @return string Page title. 1431 */ 1432 function _wp_privacy_settings_filter_draft_page_titles( $title, $page ) { 1433 if ( 'draft' === $page->post_status && 'privacy' === get_current_screen()->id ) { 1434 /* translators: %s: Page title. */ 1435 $title = sprintf( __( '%s (Draft)' ), $title ); 1436 } 1437 1438 return $title; 1439 } 1440 1441 /** 1442 * Checks if the user needs to update PHP. 1443 * 1444 * @since 5.1.0 1445 * @since 5.1.1 Added the {@see 'wp_is_php_version_acceptable'} filter. 1446 * 1447 * @return array|false Array of PHP version data. False on failure. 1448 */ 1449 function wp_check_php_version() { 1450 $version = phpversion(); 1451 $key = md5( $version ); 1452 1453 $response = get_site_transient( 'php_check_' . $key ); 1454 if ( false === $response ) { 1455 $url = 'http://api.wordpress.org/core/serve-happy/1.0/'; 1456 if ( wp_http_supports( array( 'ssl' ) ) ) { 1457 $url = set_url_scheme( $url, 'https' ); 1458 } 1459 1460 $url = add_query_arg( 'php_version', $version, $url ); 1461 1462 $response = wp_remote_get( $url ); 1463 1464 if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { 1465 return false; 1466 } 1467 1468 /** 1469 * Response should be an array with: 1470 * 'recommended_version' - string - The PHP version recommended by WordPress. 1471 * 'is_supported' - boolean - Whether the PHP version is actively supported. 1472 * 'is_secure' - boolean - Whether the PHP version receives security updates. 1473 * 'is_acceptable' - boolean - Whether the PHP version is still acceptable for WordPress. 1474 */ 1475 $response = json_decode( wp_remote_retrieve_body( $response ), true ); 1476 1477 if ( ! is_array( $response ) ) { 1478 return false; 1479 } 1480 1481 set_site_transient( 'php_check_' . $key, $response, WEEK_IN_SECONDS ); 1482 } 1483 1484 if ( isset( $response['is_acceptable'] ) && $response['is_acceptable'] ) { 1485 /** 1486 * Filters whether the active PHP version is considered acceptable by WordPress. 1487 * 1488 * Returning false will trigger a PHP version warning to show up in the admin dashboard to administrators. 1489 * 1490 * This filter is only run if the wordpress.org Serve Happy API considers the PHP version acceptable, ensuring 1491 * that this filter can only make this check stricter, but not loosen it. 1492 * 1493 * @since 5.1.1 1494 * 1495 * @param bool $is_acceptable Whether the PHP version is considered acceptable. Default true. 1496 * @param string $version PHP version checked. 1497 */ 1498 $response['is_acceptable'] = (bool) apply_filters( 'wp_is_php_version_acceptable', true, $version ); 1499 } 1500 1501 return $response; 1502 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Apr 20 01:00:04 2021 | Cross-referenced by PHPXref 0.7.1 |