* These functions are needed to load WordPress.
* Return the HTTP protocol sent by the server.
* @return string The HTTP protocol. Default: HTTP/1.0.
function wp_get_server_protocol() {
$protocol = isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : '';
if ( ! in_array( $protocol, array( 'HTTP/1.1', 'HTTP/2', 'HTTP/2.0' ), true ) ) {
* Fix `$_SERVER` variables for various setups.
* @global string $PHP_SELF The filename of the currently executing script,
* relative to the document root.
function wp_fix_server_vars() {
$default_server_values = array(
$_SERVER = array_merge( $default_server_values, $_SERVER );
// Fix for IIS when running with PHP ISAPI.
if ( empty( $_SERVER['REQUEST_URI'] ) || ( 'cgi-fcgi' !== PHP_SAPI && preg_match( '/^Microsoft-IIS\//', $_SERVER['SERVER_SOFTWARE'] ) ) ) {
if ( isset( $_SERVER['HTTP_X_ORIGINAL_URL'] ) ) {
$_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_ORIGINAL_URL'];
} elseif ( isset( $_SERVER['HTTP_X_REWRITE_URL'] ) ) {
$_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_REWRITE_URL'];
// Use ORIG_PATH_INFO if there is no PATH_INFO.
if ( ! isset( $_SERVER['PATH_INFO'] ) && isset( $_SERVER['ORIG_PATH_INFO'] ) ) {
$_SERVER['PATH_INFO'] = $_SERVER['ORIG_PATH_INFO'];
// Some IIS + PHP configurations put the script-name in the path-info (no need to append it twice).
if ( isset( $_SERVER['PATH_INFO'] ) ) {
if ( $_SERVER['PATH_INFO'] == $_SERVER['SCRIPT_NAME'] ) {
$_SERVER['REQUEST_URI'] = $_SERVER['PATH_INFO'];
$_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . $_SERVER['PATH_INFO'];
// Append the query string if it exists and isn't null.
if ( ! empty( $_SERVER['QUERY_STRING'] ) ) {
$_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
// Fix for PHP as CGI hosts that set SCRIPT_FILENAME to something ending in php.cgi for all requests.
if ( isset( $_SERVER['SCRIPT_FILENAME'] ) && ( strpos( $_SERVER['SCRIPT_FILENAME'], 'php.cgi' ) == strlen( $_SERVER['SCRIPT_FILENAME'] ) - 7 ) ) {
$_SERVER['SCRIPT_FILENAME'] = $_SERVER['PATH_TRANSLATED'];
// Fix for Dreamhost and other PHP as CGI hosts.
if ( strpos( $_SERVER['SCRIPT_NAME'], 'php.cgi' ) !== false ) {
unset( $_SERVER['PATH_INFO'] );
$PHP_SELF = $_SERVER['PHP_SELF'];
if ( empty( $PHP_SELF ) ) {
$_SERVER['PHP_SELF'] = preg_replace( '/(\?.*)?$/', '', $_SERVER['REQUEST_URI'] );
$PHP_SELF = $_SERVER['PHP_SELF'];
wp_populate_basic_auth_from_authorization_header();
* Populates the Basic Auth server details from the Authorization header.
* Some servers running in CGI or FastCGI mode don't pass the Authorization
* header on to WordPress. If it's been rewritten to the `HTTP_AUTHORIZATION` header,
* fill in the proper $_SERVER variables instead.
function wp_populate_basic_auth_from_authorization_header() {
// If we don't have anything to pull from, return early.
if ( ! isset( $_SERVER['HTTP_AUTHORIZATION'] ) && ! isset( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) ) {
// If either PHP_AUTH key is already set, do nothing.
if ( isset( $_SERVER['PHP_AUTH_USER'] ) || isset( $_SERVER['PHP_AUTH_PW'] ) ) {
// From our prior conditional, one of these must be set.
$header = isset( $_SERVER['HTTP_AUTHORIZATION'] ) ? $_SERVER['HTTP_AUTHORIZATION'] : $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
// Test to make sure the pattern matches expected.
if ( ! preg_match( '%^Basic [a-z\d/+]*={0,2}$%i', $header ) ) {
// Removing `Basic ` the token would start six characters in.
$token = substr( $header, 6 );
$userpass = base64_decode( $token );
list( $user, $pass ) = explode( ':', $userpass );
// Now shove them in the proper keys where we're expecting later on.
$_SERVER['PHP_AUTH_USER'] = $user;
$_SERVER['PHP_AUTH_PW'] = $pass;
* Check for the required PHP version, and the MySQL extension or
* Dies if requirements are not met.
* @global string $required_php_version The required PHP version string.
* @global string $wp_version The WordPress version string.
function wp_check_php_mysql_versions() {
global $required_php_version, $wp_version;
$php_version = phpversion();
if ( version_compare( $required_php_version, $php_version, '>' ) ) {
$protocol = wp_get_server_protocol();
header( sprintf( '%s 500 Internal Server Error', $protocol ), true, 500 );
header( 'Content-Type: text/html; charset=utf-8' );
printf( 'Your server is running PHP version %1$s but WordPress %2$s requires at least %3$s.', $php_version, $wp_version, $required_php_version );
if ( ! extension_loaded( 'mysql' ) && ! extension_loaded( 'mysqli' ) && ! extension_loaded( 'mysqlnd' )
// This runs before default constants are defined, so we can't assume WP_CONTENT_DIR is set yet.
&& ( defined( 'WP_CONTENT_DIR' ) && ! file_exists( WP_CONTENT_DIR . '/db.php' )
|| ! file_exists( ABSPATH . 'wp-content/db.php' ) )
require_once ABSPATH . WPINC . '/functions.php';
wp_load_translations_early();
'code' => 'mysql_not_found',
__( 'Your PHP installation appears to be missing the MySQL extension which is required by WordPress.' ),
__( 'Requirements Not Met' ),
* Retrieves the current environment type.
* The type can be set via the `WP_ENVIRONMENT_TYPE` global system variable,
* or a constant of the same name.
* Possible values are 'local', 'development', 'staging', and 'production'.
* If not set, the type defaults to 'production'.
* @since 5.5.1 Added the 'local' type.
* @since 5.5.1 Removed the ability to alter the list of types.
* @return string The current environment type.
function wp_get_environment_type() {
static $current_env = '';
$wp_environments = array(
// Add a note about the deprecated WP_ENVIRONMENT_TYPES constant.
if ( defined( 'WP_ENVIRONMENT_TYPES' ) && function_exists( '_deprecated_argument' ) ) {
if ( function_exists( '__' ) ) {
/* translators: %s: WP_ENVIRONMENT_TYPES */
$message = sprintf( __( 'The %s constant is no longer supported.' ), 'WP_ENVIRONMENT_TYPES' );
$message = sprintf( 'The %s constant is no longer supported.', 'WP_ENVIRONMENT_TYPES' );
// Check if the environment variable has been set, if `getenv` is available on the system.
if ( function_exists( 'getenv' ) ) {
$has_env = getenv( 'WP_ENVIRONMENT_TYPE' );
if ( false !== $has_env ) {
// Fetch the environment from a constant, this overrides the global system variable.
if ( defined( 'WP_ENVIRONMENT_TYPE' ) ) {
$current_env = WP_ENVIRONMENT_TYPE;
// Make sure the environment is an allowed one, and not accidentally set to an invalid value.
if ( ! in_array( $current_env, $wp_environments, true ) ) {
$current_env = 'production';
* Don't load all of WordPress when handling a favicon.ico request.
* Instead, send the headers for a zero-length favicon and bail.
* @deprecated 5.4.0 Deprecated in favor of do_favicon().
function wp_favicon_request() {
if ( '/favicon.ico' === $_SERVER['REQUEST_URI'] ) {
header( 'Content-Type: image/vnd.microsoft.icon' );
* Die with a maintenance message when conditions are met.
* The default message can be replaced by using a drop-in (maintenance.php in
* the wp-content directory).
function wp_maintenance() {
// Return if maintenance mode is disabled.
if ( ! wp_is_maintenance_mode() ) {
if ( file_exists( WP_CONTENT_DIR . '/maintenance.php' ) ) {
require_once WP_CONTENT_DIR . '/maintenance.php';
require_once ABSPATH . WPINC . '/functions.php';
wp_load_translations_early();
header( 'Retry-After: 600' );
__( 'Briefly unavailable for scheduled maintenance. Check back in a minute.' ),
* Check if maintenance mode is enabled.
* Checks for a file in the WordPress root directory named ".maintenance".
* This file will contain the variable $upgrading, set to the time the file
* was created. If the file was created less than 10 minutes ago, WordPress
* is in maintenance mode.
* @global int $upgrading The Unix timestamp marking when upgrading WordPress began.
* @return bool True if maintenance mode is enabled, false otherwise.
function wp_is_maintenance_mode() {
if ( ! file_exists( ABSPATH . '.maintenance' ) || wp_installing() ) {
require ABSPATH . '.maintenance';
// If the $upgrading timestamp is older than 10 minutes, consider maintenance over.
if ( ( time() - $upgrading ) >= 10 * MINUTE_IN_SECONDS ) {
* Filters whether to enable maintenance mode.
* This filter runs before it can be used by plugins. It is designed for
* non-web runtimes. If this filter returns true, maintenance mode will be
* active and the request will end. If false, the request will be allowed to
* continue processing even if maintenance mode should be active.
* @param bool $enable_checks Whether to enable maintenance mode. Default true.
* @param int $upgrading The timestamp set in the .maintenance file.
if ( ! apply_filters( 'enable_maintenance_mode', true, $upgrading ) ) {
* Start the WordPress micro-timer.
* @global float $timestart Unix timestamp set at the beginning of the page load.
* @return bool Always returns true.
$timestart = microtime( true );
* Retrieve or display the time from the page start to when function is called.
* @global float $timestart Seconds from when timer_start() is called.
* @global float $timeend Seconds from when function is called.
* @param int|bool $display Whether to echo or return the results. Accepts 0|false for return,
* 1|true for echo. Default 0|false.
* @param int $precision The number of digits from the right of the decimal to display.
* @return string The "second.microsecond" finished time calculation. The number is formatted
* for human consumption, both localized and rounded.
function timer_stop( $display = 0, $precision = 3 ) {
global $timestart, $timeend;
$timeend = microtime( true );
$timetotal = $timeend - $timestart;
$r = ( function_exists( 'number_format_i18n' ) ) ? number_format_i18n( $timetotal, $precision ) : number_format( $timetotal, $precision );
* Set PHP error reporting based on WordPress debug settings.
* Uses three constants: `WP_DEBUG`, `WP_DEBUG_DISPLAY`, and `WP_DEBUG_LOG`.
* All three can be defined in wp-config.php. By default, `WP_DEBUG` and
* `WP_DEBUG_LOG` are set to false, and `WP_DEBUG_DISPLAY` is set to true.
* When `WP_DEBUG` is true, all PHP notices are reported. WordPress will also
* display internal notices: when a deprecated WordPress function, function
* argument, or file is used. Deprecated code may be removed from a later
* It is strongly recommended that plugin and theme developers use `WP_DEBUG`
* in their development environments.
* `WP_DEBUG_DISPLAY` and `WP_DEBUG_LOG` perform no function unless `WP_DEBUG`
* When `WP_DEBUG_DISPLAY` is true, WordPress will force errors to be displayed.
* `WP_DEBUG_DISPLAY` defaults to true. Defining it as null prevents WordPress
* from changing the global configuration setting. Defining `WP_DEBUG_DISPLAY`
* as false will force errors to be hidden.
* When `WP_DEBUG_LOG` is true, errors will be logged to `wp-content/debug.log`.
* When `WP_DEBUG_LOG` is a valid path, errors will be logged to the specified file.
* Errors are never displayed for XML-RPC, REST, and Ajax requests.
* @since 5.1.0 `WP_DEBUG_LOG` can be a file path.
function wp_debug_mode() {
* Filters whether to allow the debug mode check to occur.
* This filter runs before it can be used by plugins. It is designed for
* non-web run-times. Returning false causes the `WP_DEBUG` and related
* constants to not be checked and the default PHP values for errors
* will be used unless you take care to update them yourself.
* To use this filter you must define a `$wp_filter` global before
* WordPress loads, usually in `wp-config.php`.
* $GLOBALS['wp_filter'] = array(
* 'enable_wp_debug_mode_checks' => array(
* 'function' => function() {
* @param bool $enable_debug_mode Whether to enable debug mode checks to occur. Default true.
if ( ! apply_filters( 'enable_wp_debug_mode_checks', true ) ) {
error_reporting( E_ALL );
if ( WP_DEBUG_DISPLAY ) {
ini_set( 'display_errors', 1 );
} elseif ( null !== WP_DEBUG_DISPLAY ) {
ini_set( 'display_errors', 0 );
if ( in_array( strtolower( (string) WP_DEBUG_LOG ), array( 'true', '1' ), true ) ) {
$log_path = WP_CONTENT_DIR . '/debug.log';
} elseif ( is_string( WP_DEBUG_LOG ) ) {
$log_path = WP_DEBUG_LOG;
ini_set( 'log_errors', 1 );
ini_set( 'error_log', $log_path );
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 );
if ( defined( 'XMLRPC_REQUEST' ) || defined( 'REST_REQUEST' ) || ( defined( 'WP_INSTALLING' ) && WP_INSTALLING ) || wp_doing_ajax() || wp_is_json_request() ) {
ini_set( 'display_errors', 0 );
* Set the location of the language directory.
* To set directory manually, define the `WP_LANG_DIR` constant
* If the language directory exists within `WP_CONTENT_DIR`, it
* is used. Otherwise the language directory is assumed to live
function wp_set_lang_dir() {
if ( ! defined( 'WP_LANG_DIR' ) ) {
if ( file_exists( WP_CONTENT_DIR . '/languages' ) && @is_dir( WP_CONTENT_DIR . '/languages' ) || ! @is_dir( ABSPATH . WPINC . '/languages' ) ) {
* Server path of the language directory.
* No leading slash, no trailing slash, full path, not relative to ABSPATH
define( 'WP_LANG_DIR', WP_CONTENT_DIR . '/languages' );
if ( ! defined( 'LANGDIR' ) ) {