[ 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 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_writeable( $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                  /**
 692                   * Filters a screen option value before it is set.
 693                   *
 694                   * The filter can also be used to modify non-standard [items]_per_page
 695                   * settings. See the parent function for a full list of standard options.
 696                   *
 697                   * Returning false to the filter will skip saving the current option.
 698                   *
 699                   * @since 2.8.0
 700                   *
 701                   * @see set_screen_options()
 702                   *
 703                   * @param bool     $keep   Whether to save or skip saving the screen option value. Default false.
 704                   * @param string   $option The option name.
 705                   * @param int      $value  The number of rows to use.
 706                   */
 707                  $value = apply_filters( 'set-screen-option', false, $option, $value ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
 708  
 709                  if ( false === $value ) {
 710                      return;
 711                  }
 712                  break;
 713          }
 714  
 715          update_user_meta( $user->ID, $option, $value );
 716  
 717          $url = remove_query_arg( array( 'pagenum', 'apage', 'paged' ), wp_get_referer() );
 718          if ( isset( $_POST['mode'] ) ) {
 719              $url = add_query_arg( array( 'mode' => $_POST['mode'] ), $url );
 720          }
 721  
 722          wp_safe_redirect( $url );
 723          exit;
 724      }
 725  }
 726  
 727  /**
 728   * Check if rewrite rule for WordPress already exists in the IIS 7+ configuration file
 729   *
 730   * @since 2.8.0
 731   *
 732   * @return bool
 733   * @param string $filename The file path to the configuration file
 734   */
 735  function iis7_rewrite_rule_exists( $filename ) {
 736      if ( ! file_exists( $filename ) ) {
 737          return false;
 738      }
 739      if ( ! class_exists( 'DOMDocument', false ) ) {
 740          return false;
 741      }
 742  
 743      $doc = new DOMDocument();
 744      if ( $doc->load( $filename ) === false ) {
 745          return false;
 746      }
 747      $xpath = new DOMXPath( $doc );
 748      $rules = $xpath->query( '/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]' );
 749      if ( 0 == $rules->length ) {
 750          return false;
 751      } else {
 752          return true;
 753      }
 754  }
 755  
 756  /**
 757   * Delete WordPress rewrite rule from web.config file if it exists there
 758   *
 759   * @since 2.8.0
 760   *
 761   * @param string $filename Name of the configuration file
 762   * @return bool
 763   */
 764  function iis7_delete_rewrite_rule( $filename ) {
 765      // If configuration file does not exist then rules also do not exist, so there is nothing to delete.
 766      if ( ! file_exists( $filename ) ) {
 767          return true;
 768      }
 769  
 770      if ( ! class_exists( 'DOMDocument', false ) ) {
 771          return false;
 772      }
 773  
 774      $doc                     = new DOMDocument();
 775      $doc->preserveWhiteSpace = false;
 776  
 777      if ( $doc->load( $filename ) === false ) {
 778          return false;
 779      }
 780      $xpath = new DOMXPath( $doc );
 781      $rules = $xpath->query( '/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]' );
 782      if ( $rules->length > 0 ) {
 783          $child  = $rules->item( 0 );
 784          $parent = $child->parentNode;
 785          $parent->removeChild( $child );
 786          $doc->formatOutput = true;
 787          saveDomDocument( $doc, $filename );
 788      }
 789      return true;
 790  }
 791  
 792  /**
 793   * Add WordPress rewrite rule to the IIS 7+ configuration file.
 794   *
 795   * @since 2.8.0
 796   *
 797   * @param string $filename The file path to the configuration file
 798   * @param string $rewrite_rule The XML fragment with URL Rewrite rule
 799   * @return bool
 800   */
 801  function iis7_add_rewrite_rule( $filename, $rewrite_rule ) {
 802      if ( ! class_exists( 'DOMDocument', false ) ) {
 803          return false;
 804      }
 805  
 806      // If configuration file does not exist then we create one.
 807      if ( ! file_exists( $filename ) ) {
 808          $fp = fopen( $filename, 'w' );
 809          fwrite( $fp, '<configuration/>' );
 810          fclose( $fp );
 811      }
 812  
 813      $doc                     = new DOMDocument();
 814      $doc->preserveWhiteSpace = false;
 815  
 816      if ( $doc->load( $filename ) === false ) {
 817          return false;
 818      }
 819  
 820      $xpath = new DOMXPath( $doc );
 821  
 822      // First check if the rule already exists as in that case there is no need to re-add it.
 823      $wordpress_rules = $xpath->query( '/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]' );
 824      if ( $wordpress_rules->length > 0 ) {
 825          return true;
 826      }
 827  
 828      // Check the XPath to the rewrite rule and create XML nodes if they do not exist.
 829      $xmlnodes = $xpath->query( '/configuration/system.webServer/rewrite/rules' );
 830      if ( $xmlnodes->length > 0 ) {
 831          $rules_node = $xmlnodes->item( 0 );
 832      } else {
 833          $rules_node = $doc->createElement( 'rules' );
 834  
 835          $xmlnodes = $xpath->query( '/configuration/system.webServer/rewrite' );
 836          if ( $xmlnodes->length > 0 ) {
 837              $rewrite_node = $xmlnodes->item( 0 );
 838              $rewrite_node->appendChild( $rules_node );
 839          } else {
 840              $rewrite_node = $doc->createElement( 'rewrite' );
 841              $rewrite_node->appendChild( $rules_node );
 842  
 843              $xmlnodes = $xpath->query( '/configuration/system.webServer' );
 844              if ( $xmlnodes->length > 0 ) {
 845                  $system_webServer_node = $xmlnodes->item( 0 );
 846                  $system_webServer_node->appendChild( $rewrite_node );
 847              } else {
 848                  $system_webServer_node = $doc->createElement( 'system.webServer' );
 849                  $system_webServer_node->appendChild( $rewrite_node );
 850  
 851                  $xmlnodes = $xpath->query( '/configuration' );
 852                  if ( $xmlnodes->length > 0 ) {
 853                      $config_node = $xmlnodes->item( 0 );
 854                      $config_node->appendChild( $system_webServer_node );
 855                  } else {
 856                      $config_node = $doc->createElement( 'configuration' );
 857                      $doc->appendChild( $config_node );
 858                      $config_node->appendChild( $system_webServer_node );
 859                  }
 860              }
 861          }
 862      }
 863  
 864      $rule_fragment = $doc->createDocumentFragment();
 865      $rule_fragment->appendXML( $rewrite_rule );
 866      $rules_node->appendChild( $rule_fragment );
 867  
 868      $doc->encoding     = 'UTF-8';
 869      $doc->formatOutput = true;
 870      saveDomDocument( $doc, $filename );
 871  
 872      return true;
 873  }
 874  
 875  /**
 876   * Saves the XML document into a file
 877   *
 878   * @since 2.8.0
 879   *
 880   * @param DOMDocument $doc
 881   * @param string $filename
 882   */
 883  function saveDomDocument( $doc, $filename ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid
 884      $config = $doc->saveXML();
 885      $config = preg_replace( "/([^\r])\n/", "$1\r\n", $config );
 886      $fp     = fopen( $filename, 'w' );
 887      fwrite( $fp, $config );
 888      fclose( $fp );
 889  }
 890  
 891  /**
 892   * Display the default admin color scheme picker (Used in user-edit.php)
 893   *
 894   * @since 3.0.0
 895   *
 896   * @global array $_wp_admin_css_colors
 897   *
 898   * @param int $user_id User ID.
 899   */
 900  function admin_color_scheme_picker( $user_id ) {
 901      global $_wp_admin_css_colors;
 902  
 903      ksort( $_wp_admin_css_colors );
 904  
 905      if ( isset( $_wp_admin_css_colors['fresh'] ) ) {
 906          // Set Default ('fresh') and Light should go first.
 907          $_wp_admin_css_colors = array_filter(
 908              array_merge(
 909                  array(
 910                      'fresh' => '',
 911                      'light' => '',
 912                  ),
 913                  $_wp_admin_css_colors
 914              )
 915          );
 916      }
 917  
 918      $current_color = get_user_option( 'admin_color', $user_id );
 919  
 920      if ( empty( $current_color ) || ! isset( $_wp_admin_css_colors[ $current_color ] ) ) {
 921          $current_color = 'fresh';
 922      }
 923  
 924      ?>
 925      <fieldset id="color-picker" class="scheme-list">
 926          <legend class="screen-reader-text"><span><?php _e( 'Admin Color Scheme' ); ?></span></legend>
 927          <?php
 928          wp_nonce_field( 'save-color-scheme', 'color-nonce', false );
 929          foreach ( $_wp_admin_css_colors as $color => $color_info ) :
 930  
 931              ?>
 932              <div class="color-option <?php echo ( $color == $current_color ) ? 'selected' : ''; ?>">
 933                  <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 ); ?> />
 934                  <input type="hidden" class="css_url" value="<?php echo esc_url( $color_info->url ); ?>" />
 935                  <input type="hidden" class="icon_colors" value="<?php echo esc_attr( wp_json_encode( array( 'icons' => $color_info->icon_colors ) ) ); ?>" />
 936                  <label for="admin_color_<?php echo esc_attr( $color ); ?>"><?php echo esc_html( $color_info->name ); ?></label>
 937                  <table class="color-palette">
 938                      <tr>
 939                      <?php
 940  
 941                      foreach ( $color_info->colors as $html_color ) {
 942                          ?>
 943                          <td style="background-color: <?php echo esc_attr( $html_color ); ?>">&nbsp;</td>
 944                          <?php
 945                      }
 946  
 947                      ?>
 948                      </tr>
 949                  </table>
 950              </div>
 951              <?php
 952  
 953          endforeach;
 954  
 955          ?>
 956      </fieldset>
 957      <?php
 958  }
 959  
 960  /**
 961   *
 962   * @global array $_wp_admin_css_colors
 963   */
 964  function wp_color_scheme_settings() {
 965      global $_wp_admin_css_colors;
 966  
 967      $color_scheme = get_user_option( 'admin_color' );
 968  
 969      // It's possible to have a color scheme set that is no longer registered.
 970      if ( empty( $_wp_admin_css_colors[ $color_scheme ] ) ) {
 971          $color_scheme = 'fresh';
 972      }
 973  
 974      if ( ! empty( $_wp_admin_css_colors[ $color_scheme ]->icon_colors ) ) {
 975          $icon_colors = $_wp_admin_css_colors[ $color_scheme ]->icon_colors;
 976      } elseif ( ! empty( $_wp_admin_css_colors['fresh']->icon_colors ) ) {
 977          $icon_colors = $_wp_admin_css_colors['fresh']->icon_colors;
 978      } else {
 979          // Fall back to the default set of icon colors if the default scheme is missing.
 980          $icon_colors = array(
 981              'base'    => '#a0a5aa',
 982              'focus'   => '#00a0d2',
 983              'current' => '#fff',
 984          );
 985      }
 986  
 987      echo '<script type="text/javascript">var _wpColorScheme = ' . wp_json_encode( array( 'icons' => $icon_colors ) ) . ";</script>\n";
 988  }
 989  
 990  /**
 991   * @since 3.3.0
 992   */
 993  function _ipad_meta() {
 994      if ( wp_is_mobile() ) {
 995          ?>
 996          <meta name="viewport" id="viewport-meta" content="width=device-width, initial-scale=1">
 997          <?php
 998      }
 999  }
