HEX
Server: nginx
System: Linux pool64-304-45.dca.atomicsites.net 5.10.0-31-amd64 #1 SMP Debian 5.10.221-1 (2024-07-14) x86_64
User: (0)
PHP: 8.4.19
Disabled: pcntl_fork
Upload Files
File: //scripts/env.php
<?php

ini_set( 'display_errors', '0' );
define( 'WP_DEBUG_DISPLAY', false );

// Maintain existing PHP behavior for >= 8.1
if ( function_exists( 'mysqli_report' ) ) {
	mysqli_report( MYSQLI_REPORT_OFF );
}

// s2member fix see: https://wordpress.org/support/topic/error-s2member-unable-to-locate-wordpress-directory
$_SERVER['WP_DIR'] = dirname( __FILE__ ) . '/../srv/htdocs/__wp__/';

function __atomic_env_define( $constant_name, $env_var=null, $default=null ) {
	if ( defined( $constant_name ) )
		return;
	if ( $env_var === null )
		$env_var = $constant_name;
	$value = getenv( $env_var );
	if ( $value === false && $default !== null )
		$value = $default;
	define( $constant_name, $value );
	// if executing under cli don't putenv or unset variables
	if ( 'cli' !== php_sapi_name() ) {
		unset( $_SERVER[ $env_var ] );
		unset( $_ENV[ $env_var ] );
		putenv( $env_var );
	}
}

__atomic_env_define( 'WP_MEMORY_LIMIT', 'ATOMIC_SITE_MEMORY_LIMIT', '512M' ); 
__atomic_env_define( 'WP_MAX_MEMORY_LIMIT', 'ATOMIC_SITE_MEMORY_LIMIT', '512M' );

if ( 'cli' == php_sapi_name() ) {
	ini_set( 'memory_limit', WP_MEMORY_LIMIT );
}

// For disabling outbound UDP ports 80, 3244 that trigger firewall alerts in WP defender plugin
define( 'WD_DONT_CHECK_UDP', true );

// Force flow-flow to use WPDB which prevents it from creating deadlocks in MariaDB
define('FF_USE_WPDB', true);

// This section of code needs to run before anything else, so that REMOTE_ADDR is set correctly in production
if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
	$_SERVER['REMOTE_ADDR_ORIG'] = $_SERVER['REMOTE_ADDR'];
}

if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && strstr( $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https' ) )
	$_SERVER['HTTPS'] = 'on';

// Proxied request, adjust SERVER_PORT accordingly
if ( isset( $_SERVER['HTTP_X_FORWARDED_PORT'] ) && is_numeric( $_SERVER['HTTP_X_FORWARDED_PORT'] ) )
	$_SERVER['SERVER_PORT'] = intval( $_SERVER['HTTP_X_FORWARDED_PORT'] );

if ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) &&
	( filter_var( $_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ||
	filter_var( $_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) )
	$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];

// Clear some default fpm vars that are not used and/or shouldn't be accessed by the site
$vars_to_remove = array( 'HOME', 'USER', 'REMOTE_ADDR_ORIG', 'HTTP_X_IP_TRAIL', 'PHP_ADMIN_VALUE' );
foreach( $vars_to_remove as $var_to_remove ) {
	putenv( $var_to_remove );
	unset( $_SERVER[ $var_to_remove ] );
	unset( $_ENV[ $var_to_remove ] );
}

// From http://php.net/manual/en/reserved.variables.server.php
// PATH_TRANSLATED should only exist if PATH_INFO is defined
if ( empty( $_SERVER['PATH_INFO']  ) )
	unset( $_SERVER['PATH_TRANSLATED'] );

# Required to run WP transparently from symlinked subdir
define( 'FS_METHOD', 'direct' );


# If we don't have a client id we can't securely serve the site, so just die
if ( ! isset( $_SERVER['ATOMIC_CLIENT_ID'] ) && 'cli' !== php_sapi_name() ) {
	http_response_code( 503 );
	die( 'Client ID Not found.' );
}

if ( 'cli' == php_sapi_name() ) {
	define( 'AT_PROXIED_REQUEST', false );
} elseif ( '1' === $_SERVER['ATOMIC_CLIENT_ID'] && isset( $_SERVER['A8C_PROXIED_REQUEST'] ) && '1' === $_SERVER['A8C_PROXIED_REQUEST'] ) {
	define( 'AT_PROXIED_REQUEST', true );
} elseif ( '2' === $_SERVER['ATOMIC_CLIENT_ID'] && isset( $_SERVER['A8C_PROXIED_REQUEST'] ) && '1' === $_SERVER['A8C_PROXIED_REQUEST'] ) {
	define( 'AT_PROXIED_REQUEST', true );
} elseif ( '3' === $_SERVER['ATOMIC_CLIENT_ID'] && isset( $_SERVER['PRESSABLE_PROXIED_REQUEST'] )  && '1' === $_SERVER['PRESSABLE_PROXIED_REQUEST'] ) {
	define( 'AT_PROXIED_REQUEST', true );
} elseif ( '5' === $_SERVER['ATOMIC_CLIENT_ID'] && isset( $_SERVER['A8C_PROXIED_REQUEST'] ) && '1' === $_SERVER['A8C_PROXIED_REQUEST'] ) {
	define( 'AT_PROXIED_REQUEST', true );
} elseif ( '6' === $_SERVER['ATOMIC_CLIENT_ID'] && isset( $_SERVER['A8C_PROXIED_REQUEST'] ) && '1' === $_SERVER['A8C_PROXIED_REQUEST'] ) {
	define( 'AT_PROXIED_REQUEST', true );
} elseif ( '8' === $_SERVER['ATOMIC_CLIENT_ID'] && isset( $_SERVER['A8C_PROXIED_REQUEST'] ) && '1' === $_SERVER['A8C_PROXIED_REQUEST'] ) {
	define( 'AT_PROXIED_REQUEST', true );
} elseif ( '13' === $_SERVER['ATOMIC_CLIENT_ID'] && isset( $_SERVER['A8C_PROXIED_REQUEST'] ) && '1' === $_SERVER['A8C_PROXIED_REQUEST'] ) {
	define( 'AT_PROXIED_REQUEST', true );
} elseif ( '109' === $_SERVER['ATOMIC_CLIENT_ID'] && isset( $_SERVER['A8C_PROXIED_REQUEST'] ) && '1' === $_SERVER['A8C_PROXIED_REQUEST'] ) {
	define( 'AT_PROXIED_REQUEST', true );
} elseif ( '118' === $_SERVER['ATOMIC_CLIENT_ID'] && isset( $_SERVER['A8C_PROXIED_REQUEST'] ) && '1' === $_SERVER['A8C_PROXIED_REQUEST'] ) {
	define( 'AT_PROXIED_REQUEST', true );
} elseif ( '131' === $_SERVER['ATOMIC_CLIENT_ID'] && isset( $_SERVER['A8C_PROXIED_REQUEST'] ) && '1' === $_SERVER['A8C_PROXIED_REQUEST'] ) {
	define( 'AT_PROXIED_REQUEST', true );
} else {
	define( 'AT_PROXIED_REQUEST', false );
}

