1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | /* |
||
6 | * This file is part of the box project. |
||
7 | * |
||
8 | * (c) Kevin Herrera <[email protected]> |
||
9 | * Théo Fidry <[email protected]> |
||
10 | * |
||
11 | * This source file is subject to the MIT license that is bundled |
||
12 | * with this source code in the file LICENSE. |
||
13 | */ |
||
14 | |||
15 | namespace KevinGH\Box\Console\Php; |
||
16 | |||
17 | use Composer\XdebugHandler\Process; |
||
18 | use Composer\XdebugHandler\XdebugHandler; |
||
19 | use function getenv; |
||
20 | use function ini_get; |
||
21 | use function ini_set; |
||
22 | use const KevinGH\Box\BOX_MEMORY_LIMIT; |
||
23 | use function KevinGH\Box\FileSystem\append_to_file; |
||
24 | use function KevinGH\Box\format_size; |
||
25 | use function KevinGH\Box\memory_to_bytes; |
||
26 | use const PHP_EOL; |
||
27 | use Psr\Log\LoggerInterface; |
||
28 | use function sprintf; |
||
29 | use function trim; |
||
30 | |||
31 | /** |
||
32 | * @private |
||
33 | */ |
||
34 | final class PhpSettingsHandler extends XdebugHandler |
||
35 | { |
||
36 | private $logger; |
||
37 | private $pharReadonly; |
||
38 | private $boxMemoryLimitInBytes; |
||
39 | |||
40 | /** |
||
41 | * {@inheritdoc} |
||
42 | */ |
||
43 | public function __construct(LoggerInterface $logger) |
||
44 | { |
||
45 | parent::__construct('box', '--ansi'); |
||
46 | |||
47 | $this->setLogger($logger); |
||
48 | $this->logger = $logger; |
||
49 | |||
50 | $this->pharReadonly = '1' === ini_get('phar.readonly'); |
||
51 | $this->boxMemoryLimitInBytes = $this->checkMemoryLimit(); |
||
52 | } |
||
53 | |||
54 | /** |
||
55 | * {@inheritdoc} |
||
56 | */ |
||
57 | public function check(): void |
||
58 | { |
||
59 | parent::check(); |
||
60 | |||
61 | if (self::getRestartSettings()) { |
||
62 | Process::setEnv('PHPRC', XdebugHandler::getRestartSettings()['tmpIni']); |
||
63 | Process::setEnv('PHP_INI_SCAN_DIR', ''); |
||
64 | } |
||
65 | |||
66 | // Bump the memory limit in the current process if necessary |
||
67 | $this->bumpMemoryLimit(); |
||
68 | } |
||
69 | |||
70 | /** |
||
71 | * {@inheritdoc} |
||
72 | */ |
||
73 | protected function requiresRestart($isLoaded): bool |
||
74 | { |
||
75 | if ($this->pharReadonly) { |
||
76 | $this->logger->debug('phar.readonly is enabled'); |
||
77 | |||
78 | return true; |
||
79 | } |
||
80 | |||
81 | $this->logger->debug('phar.readonly is disabled'); |
||
82 | |||
83 | return parent::requiresRestart($isLoaded); |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * {@inheritdoc} |
||
88 | */ |
||
89 | protected function restart($command): void |
||
90 | { |
||
91 | // Disable phar.readonly if set |
||
92 | $this->disablePharReadonly(); |
||
93 | |||
94 | // Bump the memory limit in the restated process if necessary |
||
95 | $this->bumpMemoryLimit(); |
||
96 | |||
97 | parent::restart($command); |
||
98 | } |
||
99 | |||
100 | /** |
||
101 | * @return false|int the desired memory limit for Box |
||
102 | */ |
||
103 | private function checkMemoryLimit() |
||
104 | { |
||
105 | $memoryLimit = getenv(BOX_MEMORY_LIMIT); |
||
106 | |||
107 | if (false === $memoryLimit) { |
||
108 | $memoryLimitInBytes = false; |
||
109 | } elseif ('-1' === $memoryLimit) { |
||
110 | $memoryLimitInBytes = -1; |
||
111 | } else { |
||
112 | $memoryLimitInBytes = memory_to_bytes($memoryLimit); |
||
113 | } |
||
114 | |||
115 | return $memoryLimitInBytes; |
||
116 | } |
||
117 | |||
118 | private function disablePharReadonly(): void |
||
119 | { |
||
120 | if (ini_get('phar.readonly')) { |
||
121 | append_to_file($this->tmpIni, 'phar.readonly=0'.PHP_EOL); |
||
122 | |||
123 | $this->logger->debug('Configured `phar.readonly=0`'); |
||
124 | } |
||
125 | } |
||
126 | |||
127 | /** |
||
128 | * @see https://github.com/composer/composer/blob/34c371f5f23e25eb9aa54ccc65136cf50930612e/bin/composer#L20-L50 |
||
129 | */ |
||
130 | private function bumpMemoryLimit(): void |
||
131 | { |
||
132 | $memoryLimit = trim(ini_get('memory_limit')); |
||
133 | $memoryLimitInBytes = '-1' === $memoryLimit ? -1 : memory_to_bytes($memoryLimit); |
||
134 | |||
135 | $bumpMemoryLimit = false === $this->boxMemoryLimitInBytes && -1 !== $memoryLimitInBytes && $memoryLimitInBytes < 1024 * 1024 * 512; |
||
136 | $setUserDefinedMemoryLimit = $this->boxMemoryLimitInBytes && $memoryLimitInBytes !== $this->boxMemoryLimitInBytes; |
||
0 ignored issues
–
show
|
|||
137 | |||
138 | if ($bumpMemoryLimit && false === $setUserDefinedMemoryLimit) { |
||
139 | if ($this->tmpIni) { |
||
140 | // Is for the restarted process |
||
141 | append_to_file($this->tmpIni, 'memory_limit=512M'.PHP_EOL); |
||
142 | } else { |
||
143 | // Is for the current process |
||
144 | ini_set('memory_limit', '512M'); |
||
145 | } |
||
146 | |||
147 | $this->logger->debug( |
||
148 | sprintf( |
||
149 | 'Changed the memory limit from "%s" to "%s"', |
||
150 | format_size($memoryLimitInBytes, 0), |
||
151 | '512M' |
||
152 | ) |
||
153 | ); |
||
154 | } elseif ($setUserDefinedMemoryLimit) { |
||
155 | if ($this->tmpIni) { |
||
156 | // Is for the restarted process |
||
157 | append_to_file($this->tmpIni, 'memory_limit='.$this->boxMemoryLimitInBytes.PHP_EOL); |
||
158 | } else { |
||
159 | // Is for the current process |
||
160 | ini_set('memory_limit', (string) $this->boxMemoryLimitInBytes); |
||
161 | } |
||
162 | |||
163 | $this->logger->debug( |
||
164 | sprintf( |
||
165 | 'Changed the memory limit from "%s" to %s="%s"', |
||
166 | format_size($memoryLimitInBytes, 0), |
||
167 | BOX_MEMORY_LIMIT, |
||
168 | format_size($this->boxMemoryLimitInBytes, 0) |
||
169 | ) |
||
170 | ); |
||
171 | } else { |
||
172 | $this->logger->debug( |
||
173 | sprintf( |
||
174 | 'Current memory limit: "%s"', |
||
175 | format_size($memoryLimitInBytes, 0) |
||
176 | ) |
||
177 | ); |
||
178 | } |
||
179 | } |
||
180 | } |
||
181 |
In PHP, under loose comparison (like
==
, or!=
, orswitch
conditions), values of different types might be equal.For
integer
values, zero is a special case, in particular the following results might be unexpected: