[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-admin/includes/ -> misc.php (source)

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


Generated: Wed Jul 24 01:00:02 2019 Cross-referenced by PHPXref 0.7.1