# We don't want this to be overidden in custom-redirects.php
__atomic_env_define( 'AT_SITE_SUSPENDED', 'SUSPENDED' ); // Whether the site is suspended

/*
 * Catch cases when WP failed to connect to the database.
 */
function __atomic_wp_die_dead_db( $callback ) {
    $backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 10 );

	foreach ( $backtrace as $trace ) {
		if ( 'dead_db' === $trace['function'] ) {
			$GLOBALS['__atomic_dead_db'] = true;
			break;
		}

		if ( isset( $trace['file'] ) && '/wp-content/db-error.php' === substr( $trace['file'], -24 ) ) {
			$GLOBALS['__atomic_dead_db'] = true;
			break;
		}
	}

    return $callback;
}
atomic_add_filter( 'wp_die_handler', '__atomic_wp_die_dead_db', 0, 1 );
atomic_add_filter( 'wp_die_ajax_handler', '__atomic_wp_die_dead_db', 0, 1 );
atomic_add_filter( 'wp_die_json_handler', '__atomic_wp_die_dead_db', 0, 1 );
atomic_add_filter( 'wp_die_jsonp_handler', '__atomic_wp_die_dead_db', 0, 1 );
atomic_add_filter( 'wp_die_xml_handler', '__atomic_wp_die_dead_db', 0, 1 );
atomic_add_filter( 'wp_die_xmlrpc_handler', '__atomic_wp_die_dead_db', 0, 1 );

/*
 * Sanity check and correct bad status codes [and later on maybe caching headers].
 */
function __atomic_header_callback() {
	$current_http_response_code = http_response_code();

	if ( 502 == $current_http_response_code || // 502s are special for us, not allowed for users
		$current_http_response_code < 100 || $current_http_response_code > 599 ) // matches the strictest check in Nginx
	{
		error_log( "Error: Sent an incorrect $current_http_response_code status code." );
		http_response_code( 500 );
		header( "{$_SERVER['SERVER_PROTOCOL']} 500 Internal Server Error", true, 500 );
	}

	// Make an exception for MySQL connection errors where we want 502
	// We have this in addition to the __atomic_wp_die_dead_db() filter above
	// because some users install db-error.php and exit there without wp_die().
	$last_error = error_get_last();
	if ( $last_error && false !== strpos( $last_error['message'], 'mysqli_real_connect' ) ) {
		$conn_failure_strings = [ 'Too many connections', 'Connection timed out', 'Connection refused' ];
		foreach ( $conn_failure_strings as $conn_failure ) {
			if ( false === strpos( $last_error['message'], $conn_failure ) ) {
				$GLOBALS['__atomic_dead_db'] = true;
				break;
			}
		}
	}

	if ( ! empty( $GLOBALS['__atomic_dead_db'] ) && $current_http_response_code >= 500 ) {
		http_response_code( 502 );
		header( "{$_SERVER['SERVER_PROTOCOL']} 502 Bad Gateway", true, 502 );
	}
}
if ( 'cli' !== php_sapi_name() && ! header_register_callback('__atomic_header_callback') ) {
	http_response_code( 503 );
	die( 'Unexpected PHP error.' );
}   

final class Atomic_Persistent_Data implements Iterator {
	private $initialized;
	private $filename;
	private $encrypted;
	private $decrypted;

	private $index = array();
	private $position = 0;

	public function __construct( $filename = null ) {
		$this->initialized = false;
		$this->filename = $filename;
	}

	private function initialize() {
		if ( false !== $this->initialized ) {
			return;
		}
		$this->initialized = true;
		$this->encrypted = new stdClass();
		$this->decrypted = new stdClass();
		if ( empty( $this->filename ) ) {
			$this->filename = sys_get_temp_dir() . '/.at-persistent-data';
		}
		if ( ! file_exists( $this->filename ) ) {
			return;
		}
		if ( ! is_readable( $this->filename ) ) {
			return;
		}
		if ( ! is_file( $this->filename ) ) {
			return;
		}
		$contents = file_get_contents( $this->filename );
		if ( false === $contents || empty( $contents ) ) {
			return;
		}
		$data = json_decode( $contents );
		if ( false === $data || empty( $data ) ) {
			return;
		}
		$this->index = array_keys( get_object_vars( $data ) );
		if ( empty( $data->_version ) || false === $data->_encrypted ) {
			$this->encrypted = $data;
			$this->decrypted = $data;
		} else {
			$this->encrypted = $data;
		}
	}

