Passed
Push — master ( d13433...bd569e )
by Théo
02:47
created

bump_open_file_descriptor_limit()   B

Complexity

Conditions 8
Paths 3

Size

Total Lines 50
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 33
dl 0
loc 50
rs 8.1475
c 0
b 0
f 0
cc 8
nc 3
nop 2
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;
16
17
use function array_key_exists;
18
use Assert\Assertion;
19
use function bin2hex;
20
use function class_alias;
21
use function class_exists;
22
use Closure;
23
use function constant;
24
use function define;
25
use function defined;
26
use ErrorException;
27
use function floor;
28
use function function_exists;
29
use KevinGH\Box\Console\IO\IO;
30
use KevinGH\Box\Console\Php\PhpSettingsHandler;
31
use function KevinGH\Box\FileSystem\copy;
32
use function log;
33
use function number_format;
34
use PackageVersions\Versions;
35
use Phar;
36
use function posix_getrlimit;
37
use function posix_setrlimit;
38
use function random_bytes;
39
use function sprintf;
40
use function str_replace;
41
use function strlen;
42
use function strtolower;
43
use Symfony\Component\Console\Helper\Helper;
44
use Symfony\Component\Console\Logger\ConsoleLogger;
45
use Symfony\Component\Console\Output\OutputInterface;
46
47
/**
48
 * @private
49
 */
50
function get_box_version(): string
51
{
52
    $rawVersion = Versions::getVersion('humbug/box');
53
54
    [$prettyVersion, $commitHash] = explode('@', $rawVersion);
55
56
    return $prettyVersion.'@'.substr($commitHash, 0, 7);
57
}
58
59
/**
60
 * @private
61
 *
62
 * @return array<string,int>
63
 */
64
function get_phar_compression_algorithms(): array
65
{
66
    static $algorithms = [
67
        'GZ' => Phar::GZ,
68
        'BZ2' => Phar::BZ2,
69
        'NONE' => Phar::NONE,
70
    ];
71
72
    return $algorithms;
73
}
74
75
/**
76
 * @private
77
 */
78
function get_phar_compression_algorithm_extension(int $algorithm): ?string
79
{
80
    static $extensions = [
81
        Phar::GZ => 'zlib',
82
        Phar::BZ2 => 'bz2',
83
        Phar::NONE => null,
84
    ];
85
86
    Assertion::true(
87
        array_key_exists($algorithm, $extensions),
88
        sprintf('Unknown compression algorithm code "%d"', $algorithm)
89
    );
90
91
    return $extensions[$algorithm];
92
}
93
94
/**
95
 * @private
96
 *
97
 * @return array<string,int>
98
 */
99
function get_phar_signing_algorithms(): array
100
{
101
    static $algorithms = [
102
        'MD5' => Phar::MD5,
103
        'SHA1' => Phar::SHA1,
104
        'SHA256' => Phar::SHA256,
105
        'SHA512' => Phar::SHA512,
106
        'OPENSSL' => Phar::OPENSSL,
107
    ];
108
109
    return $algorithms;
110
}
111
112
/**
113
 * @private
114
 */
115
function format_size(int $size, int $decimals = 2): string
116
{
117
    if (-1 === $size) {
118
        return '-1';
119
    }
120
121
    $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
122
123
    $power = $size > 0 ? (int) floor(log($size, 1024)) : 0;
124
125
    return sprintf(
126
        '%s%s',
127
        number_format(
128
            $size / (1024 ** $power),
129
            $decimals,
130
            '.',
131
            ','
132
        ),
133
        $units[$power]
134
    );
135
}
136
137
/**
138
 * @private
139
 */
140
function memory_to_bytes(string $value): int
141
{
142
    $unit = strtolower($value[strlen($value) - 1]);
143
144
    $bytes = (int) $value;
145
146
    switch ($unit) {
147
        case 'g':
148
            $bytes *= 1024;
149
        // no break (cumulative multiplier)
150
        case 'm':
151
            $bytes *= 1024;
152
        // no break (cumulative multiplier)
153
        case 'k':
154
            $bytes *= 1024;
155
    }
156
157
    return $bytes;
158
}
159
160
/**
161
 * @private
162
 */
163
function format_time(float $secs): string
164
{
165
    return str_replace(
166
        ' ',
167
        '',
168
        Helper::formatTime($secs)
169
    );
170
}
171
172
/**
173
 * @private
174
 */
