Completed
Pull Request — develop (#1033)
by Rafael Corrêa
02:49
created

Exec::isPipefailOptionAvailable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace N98\Util;
4
5
use RuntimeException;
6
7
/**
8
 * Class Exec
9
 *
10
 * @package N98\Util
11
 */
12
class Exec
13
{
14
    /**
15
     * @var string
16
     */
17
    const REDIRECT_STDERR_TO_STDOUT = ' 2>&1';
18
19
    /**
20
     * @var int (0-255)
21
     */
22
    const CODE_CLEAN_EXIT = 0;
23
24
    /**
25
     * Every error in a pipe will be exited with an error code
26
     */
27
    const SET_O_PIPEFAIL = 'set -o pipefail;';
28
29
    /**
30
     * @param string $command
31
     * @param string|null $output
32
     * @param int $returnCode
33
     */
34
    public static function run($command, &$output = null, &$returnCode = null)
35
    {
36
        if (!self::allowed()) {
37
            $message = sprintf("No PHP exec(), can not execute command '%s'.", $command);
38
            throw new RuntimeException($message);
39
        }
40
41
        if (OperatingSystem::isBashCompatibleShell() && self::isPipefailOptionAvailable()) {
42
            $command = self::SET_O_PIPEFAIL . $command;
43
        }
44
45
        $command .= self::REDIRECT_STDERR_TO_STDOUT;
46
47
        exec($command, $outputArray, $returnCode);
48
        $output = self::parseCommandOutput((array) $outputArray);
49
50
        if ($returnCode !== self::CODE_CLEAN_EXIT) {
51
            throw new RuntimeException(
52
                sprintf("Exit status %d for command %s. Output was: %s", $returnCode, $command, $output)
53
            );
54
        }
55
    }
56
57
    /**
58
     * Exec class is allowed to run
59
     *
60
     * @return bool
61
     */
62
    public static function allowed()
63
    {
64
        return function_exists('exec');
65
    }
66
67
    /**
68
     * string from array of strings representing one line per entry
69
     *
70
     * @param array $commandOutput
71
     * @return string
72
     */
73
    private static function parseCommandOutput(array $commandOutput)
74
    {
75
        return implode(PHP_EOL, $commandOutput) . PHP_EOL;
76
    }
77
78
    /**
79
     * @return bool
80
     */
81
    private static function isPipefailOptionAvailable()
82
    {
83
        exec('set -o | grep pipefail 2>&1', $output, $returnCode);
84
85
        return $returnCode == self::CODE_CLEAN_EXIT;
86
    }
87
}
88