	private function __key() {
		static $key = null;
		if ( null === $key ) {
			$key = hash_hkdf(
				'sha256',
				constant( 'DB_PASSWORD' ),
				SODIUM_CRYPTO_SECRETBOX_KEYBYTES,
				'site-persist-data',
				'site-persist-data'
			);
		}

		return $key;
	}

	public function __get( $name ) {
		$this->initialize();
		if ( property_exists( $this->decrypted, $name ) ) {
			return $this->decrypted->{$name};
		}
		if ( ! property_exists( $this->encrypted, $name ) ) {
			return null;
		}
		if ( ! is_object( $this->encrypted->{$name} ) || ! property_exists( $this->encrypted->{$name}, 'nonce' ) || ! property_exists( $this->encrypted->{$name}, 'value' ) ) {
			$this->decrypted->{$name} = $this->encrypted->{$name};

			return $this->decrypted->{$name};
		}
		try {
			$this->decrypted->{$name} = sodium_crypto_secretbox_open(
				sodium_base642bin( $this->encrypted->{$name}->value, SODIUM_BASE64_VARIANT_URLSAFE ),
				sodium_base642bin( $this->encrypted->{$name}->nonce, SODIUM_BASE64_VARIANT_URLSAFE ),
				$this->__key()
			);
			return $this->decrypted->{$name};
		} catch ( Throwable $ex ) {
			error_log( sprintf( 'Critical error decrypting %s: %s', $name, $ex->getMessage() ) );
			return null;
		}
	}

	public function __isset( $name ) {
		$this->initialize();
		return property_exists( $this->encrypted, $name );
	}

	// iterator
	#[\ReturnTypeWillChange]
	public function current() {
		$this->initialize();
		return $this->__get( $this->index[ $this->position ] );
	}

	// iterator
	#[\ReturnTypeWillChange]
	public function key() {
		$this->initialize();
		return $this->index[ $this->position ];
	}

	// iterator
	#[\ReturnTypeWillChange]
	public function next() {
		$this->initialize();
		++$this->position;
	}

	// iterator
	#[\ReturnTypeWillChange]
	public function rewind() {
		$this->initialize();
		$this->position = 0;
	}

	// iterator
	#[\ReturnTypeWillChange]
	public function valid() {
		$this->initialize();
		return isset( $this->index[ $this->position ] );
	}
}

# Per-client env.php. We want need the file names to be unique to not cause opcache collisions since they are executed in the chroot
$client_env_file = dirname( __FILE__ ) . '/env-client-' . $_SERVER['ATOMIC_CLIENT_ID'] . '.php';
if ( file_exists( $client_env_file ) ) {
	include( $client_env_file );
}

switch( $_SERVER['ATOMIC_CLIENT_ID'] ) {
	case "2":
		// Used by Jetpack and maybe some other stuff
		// See http://wp.me/p72Wkx-gY
		define( 'IS_ATOMIC', true );
		define( 'AT_SMTP_PORT', 25 );
		define( 'WPCLOUD_STAGING_DOMAIN', '.wpcomstaging.com' );
		define( 'WPCLOUD_STAGING_ALLOW_INDEXING', false );
		$atomic_hosting_provider = 'WordPress.com';
		break;
	case "3":
		define( 'IS_PRESSABLE', true );
		define( 'AT_SMTP_PORT', 26 );
		define( 'WPCLOUD_STAGING_DOMAIN', '.mystagingwebsite.com' );
		define( 'WPCLOUD_STAGING_ALLOW_INDEXING', false );
		$atomic_hosting_provider = 'Pressable';
		break;
	case "6":
		define( 'AT_SMTP_PORT', 25 );
		$atomic_hosting_provider = 'Newspack';
		break;
	case "8":
		define( 'AT_SMTP_PORT', 25 );
		$atomic_hosting_provider = 'HappyP2';
		break;
	case "9":
		define( 'AT_SMTP_PORT', 25 ); // @TODO
		$atomic_hosting_provider = 'Automattic'; // @TODO
		break;
	case "118": // commerce-garden
		define( 'IS_ATOMIC', true );
		define( 'AT_SMTP_PORT', 27 );
		$atomic_hosting_provider = 'WordPress.com';
		break;
	case "131": // wpcom-flex 
		define( 'IS_ATOMIC', true );
		define( 'AT_SMTP_PORT', 25 );
		$atomic_hosting_provider = 'WordPress.com';
		break;
	default :
		define( 'IS_ATOMIC', true );
		define( 'AT_SMTP_PORT', 25 );
		$atomic_hosting_provider = 'Automattic';
		break;
}

/*
 * Determine if staging sites should allow indexing when robots.txt file does not exist.
 * Existing robots.txt file is served by NGINX.
 * 
 * @return Do not handle the request, continue to WP.
 */
function atomic_maybe_handle_staging_robots_txt_request() {
	// Check constants defined, if not continue to WP (existing behavior)
	if ( ! defined( 'WPCLOUD_STAGING_DOMAIN' ) || ! defined( 'WPCLOUD_STAGING_ALLOW_INDEXING' ) ) {
		return;
	}
	// If staging indexing enabled, allow WP to handle
	if ( WPCLOUD_STAGING_ALLOW_INDEXING ) {
		return;
	}
	// Check if robots request
	if ( ! isset( $_SERVER['REQUEST_URI'] ) ||  '/robots.txt' !== strtok( $_SERVER['REQUEST_URI'], '?' ) ) {
		return;
	}
	// Check if staging domain request
	if ( ! isset( $_SERVER['HTTP_HOST'] ) || WPCLOUD_STAGING_DOMAIN !== substr( $_SERVER['HTTP_HOST'], 0 - strlen( WPCLOUD_STAGING_DOMAIN ) ) ) {
		return;
	}

	// Disallow by default
	header( 'Content-Type: text/plain; charset=utf-8' );
	echo "User-agent: *\nDisallow: /\n";
	exit;
}
atomic_maybe_handle_staging_robots_txt_request();

