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


Generated : Thu Mar 28 08:20:01 2024 Cross-referenced by PHPXref