Passed
Push — master ( 9495ee...5f785c )
by Joao
02:59
created

_Lib::liveExecuteCommand()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 43
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 22
nc 6
nop 1
dl 0
loc 43
rs 8.439
c 0
b 0
f 0
1
<?php
2
3
namespace Builder;
4
5
class _Lib
6
{
7
    protected $container;
8
    protected $image;
9
    protected $workdir;
10
    protected $systemOs;
11
12
    public function __construct()
13
    {
14
        $this->workdir = realpath(__DIR__ . '/../..');
15
    }
16
17
    public function getSystemOs()
18
    {
19
        if (!$this->systemOs) {
20
            $this->systemOs = php_uname('s');
21
            if (preg_match('/[Dd]arwin/', $this->systemOs)) {
22
                $this->systemOs = 'Darwin';
23
            } elseif (preg_match('/[Ww]in/', $this->systemOs)) {
24
                $this->systemOs = 'Windows';
25
            }
26
        }
27
28
        return $this->systemOs;
29
    }
30
31
    public function fixDir($command)
32
    {
33
        if ($this->getSystemOs() === "Windows") {
34
            return str_replace('/', '\\', $command);
35
        }
36
        return $command;
37
    }
38
39
    /**
40
     * Execute the given command by displaying console output live to the user.
41
     *
42
     * @param  string|array $cmd :  command to be executed
43
     * @return array   exit_status  :  exit status of the executed command
44
     *                  output       :  console output of the executed command
45
     * @throws \ByJG\Config\Exception\ConfigNotFoundException
46
     * @throws \ByJG\Config\Exception\EnvironmentException
47
     * @throws \ByJG\Config\Exception\KeyNotFoundException
48
     * @throws \Psr\SimpleCache\InvalidArgumentException
49
     */
50
    protected function liveExecuteCommand($cmd)
51
    {
52
        // while (@ ob_end_flush()); // end all output buffers if any
53
54
        if (is_array($cmd)) {
55
            foreach ($cmd as $item) {
56
                $this->liveExecuteCommand($item);
57
            }
58
            return null;
59
        }
60
61
        $cmd = $this->replaceVariables($cmd);
62
        echo "\n>> $cmd\n";
63
64
        $complement = " 2>&1 ; echo Exit status : $?";
65
        if ($this->getSystemOs() === "Windows") {
66
            $complement = ' & echo Exit status : %errorlevel%';
67
        }
68
        $proc = popen("$cmd $complement", 'r');
69
70
        $completeOutput = "";
71
72
        while (!feof($proc)) {
0 ignored issues
show
Bug introduced by
It seems like $proc can also be of type false; however, parameter $handle of feof() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

72
        while (!feof(/** @scrutinizer ignore-type */ $proc)) {
Loading history...
73
            $liveOutput     = fread($proc, 4096);
0 ignored issues
show
Bug introduced by
It seems like $proc can also be of type false; however, parameter $handle of fread() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

73
            $liveOutput     = fread(/** @scrutinizer ignore-type */ $proc, 4096);
Loading history...
74
            $completeOutput = $completeOutput . $liveOutput;
75
            echo "$liveOutput";
76
            @ flush();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for flush(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

76
            /** @scrutinizer ignore-unhandled */ @ flush();

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
Bug introduced by
Are you sure the usage of flush() is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
77
        }
78
79
        pclose($proc);
0 ignored issues
show
Bug introduced by
It seems like $proc can also be of type false; however, parameter $handle of pclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

79
        pclose(/** @scrutinizer ignore-type */ $proc);
Loading history...
80
81
        // get exit status
82
        preg_match('/[0-9]+$/', $completeOutput, $matches);
83
84
        $exitStatus = intval($matches[0]);
85
        // if ($exitStatus !== 0) {
86
        //     exit($exitStatus);
87
        // }
88
89
        // return exit status and intended output
90
        return array (
91
            'exit_status'  => $exitStatus,
92
            'output'       => str_replace("Exit status : " . $matches[0], '', $completeOutput)
93
        );
94
    }
95
96
    protected $dockerVariables = null;
97
98
    /**
99
     * @return array|null
100
     * @throws \ByJG\Config\Exception\ConfigNotFoundException
101
     * @throws \ByJG\Config\Exception\EnvironmentException
102
     * @throws \ByJG\Config\Exception\KeyNotFoundException
103
     * @throws \Psr\SimpleCache\InvalidArgumentException
104
     */
105
    protected function getDockerVariables()
106
    {
107
        // Builder Variables
108
        if ($this->dockerVariables === null) {
109
            $this->dockerVariables = [
110
                '%env%'     => Psr11::environment()->getCurrentEnv(),
111
                '%workdir%' => $this->workdir
112
            ];
113
114
            // Get User Variables
115
            $variables = Psr11::container()->get('BUILDER_VARIABLES');
116
            foreach ((array)$variables as $variable => $value) {
117
                $this->dockerVariables["%$variable%"] = $this->replaceVariables($value);
118
            }
119
        }
120
121
        return $this->dockerVariables;
122
    }
123
124
    /**
125
     * @param string|\Closure $variableValue
126
     * @return mixed
127
     * @throws \ByJG\Config\Exception\ConfigNotFoundException
128
     * @throws \ByJG\Config\Exception\EnvironmentException
129
     * @throws \ByJG\Config\Exception\KeyNotFoundException
130
     * @throws \Psr\SimpleCache\InvalidArgumentException
131
     */
132
    protected function replaceVariables($variableValue)
133
    {
134
        // Builder Variables
135
        $args = $this->getDockerVariables();
136
137
        if ($variableValue instanceof \Closure) {
138
            $string = $variableValue($args);
139
        } else {
140
            $string = $variableValue;
141
        }
142
143
        // Replace variables into string
144
        foreach ($args as $arg => $value) {
145
            $string = str_replace($arg, $value, $string);
146
        }
147
148
        return $string;
149
    }
150
}
151