if ( isset( $_SERVER['REQUEST_URI'] ) && '/.well-known/hosting-provider' == $_SERVER['REQUEST_URI'] && isset( $atomic_hosting_provider ) ) {
	die( $atomic_hosting_provider . "\n" );
}

// Disable Patchwork.
eval('namespace Patchwork; function replace() {}');

// Any non-overridable constants should be defined above
// If a custom-redirects.php file exists in the site's htdocs folder, then
// require it. Also check in CLI context because custom-redirects.php
// could be defining DB_{CHARSET,COLLATE} and not having CLI context match
// can produce unexpected results. Because defines haven't been set yet,
// need to use 'getenv'.
$custom_redirects = '/srv/htdocs/custom-redirects.php';

if ( file_exists( $custom_redirects ) ) {
	require $custom_redirects;
}
// Any overridable constants should be defined, conditionally, below

// MySQL settings - we set them here so that we remove the sensitive data from $_SERVER before customer-executed code
// These are overridable in custom-redirects.php
__atomic_env_define( 'DB_NAME' );                     // The name of the database for WordPress
__atomic_env_define( 'DB_USER' );                     // MySQL database username
__atomic_env_define( 'DB_PASSWORD' );                 // MySQL database password
__atomic_env_define( 'DB_HOST', null, '127.0.0.1' );  // MySQL hostname
__atomic_env_define( 'DB_CHARSET', null, 'utf8mb4' ); // Database Charset to use in creating database tables.
__atomic_env_define( 'DB_COLLATE' );                  // The Database Collate type. Don't change this if in doubt

// Atomic Service Definitions. These are overridable in custom-redirects.php
__atomic_env_define( 'ATOMIC_SITE_ID' );
__atomic_env_define( 'ATOMIC_CLIENT_ID' );
__atomic_env_define( 'ATOMIC_SERVER_POOL_ID' );
__atomic_env_define( 'ATOMIC_SITE_API_KEY', null, '' ); // Virtual API key from metadata used by sites for calling real API
__atomic_env_define( 'WP_CACHE_KEY_SALT' );           // Cache key prefix.  Used in object-cache.php
__atomic_env_define( 'AT_SMTP_PASS', 'SMTP_PASS' );     // SMTP Password.  Used in /mu-plugins/mail.php
__atomic_env_define( 'JETPACK_BLOG_TOKEN' );          // Force a jetpack blog connection token if one is provided
__atomic_env_define( 'AT_DEVELOPMENT_MODE', 'DEVELOPMENT_MODE' );
__atomic_env_define( 'PHP_FS_PERMISSIONS', 'PHP_FS_PERMISSIONS' );
__atomic_env_define( 'AT_PRIVACY_MODEL', 'PRIVACY_MODEL' );
__atomic_env_define( 'AT_GAUGES_ID', 'GAUGES_ID' );
__atomic_env_define( 'AT_PHOTON_SUBSIZES', 'PHOTON_SUBSIZES', '' );
__atomic_env_define( 'AT_DEREFERENCED_SOFTWARE', 'DEREFERENCED_SOFTWARE', '0' );
__atomic_env_define( 'ATOMIC_APM_ENABLED' );
__atomic_env_define( 'AT_PHP_CURRENT_CONNECTIONS', 'PHP_CURRENT_CONNECTIONS' );
__atomic_env_define( 'AT_PHP_BURST_STATUS', 'PHP_BURST_STATUS' );

if ( ! AT_DEREFERENCED_SOFTWARE ) {
	// Disable core WP updates for sites that should be using a managed version.
	// Set this constant because Jetpack overrides the auto-update filters,
	// and other plugins could as well.
	define( 'WP_AUTO_UPDATE_CORE', false );
}

// Local API url prefix
define( 'SITE_API_BASE', 'http://127.0.0.1:47002/api/v1.0' );
// Page Optimize setup
define( 'PAGE_OPTIMIZE_CACHE_DIR', false ); // Disable cache
// paths so we can run service.php w/o WP
define( 'PAGE_OPTIMIZE_CONCAT_BASE_DIR', '/srv/htdocs' );
define( 'PAGE_OPTIMIZE_ABSPATH', PAGE_OPTIMIZE_CONCAT_BASE_DIR . '/__wp__' );

if ( !defined( 'WPCOM_API_KEY' ) )
	define( 'WPCOM_API_KEY', '98e6b103f2e3' );

define( 'THEMES_SYMLINK_BASE', '../../../wordpress/themes' );

# For wp-cli to work
if ( 'cli' == php_sapi_name() ) {
	__atomic_env_define( 'DOMAIN_NAME' );
	// WP CLI if provided with --url arg should set WP_{HOME,SITEURL} the same way its set for HTTP
	// otherwise it will use the home/siteurl options which most likely will return a staging address
	// needs to be added as an action though because WP CLI setting of $_SERVER vars when --url
	// present happens after env.php is required. if --url isn't provided then none of the
	// usable $_SERVER vars get set, so the behavior should stay consistent for things that dont pass --url
	atomic_add_action( 'muplugins_loaded', 'maybe_set_wp_home_and_wp_siteurl', 0 );

	// disable WP cron reuqests from firing when using WP CLI
	define( 'DISABLE_WP_CRON', true );
	define( 'WP_HOME','https://' . DOMAIN_NAME );
	define( 'WP_SITEURL','https://' . DOMAIN_NAME );

	// no Batcache with CLI
	if ( isset( $_SERVER[ 'argv' ] ) )
		$batcache['max_age'] = 0;
}

