Completed
Pull Request — master (#72)
by Jan Philipp
02:16
created

ProcessExecutor::executeProcessCommand()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 12
nc 1
nop 3
1
<?php declare(strict_types=1);
2
3
4
namespace Shopware\Psh\ScriptRuntime;
5
6
use Shopware\Psh\Listing\Script;
7
use Symfony\Component\Process\Process;
8
9
/**
10
 * Execute a command in a separate process
11
 */
12
class ProcessExecutor
13
{
14
    /**
15
     * @var ProcessEnvironment
16
     */
17
    private $environment;
18
19
    /**
20
     * @var TemplateEngine
21
     */
22
    private $templateEngine;
23
24
    /**
25
     * @var Logger
26
     */
27
    private $logger;
28
29
    /**
30
     * @var string
31
     */
32
    private $applicationDirectory;
33
34
    /**
35
     * ProcessExecutor constructor.
36
     * @param ProcessEnvironment $environment
37
     * @param TemplateEngine $templateEngine
38
     * @param Logger $logger
39
     * @param string $applicationDirectory
40
     */
41
    public function __construct(
42
        ProcessEnvironment $environment,
43
        TemplateEngine $templateEngine,
44
        Logger $logger,
45
        string $applicationDirectory
46
    ) {
47
        $this->environment = $environment;
48
        $this->templateEngine = $templateEngine;
49
        $this->logger = $logger;
50
        $this->applicationDirectory = $applicationDirectory;
51
    }
52
53
    /**
54
     * @param Script $script
55
     * @param Command[] $commands
56
     */
57
    public function execute(Script $script, array $commands)
58
    {
59
        $this->logger->startScript($script);
60
61
        $this->executeTemplateRendering();
62
63
        foreach ($commands as $index => $command) {
64
            switch ($command) {
65
                case $command instanceof ProcessCommand:
66
                    $this->executeProcessCommand($command, $index, count($commands));
0 ignored issues
show
Compatibility introduced by
$command of type object<Shopware\Psh\ScriptRuntime\Command> is not a sub-type of object<Shopware\Psh\ScriptRuntime\ProcessCommand>. It seems like you assume a concrete implementation of the interface Shopware\Psh\ScriptRuntime\Command to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
67
                    break;
68
                case $command instanceof TemplateCommand:
69
                    $this->executeTemplateCommand($command, $index, count($commands));
0 ignored issues
show
Compatibility introduced by
$command of type object<Shopware\Psh\ScriptRuntime\Command> is not a sub-type of object<Shopware\Psh\Scri...untime\TemplateCommand>. It seems like you assume a concrete implementation of the interface Shopware\Psh\ScriptRuntime\Command to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
70
                    break;
71
            }
72
        }
73
74
        $this->logger->finishScript($script);
75
    }
76
77
    private function executeTemplateRendering()
78
    {
79
        foreach ($this->environment->getTemplates() as $template) {
80
            $this->renderTemplate($template);
81
        }
82
    }
83
84
    /**
85
     * @param ProcessCommand $command
86
     * @return string
87
     */
88
    protected function getParsedShellCommand(ProcessCommand $command): string
89
    {
90
        $rawShellCommand = $command->getShellCommand();
91
92
        $parsedCommand = $this->templateEngine->render(
93
            $rawShellCommand,
94
            $this->environment->getAllValues()
95
        );
96
97
        return $parsedCommand;
98
    }
99
100
    /**
101
     * @param Process $process
102
     */
103
    protected function setUpProcess(ProcessCommand $command, Process $process)
104
    {
105
        $process->setWorkingDirectory($this->applicationDirectory);
106
        $process->setTimeout(0);
107
        $process->setTty($command->isTTy());
108
    }
109
110
    /**
111
     * @param Process $process
112
     */
113
    protected function runProcess(Process $process)
114
    {
115
        $process->run(function ($type, $response) {
116
            if (Process::ERR === $type) {
117
                $this->logger->err($response);
118
            } else {
119
                $this->logger->out($response);
120
            }
121
        });
122
    }
123
124
    /**
125
     * @param ProcessCommand $command
126
     * @param Process $process
127
     */
128
    protected function testProcessResultValid(ProcessCommand $command, Process $process)
129
    {
130
        if (!$command->isIgnoreError() && !$process->isSuccessful()) {
131
            throw new ExecutionErrorException('Command exited with Error');
132
        }
133
    }
134
135
    /**
136
     * @param Template $template
137
     */
138
    private function renderTemplate(Template $template)
139
    {
140
        $renderedTemplateDestination = $this->templateEngine
141
            ->render($template->getDestination(), $this->environment->getAllValues());
142
143
        $template->setDestination($renderedTemplateDestination);
144
145
        $renderedTemplateContent = $this->templateEngine
146
            ->render($template->getContent(), $this->environment->getAllValues());
147
148
        $template->setContents($renderedTemplateContent);
149
    }
150
151
    /**
152
     * @param ProcessCommand $command
153
     * @param int $index
154
     * @param int $maxCommands
155
     */
156
    private function executeProcessCommand(ProcessCommand $command, int $index, int $maxCommands)
157
    {
158
        $parsedCommand = $this->getParsedShellCommand($command);
159
160
        $this->logger->logCommandStart(
161
            $parsedCommand,
162
            $command->getLineNumber(),
163
            $command->isIgnoreError(),
164
            $index,
165
            $maxCommands
166
        );
167
168
        $process = $this->environment->createProcess($parsedCommand);
169
170
        $this->setUpProcess($command, $process);
171
        $this->runProcess($process);
172
        $this->testProcessResultValid($command, $process);
173
    }
174
175
    /**
176
     * @param TemplateCommand $command
177
     * @param int $index
178
     * @param int $maxCommands
179
     */
180
    private function executeTemplateCommand(TemplateCommand $command, int $index, int $maxCommands)
181
    {
182
        $template = $command->getTemplate();
183
184
        $this->logger->logTemplate(
185
            $template->getDestination(),
186
            $command->getLineNumber(),
187
            $index,
188
            $maxCommands
189
        );
190
191
        $this->renderTemplate($template);
192
    }
193
}
194