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


Generated : Sat Nov 23 08:20:01 2024 Cross-referenced by PHPXref