define( 'WP_CONTENT_DIR', realpath( '/srv/htdocs/wp-content' ) );
define( 'ATOMIC_MU_PLUGIN_DIR', realpath( '/wordpress/mu-plugins' ) );
// for AT sites
define( 'THEMES_PATH_BASE', realpath( '/wordpress/themes' ) );
$memcached_servers = array( '127.0.0.1:11211' );

if ( isset( $_SERVER['SERVER_NAME'] ) && $_SERVER['SERVER_NAME'] ) {
	if ( isset( $_SERVER['HTTPS'] ) && 'on' == $_SERVER['HTTPS'] ) {
		define( 'WP_HOME','https://' . $_SERVER['SERVER_NAME'] );
		define( 'WP_SITEURL','https://' . $_SERVER['SERVER_NAME'] );
	} else {
		define( 'WP_HOME','http://' . $_SERVER['SERVER_NAME'] );
		define( 'WP_SITEURL','http://' . $_SERVER['SERVER_NAME'] );
	}
}

// require SSL for wp-login/wp-admin when enabled or when staging
if ( getenv( 'SSL_ENABLED' ) === "true" || ( isset( $_SERVER['HTTP_HOST'] ) && strpos( $_SERVER['HTTP_HOST'], ".mystagingwebsite.com" ) > 0 ) ) {
	define( 'FORCE_SSL_LOGIN', true );
	define( 'FORCE_SSL_ADMIN', true );
} else {
	define( 'FORCE_SSL_LOGIN', false );
	define( 'FORCE_SSL_ADMIN', false );
}
unset( $_SERVER['SSL_ENABLED'] );

if ( AT_PROXIED_REQUEST ) {
	ini_set( 'error_reporting', -1 ); // E_ALL + forward compat

	global $batcache;
	$batcache['max_age'] = 0;

	define( 'WP_CACHE', false );
	define( 'WP_DEBUG', true );
	// when proxied turn off WP_DEBUG_LOG if defined
	// we want errors sent to logstash
	define( 'WP_DEBUG_LOG', false );
	define( 'SAVEQUERIES', true );

	// Record the start time of each database query
	atomic_add_filter( 'query', 'atomic_debug_query_offsets', 1e9, 1 );
	function atomic_debug_query_offsets( $query ) {
		$offset = sprintf( '%0.6f', microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'] );
		$GLOBALS[ 'atomic_debug_query_offsets' ][ $offset ] = $query;
		return $query;
	}
	atomic_add_filter( 'swift_performance_is_cacheable', '__atomic_return_false' );
	atomic_add_filter( 'swift_performance_is_cacheable_dynamic', '__atomic_return_false' );
	atomic_add_filter( 'swift_performance_is_cacheable_ajax', '__atomic_return_false' );
	function __atomic_return_false() {
		return false;
	}
}

defined( 'WP_CACHE' ) or define( 'WP_CACHE', true );
$batcache['cache_redirects'] = true;
header( 'X-AT-I-Renderer: php' );

// Allow adding filters/actions prior to loading WordPress.
// $function_to_add MUST be a string.
function atomic_add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
	global $wp_filter;
	$wp_filter[$tag][$priority][$function_to_add] = array('function' => $function_to_add, 'accepted_args' => $accepted_args);
}
function atomic_add_action( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
	atomic_add_filter( $tag, $function_to_add, $priority, $accepted_args );
}

// Load our mu-plugins after customer mu-plugins
// NOTE: this means our mu-plugins can't use the muplugins_loaded action!
atomic_add_action( 'muplugins_loaded', 'atomic_load_mu_plugins', 0 );
function atomic_load_mu_plugins() {
	$mu_plugins      = array();
	$persistent_data = null;
	$overrides       = null;
	if ( ! is_dir( ATOMIC_MU_PLUGIN_DIR ) ) {
		return;
	}
	if ( ! $dh = opendir( ATOMIC_MU_PLUGIN_DIR ) ) {
		return;
	}
	// If we are told to enable this feature via a define in wp-config.php then initialize
	// the required data structures
	if ( defined( 'WPCLOUD_ALLOW_FILTERED_MU_PLUGINS' ) && WPCLOUD_ALLOW_FILTERED_MU_PLUGINS ) {
		$persistent_data = new Atomic_Persistent_Data();
		$overrides       = array(
			'loaded'  => array(),
			'skipped' => array(),
		);
		$disable_all     = false;
		if ( ! empty( $persistent_data->{"disable_mu-plugin_all"} ) ) {
			$disable_all = true;
		}
	}
	while ( ( $plugin = readdir( $dh ) ) !== false ) {
		// Early continue for non-php-files
		if ( substr( $plugin, -4 ) !== '.php' ) {
			continue;
		}
		// Early continue for when we are not configured to disable mu-plugins
		if ( null === $persistent_data ) {
			$mu_plugins[] = $plugin;
			continue;
		}
		// If we have been asked to skip this then
		if ( true === $disable_all || ! empty( $persistent_data->{"disable_mu-plugin_$plugin"} ) ) {
			// First: never allow disabling of the following mu-plugins:
			//	atomic-*, wpcloud-*, mail.php
			if ( ! empty( preg_match( '/^(atomic|wpcloud|mail\.php$)/', $plugin ) ) ) {
				$overrides['loaded'][] = rawurlencode( $plugin );
				$mu_plugins[] = $plugin;
				continue;
			}
			// Early continue for disabled mu-plugin
			$overrides['skipped'][] = rawurlencode( $plugin );
			continue;
		}
		// The plugin has not been specifically disabled, so add the plugin to the list
		$overrides['loaded'][] = rawurlencode( $plugin );
		$mu_plugins[] = $plugin;
	}
	if ( ! empty( $overrides ) ) {
		header( 'X-Mu-Plugins-Loaded: ' . implode( '; ', $overrides['loaded'] ) );
		header( 'X-Mu-Plugins-Skipped: ' . implode( '; ', $overrides['skipped'] ) );
	}
	closedir( $dh );
	sort( $mu_plugins );
	foreach ( $mu_plugins as $mu_plugin ) {
		load_atomic_mu_plugin( $mu_plugin );
	}
}