175
function register_aliases(): void
176
{
177
    // Exposes the finder used by PHP-Scoper PHAR to allow its usage in the configuration file.
178
    if (false === class_exists(\Isolated\Symfony\Component\Finder\Finder::class)) {
179
        class_alias(\Symfony\Component\Finder\Finder::class, \Isolated\Symfony\Component\Finder\Finder::class);
180
    }
181
182
    // Register compactors aliases
183
    if (false === class_exists(\Herrera\Box\Compactor\Json::class, false)) {
184
        class_alias(\KevinGH\Box\Compactor\Json::class, \Herrera\Box\Compactor\Json::class);
185
    }
186
187
    if (false === class_exists(\Herrera\Box\Compactor\Php::class, false)) {
188
        class_alias(\KevinGH\Box\Compactor\Php::class, \Herrera\Box\Compactor\Php::class);
189
    }
190
}
191
192
/**
193
 * @private
194
 */
195
function disable_parallel_processing(): void
196
{
197
    if (false === defined(_NO_PARALLEL_PROCESSING)) {
198
        define(_NO_PARALLEL_PROCESSING, true);
199
    }
200
}
201
202
/**
203
 * @private
204
 */
205
function is_parallel_processing_enabled(): bool
206
{
207
    return false === defined(_NO_PARALLEL_PROCESSING) || false === constant(_NO_PARALLEL_PROCESSING);
208
}
209
210
/**
211
 * @private
212
 *
213
 * @return string Random 12 characters long (plus the prefix) string composed of a-z characters and digits
214
 */
215
function unique_id(string $prefix): string
216
{
217
    return $prefix.bin2hex(random_bytes(6));
218
}
219
220
/**
221
 * @private
222
 */
223
function create_temporary_phar(string $file): string
224
{
225
    $tmpFile = sys_get_temp_dir().'/'.unique_id('').basename($file);
226
227
    if ('' === pathinfo($file, PATHINFO_EXTENSION)) {
228
        $tmpFile .= '.phar';
229
    }
230
231
    copy($file, $tmpFile, true);
232
233
    return $tmpFile;
234
}
235
236
/**
237
 * @private
238
 */
239
function check_php_settings(IO $io): void
240
{
241
    (new PhpSettingsHandler(
242
        new ConsoleLogger(
243
            $io->getOutput()
244
        )
245
    ))->check();
246
}
247
248
/**
249
 * @private
250
 */
251
function noop(): Closure
252
{
253
    return static function (): void {};
254
}
255
256
/**
257
 * Converts errors to exceptions.
258
 *
259
 * @private
260
 */
261
function register_error_handler(): void
262
{
263
    set_error_handler(
264
        static function (int $code, string $message, string $file = '', int $line = -1): void {
265
            if (error_reporting() & $code) {
266
                throw new ErrorException($message, 0, $code, $file, $line);
267
            }
268
        }
269
    );
270
}
271
272
/**
273
 * Bumps the maximum number of open file descriptor if necessary.
274
 *
275
 * @return Closure callable to call to restore the original maximum number of open files descriptors
276
 */
277
function bump_open_file_descriptor_limit(Box $box, IO $io): Closure
278
{
279
    $filesCount = count($box) + 128;  // Add a little extra for good measure
280
281
    if (false === function_exists('posix_getrlimit') || false === function_exists('posix_setrlimit')) {
282
        $io->writeln(
283
            '<info>[debug] Could not check the maximum number of open file descriptors: the functions "posix_getrlimit()" and '
284
            .'"posix_setrlimit" could not be found.</info>',
285
            OutputInterface::VERBOSITY_DEBUG
286
        );
287
288
        return static function (): void {};
289
    }
290
291
    $softLimit = posix_getrlimit()['soft openfiles'];
292
    $hardLimit = posix_getrlimit()['hard openfiles'];
293
294
    if ($softLimit >= $filesCount) {
295
        return static function (): void {};
296
    }
297
298
    $io->writeln(
299
        sprintf(
300
            '<info>[debug] Increased the maximum number of open file descriptors from ("%s", "%s") to ("%s", "%s")'
301
            .'</info>',
302
            $softLimit,
303
            $hardLimit,
304
            $filesCount,
305
            'unlimited'
306
        ),
307
        OutputInterface::VERBOSITY_DEBUG
308
    );
309
310
    posix_setrlimit(
311
        POSIX_RLIMIT_NOFILE,
312
        $filesCount,
313
        'unlimited' === $hardLimit ? POSIX_RLIMIT_INFINITY : $hardLimit
314
    );
315
316
    return static function () use ($io, $softLimit, $hardLimit): void {
317
        if (function_exists('posix_setrlimit') && isset($softLimit, $hardLimit)) {
318
            posix_setrlimit(
319
                POSIX_RLIMIT_NOFILE,
320
                $softLimit,
321
                'unlimited' === $hardLimit ? POSIX_RLIMIT_INFINITY : $hardLimit
322
            );
323
324
            $io->writeln(
325
                '<info>[debug] Restored the maximum number of open file descriptors</info>',
326
                OutputInterface::VERBOSITY_DEBUG
327
            );
328
        }
329
    };
330
}
331