1000  
1001  /**
1002   * Check lock status for posts displayed on the Posts screen
1003   *
1004   * @since 3.6.0
1005   *
1006   * @param array  $response  The Heartbeat response.
1007   * @param array  $data      The $_POST data sent.
1008   * @param string $screen_id The screen id.
1009   * @return array The Heartbeat response.
1010   */
1011  function wp_check_locked_posts( $response, $data, $screen_id ) {
1012      $checked = array();
1013  
1014      if ( array_key_exists( 'wp-check-locked-posts', $data ) && is_array( $data['wp-check-locked-posts'] ) ) {
1015          foreach ( $data['wp-check-locked-posts'] as $key ) {
1016              $post_id = absint( substr( $key, 5 ) );
1017              if ( ! $post_id ) {
1018                  continue;
1019              }
1020  
1021              $user_id = wp_check_post_lock( $post_id );
1022              if ( $user_id ) {
1023                  $user = get_userdata( $user_id );
1024                  if ( $user && current_user_can( 'edit_post', $post_id ) ) {
1025                      $send = array(
1026                          /* translators: %s: User's display name. */
1027                          'text' => sprintf( __( '%s is currently editing' ), $user->display_name ),
1028                      );
1029  
1030                      $avatar = get_avatar( $user->ID, 18 );
1031                      if ( $avatar && preg_match( "|src='([^']+)'|", $avatar, $matches ) ) {
1032                          $send['avatar_src'] = $matches[1];
1033                      }
1034  
1035                      $checked[ $key ] = $send;
1036                  }
1037              }
1038          }
1039      }
1040  
1041      if ( ! empty( $checked ) ) {
1042          $response['wp-check-locked-posts'] = $checked;
1043      }
1044  
1045      return $response;
1046  }
1047  
1048  /**
1049   * Check lock status on the New/Edit Post screen and refresh the lock
1050   *
1051   * @since 3.6.0
1052   *
1053   * @param array  $response  The Heartbeat response.
1054   * @param array  $data      The $_POST data sent.
1055   * @param string $screen_id The screen id.
1056   * @return array The Heartbeat response.
1057   */
1058  function wp_refresh_post_lock( $response, $data, $screen_id ) {
1059      if ( array_key_exists( 'wp-refresh-post-lock', $data ) ) {
1060          $received = $data['wp-refresh-post-lock'];
1061          $send     = array();
1062  
1063          $post_id = absint( $received['post_id'] );
1064          if ( ! $post_id ) {
1065              return $response;
1066          }
1067  
1068          if ( ! current_user_can( 'edit_post', $post_id ) ) {
1069              return $response;
1070          }
1071  
1072          $user_id = wp_check_post_lock( $post_id );
1073          $user    = get_userdata( $user_id );
1074          if ( $user ) {
1075              $error = array(
1076                  /* translators: %s: User's display name. */
1077                  'text' => sprintf( __( '%s has taken over and is currently editing.' ), $user->display_name ),
1078              );
1079  
1080              $avatar = get_avatar( $user->ID, 64 );
1081              if ( $avatar ) {
1082                  if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) {
1083                      $error['avatar_src'] = $matches[1];
1084                  }
1085              }
1086  
1087              $send['lock_error'] = $error;
1088          } else {
1089              $new_lock = wp_set_post_lock( $post_id );
1090              if ( $new_lock ) {
1091                  $send['new_lock'] = implode( ':', $new_lock );
1092              }
1093          }
1094  
1095          $response['wp-refresh-post-lock'] = $send;
1096      }
1097  
1098      return $response;
1099  }
1100  
1101  /**
1102   * Check nonce expiration on the New/Edit Post screen and refresh if needed
1103   *
1104   * @since 3.6.0
1105   *
1106   * @param array  $response  The Heartbeat response.
1107   * @param array  $data      The $_POST data sent.
1108   * @param string $screen_id The screen id.
1109   * @return array The Heartbeat response.
1110   */
1111  function wp_refresh_post_nonces( $response, $data, $screen_id ) {
1112      if ( array_key_exists( 'wp-refresh-post-nonces', $data ) ) {
1113          $received                           = $data['wp-refresh-post-nonces'];
1114          $response['wp-refresh-post-nonces'] = array( 'check' => 1 );
1115  
1116          $post_id = absint( $received['post_id'] );
1117          if ( ! $post_id ) {
1118              return $response;
1119          }
1120  
1121          if ( ! current_user_can( 'edit_post', $post_id ) ) {
1122              return $response;
1123          }
1124  
1125          $response['wp-refresh-post-nonces'] = array(
1126              'replace' => array(
1127                  'getpermalinknonce'    => wp_create_nonce( 'getpermalink' ),
1128                  'samplepermalinknonce' => wp_create_nonce( 'samplepermalink' ),
1129                  'closedpostboxesnonce' => wp_create_nonce( 'closedpostboxes' ),
1130                  '_ajax_linking_nonce'  => wp_create_nonce( 'internal-linking' ),
1131                  '_wpnonce'             => wp_create_nonce( 'update-post_' . $post_id ),
1132              ),
1133          );
1134      }
1135  
1136      return $response;
1137  }
1138  
1139  /**
1140   * Add the latest Heartbeat and REST-API nonce to the Heartbeat response.
1141   *
1142   * @since 5.0.0
1143   *
1144   * @param array  $response  The Heartbeat response.
1145   * @return array The Heartbeat response.
1146   */
1147  function wp_refresh_heartbeat_nonces( $response ) {
1148      // Refresh the Rest API nonce.
1149      $response['rest_nonce'] = wp_create_nonce( 'wp_rest' );
1150  
1151      // Refresh the Heartbeat nonce.
1152      $response['heartbeat_nonce'] = wp_create_nonce( 'heartbeat-nonce' );
1153      return $response;
1154  }
1155  
1156  /**
1157   * Disable suspension of Heartbeat on the Add/Edit Post screens.
1158   *
1159   * @since 3.8.0
1160   *
1161   * @global string $pagenow
1162   *
1163   * @param array $settings An array of Heartbeat settings.
1164   * @return array Filtered Heartbeat settings.
1165   */
1166  function wp_heartbeat_set_suspension( $settings ) {
1167      global $pagenow;
1168  
1169      if ( 'post.php' === $pagenow || 'post-new.php' === $pagenow ) {
1170          $settings['suspension'] = 'disable';
1171      }
1172  
1173      return $settings;
1174  }
1175  
1176  /**
1177   * Autosave with heartbeat
1178   *
1179   * @since 3.9.0
1180   *
1181   * @param array $response The Heartbeat response.
1182   * @param array $data     The $_POST data sent.
1183   * @return array The Heartbeat response.
1184   */
1185  function heartbeat_autosave( $response, $data ) {
1186      if ( ! empty( $data['wp_autosave'] ) ) {
1187          $saved = wp_autosave( $data['wp_autosave'] );
1188  
1189          if ( is_wp_error( $saved ) ) {
1190              $response['wp_autosave'] = array(
1191                  'success' => false,
1192                  'message' => $saved->get_error_message(),
1193              );
1194          } elseif ( empty( $saved ) ) {
1195              $response['wp_autosave'] = array(
1196                  'success' => false,
1197                  'message' => __( 'Error while saving.' ),
1198              );
1199          } else {
1200              /* translators: Draft saved date format, see https://www.php.net/date */
1201              $draft_saved_date_format = __( 'g:i:s a' );
1202              $response['wp_autosave'] = array(
1203                  'success' => true,
1204                  /* translators: %s: Date and time. */
1205                  'message' => sprintf( __( 'Draft saved at %s.' ), date_i18n( $draft_saved_date_format ) ),
1206              );
1207          }
1208      }
1209  
1210      return $response;
1211  }
1212  
1213  /**
1214   * Remove single-use URL parameters and create canonical link based on new URL.
1215   *
1216   * Remove specific query string parameters from a URL, create the canonical link,
1217   * put it in the admin header, and change the current URL to match.
1218   *
1219   * @since 4.2.0
1220   */
1221  function wp_admin_canonical_url() {
1222      $removable_query_args = wp_removable_query_args();
1223  
1224      if ( empty( $removable_query_args ) ) {
1225          return;
1226      }
1227  
1228      // Ensure we're using an absolute URL.
1229      $current_url  = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
1230      $filtered_url = remove_query_arg( $removable_query_args, $current_url );
1231      ?>
1232      <link id="wp-admin-canonical" rel="canonical" href="<?php echo esc_url( $filtered_url ); ?>" />
1233      <script>
1234          if ( window.history.replaceState ) {
1235              window.history.replaceState( null, null, document.getElementById( 'wp-admin-canonical' ).href + window.location.hash );
1236          }
1237      </script>
1238      <?php
1239  }
1240  
1241  /**
1242   * Send a referrer policy header so referrers are not sent externally from administration screens.
1243   *
1244   * @since 4.9.0
1245   */
1246  function wp_admin_headers() {
1247      $policy = 'strict-origin-when-cross-origin';
1248  
1249      /**
1250       * Filters the admin referrer policy header value.
1251       *
1252       * @since 4.9.0
1253       * @since 4.9.5 The default value was changed to 'strict-origin-when-cross-origin'.
1254       *
1255       * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
1256       *
1257       * @param string $policy The admin referrer policy header value. Default 'strict-origin-when-cross-origin'.
1258       */
1259      $policy = apply_filters( 'admin_referrer_policy', $policy );
1260  
1261      header( sprintf( 'Referrer-Policy: %s', $policy ) );
1262  }
1263  
1264  /**
1265   * Outputs JS that reloads the page if the user navigated to it with the Back or Forward button.
1266   *
1267   * Used on the Edit Post and Add New Post screens. Needed to ensure the page is not loaded from browser cache,
1268   * so the post title and editor content are the last saved versions. Ideally this script should run first in the head.
1269   *
1270   * @since 4.6.0
1271   */
1272  function wp_page_reload_on_back_button_js() {
1273      ?>
1274      <script>
1275          if ( typeof performance !== 'undefined' && performance.navigation && performance.navigation.type === 2 ) {
1276              document.location.reload( true );
1277          }
1278      </script>
1279      <?php
1280  }
1281  
1282  /**
1283   * Send a confirmation request email when a change of site admin email address is attempted.
1284   *
1285   * The new site admin address will not become active until confirmed.
1286   *
1287   * @since 3.0.0
1288   * @since 4.9.0 This function was moved from wp-admin/includes/ms.php so it's no longer Multisite specific.
1289   *
1290   * @param string $old_value The old site admin email address.
1291   * @param string $value     The proposed new site admin email address.
1292   */
1293  function update_option_new_admin_email( $old_value, $value ) {
1294      if ( get_option( 'admin_email' ) === $value || ! is_email( $value ) ) {
1295          return;
1296      }
1297  
1298      $hash            = md5( $value . time() . wp_rand() );
1299      $new_admin_email = array(
1300          'hash'     => $hash,
1301          'newemail' => $value,
1302      );
1303      update_option( 'adminhash', $new_admin_email );
1304  
1305      $switched_locale = switch_to_locale( get_user_locale() );
1306  
1307      /* translators: Do not translate USERNAME, ADMIN_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */
1308      $email_text = __(
1309          'Howdy ###USERNAME###,
1310  
1311  You recently requested to have the administration email address on
1312  your site changed.
1313  
1314  If this is correct, please click on the following link to change it:
1315  ###ADMIN_URL###
1316  
1317  You can safely ignore and delete this email if you do not want to
1318  take this action.
1319  
1320  This email has been sent to ###EMAIL###
1321  
1322  Regards,
1323  All at ###SITENAME###
1324  ###SITEURL###'
1325      );
1326  
1327      /**
1328       * Filters the text of the email sent when a change of site admin email address is attempted.
1329       *
1330       * The following strings have a special meaning and will get replaced dynamically:
1331       * ###USERNAME###  The current user's username.
1332       * ###ADMIN_URL### The link to click on to confirm the email change.
1333       * ###EMAIL###     The proposed new site admin email address.
1334       * ###SITENAME###  The name of the site.
1335       * ###SITEURL###   The URL to the site.
1336       *
1337       * @since MU (3.0.0)
1338       * @since 4.9.0 This filter is no longer Multisite specific.
1339       *
1340       * @param string $email_text      Text in the email.
1341       * @param array  $new_admin_email {
1342       *     Data relating to the new site admin email address.
1343       *
1344       *     @type string $hash     The secure hash used in the confirmation link URL.
1345       *     @type string $newemail The proposed new site admin email address.
1346       * }
1347       */
1348      $content = apply_filters( 'new_admin_email_content', $email_text, $new_admin_email );
1349  
1350      $current_user = wp_get_current_user();
1351      $content      = str_replace( '###USERNAME###', $current_user->user_login, $content );
1352      $content      = str_replace( '###ADMIN_URL###', esc_url( self_admin_url( 'options.php?adminhash=' . $hash ) ), $content );
1353      $content      = str_replace( '###EMAIL###', $value, $content );
1354      $content      = str_replace( '###SITENAME###', wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), $content );
1355      $content      = str_replace( '###SITEURL###', home_url(), $content );
1356  
1357      wp_mail(
1358          $value,
1359          sprintf(
1360              /* translators: New admin email address notification email subject. %s: Site title. */
1361              __( '[%s] New Admin Email Address' ),
1362              wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES )
1363          ),
1364          $content
1365      );
1366  
1367      if ( $switched_locale ) {
1368          restore_previous_locale();
1369      }
1370  }
1371  
1372  /**
1373   * Appends '(Draft)' to draft page titles in the privacy page dropdown
1374   * so that unpublished content is obvious.
1375   *
1376   * @since 4.9.8
1377   * @access private
1378   *
1379   * @param string  $title Page title.
1380   * @param WP_Post $page  Page data object.
1381   *
1382   * @return string Page title.
1383   */
1384  function _wp_privacy_settings_filter_draft_page_titles( $title, $page ) {
1385      if ( 'draft' === $page->post_status && 'privacy' === get_current_screen()->id ) {
1386          /* translators: %s: Page title. */
1387          $title = sprintf( __( '%s (Draft)' ), $title );
1388      }
1389  
1390      return $title;
1391  }
1392  
1393  /**
1394   * Checks if the user needs to update PHP.
1395   *
1396   * @since 5.1.0
1397   * @since 5.1.1 Added the {@see 'wp_is_php_version_acceptable'} filter.
1398   *
1399   * @return array|false $response Array of PHP version data. False on failure.
1400   */
1401  function wp_check_php_version() {
1402      $version = phpversion();
1403      $key     = md5( $version );
1404  
1405      $response = get_site_transient( 'php_check_' . $key );
1406      if ( false === $response ) {
1407          $url = 'http://api.wordpress.org/core/serve-happy/1.0/';
1408          if ( wp_http_supports( array( 'ssl' ) ) ) {
1409              $url = set_url_scheme( $url, 'https' );
1410          }
1411  
1412          $url = add_query_arg( 'php_version', $version, $url );
1413  
1414          $response = wp_remote_get( $url );
1415  
1416          if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
1417              return false;
1418          }
1419  
1420          /**
1421           * Response should be an array with:
1422           *  'recommended_version' - string - The PHP version recommended by WordPress.
1423           *  'is_supported' - boolean - Whether the PHP version is actively supported.
1424           *  'is_secure' - boolean - Whether the PHP version receives security updates.
1425           *  'is_acceptable' - boolean - Whether the PHP version is still acceptable for WordPress.
1426           */
1427          $response = json_decode( wp_remote_retrieve_body( $response ), true );
1428  
1429          if ( ! is_array( $response ) ) {
1430              return false;
1431          }
1432  
1433          set_site_transient( 'php_check_' . $key, $response, WEEK_IN_SECONDS );
1434      }
1435  
1436      if ( isset( $response['is_acceptable'] ) && $response['is_acceptable'] ) {
1437          /**
1438           * Filters whether the active PHP version is considered acceptable by WordPress.
1439           *
1440           * Returning false will trigger a PHP version warning to show up in the admin dashboard to administrators.
1441           *
1442           * This filter is only run if the wordpress.org Serve Happy API considers the PHP version acceptable, ensuring
1443           * that this filter can only make this check stricter, but not loosen it.
1444           *
1445           * @since 5.1.1
1446           *
1447           * @param bool   $is_acceptable Whether the PHP version is considered acceptable. Default true.
1448           * @param string $version       PHP version checked.
1449           */
1450          $response['is_acceptable'] = (bool) apply_filters( 'wp_is_php_version_acceptable', true, $version );
1451      }
1452  
1453      return $response;
1454  }


Generated: Thu Jun 4 01:00:04 2020 Cross-referenced by PHPXref 0.7.1