// APM AutoInstrumentation for WordPress
if ( 'true' === ATOMIC_APM_ENABLED && extension_loaded( 'elastic_apm' ) && class_exists( '\Elastic\Apm\ElasticApm', true ) ) {
	function atomic_apm_auto_instrumentation_wp_hook( $hook_name, $value = null ) {
		global $atomic_apm_wp_stage_spans;
		global $wp_actions;
		global $wp_filter;

		##
		# Add artificial grouping spans for WP Hooks
		##

		// Bail if stages are not setup
		if ( !is_array( $atomic_apm_wp_stage_spans ) ) {
			return;
		}

		// Stop setup stage on first call to wp action
		if ( $atomic_apm_wp_stage_spans['setup'] instanceof \Elastic\Apm\SpanInterface && !$atomic_apm_wp_stage_spans['setup']->hasEnded() && 'wp' === $hook_name ) {
			$atomic_apm_wp_stage_spans['setup']->end();
		}

		// Stop content stage on first call to shutdown action
		if ( $atomic_apm_wp_stage_spans['content'] instanceof \Elastic\Apm\SpanInterface && !$atomic_apm_wp_stage_spans['content']->hasEnded() && 'shutdown' === $hook_name ) {
			$atomic_apm_wp_stage_spans['content']->end();
		}

		// First hooked action, start a WP Setup stage
		if ( null === $atomic_apm_wp_stage_spans['setup'] ) {
			$atomic_apm_wp_stage_spans['setup'] = \Elastic\Apm\ElasticApm::getCurrentTransaction()->beginCurrentSpan(
				'Stage: Setup',
				'wp',
				'wp_stage',
				'setup'
			);
		}

		// First call of wp action start content stage
		if ( null === $atomic_apm_wp_stage_spans['content'] && 'wp' === $hook_name ) {
			$atomic_apm_wp_stage_spans['content'] = \Elastic\Apm\ElasticApm::getCurrentTransaction()->beginCurrentSpan(
				'Stage: Content',
				'wp',
				'wp_stage',
				'content'
			);
		}

		##
		# Process "real" spans from actual WP Hook calls
		##

		// Ignore filters
		if ( ! isset( $wp_actions[ $hook_name ] ) ) {
			return;
		}

		// Ignore invalid hooks
		if ( ! isset( $wp_filter[ $hook_name ] ) || ! is_a( $wp_filter[ $hook_name ] , 'WP_Hook' ) ) {
			return;
		}

		// Ignore if we're not working with a WP_Hook object with callbacks
		if ( ! $wp_filter[ $hook_name ]->has_filters() ) {
			return;
		}

		$callback_names = array();
		foreach ( $wp_filter[ $hook_name ]->callbacks as $priority => $callbacks ) {
			foreach ( $callbacks as $callback ) {
				if ( is_string( $callback['function'] ) ) {
					$callback_names[] = $callback['function'] . '()';
				} elseif ( is_array( $callback['function'] ) && is_string( $callback['function'][0] ) ) {
					$callback_names[] = $callback['function'][0] . '::' . $callback['function'][1] . '()';
				} elseif ( is_array( $callback['function'] ) && is_object( $callback['function'][0] ) ) {
					$callback_names[] = get_class( $callback['function'][0] ) . '->' . $callback['function'][1] . '()';
				} elseif ( $callback['function'] instanceof Closure ) {
					$reflection = new ReflectionFunction( $callback['function'] );
					if ( '/scripts/env.php' === $reflection->getFileName() ) {
						continue; // Hide thyself
					}
					$callback_names[] = sprintf(
						'[%s:%d-%d]',
						$reflection->getFileName(),
						$reflection->getStartLine(),
						$reflection->getEndLine()
					);
				} elseif ( is_object( $callback['function'] ) && method_exists( $callback['function'], '__invoke' ) ) {
					$callback_names[] = get_class( $callback['function'] ) . '->__invoke()';
				} else {
					$callback_names[] = '[unknown]';
				}
			}
		}

		// Ignore if we don't have any hooked callables to show
		if ( 0 === count( $callback_names ) ) {
			return;
		}

		if ( null === $value ) {
			$arg_display = sprintf( "'%s'", $hook_name );
		} else {
			$arg_display = sprintf( "'%s', <%s>", $hook_name, gettype( $value ) );
		}

		// Start Span
		$span = \Elastic\Apm\ElasticApm::getCurrentTransaction()->beginCurrentSpan(
			"do_action($arg_display)",
			'wp',
			'wp_hook',
			'do_action'
		);

		// Set context for span
		foreach ( $callback_names as $callback_idx => $callback_name ) {
			if ( $callback_idx > 25 ) {
				break;
			}
			$span->context()->setLabel(
				sprintf( 'hooked-%02d', $callback_idx ),
				$callback_name
			);
			// Elastic APM breaks if context is changed too fast so we sleep a bit between each set
			usleep( 50 );
		}
		$span->context()->setLabel( 'hooked-count', count( $callback_names ) );

		// Add a callback to end the span at lowest priority
		$wp_filter[ $hook_name ]->add_filter(
			$hook_name,
			function () use ( $span ) {
				if ( !$span->hasEnded() ) {
					$span->end();
				}
			},
			PHP_INT_MAX,
			0
		);
	}

	$atomic_apm_wp_stage_spans = array(
		'setup' => null,
		'content' => null,
	);

	atomic_add_action( 'all', 'atomic_apm_auto_instrumentation_wp_hook', PHP_INT_MIN, 2 );
	register_shutdown_function( function () {
		global $atomic_apm_wp_stage_spans;

		if ( !is_array( $atomic_apm_wp_stage_spans ) ) {
			return;
		}

		foreach ( $atomic_apm_wp_stage_spans as $maybe_span ) {
			if ( $maybe_span instanceof \Elastic\Apm\SpanInterface && !$maybe_span->hasEnded() ) {
				$maybe_span->end();
			}
		}
	} );
}

