Completed
Push — 4 ( d81698...961096 )
by Guy
38s queued 19s
created

Environment::getEnv()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 9
nc 4
nop 1
dl 0
loc 11
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Core;
4
5
/**
6
 * Consolidates access and modification of PHP global variables and settings.
7
 * This class should be used sparingly, and only if information cannot be obtained
8
 * from a current {@link HTTPRequest} object.
9
 *
10
 * Acts as the primary store for environment variables, including those loaded
11
 * from .env files. Applications should use Environment::getEnv() instead of php's
12
 * `getenv` in order to include `.env` configuration, as the system's actual
13
 * environment variables are treated immutably.
14
 */
15
class Environment
16
{
17
    /**
18
     * Set maximum limit allowed for increaseMemoryLimit
19
     *
20
     * @var float|null
21
     */
22
    protected static $memoryLimitMax = null;
23
24
    /**
25
     * Set maximum limited allowed for increaseTimeLimit
26
     *
27
     * @var int|null
28
     */
29
    protected static $timeLimitMax = null;
30
31
    /**
32
     * Local overrides for all $_ENV var protected from cross-process operations
33
     *
34
     * @var array
35
     */
36
    protected static $env = [];
37
38
    /**
39
     * Extract env vars prior to modification
40
     *
41
     * @return array List of all super globals
42
     */
43
    public static function getVariables()
44
    {
45
        // Suppress return by-ref
46
        $vars = [ 'env' => static::$env ];
47
        // needs to use a for loop, using `array_merge([], $GLOBALS);` left reference traces somehow
48
        foreach ($GLOBALS as $varName => $varValue) {
49
            $vars[$varName] = $varValue;
50
        }
51
52
        return $vars;
53
    }
54
55
    /**
56
     * Restore a backed up or modified list of vars to $globals
57
     *
58
     * @param array $vars
59
     */
60
    public static function setVariables(array $vars)
61
    {
62
        foreach ($vars as $varName => $varValue) {
63
            if ($varName === 'env') {
64
                continue;
65
            }
66
            $GLOBALS[$varName] = $varValue;
67
        }
68
        if (array_key_exists('env', $vars)) {
69
            static::$env = $vars['env'];
70
        }
71
    }
72
73
    /**
74
     * Increase the memory limit to the given level if it's currently too low.
75
     * Only increases up to the maximum defined in {@link setMemoryLimitMax()},
76
     * and defaults to the 'memory_limit' setting in the PHP configuration.
77
     *
78
     * @param string|float|int $memoryLimit A memory limit string, such as "64M".  If omitted, unlimited memory will be set.
79
     * @return bool true indicates a successful change, false a denied change.
80
     */
81
    public static function increaseMemoryLimitTo($memoryLimit = -1)
82
    {
83
        $memoryLimit = Convert::memstring2bytes($memoryLimit);
84
        $curLimit = Convert::memstring2bytes(ini_get('memory_limit'));
85
86
        // Can't go higher than infinite
87
        if ($curLimit < 0) {
88
            return true;
89
        }
90
91
        // Check hard maximums
92
        $max = static::getMemoryLimitMax();
93
        if ($max > 0 && ($memoryLimit < 0 || $memoryLimit > $max)) {
94
            $memoryLimit = $max;
95
        }
96
97
        // Increase the memory limit if it's too low
98
        if ($memoryLimit < 0) {
99
            ini_set('memory_limit', '-1');
100
        } elseif ($memoryLimit > $curLimit) {
101
            ini_set('memory_limit', Convert::bytes2memstring($memoryLimit));
102
        }
103
104
        return true;
105
    }
106
107
    /**
108
     * Set the maximum allowed value for {@link increaseMemoryLimitTo()}.
109
     * The same result can also be achieved through 'suhosin.memory_limit'
110
     * if PHP is running with the Suhosin system.
111
     *
112
     * @param string|float $memoryLimit Memory limit string or float value
113
     */
114
    static function setMemoryLimitMax($memoryLimit)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
115
    {
116
        if (isset($memoryLimit) && !is_numeric($memoryLimit)) {
117
            $memoryLimit = Convert::memstring2bytes($memoryLimit);
118
        }
119
        static::$memoryLimitMax = $memoryLimit;
120
    }
121
122
    /**
123
     * @return int Memory limit in bytes
124
     */
125
    public static function getMemoryLimitMax()
126
    {
127
        if (static::$memoryLimitMax === null) {
128
            return Convert::memstring2bytes(ini_get('memory_limit'));
129
        }
130
        return static::$memoryLimitMax;
131
    }
132
133
    /**
134
     * Increase the time limit of this script. By default, the time will be unlimited.
135
     * Only works if 'safe_mode' is off in the PHP configuration.
136
     * Only values up to {@link getTimeLimitMax()} are allowed.
137
     *
138
     * @param int $timeLimit The time limit in seconds.  If omitted, no time limit will be set.
139
     * @return Boolean TRUE indicates a successful change, FALSE a denied change.
140
     */
141
    public static function increaseTimeLimitTo($timeLimit = null)
142
    {
143
        // Check vs max limit
144
        $max = static::getTimeLimitMax();
145
        if ($max > 0 && $timeLimit > $max) {
146
            return false;
147
        }
148
149
        if (!$timeLimit) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $timeLimit of type integer|null is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
150
            set_time_limit(0);
151
        } else {
152
            $currTimeLimit = ini_get('max_execution_time');
153
            // Only increase if its smaller
154
            if ($currTimeLimit > 0 && $currTimeLimit < $timeLimit) {
155
                set_time_limit($timeLimit);
156
            }
157
        }
158
        return true;
159
    }
160
161
    /**
162
     * Set the maximum allowed value for {@link increaseTimeLimitTo()};
163
     *
164
     * @param int $timeLimit Limit in seconds
165
     */
166
    public static function setTimeLimitMax($timeLimit)
167
    {
168
        static::$timeLimitMax = $timeLimit;
169
    }
170
171
    /**
172
     * @return Int Limit in seconds
173
     */
174
    public static function getTimeLimitMax()
175
    {
176
        return static::$timeLimitMax;
177
    }
178
179
    /**
180
     * Get value of environment variable
181
     *
182
     * @param string $name
183
     * @return mixed Value of the environment variable, or false if not set
184
     */
185
    public static function getEnv($name)
186
    {
187
        switch (true) {
188
            case  is_array(static::$env) && array_key_exists($name, static::$env):
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
189
                return static::$env[$name];
190
            case  is_array($_ENV) && array_key_exists($name, $_ENV):
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
191
                return $_ENV[$name];
192
            case  is_array($_SERVER) && array_key_exists($name, $_SERVER):
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
193
                return $_SERVER[$name];
194
            default:
195
                return getenv($name);
196
        }
197
    }
198
199
    /**
200
     * Set environment variable using php.ini syntax.
201
     * Acts as a process-isolated version of putenv()
202
     * Note: This will be parsed via parse_ini_string() which handles quoted values
203
     *
204
     * @param string $string Setting to assign in KEY=VALUE or KEY="VALUE" syntax
205
     */
206
    public static function putEnv($string)
207
    {
208
        // Parse name-value pairs
209
        $envVars = parse_ini_string($string) ?: [];
210
        foreach ($envVars as $name => $value) {
211
            self::setEnv($name, $value);
212
        }
213
    }
214
215
    /**
216
     * Set environment variable via $name / $value pair
217
     *
218
     * @param string $name
219
     * @param string $value
220
     */
221
    public static function setEnv($name, $value)
222
    {
223
        static::$env[$name] = $value;
224
    }
225
}
226