mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
257 lines
8.0 KiB
PHP
257 lines
8.0 KiB
PHP
<?php
|
|
|
|
namespace SilverStripe\Core;
|
|
|
|
/**
|
|
* Consolidates access and modification of PHP global variables and settings.
|
|
* This class should be used sparingly, and only if information cannot be obtained
|
|
* from a current {@link HTTPRequest} object.
|
|
*
|
|
* Acts as the primary store for environment variables, including those loaded
|
|
* from .env files. Applications should use Environment::getEnv() instead of php's
|
|
* `getenv` in order to include `.env` configuration, as the system's actual
|
|
* environment variables are treated immutably.
|
|
*/
|
|
class Environment
|
|
{
|
|
/**
|
|
* Set maximum limit allowed for increaseMemoryLimit
|
|
*
|
|
* @var float|null
|
|
*/
|
|
protected static $memoryLimitMax = null;
|
|
|
|
/**
|
|
* Set maximum limited allowed for increaseTimeLimit
|
|
*
|
|
* @var int|null
|
|
*/
|
|
protected static $timeLimitMax = null;
|
|
|
|
/**
|
|
* Local overrides for all $_ENV var protected from cross-process operations
|
|
*
|
|
* @var array
|
|
*/
|
|
protected static $env = [];
|
|
|
|
/**
|
|
* Extract env vars prior to modification
|
|
*
|
|
* @return array List of all super globals
|
|
*/
|
|
public static function getVariables()
|
|
{
|
|
// Suppress return by-ref
|
|
$vars = [ 'env' => static::$env ];
|
|
// needs to use a for loop, using `array_merge([], $GLOBALS);` left reference traces somehow
|
|
foreach ($GLOBALS as $varName => $varValue) {
|
|
$vars[$varName] = $varValue;
|
|
}
|
|
|
|
return $vars;
|
|
}
|
|
|
|
/**
|
|
* Restore a backed up or modified list of vars to $globals
|
|
*
|
|
* @param array $vars
|
|
*/
|
|
public static function setVariables(array $vars)
|
|
{
|
|
foreach ($vars as $varName => $varValue) {
|
|
if ($varName === 'env') {
|
|
continue;
|
|
}
|
|
$GLOBALS[$varName] = $varValue;
|
|
}
|
|
if (array_key_exists('env', $vars ?? [])) {
|
|
static::$env = $vars['env'];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Increase the memory limit to the given level if it's currently too low.
|
|
* Only increases up to the maximum defined in {@link setMemoryLimitMax()},
|
|
* and defaults to the 'memory_limit' setting in the PHP configuration.
|
|
*
|
|
* @param string|float|int $memoryLimit A memory limit string, such as "64M". If omitted, unlimited memory will be set.
|
|
* @return bool true indicates a successful change, false a denied change.
|
|
*/
|
|
public static function increaseMemoryLimitTo($memoryLimit = -1)
|
|
{
|
|
$memoryLimit = Convert::memstring2bytes($memoryLimit);
|
|
$curLimit = Convert::memstring2bytes(ini_get('memory_limit'));
|
|
|
|
// Can't go higher than infinite
|
|
if ($curLimit < 0) {
|
|
return true;
|
|
}
|
|
|
|
// Check hard maximums
|
|
$max = static::getMemoryLimitMax();
|
|
if ($max > 0 && ($memoryLimit < 0 || $memoryLimit > $max)) {
|
|
$memoryLimit = $max;
|
|
}
|
|
|
|
// Increase the memory limit if it's too low
|
|
if ($memoryLimit < 0) {
|
|
ini_set('memory_limit', '-1');
|
|
} elseif ($memoryLimit > $curLimit) {
|
|
ini_set('memory_limit', Convert::bytes2memstring($memoryLimit));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Set the maximum allowed value for {@link increaseMemoryLimitTo()}.
|
|
* The same result can also be achieved through 'suhosin.memory_limit'
|
|
* if PHP is running with the Suhosin system.
|
|
*
|
|
* @param string|float $memoryLimit Memory limit string or float value
|
|
*/
|
|
static function setMemoryLimitMax($memoryLimit)
|
|
{
|
|
if (isset($memoryLimit) && !is_numeric($memoryLimit)) {
|
|
$memoryLimit = Convert::memstring2bytes($memoryLimit);
|
|
}
|
|
static::$memoryLimitMax = $memoryLimit;
|
|
}
|
|
|
|
/**
|
|
* @return int Memory limit in bytes
|
|
*/
|
|
public static function getMemoryLimitMax()
|
|
{
|
|
if (static::$memoryLimitMax === null) {
|
|
return Convert::memstring2bytes(ini_get('memory_limit'));
|
|
}
|
|
return static::$memoryLimitMax;
|
|
}
|
|
|
|
/**
|
|
* Increase the time limit of this script. By default, the time will be unlimited.
|
|
* Only works if 'safe_mode' is off in the PHP configuration.
|
|
* Only values up to {@link getTimeLimitMax()} are allowed.
|
|
*
|
|
* @param int $timeLimit The time limit in seconds. If omitted, no time limit will be set.
|
|
* @return Boolean TRUE indicates a successful change, FALSE a denied change.
|
|
*/
|
|
public static function increaseTimeLimitTo($timeLimit = null)
|
|
{
|
|
// Check vs max limit
|
|
$max = static::getTimeLimitMax();
|
|
if ($max > 0 && $timeLimit > $max) {
|
|
return false;
|
|
}
|
|
|
|
if (!$timeLimit) {
|
|
set_time_limit(0);
|
|
} else {
|
|
$currTimeLimit = ini_get('max_execution_time');
|
|
// Only increase if its smaller
|
|
if ($currTimeLimit > 0 && $currTimeLimit < $timeLimit) {
|
|
set_time_limit($timeLimit ?? 0);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Set the maximum allowed value for {@link increaseTimeLimitTo()};
|
|
*
|
|
* @param int $timeLimit Limit in seconds
|
|
*/
|
|
public static function setTimeLimitMax($timeLimit)
|
|
{
|
|
static::$timeLimitMax = $timeLimit;
|
|
}
|
|
|
|
/**
|
|
* @return Int Limit in seconds
|
|
*/
|
|
public static function getTimeLimitMax()
|
|
{
|
|
return static::$timeLimitMax;
|
|
}
|
|
|
|
/**
|
|
* Get value of environment variable.
|
|
* If the value is false, you should check Environment::hasEnv() to see
|
|
* if the value is an actual environment variable value or if the variable
|
|
* simply hasn't been set.
|
|
*
|
|
* @param string $name
|
|
* @return mixed Value of the environment variable, or false if not set
|
|
*/
|
|
public static function getEnv($name)
|
|
{
|
|
if (array_key_exists($name, static::$env)) {
|
|
return static::$env[$name];
|
|
}
|
|
// isset() is used for $_ENV and $_SERVER instead of array_key_exists() to fix a very strange issue that
|
|
// occured in CI running silverstripe/recipe-kitchen-sink where PHP would timeout due apparently due to an
|
|
// excessively high number of array method calls. isset() is not used for static::$env above because
|
|
// values there may be null, and isset() will return false for null values
|
|
// Symfony also uses isset() for reading $_ENV and $_SERVER values
|
|
// https://github.com/symfony/dependency-injection/blob/6.2/EnvVarProcessor.php#L148
|
|
if (isset($_ENV[$name])) {
|
|
return $_ENV[$name];
|
|
}
|
|
if (isset($_SERVER[$name])) {
|
|
return $_SERVER[$name];
|
|
}
|
|
return getenv($name);
|
|
}
|
|
|
|
/**
|
|
* Set environment variable using php.ini syntax.
|
|
* Acts as a process-isolated version of putenv()
|
|
* Note: This will be parsed via parse_ini_string() which handles quoted values
|
|
*
|
|
* @param string $string Setting to assign in KEY=VALUE or KEY="VALUE" syntax
|
|
*/
|
|
public static function putEnv($string)
|
|
{
|
|
// Parse name-value pairs
|
|
$envVars = parse_ini_string($string ?? '') ?: [];
|
|
foreach ($envVars as $name => $value) {
|
|
self::setEnv($name, $value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set environment variable via $name / $value pair
|
|
*
|
|
* @param string $name
|
|
* @param string $value
|
|
*/
|
|
public static function setEnv($name, $value)
|
|
{
|
|
static::$env[$name] = $value;
|
|
}
|
|
|
|
/**
|
|
* Check if an environment variable is set
|
|
*/
|
|
public static function hasEnv(string $name): bool
|
|
{
|
|
// See getEnv() for an explanation of why isset() is used for $_ENV and $_SERVER
|
|
return array_key_exists($name, static::$env)
|
|
|| isset($_ENV[$name])
|
|
|| isset($_SERVER[$name])
|
|
|| getenv($name) !== false;
|
|
}
|
|
|
|
/**
|
|
* Returns true if this script is being run from the command line rather than the web server
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function isCli()
|
|
{
|
|
return in_array(strtolower(php_sapi_name() ?? ''), ['cli', 'phpdbg']);
|
|
}
|
|
}
|