// used for WP CLI when provided with --url arg, see above comment
function maybe_set_wp_home_and_wp_siteurl() {
	if ( isset( $_SERVER['SERVER_NAME'] ) ) {
		if ( isset( $_SERVER['HTTPS'] ) && 'on' == $_SERVER['HTTPS'] ) {
			if ( ! defined( 'WP_HOME' ) ) {
				define( 'WP_HOME','https://' . $_SERVER['SERVER_NAME'] );
			}
			if ( ! defined( 'WP_SITEURL' ) ) {
				define( 'WP_SITEURL','https://' . $_SERVER['SERVER_NAME'] );
			}
		} else {
			if ( ! defined( 'WP_HOME' ) ) {
				define( 'WP_HOME','http://' . $_SERVER['SERVER_NAME'] );
			}
			if ( ! defined( 'WP_SITEURL' ) ) {
				define( 'WP_SITEURL','http://' . $_SERVER['SERVER_NAME'] );
			}
		}
	}
}

// Set memory limit for WP-CLI requests
// See: https://github.com/wp-cli/wp-cli/issues/5547
atomic_add_action( 'muplugins_loaded', 'atomic_set_memory_limit' );
function atomic_set_memory_limit() {
	if ( ! defined( 'WP_MEMORY_LIMIT' ) || ! defined( 'WP_CLI' ) ) {
		return;
	}

	if ( ! is_callable( 'WP_CLI', 'add_hook' ) ) {
		return;
	}

	WP_CLI::add_hook( 'after_wp_load', function() {
		WP_CLI::debug( 'Setting memory limit to ' . WP_MEMORY_LIMIT, 'atomic' );
		ini_set( 'memory_limit', WP_MEMORY_LIMIT );
	} );
}

// Show correct memory limits in Site Health - Info screen
// PHP caches calls to ini_get() in opcache so we can't trust them at run time
// See: https://github.com/php/php-src/issues/8699
atomic_add_filter( 'debug_information', 'atomic_memory_limit_debug' );
function atomic_memory_limit_debug( $info ) {
	if ( defined( 'WP_MEMORY_LIMIT' ) && ! empty( $info['wp-server']['fields']['memory_limit']['value'] ) ) {
		$info['wp-server']['fields']['memory_limit']['value'] = WP_MEMORY_LIMIT;
	}

	if ( defined( 'WP_MAX_MEMORY_LIMIT' ) && ! empty( $info['wp-server']['fields']['admin_memory_limit']['value'] ) ) {
		$info['wp-server']['fields']['admin_memory_limit']['value'] = WP_MAX_MEMORY_LIMIT;
	}

	return $info;
}

// Correctly load mu-plugin from a symlinked subdir of mu-plugins.
// The argument must be relative to our subdir of mu-plugins.
// Sample args: 'mail.php' | 'debug-bar/debug-bar.php'
function load_atomic_mu_plugin( $relative_path ) {
	$abs_path = ATOMIC_MU_PLUGIN_DIR . '/' . $relative_path;
	include_once( $abs_path );
}

// Plugins outside of WP_CONTENT_DIR always get bad asset URLs.
atomic_add_filter( 'plugins_url', 'atomic_symlinked_plugins_url', 0, 3 );
function atomic_symlinked_plugins_url( $url, $path, $plugin ) {
	$url = preg_replace(
		// The subpattern eats multisite path prefixes. It uses a
		// lookbehind assertion to avoid consuming a prefix preceded
		// by a double slash; this preserves the hostname.
		'#((?<!/)/[^/]+)*/wp-content/plugins/wordpress/mu-plugins/#',
		'/wp-content/mu-host-plugins/',
		$url
	);
	return $url;
}

// See: http://php.net/manual/en/class.sessionhandlerinterface.php
final class AtomicSessionHandler implements SessionHandlerInterface {

	private $save_path = '';
	private $name = '';
	private $mc = null;

	#[\ReturnTypeWillChange]
	public function destroy( $session_id ) {
		if ( $this->mc === null )
			return false;
		return $this->mc->delete( $this->key( $session_id ) );
	}

	#[\ReturnTypeWillChange]
	public function read( $session_id ) {
		if ( $this->mc === null )
			return '';
		$data = $this->mc->get( $this->key( $session_id ) );
		if ( false === $data ) {
			$data = '';
		}
		return $data;
	}

	#[\ReturnTypeWillChange]
	public function write( $session_id, $session_data ) {
		if ( $this->mc === null )
			return false;
		return $this->mc->set( $this->key( $session_id ), $session_data, MEMCACHE_COMPRESSED, ini_get( 'session.gc_maxlifetime' ) );
	}

