[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> load.php (source)

   1  <?php
   2  /**
   3   * These functions are needed to load WordPress.
   4   *
   5   * @package WordPress
   6   */
   7  
   8  /**
   9   * Returns the HTTP protocol sent by the server.
  10   *
  11   * @since 4.4.0
  12   *
  13   * @return string The HTTP protocol. Default: HTTP/1.0.
  14   */
  15  function wp_get_server_protocol() {
  16      $protocol = $_SERVER['SERVER_PROTOCOL'] ?? '';
  17  
  18      if ( ! in_array( $protocol, array( 'HTTP/1.1', 'HTTP/2', 'HTTP/2.0', 'HTTP/3' ), true ) ) {
  19          $protocol = 'HTTP/1.0';
  20      }
  21  
  22      return $protocol;
  23  }
  24  
  25  /**
  26   * Fixes `$_SERVER` variables for various setups.
  27   *
  28   * @since 3.0.0
  29   * @access private
  30   *
  31   * @global string $PHP_SELF The filename of the currently executing script,
  32   *                          relative to the document root.
  33   */
  34  function wp_fix_server_vars() {
  35      global $PHP_SELF;
  36  
  37      $default_server_values = array(
  38          'SERVER_SOFTWARE' => '',
  39          'REQUEST_URI'     => '',
  40      );
  41  
  42      $_SERVER = array_merge( $default_server_values, $_SERVER );
  43  
  44      // Fix for IIS when running with PHP ISAPI.
  45      if ( empty( $_SERVER['REQUEST_URI'] )
  46          || ( 'cgi-fcgi' !== PHP_SAPI && preg_match( '/^Microsoft-IIS\//', $_SERVER['SERVER_SOFTWARE'] ) )
  47      ) {
  48  
  49          if ( isset( $_SERVER['HTTP_X_ORIGINAL_URL'] ) ) {
  50              // IIS Mod-Rewrite.
  51              $_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_ORIGINAL_URL'];
  52          } elseif ( isset( $_SERVER['HTTP_X_REWRITE_URL'] ) ) {
  53              // IIS Isapi_Rewrite.
  54              $_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_REWRITE_URL'];
  55          } else {
  56              // Use ORIG_PATH_INFO if there is no PATH_INFO.
  57              if ( ! isset( $_SERVER['PATH_INFO'] ) && isset( $_SERVER['ORIG_PATH_INFO'] ) ) {
  58                  $_SERVER['PATH_INFO'] = $_SERVER['ORIG_PATH_INFO'];
  59              }
  60  
  61              // Some IIS + PHP configurations put the script-name in the path-info (no need to append it twice).
  62              if ( isset( $_SERVER['PATH_INFO'] ) ) {
  63                  if ( $_SERVER['PATH_INFO'] === $_SERVER['SCRIPT_NAME'] ) {
  64                      $_SERVER['REQUEST_URI'] = $_SERVER['PATH_INFO'];
  65                  } else {
  66                      $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . $_SERVER['PATH_INFO'];
  67                  }
  68              }
  69  
  70              // Append the query string if it exists and isn't null.
  71              if ( ! empty( $_SERVER['QUERY_STRING'] ) ) {
  72                  $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
  73              }
  74          }
  75      }
  76  
  77      // Fix for PHP as CGI hosts that set SCRIPT_FILENAME to something ending in php.cgi for all requests.
  78      if ( isset( $_SERVER['SCRIPT_FILENAME'] ) && str_ends_with( $_SERVER['SCRIPT_FILENAME'], 'php.cgi' ) ) {
  79          $_SERVER['SCRIPT_FILENAME'] = $_SERVER['PATH_TRANSLATED'];
  80      }
  81  
  82      // Fix for Dreamhost and other PHP as CGI hosts.
  83      if ( isset( $_SERVER['SCRIPT_NAME'] ) && str_contains( $_SERVER['SCRIPT_NAME'], 'php.cgi' ) ) {
  84          unset( $_SERVER['PATH_INFO'] );
  85      }
  86  
  87      // Fix empty PHP_SELF.
  88      $PHP_SELF = $_SERVER['PHP_SELF'];
  89      if ( empty( $PHP_SELF ) ) {
  90          $_SERVER['PHP_SELF'] = preg_replace( '/(\?.*)?$/', '', $_SERVER['REQUEST_URI'] );
  91          $PHP_SELF            = $_SERVER['PHP_SELF'];
  92      }
  93  
  94      wp_populate_basic_auth_from_authorization_header();
  95  }
  96  
  97  /**
  98   * Populates the Basic Auth server details from the Authorization header.
  99   *
 100   * Some servers running in CGI or FastCGI mode don't pass the Authorization
 101   * header on to WordPress.  If it's been rewritten to the `HTTP_AUTHORIZATION` header,
 102   * fill in the proper $_SERVER variables instead.
 103   *
 104   * @since 5.6.0
 105   */
 106  function wp_populate_basic_auth_from_authorization_header() {
 107      // If we don't have anything to pull from, return early.
 108      if ( ! isset( $_SERVER['HTTP_AUTHORIZATION'] ) && ! isset( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) ) {
 109          return;
 110      }
 111  
 112      // If either PHP_AUTH key is already set, do nothing.
 113      if ( isset( $_SERVER['PHP_AUTH_USER'] ) || isset( $_SERVER['PHP_AUTH_PW'] ) ) {
 114          return;
 115      }
 116  
 117      // From our prior conditional, one of these must be set.
 118      $header = $_SERVER['HTTP_AUTHORIZATION'] ?? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
 119  
 120      // Test to make sure the pattern matches expected.
 121      if ( ! preg_match( '%^Basic [a-z\d/+]*={0,2}$%i', $header ) ) {
 122          return;
 123      }
 124  
 125      // Removing `Basic ` the token would start six characters in.
 126      $token    = substr( $header, 6 );
 127      $userpass = base64_decode( $token );
 128  
 129      // There must be at least one colon in the string.
 130      if ( ! str_contains( $userpass, ':' ) ) {
 131          return;
 132      }
 133  
 134      list( $user, $pass ) = explode( ':', $userpass, 2 );
 135  
 136      // Now shove them in the proper keys where we're expecting later on.
 137      $_SERVER['PHP_AUTH_USER'] = $user;
 138      $_SERVER['PHP_AUTH_PW']   = $pass;
 139  }
 140  
 141  /**
 142   * Checks the server requirements.
 143   *
 144   *   - PHP version
 145   *   - PHP extensions
 146   *   - MySQL or MariaDB version (unless a database drop-in is present)
 147   *
 148   * Dies if requirements are not met.
 149   *
 150   * @since 3.0.0
 151   * @access private
 152   *
 153   * @global string   $required_php_version    The minimum required PHP version string.
 154   * @global string[] $required_php_extensions The names of required PHP extensions.
 155   * @global string   $wp_version              The WordPress version string.
 156   */
 157  function wp_check_php_mysql_versions() {
 158      global $required_php_version, $required_php_extensions, $wp_version;
 159  
 160      $php_version = PHP_VERSION;
 161  
 162      if ( version_compare( $required_php_version, $php_version, '>' ) ) {
 163          $protocol = wp_get_server_protocol();
 164          header( sprintf( '%s 500 Internal Server Error', $protocol ), true, 500 );
 165          header( 'Content-Type: text/html; charset=utf-8' );
 166          printf(
 167              'Your server is running PHP version %1$s but WordPress %2$s requires at least %3$s.',
 168              $php_version,
 169              $wp_version,
 170              $required_php_version
 171          );
 172          exit( 1 );
 173      }
 174  
 175      $missing_extensions = array();
 176  
 177      if ( isset( $required_php_extensions ) && is_array( $required_php_extensions ) ) {
 178          foreach ( $required_php_extensions as $extension ) {
 179              if ( extension_loaded( $extension ) ) {
 180                  continue;
 181              }
 182  
 183              $missing_extensions[] = sprintf(
 184                  'WordPress %1$s requires the <code>%2$s</code> PHP extension.',
 185                  $wp_version,
 186                  $extension
 187              );
 188          }
 189      }
 190  
 191      if ( count( $missing_extensions ) > 0 ) {
 192          $protocol = wp_get_server_protocol();
 193          header( sprintf( '%s 500 Internal Server Error', $protocol ), true, 500 );
 194          header( 'Content-Type: text/html; charset=utf-8' );
 195          echo implode( '<br>', $missing_extensions );
 196          exit( 1 );
 197      }
 198  
 199      // This runs before default constants are defined, so we can't assume WP_CONTENT_DIR is set yet.
 200      $wp_content_dir = defined( 'WP_CONTENT_DIR' ) ? WP_CONTENT_DIR : ABSPATH . 'wp-content';
 201  
 202      if ( ! function_exists( 'mysqli_connect' )
 203          && ! file_exists( $wp_content_dir . '/db.php' )
 204      ) {
 205          require_once  ABSPATH . WPINC . '/functions.php';
 206          wp_load_translations_early();
 207  
 208          $message = '<p>' . __( 'Your PHP installation appears to be missing the MySQL extension which is required by WordPress.' ) . "</p>\n";
 209  
 210          $message .= '<p>' . sprintf(
 211              /* translators: %s: mysqli. */
 212              __( 'Please check that the %s PHP extension is installed and enabled.' ),
 213              '<code>mysqli</code>'
 214          ) . "</p>\n";
 215  
 216          $message .= '<p>' . sprintf(
 217              /* translators: %s: Support forums URL. */
 218              __( 'If you are unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href="%s">WordPress support forums</a>.' ),
 219              __( 'https://wordpress.org/support/forums/' )
 220          ) . "</p>\n";
 221  
 222          $args = array(
 223              'exit' => false,
 224              'code' => 'mysql_not_found',
 225          );
 226          wp_die(
 227              $message,
 228              __( 'Requirements Not Met' ),
 229              $args
 230          );
 231          exit( 1 );
 232      }
 233  }
 234  
 235  /**
 236   * Retrieves the current environment type.
 237   *
 238   * The type can be set via the `WP_ENVIRONMENT_TYPE` global system variable,
 239   * or a constant of the same name.
 240   *
 241   * Possible values are 'local', 'development', 'staging', and 'production'.
 242   * If not set, the type defaults to 'production'.
 243   *
 244   * @since 5.5.0
 245   * @since 5.5.1 Added the 'local' type.
 246   * @since 5.5.1 Removed the ability to alter the list of types.
 247   *
 248   * @return string The current environment type.
 249   */
 250  function wp_get_environment_type() {
 251      static $current_env = '';
 252  
 253      if ( ! defined( 'WP_RUN_CORE_TESTS' ) && $current_env ) {
 254          return $current_env;
 255      }
 256  
 257      $wp_environments = array(
 258          'local',
 259          'development',
 260          'staging',
 261          'production',
 262      );
 263  
 264      // Add a note about the deprecated WP_ENVIRONMENT_TYPES constant.
 265      if ( defined( 'WP_ENVIRONMENT_TYPES' ) && function_exists( '_deprecated_argument' ) ) {
 266          if ( function_exists( '__' ) ) {
 267              /* translators: %s: WP_ENVIRONMENT_TYPES */
 268              $message = sprintf( __( 'The %s constant is no longer supported.' ), 'WP_ENVIRONMENT_TYPES' );
 269          } else {
 270              $message = sprintf( 'The %s constant is no longer supported.', 'WP_ENVIRONMENT_TYPES' );
 271          }
 272  
 273          _deprecated_argument(
 274              'define()',
 275              '5.5.1',
 276              $message
 277          );
 278      }
 279  
 280      // Check if the environment variable has been set, if `getenv` is available on the system.
 281      if ( function_exists( 'getenv' ) ) {
 282          $has_env = getenv( 'WP_ENVIRONMENT_TYPE' );
 283          if ( false !== $has_env ) {
 284              $current_env = $has_env;
 285          }
 286      }
 287  
 288      // Fetch the environment from a constant, this overrides the global system variable.
 289      if ( defined( 'WP_ENVIRONMENT_TYPE' ) && WP_ENVIRONMENT_TYPE ) {
 290          $current_env = WP_ENVIRONMENT_TYPE;
 291      }
 292  
 293      // Make sure the environment is an allowed one, and not accidentally set to an invalid value.
 294      if ( ! in_array( $current_env, $wp_environments, true ) ) {
 295          $current_env = 'production';
 296      }
 297  
 298      return $current_env;
 299  }
 300  
 301  /**
 302   * Retrieves the current development mode.
 303   *
 304   * The development mode affects how certain parts of the WordPress application behave,
 305   * which is relevant when developing for WordPress.
 306   *
 307   * Development mode can be set via the `WP_DEVELOPMENT_MODE` constant in `wp-config.php`.
 308   * Possible values are 'core', 'plugin', 'theme', 'all', or an empty string to disable
 309   * development mode. 'all' is a special value to signify that all three development modes
 310   * ('core', 'plugin', and 'theme') are enabled.
 311   *
 312   * Development mode is considered separately from `WP_DEBUG` and wp_get_environment_type().
 313   * It does not affect debugging output, but rather functional nuances in WordPress.
 314   *
 315   * This function retrieves the currently set development mode value. To check whether
 316   * a specific development mode is enabled, use wp_is_development_mode().
 317   *
 318   * @since 6.3.0
 319   *
 320   * @return string The current development mode.
 321   */
 322  function wp_get_development_mode() {
 323      static $current_mode = null;
 324  
 325      if ( ! defined( 'WP_RUN_CORE_TESTS' ) && null !== $current_mode ) {
 326          return $current_mode;
 327      }
 328  
 329      $development_mode = WP_DEVELOPMENT_MODE;
 330  
 331      // Exclusively for core tests, rely on the `$_wp_tests_development_mode` global.
 332      if ( defined( 'WP_RUN_CORE_TESTS' ) && isset( $GLOBALS['_wp_tests_development_mode'] ) ) {
 333          $development_mode = $GLOBALS['_wp_tests_development_mode'];
 334      }
 335  
 336      $valid_modes = array(
 337          'core',
 338          'plugin',
 339          'theme',
 340          'all',
 341          '',
 342      );
 343  
 344      if ( ! in_array( $development_mode, $valid_modes, true ) ) {
 345          $development_mode = '';
 346      }
 347  
 348      $current_mode = $development_mode;
 349  
 350      return $current_mode;
 351  }
 352  
 353  /**
 354   * Checks whether the site is in the given development mode.
 355   *
 356   * @since 6.3.0
 357   *
 358   * @param string $mode Development mode to check for. Either 'core', 'plugin', 'theme', or 'all'.
 359   * @return bool True if the given mode is covered by the current development mode, false otherwise.
 360   */
 361  function wp_is_development_mode( $mode ) {
 362      $current_mode = wp_get_development_mode();
 363      if ( empty( $current_mode ) ) {
 364          return false;
 365      }
 366  
 367      // Return true if the current mode encompasses all modes.
 368      if ( 'all' === $current_mode ) {
 369          return true;
 370      }
 371  
 372      // Return true if the current mode is the given mode.
 373      return $mode === $current_mode;
 374  }
 375  
 376  /**
 377   * Ensures all of WordPress is not loaded when handling a favicon.ico request.
 378   *
 379   * Instead, send the headers for a zero-length favicon and bail.
 380   *
 381   * @since 3.0.0
 382   * @deprecated 5.4.0 Deprecated in favor of do_favicon().
 383   */
 384  function wp_favicon_request() {
 385      if ( '/favicon.ico' === $_SERVER['REQUEST_URI'] ) {
 386          header( 'Content-Type: image/vnd.microsoft.icon' );
 387          exit;
 388      }
 389  }
 390  
 391  /**
 392   * Dies with a maintenance message when conditions are met.
 393   *
 394   * The default message can be replaced by using a drop-in (maintenance.php in
 395   * the wp-content directory).
 396   *
 397   * @since 3.0.0
 398   * @since 7.2.0 Added status, no-cache and retry-after headers before loading a custom `maintenance.php` drop-in.
 399   * @access private
 400   */
 401  function wp_maintenance() {
 402      // Return if maintenance mode is disabled.
 403      if ( ! wp_is_maintenance_mode() ) {
 404          return;
 405      }
 406  
 407      require_once  ABSPATH . WPINC . '/functions.php';
 408  
 409      if ( file_exists( WP_CONTENT_DIR . '/maintenance.php' ) ) {
 410          status_header( 503 );
 411          nocache_headers();
 412          header( 'Retry-After: 600' );
 413          require_once WP_CONTENT_DIR . '/maintenance.php';
 414          die();
 415      }
 416  
 417      wp_load_translations_early();
 418  
 419      header( 'Retry-After: 600' );
 420  
 421      wp_die(
 422          __( 'Briefly unavailable for scheduled maintenance. Check back in a minute.' ),
 423          __( 'Maintenance' ),
 424          503
 425      );
 426  }
 427  
 428  /**
 429   * Checks if maintenance mode is enabled.
 430   *
 431   * Checks for a file in the WordPress root directory named ".maintenance".
 432   * This file will contain the variable $upgrading, set to the time the file
 433   * was created. If the file was created less than 10 minutes ago, WordPress
 434   * is in maintenance mode.
 435   *
 436   * @since 5.5.0
 437   *
 438   * @global int $upgrading The Unix timestamp marking when upgrading WordPress began.
 439   *
 440   * @return bool True if maintenance mode is enabled, false otherwise.
 441   */
 442  function wp_is_maintenance_mode() {
 443      global $upgrading;
 444  
 445      if ( ! file_exists( ABSPATH . '.maintenance' ) || wp_installing() ) {
 446          return false;
 447      }
 448  
 449      require ABSPATH . '.maintenance';
 450  
 451      // If the $upgrading timestamp is older than 10 minutes, consider maintenance over.
 452      if ( ( time() - $upgrading ) >= 10 * MINUTE_IN_SECONDS ) {
 453          return false;
 454      }
 455  
 456      // Don't enable maintenance mode while scraping for fatal errors.
 457      if ( is_int( $upgrading ) && isset( $_REQUEST['wp_scrape_key'], $_REQUEST['wp_scrape_nonce'] ) ) {
 458          $key   = stripslashes( $_REQUEST['wp_scrape_key'] );
 459          $nonce = stripslashes( $_REQUEST['wp_scrape_nonce'] );
 460  
 461          if ( md5( $upgrading ) === $key && (int) $nonce === $upgrading ) {
 462              return false;
 463          }
 464      }
 465  
 466      /**
 467       * Filters whether to enable maintenance mode.
 468       *
 469       * This filter runs before it can be used by plugins. It is designed for
 470       * non-web runtimes. If this filter returns true, maintenance mode will be
 471       * active and the request will end. If false, the request will be allowed to
 472       * continue processing even if maintenance mode should be active.
 473       *
 474       * @since 4.6.0
 475       *
 476       * @param bool $enable_checks Whether to enable maintenance mode. Default true.
 477       * @param int  $upgrading     The timestamp set in the .maintenance file.
 478       */
 479      if ( ! apply_filters( 'enable_maintenance_mode', true, $upgrading ) ) {
 480          return false;
 481      }
 482  
 483      return true;
 484  }
 485  
 486  /**
 487   * Gets the time elapsed so far during this PHP script.
 488   *
 489   * @since 5.8.0
 490   *
 491   * @return float Seconds since the PHP script started.
 492   */
 493  function timer_float() {
 494      return microtime( true ) - $_SERVER['REQUEST_TIME_FLOAT'];
 495  }
 496  
 497  /**
 498   * Starts the WordPress micro-timer.
 499   *
 500   * @since 0.71
 501   * @access private
 502   *
 503   * @see timer_stop()
 504   *
 505   * @global float $timestart Unix timestamp set at the beginning of the page load.
 506   *
 507   * @return bool Always returns true.
 508   */
 509  function timer_start() {
 510      global $timestart;
 511  
 512      $timestart = microtime( true );
 513  
 514      return true;
 515  }
 516  
 517  /**
 518   * Retrieves or displays the time from the page start to when function is called.
 519   *
 520   * @since 0.71
 521   *
 522   * @global float   $timestart Seconds from when timer_start() is called.
 523   * @global float   $timeend   Seconds from when function is called.
 524   *
 525   * @param int|bool $display   Whether to echo or return the results. Accepts 0|false for return,
 526   *                            1|true for echo. Default 0|false.
 527   * @param int      $precision The number of digits from the right of the decimal to display.
 528   *                            Default 3.
 529   * @return string The "second.microsecond" finished time calculation. The number is formatted
 530   *                for human consumption, both localized and rounded.
 531   */
 532  function timer_stop( $display = 0, $precision = 3 ) {
 533      global $timestart, $timeend;
 534  
 535      $timeend   = microtime( true );
 536      $timetotal = $timeend - $timestart;
 537  
 538      if ( function_exists( 'number_format_i18n' ) ) {
 539          $r = number_format_i18n( $timetotal, $precision );
 540      } else {
 541          $r = number_format( $timetotal, $precision );
 542      }
 543  
 544      if ( $display ) {
 545          echo $r;
 546      }
 547  
 548      return $r;
 549  }
 550  
 551  /**
 552   * Sets PHP error reporting based on WordPress debug settings.
 553   *
 554   * Uses three constants: `WP_DEBUG`, `WP_DEBUG_DISPLAY`, and `WP_DEBUG_LOG`.
 555   * All three can be defined in wp-config.php. By default, `WP_DEBUG` and
 556   * `WP_DEBUG_LOG` are set to false, and `WP_DEBUG_DISPLAY` is set to true.
 557   *
 558   * When `WP_DEBUG` is true, all PHP notices are reported. WordPress will also
 559   * display internal notices: when a deprecated WordPress function, function
 560   * argument, or file is used. Deprecated code may be removed from a later
 561   * version.
 562   *
 563   * It is strongly recommended that plugin and theme developers use `WP_DEBUG`
 564   * in their development environments.
 565   *
 566   * `WP_DEBUG_DISPLAY` and `WP_DEBUG_LOG` perform no function unless `WP_DEBUG`
 567   * is true.
 568   *
 569   * When `WP_DEBUG_DISPLAY` is true, WordPress will force errors to be displayed.
 570   * `WP_DEBUG_DISPLAY` defaults to true. Defining it as null prevents WordPress
 571   * from changing the global configuration setting. Defining `WP_DEBUG_DISPLAY`
 572   * as false will force errors to be hidden.
 573   *
 574   * When `WP_DEBUG_LOG` is true, errors will be logged to `wp-content/debug.log`.
 575   * When `WP_DEBUG_LOG` is a valid path, errors will be logged to the specified file.
 576   *
 577   * Errors are never displayed for XML-RPC, REST, `ms-files.php`, and Ajax requests.
 578   *
 579   * @since 3.0.0
 580   * @since 5.1.0 `WP_DEBUG_LOG` can be a file path.
 581   * @access private
 582   */
 583  function wp_debug_mode() {
 584      /**
 585       * Filters whether to allow the debug mode check to occur.
 586       *
 587       * This filter runs before it can be used by plugins. It is designed for
 588       * non-web runtimes. Returning false causes the `WP_DEBUG` and related
 589       * constants to not be checked and the default PHP values for errors
 590       * will be used unless you take care to update them yourself.
 591       *
 592       * To use this filter you must define a `$wp_filter` global before
 593       * WordPress loads, usually in `wp-config.php`.
 594       *
 595       * Example:
 596       *
 597       *     $GLOBALS['wp_filter'] = array(
 598       *         'enable_wp_debug_mode_checks' => array(
 599       *             10 => array(
 600       *                 array(
 601       *                     'accepted_args' => 0,
 602       *                     'function'      => function() {
 603       *                         return false;
 604       *                     },
 605       *                 ),
 606       *             ),
 607       *         ),
 608       *     );
 609       *
 610       * @since 4.6.0
 611       *
 612       * @param bool $enable_debug_mode Whether to enable debug mode checks to occur. Default true.
 613       */
 614      if ( ! apply_filters( 'enable_wp_debug_mode_checks', true ) ) {
 615          return;
 616      }
 617  
 618      if ( WP_DEBUG ) {
 619          error_reporting( E_ALL );
 620  
 621          if ( WP_DEBUG_DISPLAY ) {
 622              ini_set( 'display_errors', 1 );
 623          } elseif ( null !== WP_DEBUG_DISPLAY ) {
 624              ini_set( 'display_errors', 0 );
 625          }
 626  
 627          if ( in_array( strtolower( (string) WP_DEBUG_LOG ), array( 'true', '1' ), true ) ) {
 628              $log_path = WP_CONTENT_DIR . '/debug.log';
 629          } elseif ( is_string( WP_DEBUG_LOG ) ) {
 630              $log_path = WP_DEBUG_LOG;
 631          } else {
 632              $log_path = false;
 633          }
 634  
 635          if ( $log_path ) {
 636              ini_set( 'log_errors', 1 );
 637              ini_set( 'error_log', $log_path );
 638          }
 639      } else {
 640          error_reporting( E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR );
 641      }
 642  
 643      /*
 644       * The 'REST_REQUEST' check here is optimistic as the constant is most
 645       * likely not set at this point even if it is in fact a REST request.
 646       */
 647      if ( defined( 'XMLRPC_REQUEST' ) || defined( 'REST_REQUEST' ) || defined( 'MS_FILES_REQUEST' )
 648          || ( defined( 'WP_INSTALLING' ) && WP_INSTALLING )
 649          || wp_doing_ajax() || wp_is_json_request()
 650      ) {
 651          ini_set( 'display_errors', 0 );
 652      }
 653  }
 654  
 655  /**
 656   * Sets the location of the language directory.
 657   *
 658   * To set directory manually, define the `WP_LANG_DIR` constant
 659   * in wp-config.php.
 660   *
 661   * If the language directory exists within `WP_CONTENT_DIR`, it
 662   * is used. Otherwise the language directory is assumed to live
 663   * in `WPINC`.
 664   *
 665   * @since 3.0.0
 666   * @access private
 667   */
 668  function wp_set_lang_dir() {
 669      if ( ! defined( 'WP_LANG_DIR' ) ) {
 670          if ( file_exists( WP_CONTENT_DIR . '/languages' ) && @is_dir( WP_CONTENT_DIR . '/languages' )
 671              || ! @is_dir( ABSPATH . WPINC . '/languages' )
 672          ) {
 673              /**
 674               * Server path of the language directory.
 675               *
 676               * No leading slash, no trailing slash, full path, not relative to ABSPATH
 677               *
 678               * @since 2.1.0
 679               */
 680              define( 'WP_LANG_DIR', WP_CONTENT_DIR . '/languages' );
 681  
 682              if ( ! defined( 'LANGDIR' ) ) {
 683                  // Old static relative path maintained for limited backward compatibility - won't work in some cases.
 684                  define( 'LANGDIR', 'wp-content/languages' );
 685              }
 686          } else {
 687              /**
 688               * Server path of the language directory.
 689               *
 690               * No leading slash, no trailing slash, full path, not relative to `ABSPATH`.
 691               *
 692               * @since 2.1.0
 693               */
 694              define( 'WP_LANG_DIR', ABSPATH . WPINC . '/languages' );
 695  
 696              if ( ! defined( 'LANGDIR' ) ) {
 697                  // Old relative path maintained for backward compatibility.
 698                  define( 'LANGDIR', WPINC . '/languages' );
 699              }
 700          }
 701      }
 702  }
 703  
 704  /**
 705   * Loads the database class file and instantiates the `$wpdb` global.
 706   *
 707   * @since 2.5.0
 708   *
 709   * @global wpdb $wpdb WordPress database abstraction object.
 710   */
 711  function require_wp_db() {
 712      global $wpdb;
 713  
 714      require_once  ABSPATH . WPINC . '/class-wpdb.php';
 715  
 716      if ( file_exists( WP_CONTENT_DIR . '/db.php' ) ) {
 717          require_once WP_CONTENT_DIR . '/db.php';
 718      }
 719  
 720      if ( isset( $wpdb ) ) {
 721          return;
 722      }
 723  
 724      $dbuser     = defined( 'DB_USER' ) ? DB_USER : '';
 725      $dbpassword = defined( 'DB_PASSWORD' ) ? DB_PASSWORD : '';
 726      $dbname     = defined( 'DB_NAME' ) ? DB_NAME : '';
 727      $dbhost     = defined( 'DB_HOST' ) ? DB_HOST : '';
 728  
 729      $wpdb = new wpdb( $dbuser, $dbpassword, $dbname, $dbhost );
 730  }
 731  
 732  /**
 733   * Sets the database table prefix and the format specifiers for database
 734   * table columns.
 735   *
 736   * Columns not listed here default to `%s`.
 737   *
 738   * @since 3.0.0
 739   * @access private
 740   *
 741   * @global wpdb   $wpdb         WordPress database abstraction object.
 742   * @global string $table_prefix The database table prefix.
 743   */
 744  function wp_set_wpdb_vars() {
 745      global $wpdb, $table_prefix;
 746  
 747      if ( ! empty( $wpdb->error ) ) {
 748          dead_db();
 749      }
 750  
 751      $wpdb->field_types = array(
 752          'post_author'      => '%d',
 753          'post_parent'      => '%d',
 754          'menu_order'       => '%d',
 755          'term_id'          => '%d',
 756          'term_group'       => '%d',
 757          'term_taxonomy_id' => '%d',
 758          'parent'           => '%d',
 759          'count'            => '%d',
 760          'object_id'        => '%d',
 761          'term_order'       => '%d',
 762          'ID'               => '%d',
 763          'comment_ID'       => '%d',
 764          'comment_post_ID'  => '%d',
 765          'comment_parent'   => '%d',
 766          'user_id'          => '%d',
 767          'link_id'          => '%d',
 768          'link_owner'       => '%d',
 769          'link_rating'      => '%d',
 770          'option_id'        => '%d',
 771          'blog_id'          => '%d',
 772          'meta_id'          => '%d',
 773          'post_id'          => '%d',
 774          'user_status'      => '%d',
 775          'umeta_id'         => '%d',
 776          'comment_karma'    => '%d',
 777          'comment_count'    => '%d',
 778          // Multisite:
 779          'active'           => '%d',
 780          'cat_id'           => '%d',
 781          'deleted'          => '%d',
 782          'lang_id'          => '%d',
 783          'mature'           => '%d',
 784          'public'           => '%d',
 785          'site_id'          => '%d',
 786          'spam'             => '%d',
 787      );
 788  
 789      $prefix = $wpdb->set_prefix( $table_prefix );
 790  
 791      if ( is_wp_error( $prefix ) ) {
 792          wp_load_translations_early();
 793          wp_die(
 794              sprintf(
 795                  /* translators: 1: $table_prefix, 2: wp-config.php */
 796                  __( '<strong>Error:</strong> %1$s in %2$s can only contain numbers, letters, and underscores.' ),
 797                  '<code>$table_prefix</code>',
 798                  '<code>wp-config.php</code>'
 799              )
 800          );
 801      }
 802  }
 803  
 804  /**
 805   * Toggles `$_wp_using_ext_object_cache` on and off without directly
 806   * touching global.
 807   *
 808   * @since 3.7.0
 809   *
 810   * @global bool $_wp_using_ext_object_cache
 811   *
 812   * @param bool $using Whether external object cache is being used.
 813   * @return bool The current 'using' setting.
 814   */
 815  function wp_using_ext_object_cache( $using = null ) {
 816      global $_wp_using_ext_object_cache;
 817  
 818      $current_using = $_wp_using_ext_object_cache;
 819  
 820      if ( null !== $using ) {
 821          $_wp_using_ext_object_cache = $using;
 822      }
 823  
 824      return $current_using;
 825  }
 826  
 827  /**
 828   * Loads the secrets.php drop-in, if one exists, and records whether it left the
 829   * Secrets API's provider, store, and keyring overrides in a usable state.
 830   *
 831   * Runs once, before must-use plugins load, so that every interface a drop-in's
 832   * classes implement already exists and every plugin sees the drop-in's provider.
 833   *
 834   * Sets `$GLOBALS['wp_secrets_dropin_loaded']` as soon as the file is found, whether
 835   * or not it then loads cleanly: wp_using_secrets_dropin() reports presence, not
 836   * health.
 837   *
 838   * Sets `$GLOBALS['wp_secrets_dropin_broken']` when the require throws, or when any of
 839   * `$GLOBALS['wp_secrets_provider']`, `$GLOBALS['wp_secrets_store']`, or
 840   * `$GLOBALS['wp_secrets_keyring']` is set to something that does not implement its
 841   * interface. A global left unset is fine: a drop-in that overrides only the keyring
 842   * leaves the other two alone. Once the flag is set, every Secrets API operation
 843   * returns WP_Error for the rest of the request rather than falling back to the
 844   * default provider, so a broken drop-in reads as unreachable, never as absent.
 845   *
 846   * PHP treats a class that implements an interface but omits a required method as an
 847   * uncatchable fatal error, even inside the try/catch around the require. That case
 848   * cannot be intercepted from PHP code.
 849   *
 850   * @since 7.2.0
 851   * @access private
 852   */
 853  function wp_load_secrets_dropin(): void {
 854      static $loaded = false;
 855  
 856      if ( $loaded ) {
 857          return;
 858      }
 859  
 860      $loaded = true;
 861  
 862      $dropin_path = WP_CONTENT_DIR . '/secrets.php';
 863  
 864      if ( ! file_exists( $dropin_path ) ) {
 865          return;
 866      }
 867  
 868      $GLOBALS['wp_secrets_dropin_loaded'] = true;
 869  
 870      try {
 871          require $dropin_path;
 872      } catch ( Throwable $e ) {
 873          $GLOBALS['wp_secrets_dropin_broken'] = true;
 874  
 875          return;
 876      }
 877  
 878      if ( isset( $GLOBALS['wp_secrets_store'] ) && ! ( $GLOBALS['wp_secrets_store'] instanceof WP_Secrets_Store ) ) {
 879          $GLOBALS['wp_secrets_dropin_broken'] = true;
 880      }
 881  
 882      if ( isset( $GLOBALS['wp_secrets_keyring'] ) && ! ( $GLOBALS['wp_secrets_keyring'] instanceof WP_Secrets_Keyring ) ) {
 883          $GLOBALS['wp_secrets_dropin_broken'] = true;
 884      }
 885  
 886      if ( isset( $GLOBALS['wp_secrets_provider'] ) && ! ( $GLOBALS['wp_secrets_provider'] instanceof WP_Secrets_Provider ) ) {
 887          $GLOBALS['wp_secrets_dropin_broken'] = true;
 888      }
 889  }
 890  
 891  /**
 892   * Starts the WordPress object cache.
 893   *
 894   * If an object-cache.php file exists in the wp-content directory,
 895   * it uses that drop-in as an external object cache.
 896   *
 897   * @since 3.0.0
 898   * @access private
 899   *
 900   * @global array $wp_filter Stores all of the filters.
 901   */
 902  function wp_start_object_cache() {
 903      global $wp_filter;
 904      static $first_init = true;
 905  
 906      // Only perform the following checks once.
 907  
 908      /**
 909       * Filters whether to enable loading of the object-cache.php drop-in.
 910       *
 911       * This filter runs before it can be used by plugins. It is designed for non-web
 912       * runtimes. If false is returned, object-cache.php will never be loaded.
 913       *
 914       * @since 5.8.0
 915       *
 916       * @param bool $enable_object_cache Whether to enable loading object-cache.php (if present).
 917       *                                  Default true.
 918       */
 919      if ( $first_init && apply_filters( 'enable_loading_object_cache_dropin', true ) ) {
 920          if ( ! function_exists( 'wp_cache_init' ) ) {
 921              /*
 922               * This is the normal situation. First-run of this function. No
 923               * caching backend has been loaded.
 924               *
 925               * We try to load a custom caching backend, and then, if it
 926               * results in a wp_cache_init() function existing, we note
 927               * that an external object cache is being used.
 928               */
 929              if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
 930                  require_once WP_CONTENT_DIR . '/object-cache.php';
 931  
 932                  if ( function_exists( 'wp_cache_init' ) ) {
 933                      wp_using_ext_object_cache( true );
 934                  }
 935  
 936                  // Re-initialize any hooks added manually by object-cache.php.
 937                  if ( $wp_filter ) {
 938                      $wp_filter = WP_Hook::build_preinitialized_hooks( $wp_filter );
 939                  }
 940              }
 941          } elseif ( ! wp_using_ext_object_cache() && file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
 942              /*
 943               * Sometimes advanced-cache.php can load object-cache.php before
 944               * this function is run. This breaks the function_exists() check
 945               * above and can result in wp_using_ext_object_cache() returning
 946               * false when actually an external cache is in use.
 947               */
 948              wp_using_ext_object_cache( true );
 949          }
 950      }
 951  
 952      if ( ! wp_using_ext_object_cache() ) {
 953          require_once  ABSPATH . WPINC . '/cache.php';
 954      }
 955  
 956      require_once  ABSPATH . WPINC . '/cache-compat.php';
 957  
 958      /*
 959       * If cache supports reset, reset instead of init if already
 960       * initialized. Reset signals to the cache that global IDs
 961       * have changed and it may need to update keys and cleanup caches.
 962       */
 963      if ( ! $first_init && function_exists( 'wp_cache_switch_to_blog' ) ) {
 964          wp_cache_switch_to_blog( get_current_blog_id() );
 965      } elseif ( function_exists( 'wp_cache_init' ) ) {
 966          wp_cache_init();
 967      }
 968  
 969      if ( function_exists( 'wp_cache_add_global_groups' ) ) {
 970          wp_cache_add_global_groups(
 971              array(
 972                  'blog-details',
 973                  'blog-id-cache',
 974                  'blog-lookup',
 975                  'blog_meta',
 976                  'global-posts',
 977                  'image_editor',
 978                  'networks',
 979                  'network-queries',
 980                  'sites',
 981                  'site-details',
 982                  'site-options',
 983                  'site-queries',
 984                  'site-transient',
 985                  'theme_files',
 986                  'translation_files',
 987                  'rss',
 988                  'users',
 989                  'user-queries',
 990                  'user_meta',
 991                  'useremail',
 992                  'userlogins',
 993                  'userslugs',
 994              )
 995          );
 996  
 997          wp_cache_add_non_persistent_groups( array( 'counts', 'plugins', 'theme_json' ) );
 998      }
 999  
1000      $first_init = false;
1001  }
1002  
1003  /**
1004   * Redirects to the installer if WordPress is not installed.
1005   *
1006   * Dies with an error message when Multisite is enabled.
1007   *
1008   * @since 3.0.0
1009   * @access private
1010   */
1011  function wp_not_installed() {
1012      if ( is_blog_installed() || wp_installing() ) {
1013          return;
1014      }
1015  
1016      nocache_headers();
1017  
1018      if ( is_multisite() ) {
1019          wp_die( __( 'The site you have requested is not installed properly. Please contact the system administrator.' ) );
1020      }
1021  
1022      require  ABSPATH . WPINC . '/kses.php';
1023      require  ABSPATH . WPINC . '/pluggable.php';
1024  
1025      $link = wp_guess_url() . '/wp-admin/install.php';
1026  
1027      wp_redirect( $link );
1028      die();
1029  }
1030  
1031  /**
1032   * Retrieves an array of must-use plugin files.
1033   *
1034   * The default directory is wp-content/mu-plugins. To change the default
1035   * directory manually, define `WPMU_PLUGIN_DIR` and `WPMU_PLUGIN_URL`
1036   * in wp-config.php.
1037   *
1038   * @since 3.0.0
1039   * @access private
1040   *
1041   * @return string[] Array of absolute paths of files to include.
1042   */
1043  function wp_get_mu_plugins() {
1044      $mu_plugins = array();
1045  
1046      if ( ! is_dir( WPMU_PLUGIN_DIR ) ) {
1047          return $mu_plugins;
1048      }
1049  
1050      $dh = opendir( WPMU_PLUGIN_DIR );
1051      if ( ! $dh ) {
1052          return $mu_plugins;
1053      }
1054  
1055      while ( ( $plugin = readdir( $dh ) ) !== false ) {
1056          if ( str_ends_with( $plugin, '.php' ) ) {
1057              $mu_plugins[] = WPMU_PLUGIN_DIR . '/' . $plugin;
1058          }
1059      }
1060  
1061      closedir( $dh );
1062  
1063      sort( $mu_plugins );
1064  
1065      return $mu_plugins;
1066  }
1067  
1068  /**
1069   * Retrieves an array of active and valid plugin files.
1070   *
1071   * While upgrading or installing WordPress, no plugins are returned.
1072   *
1073   * The default directory is `wp-content/plugins`. To change the default
1074   * directory manually, define `WP_PLUGIN_DIR` and `WP_PLUGIN_URL`
1075   * in `wp-config.php`.
1076   *
1077   * @since 3.0.0
1078   * @access private
1079   *
1080   * @return string[] Array of paths to plugin files relative to the plugins directory.
1081   */
1082  function wp_get_active_and_valid_plugins() {
1083      $plugins        = array();
1084      $active_plugins = (array) get_option( 'active_plugins', array() );
1085  
1086      // Check for hacks file if the option is enabled.
1087      if ( get_option( 'hack_file' ) && file_exists( ABSPATH . 'my-hacks.php' ) ) {
1088          _deprecated_file( 'my-hacks.php', '1.5.0' );
1089          array_unshift( $plugins, ABSPATH . 'my-hacks.php' );
1090      }
1091  
1092      if ( empty( $active_plugins ) || wp_installing() ) {
1093          return $plugins;
1094      }
1095  
1096      $network_plugins = is_multisite() ? wp_get_active_network_plugins() : false;
1097  
1098      foreach ( $active_plugins as $plugin ) {
1099          if ( ! validate_file( $plugin )                     // $plugin must validate as file.
1100              && str_ends_with( $plugin, '.php' )             // $plugin must end with '.php'.
1101              && file_exists( WP_PLUGIN_DIR . '/' . $plugin ) // $plugin must exist.
1102              // Not already included as a network plugin.
1103              && ( ! $network_plugins || ! in_array( WP_PLUGIN_DIR . '/' . $plugin, $network_plugins, true ) )
1104          ) {
1105              $plugins[] = WP_PLUGIN_DIR . '/' . $plugin;
1106          }
1107      }
1108  
1109      /*
1110       * Remove plugins from the list of active plugins when we're on an endpoint
1111       * that should be protected against WSODs and the plugin is paused.
1112       */
1113      if ( wp_is_recovery_mode() ) {
1114          $plugins = wp_skip_paused_plugins( $plugins );
1115      }
1116  
1117      return $plugins;
1118  }
1119  
1120  /**
1121   * Filters a given list of plugins, removing any paused plugins from it.
1122   *
1123   * @since 5.2.0
1124   *
1125   * @global WP_Paused_Extensions_Storage $_paused_plugins
1126   *
1127   * @param string[] $plugins Array of absolute plugin main file paths.
1128   * @return string[] Filtered array of plugins, without any paused plugins.
1129   */
1130  function wp_skip_paused_plugins( array $plugins ) {
1131      $paused_plugins = wp_paused_plugins()->get_all();
1132  
1133      if ( empty( $paused_plugins ) ) {
1134          return $plugins;
1135      }
1136  
1137      foreach ( $plugins as $index => $plugin ) {
1138          list( $plugin ) = explode( '/', plugin_basename( $plugin ) );
1139  
1140          if ( array_key_exists( $plugin, $paused_plugins ) ) {
1141              unset( $plugins[ $index ] );
1142  
1143              // Store list of paused plugins for displaying an admin notice.
1144              $GLOBALS['_paused_plugins'][ $plugin ] = $paused_plugins[ $plugin ];
1145          }
1146      }
1147  
1148      return $plugins;
1149  }
1150  
1151  /**
1152   * Retrieves an array of active and valid themes.
1153   *
1154   * While upgrading or installing WordPress, no themes are returned.
1155   *
1156   * @since 5.1.0
1157   * @access private
1158   *
1159   * @global string $pagenow            The filename of the current screen.
1160   * @global string $wp_stylesheet_path Path to current theme's stylesheet directory.
1161   * @global string $wp_template_path   Path to current theme's template directory.
1162   *
1163   * @return string[] Array of absolute paths to theme directories.
1164   */
1165  function wp_get_active_and_valid_themes() {
1166      global $pagenow, $wp_stylesheet_path, $wp_template_path;
1167  
1168      $themes = array();
1169  
1170      if ( wp_installing() && 'wp-activate.php' !== $pagenow ) {
1171          return $themes;
1172      }
1173  
1174      if ( is_child_theme() ) {
1175          $themes[] = $wp_stylesheet_path;
1176      }
1177  
1178      $themes[] = $wp_template_path;
1179  
1180      /*
1181       * Remove themes from the list of active themes when we're on an endpoint
1182       * that should be protected against WSODs and the theme is paused.
1183       */
1184      if ( wp_is_recovery_mode() ) {
1185          $themes = wp_skip_paused_themes( $themes );
1186  
1187          // If no active and valid themes exist, skip loading themes.
1188          if ( empty( $themes ) ) {
1189              add_filter( 'wp_using_themes', '__return_false' );
1190          }
1191      }
1192  
1193      return $themes;
1194  }
1195  
1196  /**
1197   * Filters a given list of themes, removing any paused themes from it.
1198   *
1199   * @since 5.2.0
1200   *
1201   * @global WP_Paused_Extensions_Storage $_paused_themes
1202   *
1203   * @param string[] $themes Array of absolute theme directory paths.
1204   * @return string[] Filtered array of absolute paths to themes, without any paused themes.
1205   */
1206  function wp_skip_paused_themes( array $themes ) {
1207      $paused_themes = wp_paused_themes()->get_all();
1208  
1209      if ( empty( $paused_themes ) ) {
1210          return $themes;
1211      }
1212  
1213      foreach ( $themes as $index => $theme ) {
1214          $theme = basename( $theme );
1215  
1216          if ( array_key_exists( $theme, $paused_themes ) ) {
1217              unset( $themes[ $index ] );
1218  
1219              // Store list of paused themes for displaying an admin notice.
1220              $GLOBALS['_paused_themes'][ $theme ] = $paused_themes[ $theme ];
1221          }
1222      }
1223  
1224      return $themes;
1225  }
1226  
1227  /**
1228   * Determines whether WordPress is in Recovery Mode.
1229   *
1230   * In this mode, plugins or themes that cause WSODs will be paused.
1231   *
1232   * @since 5.2.0
1233   *
1234   * @return bool
1235   */
1236  function wp_is_recovery_mode() {
1237      return wp_recovery_mode()->is_active();
1238  }
1239  
1240  /**
1241   * Determines whether we are currently on an endpoint that should be protected against WSODs.
1242   *
1243   * @since 5.2.0
1244   *
1245   * @global string $pagenow The filename of the current screen.
1246   *
1247   * @return bool True if the current endpoint should be protected.
1248   */
1249  function is_protected_endpoint() {
1250      // Protect login pages.
1251      if ( isset( $GLOBALS['pagenow'] ) && 'wp-login.php' === $GLOBALS['pagenow'] ) {
1252          return true;
1253      }
1254  
1255      // Protect the admin backend.
1256      if ( is_admin() && ! wp_doing_ajax() ) {
1257          return true;
1258      }
1259  
1260      // Protect Ajax actions that could help resolve a fatal error should be available.
1261      if ( is_protected_ajax_action() ) {
1262          return true;
1263      }
1264  
1265      /**
1266       * Filters whether the current request is against a protected endpoint.
1267       *
1268       * This filter is only fired when an endpoint is requested which is not already protected by
1269       * WordPress core. As such, it exclusively allows providing further protected endpoints in
1270       * addition to the admin backend, login pages and protected Ajax actions.
1271       *
1272       * @since 5.2.0
1273       *
1274       * @param bool $is_protected_endpoint Whether the currently requested endpoint is protected.
1275       *                                    Default false.
1276       */
1277      return (bool) apply_filters( 'is_protected_endpoint', false );
1278  }
1279  
1280  /**
1281   * Determines whether we are currently handling an Ajax action that should be protected against WSODs.
1282   *
1283   * @since 5.2.0
1284   *
1285   * @return bool True if the current Ajax action should be protected.
1286   */
1287  function is_protected_ajax_action() {
1288      if ( ! wp_doing_ajax() ) {
1289          return false;
1290      }
1291  
1292      if ( ! isset( $_REQUEST['action'] ) ) {
1293          return false;
1294      }
1295  
1296      $actions_to_protect = array(
1297          'edit-theme-plugin-file', // Saving changes in the core code editor.
1298          'heartbeat',              // Keep the heart beating.
1299          'install-plugin',         // Installing a new plugin.
1300          'install-theme',          // Installing a new theme.
1301          'search-plugins',         // Searching in the list of plugins.
1302          'search-install-plugins', // Searching for a plugin in the plugin install screen.
1303          'update-plugin',          // Update an existing plugin.
1304          'update-theme',           // Update an existing theme.
1305          'activate-plugin',        // Activating an existing plugin.
1306      );
1307  
1308      /**
1309       * Filters the array of protected Ajax actions.
1310       *
1311       * This filter is only fired when doing Ajax and the Ajax request has an 'action' property.
1312       *
1313       * @since 5.2.0
1314       *
1315       * @param string[] $actions_to_protect Array of strings with Ajax actions to protect.
1316       */
1317      $actions_to_protect = (array) apply_filters( 'wp_protected_ajax_actions', $actions_to_protect );
1318  
1319      if ( ! in_array( $_REQUEST['action'], $actions_to_protect, true ) ) {
1320          return false;
1321      }
1322  
1323      return true;
1324  }
1325  
1326  /**
1327   * Sets internal encoding.
1328   *
1329   * In most cases the default internal encoding is latin1, which is
1330   * of no use, since we want to use the `mb_` functions for `utf-8` strings.
1331   *
1332   * @since 3.0.0
1333   * @access private
1334   */
1335  function wp_set_internal_encoding() {
1336      if ( function_exists( 'mb_internal_encoding' ) ) {
1337          $charset = get_option( 'blog_charset' );
1338          // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
1339          if ( ! $charset || ! @mb_internal_encoding( $charset ) ) {
1340              mb_internal_encoding( 'UTF-8' );
1341          }
1342      }
1343  }
1344  
1345  /**
1346   * Adds magic quotes to `$_GET`, `$_POST`, `$_COOKIE`, and `$_SERVER`.
1347   *
1348   * Also forces `$_REQUEST` to be `$_GET + $_POST`. If `$_SERVER`,
1349   * `$_COOKIE`, or `$_ENV` are needed, use those superglobals directly.
1350   *
1351   * @since 3.0.0
1352   * @access private
1353   */
1354  function wp_magic_quotes() {
1355      // Escape with wpdb.
1356      $_GET    = add_magic_quotes( $_GET );
1357      $_POST   = add_magic_quotes( $_POST );
1358      $_COOKIE = add_magic_quotes( $_COOKIE );
1359      $_SERVER = add_magic_quotes( $_SERVER );
1360  
1361      // Force REQUEST to be GET + POST.
1362      $_REQUEST = array_merge( $_GET, $_POST );
1363  }
1364  
1365  /**
1366   * Runs just before PHP shuts down execution.
1367   *
1368   * @since 1.2.0
1369   * @access private
1370   */
1371  function shutdown_action_hook() {
1372      /**
1373       * Fires just before PHP shuts down execution.
1374       *
1375       * @since 1.2.0
1376       */
1377      do_action( 'shutdown' );
1378  
1379      wp_cache_close();
1380  }
1381  
1382  /**
1383   * Clones an object.
1384   *
1385   * @since 2.7.0
1386   * @deprecated 3.2.0
1387   *
1388   * @param object $input_object The object to clone.
1389   * @return object The cloned object.
1390   */
1391  function wp_clone( $input_object ) {
1392      // Use parens for clone to accommodate PHP 4. See #17880.
1393      return clone( $input_object );
1394  }
1395  
1396  /**
1397   * Determines whether the current request is for the login screen.
1398   *
1399   * @since 6.1.0
1400   *
1401   * @see wp_login_url()
1402   *
1403   * @return bool True if inside WordPress login screen, false otherwise.
1404   */
1405  function is_login() {
1406      return false !== stripos( wp_login_url(), $_SERVER['SCRIPT_NAME'] );
1407  }
1408  
1409  /**
1410   * Determines whether the current request is for an administrative interface page.
1411   *
1412   * Does not check if the user is an administrator; use current_user_can()
1413   * for checking roles and capabilities.
1414   *
1415   * For more information on this and similar theme functions, check out
1416   * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
1417   * Conditional Tags} article in the Theme Developer Handbook.
1418   *
1419   * @since 1.5.1
1420   *
1421   * @global WP_Screen $current_screen WordPress current screen object.
1422   *
1423   * @return bool True if inside WordPress administration interface, false otherwise.
1424   */
1425  function is_admin() {
1426      if ( isset( $GLOBALS['current_screen'] ) ) {
1427          return $GLOBALS['current_screen']->in_admin();
1428      } elseif ( defined( 'WP_ADMIN' ) ) {
1429          return WP_ADMIN;
1430      }
1431  
1432      return false;
1433  }
1434  
1435  /**
1436   * Determines whether the current request is for a site's administrative interface.
1437   *
1438   * e.g. `/wp-admin/`
1439   *
1440   * Does not check if the user is an administrator; use current_user_can()
1441   * for checking roles and capabilities.
1442   *
1443   * @since 3.1.0
1444   *
1445   * @global WP_Screen $current_screen WordPress current screen object.
1446   *
1447   * @return bool True if inside WordPress site administration pages.
1448   */
1449  function is_blog_admin() {
1450      if ( isset( $GLOBALS['current_screen'] ) ) {
1451          return $GLOBALS['current_screen']->in_admin( 'site' );
1452      } elseif ( defined( 'WP_BLOG_ADMIN' ) ) {
1453          return WP_BLOG_ADMIN;
1454      }
1455  
1456      return false;
1457  }
1458  
1459  /**
1460   * Determines whether the current request is for the network administrative interface.
1461   *
1462   * e.g. `/wp-admin/network/`
1463   *
1464   * Does not check if the user is an administrator; use current_user_can()
1465   * for checking roles and capabilities.
1466   *
1467   * Does not check if the site is a Multisite network; use is_multisite()
1468   * for checking if Multisite is enabled.
1469   *
1470   * @since 3.1.0
1471   *
1472   * @global WP_Screen $current_screen WordPress current screen object.
1473   *
1474   * @return bool True if inside WordPress network administration pages.
1475   */
1476  function is_network_admin() {
1477      if ( isset( $GLOBALS['current_screen'] ) ) {
1478          return $GLOBALS['current_screen']->in_admin( 'network' );
1479      } elseif ( defined( 'WP_NETWORK_ADMIN' ) ) {
1480          return WP_NETWORK_ADMIN;
1481      }
1482  
1483      return false;
1484  }
1485  
1486  /**
1487   * Determines whether the current request is for a user admin screen.
1488   *
1489   * e.g. `/wp-admin/user/`
1490   *
1491   * Does not check if the user is an administrator; use current_user_can()
1492   * for checking roles and capabilities.
1493   *
1494   * @since 3.1.0
1495   *
1496   * @global WP_Screen $current_screen WordPress current screen object.
1497   *
1498   * @return bool True if inside WordPress user administration pages.
1499   */
1500  function is_user_admin() {
1501      if ( isset( $GLOBALS['current_screen'] ) ) {
1502          return $GLOBALS['current_screen']->in_admin( 'user' );
1503      } elseif ( defined( 'WP_USER_ADMIN' ) ) {
1504          return WP_USER_ADMIN;
1505      }
1506  
1507      return false;
1508  }
1509  
1510  /**
1511   * Determines whether Multisite is enabled.
1512   *
1513   * @since 3.0.0
1514   *
1515   * @return bool True if Multisite is enabled, false otherwise.
1516   */
1517  function is_multisite() {
1518      if ( defined( 'MULTISITE' ) ) {
1519          return MULTISITE;
1520      }
1521  
1522      if ( defined( 'SUBDOMAIN_INSTALL' ) || defined( 'VHOST' ) || defined( 'SUNRISE' ) ) {
1523          return true;
1524      }
1525  
1526      return false;
1527  }
1528  
1529  /**
1530   * Converts a value to non-negative integer.
1531   *
1532   * @since 2.5.0
1533   * @since 7.2.0 The `int` return type was added. Finite values beyond the integer
1534   *              range are now capped at `PHP_INT_MAX` rather than overflowing.
1535   *              Non-finite values continue to return `0`, as `NAN` and `INF` have
1536   *              always cast to `0`; note that this includes numeric strings beyond
1537   *              the float range, such as `'1e309'`, which become `INF` when cast.
1538   *
1539   * @param mixed $maybeint Data you wish to have converted to a non-negative integer.
1540   * @return int A non-negative integer.
1541   *
1542   * @phpstan-template T
1543   * @phpstan-param T $maybeint
1544   * @phpstan-return (T is non-negative-int ? T : non-negative-int)
1545   */
1546  function absint( $maybeint ): int {
1547      if ( is_float( $maybeint ) ) {
1548          if ( ! is_finite( $maybeint ) ) {
1549              // Casting `NAN` or `INF` to int has produced `0` since PHP 7.0.
1550              return 0;
1551          }
1552  
1553          if ( $maybeint <= (float) PHP_INT_MIN || $maybeint >= (float) PHP_INT_MAX ) {
1554              // Casting a float beyond the integer range is unreliable and warns as of PHP 8.5.
1555              return PHP_INT_MAX;
1556          }
1557      }
1558  
1559      /*
1560       * Casting from an unknown type is the entire contract of this function, so this conversion is
1561       * deliberate: arrays, objects, and resources are converted exactly as PHP has always converted
1562       * them here, and narrowing the type first would change long-standing behavior. PHPStan flags
1563       * such casts for good reason, but that reasoning does not apply here; if the rule level is
1564       * ever raised to 9, the resulting `cast.int` error will need to be ignored or baselined.
1565       */
1566      $maybeint = (int) $maybeint;
1567  
1568      if ( PHP_INT_MIN === $maybeint ) {
1569          // `abs( PHP_INT_MIN )` overflows to a float, as `PHP_INT_MAX` is one less than `-PHP_INT_MIN`.
1570          return PHP_INT_MAX;
1571      }
1572  
1573      return abs( $maybeint );
1574  }
1575  
1576  /**
1577   * Retrieves the current site ID.
1578   *
1579   * @since 3.1.0
1580   *
1581   * @global int $blog_id
1582   *
1583   * @return int Site ID.
1584   */
1585  function get_current_blog_id() {
1586      global $blog_id;
1587  
1588      return absint( $blog_id );
1589  }
1590  
1591  /**
1592   * Retrieves the current network ID.
1593   *
1594   * @since 4.6.0
1595   *
1596   * @return int The ID of the current network.
1597   */
1598  function get_current_network_id() {
1599      if ( ! is_multisite() ) {
1600          return 1;
1601      }
1602  
1603      $current_network = get_network();
1604  
1605      if ( ! isset( $current_network->id ) ) {
1606          return get_main_network_id();
1607      }
1608  
1609      return absint( $current_network->id );
1610  }
1611  
1612  /**
1613   * Attempts an early load of translations.
1614   *
1615   * Used for errors encountered during the initial loading process, before
1616   * the locale has been properly detected and loaded.
1617   *
1618   * Designed for unusual load sequences (like setup-config.php) or for when
1619   * the script will then terminate with an error, otherwise there is a risk
1620   * that a file can be double-included.
1621   *
1622   * @since 3.4.0
1623   * @access private
1624   *
1625   * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
1626   * @global WP_Locale              $wp_locale              WordPress date and time locale object.
1627   */
1628  function wp_load_translations_early() {
1629      global $wp_textdomain_registry, $wp_locale;
1630      static $loaded = false;
1631  
1632      if ( $loaded ) {
1633          return;
1634      }
1635  
1636      $loaded = true;
1637  
1638      if ( function_exists( 'did_action' ) && did_action( 'init' ) ) {
1639          return;
1640      }
1641  
1642      // We need $wp_local_package.
1643      require  ABSPATH . WPINC . '/version.php';
1644  
1645      // Translation and localization.
1646      require_once  ABSPATH . WPINC . '/pomo/mo.php';
1647      require_once  ABSPATH . WPINC . '/l10n/class-wp-translation-controller.php';
1648      require_once  ABSPATH . WPINC . '/l10n/class-wp-translations.php';
1649      require_once  ABSPATH . WPINC . '/l10n/class-wp-translation-file.php';
1650      require_once  ABSPATH . WPINC . '/l10n/class-wp-translation-file-mo.php';
1651      require_once  ABSPATH . WPINC . '/l10n/class-wp-translation-file-php.php';
1652      require_once  ABSPATH . WPINC . '/l10n.php';
1653      require_once  ABSPATH . WPINC . '/class-wp-textdomain-registry.php';
1654      require_once  ABSPATH . WPINC . '/class-wp-locale.php';
1655      require_once  ABSPATH . WPINC . '/class-wp-locale-switcher.php';
1656  
1657      // General libraries.
1658      require_once  ABSPATH . WPINC . '/plugin.php';
1659  
1660      $locales   = array();
1661      $locations = array();
1662  
1663      if ( ! $wp_textdomain_registry instanceof WP_Textdomain_Registry ) {
1664          $wp_textdomain_registry = new WP_Textdomain_Registry();
1665      }
1666  
1667      while ( true ) {
1668          if ( defined( 'WPLANG' ) ) {
1669              if ( '' === WPLANG ) {
1670                  break;
1671              }
1672              $locales[] = WPLANG;
1673          }
1674  
1675          if ( isset( $wp_local_package ) ) {
1676              $locales[] = $wp_local_package;
1677          }
1678  
1679          if ( ! $locales ) {
1680              break;
1681          }
1682  
1683          if ( defined( 'WP_LANG_DIR' ) && @is_dir( WP_LANG_DIR ) ) {
1684              $locations[] = WP_LANG_DIR;
1685          }
1686  
1687          if ( defined( 'WP_CONTENT_DIR' ) && @is_dir( WP_CONTENT_DIR . '/languages' ) ) {
1688              $locations[] = WP_CONTENT_DIR . '/languages';
1689          }
1690  
1691          if ( @is_dir( ABSPATH . 'wp-content/languages' ) ) {
1692              $locations[] = ABSPATH . 'wp-content/languages';
1693          }
1694  
1695          if ( @is_dir( ABSPATH . WPINC . '/languages' ) ) {
1696              $locations[] = ABSPATH . WPINC . '/languages';
1697          }
1698  
1699          if ( ! $locations ) {
1700              break;
1701          }
1702  
1703          $locations = array_unique( $locations );
1704  
1705          foreach ( $locales as $locale ) {
1706              foreach ( $locations as $location ) {
1707                  if ( file_exists( $location . '/' . $locale . '.mo' ) ) {
1708                      load_textdomain( 'default', $location . '/' . $locale . '.mo', $locale );
1709  
1710                      if ( defined( 'WP_SETUP_CONFIG' ) && file_exists( $location . '/admin-' . $locale . '.mo' ) ) {
1711                          load_textdomain( 'default', $location . '/admin-' . $locale . '.mo', $locale );
1712                      }
1713  
1714                      break 2;
1715                  }
1716              }
1717          }
1718  
1719          break;
1720      }
1721  
1722      $wp_locale = new WP_Locale();
1723  }
1724  
1725  /**
1726   * Checks or sets whether WordPress is in "installation" mode.
1727   *
1728   * If the `WP_INSTALLING` constant is defined during the bootstrap, `wp_installing()` will default to `true`.
1729   *
1730   * @since 4.4.0
1731   *
1732   * @param bool $is_installing Optional. True to set WP into Installing mode, false to turn Installing mode off.
1733   *                            Omit this parameter if you only want to fetch the current status.
1734   * @return bool True if WP is installing, otherwise false. When a `$is_installing` is passed, the function will
1735   *              report whether WP was in installing mode prior to the change to `$is_installing`.
1736   */
1737  function wp_installing( $is_installing = null ) {
1738      static $installing = null;
1739  
1740      // Support for the `WP_INSTALLING` constant, defined before WP is loaded.
1741      if ( is_null( $installing ) ) {
1742          $installing = defined( 'WP_INSTALLING' ) && WP_INSTALLING;
1743      }
1744  
1745      if ( ! is_null( $is_installing ) ) {
1746          $old_installing = $installing;
1747          $installing     = $is_installing;
1748  
1749          return (bool) $old_installing;
1750      }
1751  
1752      return (bool) $installing;
1753  }
1754  
1755  /**
1756   * Determines if SSL is used.
1757   *
1758   * @since 2.6.0
1759   * @since 4.6.0 Moved from functions.php to load.php.
1760   *
1761   * @return bool True if SSL, otherwise false.
1762   */
1763  function is_ssl() {
1764      if ( isset( $_SERVER['HTTPS'] ) ) {
1765          if ( 'on' === strtolower( $_SERVER['HTTPS'] ) ) {
1766              return true;
1767          }
1768  
1769          if ( '1' === (string) $_SERVER['HTTPS'] ) {
1770              return true;
1771          }
1772      } elseif ( isset( $_SERVER['SERVER_PORT'] ) && ( '443' === (string) $_SERVER['SERVER_PORT'] ) ) {
1773          return true;
1774      }
1775  
1776      return false;
1777  }
1778  
1779  /**
1780   * Converts a shorthand byte value to an integer byte value.
1781   *
1782   * @since 2.3.0
1783   * @since 4.6.0 Moved from media.php to load.php.
1784   *
1785   * @link https://www.php.net/manual/en/function.ini-get.php
1786   * @link https://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
1787   *
1788   * @param string $value A (PHP ini) byte value, either shorthand or ordinary.
1789   * @return int An integer byte value.
1790   */
1791  function wp_convert_hr_to_bytes( $value ) {
1792      $value = strtolower( trim( $value ) );
1793      $bytes = (int) $value;
1794  
1795      if ( str_contains( $value, 'g' ) ) {
1796          $bytes *= GB_IN_BYTES;
1797      } elseif ( str_contains( $value, 'm' ) ) {
1798          $bytes *= MB_IN_BYTES;
1799      } elseif ( str_contains( $value, 'k' ) ) {
1800          $bytes *= KB_IN_BYTES;
1801      }
1802  
1803      // Deal with large (float) values which run into the maximum integer size.
1804      return min( $bytes, PHP_INT_MAX );
1805  }
1806  
1807  /**
1808   * Determines whether a PHP ini value is changeable at runtime.
1809   *
1810   * @since 4.6.0
1811   *
1812   * @link https://www.php.net/manual/en/function.ini-get-all.php
1813   *
1814   * @param string $setting The name of the ini setting to check.
1815   * @return bool True if the value is changeable at runtime. False otherwise.
1816   */
1817  function wp_is_ini_value_changeable( $setting ) {
1818      static $ini_all;
1819  
1820      if ( ! isset( $ini_all ) ) {
1821          $ini_all = false;
1822          // Sometimes `ini_get_all()` is disabled via the `disable_functions` option for "security purposes".
1823          if ( function_exists( 'ini_get_all' ) ) {
1824              $ini_all = ini_get_all();
1825          }
1826      }
1827  
1828      if ( isset( $ini_all[ $setting ]['access'] )
1829          && ( INI_ALL === $ini_all[ $setting ]['access'] || INI_USER === $ini_all[ $setting ]['access'] )
1830      ) {
1831          return true;
1832      }
1833  
1834      // If we were unable to retrieve the details, fail gracefully to assume it's changeable.
1835      if ( ! is_array( $ini_all ) ) {
1836          return true;
1837      }
1838  
1839      return false;
1840  }
1841  
1842  /**
1843   * Determines whether the current request is a WordPress Ajax request.
1844   *
1845   * @since 4.7.0
1846   *
1847   * @return bool True if it's a WordPress Ajax request, false otherwise.
1848   */
1849  function wp_doing_ajax() {
1850      /**
1851       * Filters whether the current request is a WordPress Ajax request.
1852       *
1853       * @since 4.7.0
1854       *
1855       * @param bool $wp_doing_ajax Whether the current request is a WordPress Ajax request.
1856       */
1857      return apply_filters( 'wp_doing_ajax', defined( 'DOING_AJAX' ) && DOING_AJAX );
1858  }
1859  
1860  /**
1861   * Determines whether the current request should use themes.
1862   *
1863   * @since 5.1.0
1864   *
1865   * @return bool True if themes should be used, false otherwise.
1866   */
1867  function wp_using_themes() {
1868      /**
1869       * Filters whether the current request should use themes.
1870       *
1871       * @since 5.1.0
1872       *
1873       * @param bool $wp_using_themes Whether the current request should use themes.
1874       */
1875      return apply_filters( 'wp_using_themes', defined( 'WP_USE_THEMES' ) && WP_USE_THEMES );
1876  }
1877  
1878  /**
1879   * Determines whether the current request is a WordPress cron request.
1880   *
1881   * @since 4.8.0
1882   *
1883   * @return bool True if it's a WordPress cron request, false otherwise.
1884   */
1885  function wp_doing_cron() {
1886      /**
1887       * Filters whether the current request is a WordPress cron request.
1888       *
1889       * @since 4.8.0
1890       *
1891       * @param bool $wp_doing_cron Whether the current request is a WordPress cron request.
1892       */
1893      return apply_filters( 'wp_doing_cron', defined( 'DOING_CRON' ) && DOING_CRON );
1894  }
1895  
1896  /**
1897   * Checks whether the given variable is a WordPress Error.
1898   *
1899   * Returns whether `$thing` is an instance of the `WP_Error` class.
1900   *
1901   * @since 2.1.0
1902   *
1903   * @param mixed $thing The variable to check.
1904   * @return bool Whether the variable is an instance of WP_Error.
1905   *
1906   * @phpstan-assert-if-true WP_Error $thing
1907   *
1908   * @phpstan-return ( $thing is WP_Error ? true : false )
1909   */
1910  function is_wp_error( $thing ) {
1911      $is_wp_error = ( $thing instanceof WP_Error );
1912  
1913      if ( $is_wp_error ) {
1914          /**
1915           * Fires when `is_wp_error()` is called and its parameter is an instance of WP_Error.
1916           *
1917           * @since 5.6.0
1918           *
1919           * @param WP_Error $thing The error object passed to `is_wp_error()`.
1920           */
1921          do_action( 'is_wp_error_instance', $thing );
1922      }
1923  
1924      return $is_wp_error;
1925  }
1926  
1927  /**
1928   * Determines whether file modifications are allowed.
1929   *
1930   * @since 4.8.0
1931   *
1932   * @param string $context The usage context.
1933   * @return bool True if file modification is allowed, false otherwise.
1934   */
1935  function wp_is_file_mod_allowed( $context ) {
1936      /**
1937       * Filters whether file modifications are allowed.
1938       *
1939       * @since 4.8.0
1940       *
1941       * @param bool   $file_mod_allowed Whether file modifications are allowed.
1942       * @param string $context          The usage context.
1943       */
1944      return apply_filters( 'file_mod_allowed', ! defined( 'DISALLOW_FILE_MODS' ) || ! DISALLOW_FILE_MODS, $context );
1945  }
1946  
1947  /**
1948   * Starts scraping edited file errors.
1949   *
1950   * @since 4.9.0
1951   */
1952  function wp_start_scraping_edited_file_errors() {
1953      if ( ! isset( $_REQUEST['wp_scrape_key'] ) || ! isset( $_REQUEST['wp_scrape_nonce'] ) ) {
1954          return;
1955      }
1956  
1957      $key   = substr( sanitize_key( wp_unslash( $_REQUEST['wp_scrape_key'] ) ), 0, 32 );
1958      $nonce = wp_unslash( $_REQUEST['wp_scrape_nonce'] );
1959      if ( empty( $key ) || empty( $nonce ) ) {
1960          return;
1961      }
1962  
1963      $transient = get_transient( 'scrape_key_' . $key );
1964      if ( false === $transient ) {
1965          return;
1966      }
1967  
1968      if ( $transient !== $nonce ) {
1969          if ( ! headers_sent() ) {
1970              header( 'X-Robots-Tag: noindex' );
1971              nocache_headers();
1972          }
1973          echo "###### wp_scraping_result_start:$key ######";
1974          echo wp_json_encode(
1975              array(
1976                  'code'    => 'scrape_nonce_failure',
1977                  'message' => __( 'Scrape key check failed. Please try again.' ),
1978              )
1979          );
1980          echo "###### wp_scraping_result_end:$key ######";
1981          die();
1982      }
1983  
1984      if ( ! defined( 'WP_SANDBOX_SCRAPING' ) ) {
1985          define( 'WP_SANDBOX_SCRAPING', true );
1986      }
1987  
1988      register_shutdown_function( 'wp_finalize_scraping_edited_file_errors', $key );
1989  }
1990  
1991  /**
1992   * Finalizes scraping for edited file errors.
1993   *
1994   * @since 4.9.0
1995   *
1996   * @param string $scrape_key Scrape key.
1997   */
1998  function wp_finalize_scraping_edited_file_errors( $scrape_key ) {
1999      $error = error_get_last();
2000  
2001      echo "\n###### wp_scraping_result_start:$scrape_key ######\n";
2002  
2003      if ( ! empty( $error )
2004          && in_array( $error['type'], array( E_CORE_ERROR, E_COMPILE_ERROR, E_ERROR, E_PARSE, E_USER_ERROR, E_RECOVERABLE_ERROR ), true )
2005      ) {
2006          $error = str_replace( ABSPATH, '', $error );
2007          echo wp_json_encode( $error );
2008      } else {
2009          echo wp_json_encode( true );
2010      }
2011  
2012      echo "\n###### wp_scraping_result_end:$scrape_key ######\n";
2013  }
2014  
2015  /**
2016   * Checks whether current request is a JSON request, or is expecting a JSON response.
2017   *
2018   * @since 5.0.0
2019   *
2020   * @return bool True if `Accepts` or `Content-Type` headers contain `application/json`.
2021   *              False otherwise.
2022   */
2023  function wp_is_json_request() {
2024      if ( isset( $_SERVER['HTTP_ACCEPT'] ) && wp_is_json_media_type( $_SERVER['HTTP_ACCEPT'] ) ) {
2025          return true;
2026      }
2027  
2028      if ( isset( $_SERVER['CONTENT_TYPE'] ) && wp_is_json_media_type( $_SERVER['CONTENT_TYPE'] ) ) {
2029          return true;
2030      }
2031  
2032      return false;
2033  }
2034  
2035  /**
2036   * Checks whether current request is a JSONP request, or is expecting a JSONP response.
2037   *
2038   * @since 5.2.0
2039   *
2040   * @return bool True if JSONP request, false otherwise.
2041   */
2042  function wp_is_jsonp_request() {
2043      if ( ! isset( $_GET['_jsonp'] ) ) {
2044          return false;
2045      }
2046  
2047      if ( ! function_exists( 'wp_check_jsonp_callback' ) ) {
2048          require_once  ABSPATH . WPINC . '/functions.php';
2049      }
2050  
2051      $jsonp_callback = $_GET['_jsonp'];
2052      if ( ! wp_check_jsonp_callback( $jsonp_callback ) ) {
2053          return false;
2054      }
2055  
2056      /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */
2057      $jsonp_enabled = apply_filters( 'rest_jsonp_enabled', true );
2058  
2059      return $jsonp_enabled;
2060  }
2061  
2062  /**
2063   * Checks whether a string is a valid JSON Media Type.
2064   *
2065   * @since 5.6.0
2066   *
2067   * @param string $media_type A Media Type string to check.
2068   * @return bool True if string is a valid JSON Media Type.
2069   */
2070  function wp_is_json_media_type( $media_type ) {
2071      static $cache = array();
2072  
2073      if ( ! isset( $cache[ $media_type ] ) ) {
2074          $cache[ $media_type ] = (bool) preg_match( '/(^|\s|,)application\/([\w!#\$&-\^\.\+]+\+)?json(\+oembed)?($|\s|;|,)/i', $media_type );
2075      }
2076  
2077      return $cache[ $media_type ];
2078  }
2079  
2080  /**
2081   * Checks whether current request is an XML request, or is expecting an XML response.
2082   *
2083   * @since 5.2.0
2084   *
2085   * @return bool True if `Accepts` or `Content-Type` headers contain `text/xml`
2086   *              or one of the related MIME types. False otherwise.
2087   */
2088  function wp_is_xml_request() {
2089      $accepted = array(
2090          'text/xml',
2091          'application/rss+xml',
2092          'application/atom+xml',
2093          'application/rdf+xml',
2094          'text/xml+oembed',
2095          'application/xml+oembed',
2096      );
2097  
2098      if ( isset( $_SERVER['HTTP_ACCEPT'] ) ) {
2099          foreach ( $accepted as $type ) {
2100              if ( str_contains( $_SERVER['HTTP_ACCEPT'], $type ) ) {
2101                  return true;
2102              }
2103          }
2104      }
2105  
2106      if ( isset( $_SERVER['CONTENT_TYPE'] ) && in_array( $_SERVER['CONTENT_TYPE'], $accepted, true ) ) {
2107          return true;
2108      }
2109  
2110      return false;
2111  }
2112  
2113  /**
2114   * Checks if this site is protected by HTTP Basic Auth.
2115   *
2116   * At the moment, this merely checks for the present of Basic Auth credentials. Therefore, calling
2117   * this function with a context different from the current context may give inaccurate results.
2118   * In a future release, this evaluation may be made more robust.
2119   *
2120   * Currently, this is only used by Application Passwords to prevent a conflict since it also utilizes
2121   * Basic Auth.
2122   *
2123   * @since 5.6.1
2124   *
2125   * @global string $pagenow The filename of the current screen.
2126   *
2127   * @param string $context The context to check for protection. Accepts 'login', 'admin', and 'front'.
2128   *                        Defaults to the current context.
2129   * @return bool Whether the site is protected by Basic Auth.
2130   */
2131  function wp_is_site_protected_by_basic_auth( $context = '' ) {
2132      global $pagenow;
2133  
2134      if ( ! $context ) {
2135          if ( 'wp-login.php' === $pagenow ) {
2136              $context = 'login';
2137          } elseif ( is_admin() ) {
2138              $context = 'admin';
2139          } else {
2140              $context = 'front';
2141          }
2142      }
2143  
2144      $is_protected = ! empty( $_SERVER['PHP_AUTH_USER'] ) || ! empty( $_SERVER['PHP_AUTH_PW'] );
2145  
2146      /**
2147       * Filters whether a site is protected by HTTP Basic Auth.
2148       *
2149       * @since 5.6.1
2150       *
2151       * @param bool   $is_protected Whether the site is protected by Basic Auth.
2152       * @param string $context      The context to check for protection. One of 'login', 'admin', or 'front'.
2153       */
2154      return apply_filters( 'wp_is_site_protected_by_basic_auth', $is_protected, $context );
2155  }


Generated : Thu Oct 22 08:20:34 2026 Cross-referenced by PHPXref