	private function key( $session_id ) {
		return sprintf(
			'%s:_s_:%s:%s',
			WP_CACHE_KEY_SALT,
			substr( md5( sprintf( ":%s:%s:", $this->save_path, $this->name ) ), 10, 15 ),
			md5( $session_id ) );
	}

	#[\ReturnTypeWillChange]
	public function close() {
		$this->save_path = '';
		$this->name = '';
		if ( $this->mc !== null ) {
			$this->mc->close();
			$this->mc = null;
		}
		return true;
	}

	#[\ReturnTypeWillChange]
	public function open( $save_path, $name ) {
		global $memcached_servers;

		$this->save_path = $save_path;
		$this->name = $name;
		$this->mc = new Memcache;

		$success = false;

		foreach( $memcached_servers as $server ) {
			// Most of this borrowed from wp-content/object-cache.php
			if ( 'unix://' == substr( $server, 0, 7 ) ) {
				$node = $server;
				$port = 0;
			} else {
				list ( $node, $port ) = explode(':', $server);
				if ( !$port )
					$port = ini_get('memcache.default_port');
				$port = intval($port);
				if ( !$port )
					$port = 11211;
			}

			if ( $this->mc->connect( $node, $port ) ) {
				$this->mc->setCompressThreshold(20000, 0.2);
				return true;
			}

			error_log( "AtomicSessionHandler failed to connect to $server" );
		}

		error_log( "AtomicSessionHandler failed to connect to any server" );
		$this->mc = null;
		return false;
	}

	#[\ReturnTypeWillChange]
	public function gc( $maxlifetime ) {
		return true;
	}
}

// By default store sessions in memcached instead of the filesystem
$atomic_session_handler = new AtomicSessionHandler();
session_set_save_handler( $atomic_session_handler, true );

/**
 * _atomic_platform_managed_symlink returns the path to use for creating a symlink to the managed version of specific software.
 * The path is from the location of the ling being linked, and so should not normally need to be adjusted.
 * 
 * ['drop-in', 'object-cache.php']       => ../../wordpress/drop-ins/object-cache.php
 * ['mu-plugin', 'debug-bar-loader.php'] => ../../../wordpress/mu-plugins/debug-bar-loader.php
 * ['mu-plugin', 'debug-bar']            => ../../../wordpress/mu-plugins/debug-bar
 * ['plugin', 'akismet']                 => ../../../wordpress/plugins/akismet/latest
 * ['plugin', 'akismet', '5.2']          => ../../../wordpress/plugins/akismet/5.2
 * ['theme', 'twentyseventeen']          => ../../../wordpress/themes/twentyseventeen/latest
 * ['theme', 'twentyseventeen', '3.2']   => ../../../wordpress/themes/twentyseventeen/3.2
 * ['theme', 'blahtheme', 'special']     => ../../../wordpress/themes/special/blahtheme (legacy use case only returned if exists)
 * 
 * @param string $kind one of drop-in(s), mu-pliugin(s), plugin(s), or theme(s)
 * @param string $thing the name of the managed thing. hello-dolly, or twentynineteen for example
 * @param string $version the version of the thing (defaults to "latest" which should almost always be used.)
 * 
 * @return mixed string on success, false on failure
 */
function _atomic_platform_managed_symlink( $kind, $thing, $version = 'latest' ) {
	static $symlink_root = null;
	if ( null === $symlink_root ) {
		$symlink_root = _atomic_platform_managed_symlink_root();
	}
	$kind = rtrim( $kind, 's' );
	switch( $kind ) {
    	case 'drop-in':
    		// linked to from htdocs/wp-content, ../puts the link target in htdocs, $symlink_root handles where to go below that
    		return sprintf( '../%s/%ss/%s', $symlink_root, $kind, $thing );
        case 'mu-plugin':
        	// linked to from htdocs/wp-content/mu-plugins, ../../puts the link target in htdocs, $symlink_root handles where to go below that
        	return sprintf( '../../%s/%ss/%s', $symlink_root, $kind, $thing );
        case 'plugin':
        	// linked to from htdocs/wp-content/plugins, ../../puts the link target in htdocs, $symlink_root handles where to go below that
        	return sprintf( '../../%s/%ss/%s/%s', $symlink_root, $kind, $thing, $version );
        case 'theme':
        	// linked to from htdocs/wp-content/themes, ../../puts the link target in htdocs, $symlink_root handles where to go below that
        	$maybe = sprintf( '../../%s/%ss/%s/%s', $symlink_root, $kind, $version, $thing );
        	if ( file_exists( sprintf( '/srv/htdocs/wp-content/themes/%s', $maybe ) ) ) {
        		return $maybe;
        	}
        	return sprintf( '../../%s/%ss/%s/%s', $symlink_root, $kind, $thing, $version );
        default:
        	return false;
	}
}

/**
 *  _atomic_platform_managed_symlink_root determines where a site should symlink to for managed code
 * from htdocs. For v1 link layouts this will be ../../wordpress, and for v2 this will be ../wordpress.
 * 
 * @return string path to wordpress from htdocs
 */
function _atomic_platform_managed_symlink_root() {
	static $default  = '../wordpress';

	if ( true !== file_exists( '/srv/htdocs/__wp__' ) ) {
		return $default;
	}

	// dev / dereferenced sites... Default to the safest option...
	if ( true !== is_link( '/srv/htdocs/__wp__' ) ) {
		return $default;
	}

	// v1 will point to ../../wordpress/core/{version}, return ../../wordpress
	// v2 will point to ../wordpress/core/{version} , return ../wordpress
	return dirname( readlink( '/srv/htdocs/__wp__' ), 2 );
}