Completed
Pull Request — master (#55)
by
unknown
04:28
created

Application::printConfigFiles()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
nc 4
nop 1
1
<?php declare(strict_types=1);
2
3
4
namespace Shopware\Psh\Application;
5
6
use Khill\Duration\Duration;
7
use League\CLImate\CLImate;
8
use Shopware\Psh\Config\Config;
9
use Shopware\Psh\Config\ConfigFileFinder;
10
use Shopware\Psh\Listing\Script;
11
use Shopware\Psh\Listing\ScriptNotFoundException;
12
use Shopware\Psh\Listing\ScriptPathNotValidException;
13
use Shopware\Psh\ScriptRuntime\ExecutionErrorException;
14
use Shopware\Psh\ScriptRuntime\TemplateNotValidException;
15
16
/**
17
 * Main application entry point. moves the requested data around and outputs user information.
18
 */
19
class Application
20
{
21
    const RESULT_SUCCESS = 0;
22
23
    const RESULT_ERROR = 1;
24
25
    const MIN_PADDING_SIZE = 30;
26
27
    /**
28
     * @var CLImate
29
     */
30
    public $cliMate;
31
32
    /**
33
     * @var string
34
     */
35
    private $rootDirectory;
36
37
    /**
38
     * @var ApplicationFactory
39
     */
40
    private $applicationFactory;
41
42
    /**
43
     * @var Duration
44
     */
45
    private $duration;
46
47
    /**
48
     * @param string $rootDirectory
49
     */
50
    public function __construct(string $rootDirectory)
51
    {
52
        $this->rootDirectory = $rootDirectory;
53
        $this->applicationFactory = new ApplicationFactory();
54
        $this->cliMate = new CLImate();
55
        $this->duration = new Duration();
56
    }
57
58
    /**
59
     * Main entry point to execute the application.
60
     *
61
     * @param array $inputArgs
62
     * @return int exit code
63
     */
64
    public function run(array $inputArgs): int
65
    {
66
        try {
67
            $config = $this->applicationFactory->createConfig($this->rootDirectory, $inputArgs);
68
        } catch (InvalidParameterException $e) {
69
            $this->notifyError($e->getMessage() . "\n");
70
            return self::RESULT_ERROR;
71
        }
72
73
        $scriptFinder = $this->applicationFactory->createScriptFinder($config);
74
75
        $scriptNames = $this->extractScriptNames($inputArgs);
76
        if (count($scriptNames) > 0 && $scriptNames[0] === 'bash_autocompletion_dump') {
77
            $scripts = $scriptFinder->getAllScripts();
78
            $commands = array_map(function (Script $script) {
79
                return $script->getName();
80
            }, $scripts);
81
            echo implode(' ', $commands);
82
            return self::RESULT_SUCCESS;
83
        }
84
85
        $this->printHeader($config);
86
87
        $configFiles = $this->applicationFactory->getConfigFiles($this->rootDirectory);
88
        $this->printConfigFiles($configFiles);
89
90
        try {
91
            foreach ($scriptNames as $scriptName) {
92
                $executionExitCode = $this->execute($scriptFinder->findScriptByName($scriptName), $config);
93
94
                if ($executionExitCode !== self::RESULT_SUCCESS) {
95
                    return $executionExitCode;
96
                }
97
            }
98
99
            if (isset($executionExitCode)) {
100
                return $executionExitCode;
101
            }
102
        } catch (ScriptNotFoundException $e) {
103
            $this->notifyError("Script with name {$inputArgs[1]} not found\n");
104
105
            $scripts = [];
106
            foreach ($scriptNames as $scriptName) {
107
                $newScripts = $scriptFinder->findScriptsByPartialName($scriptName);
108
                $scripts = array_merge($scripts, $newScripts);
109
            }
110
111
            if (count($scripts) > 0) {
112
                $this->cliMate->yellow()->bold('Have you been looking for this?');
113
                $this->showListing($scripts);
114
            }
115
            return self::RESULT_ERROR;
116
        }
117
118
        try {
119
            $this->showListing($scriptFinder->getAllScripts());
120
        } catch (ScriptPathNotValidException $e) {
121
            $this->notifyError($e->getMessage() . "\n");
122
            return self::RESULT_ERROR;
123
        }
124
125
        return self::RESULT_SUCCESS;
126
    }
127
128
    /**
129
     * @param Script[] $scripts
130
     */
131
    public function showListing(array $scripts)
132
    {
133
        $this->cliMate->green()->bold('Available commands:')->br();
134
135
        if (!count($scripts)) {
136
            $this->cliMate->yellow()->bold('-> Currently no scripts available');
137
        }
138
139
        $paddingSize = $this->getPaddingSize($scripts);
140
        $padding = $this->cliMate->padding($paddingSize)->char(' ');
141
142
        $scriptEnvironment = false;
143
144
        foreach ($scripts as $script) {
145
            if ($scriptEnvironment !== $script->getEnvironment()) {
146
                $scriptEnvironment = $script->getEnvironment();
147
                $this->cliMate->green()->br()->bold(($scriptEnvironment ?? 'default') . ':');
148
            }
149
150
            $padding
151
                ->label('<bold> - ' . $script->getName() . '</bold>')
152
                ->result('<dim>' . $script->getDescription() . '</dim>');
153
        }
154
155
        $this->cliMate->green()->bold("\n" . count($scripts) . " script(s) available\n");
156
    }
157
158
    /**
159
     * @param array $inputArgs
160
     * @return array
161
     */
162
    protected function extractScriptNames(array $inputArgs): array
163
    {
164
        if (!isset($inputArgs[1])) {
165
            return [];
166
        }
167
168
        return explode(',', $inputArgs[1]);
169
    }
170
171
    /**
172
     * @param Script $script
173
     * @param Config $config
174
     * @return int
175
     */
176
    protected function execute(Script $script, Config $config): int
177
    {
178
        $commands = $this->applicationFactory
179
            ->createCommands($script);
180
181
        $logger = new ClimateLogger($this->cliMate, $this->duration);
182
        $executor = $this->applicationFactory
183
            ->createProcessExecutor($script, $config, $logger, $this->rootDirectory);
184
185
        try {
186
            $executor->execute($script, $commands);
187
        } catch (ExecutionErrorException $e) {
188
            $this->notifyError("\nExecution aborted, a subcommand failed!\n");
189
            return self::RESULT_ERROR;
190
        } catch (TemplateNotValidException $e) {
191
            $this->notifyError("\n" . $e->getMessage() . "\n");
192
            return self::RESULT_ERROR;
193
        }
194
195
        $this->notifySuccess("All commands successfully executed!\n");
196
197
        return self::RESULT_SUCCESS;
198
    }
199
200
    /**
201
     * @param $string
202
     */
203
    public function notifySuccess($string)
204
    {
205
        $this->cliMate->bold()->green($string);
206
    }
207
208
    /**
209
     * @param $string
210
     */
211
    public function notifyError($string)
212
    {
213
        $this->cliMate->bold()->red($string);
214
    }
215
216
    /**
217
     * @param $config
218
     */
219
    protected function printHeader(Config $config)
220
    {
221
        $this->cliMate->green()->bold()->out("\n###################");
222
223
        if ($config->getHeader()) {
224
            $this->cliMate->out("\n" . $config->getHeader());
225
        }
226
    }
227
228
    protected function printConfigFiles(array $configFiles)
229
    {
230
        for ($i = 0; $i < count($configFiles); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
231
            $configFiles[$i] = str_replace($this->rootDirectory."/", "", $configFiles[$i]);
232
        }
233
234
        if (count($configFiles) == 1) {
235
            $this->cliMate->yellow()->out(sprintf("Using %s \n", $configFiles[0]));
236
        } else {
237
            $this->cliMate->yellow()->out(sprintf("Using %s extended by %s \n", $configFiles[0], $configFiles[1]));
238
        }
239
    }
240
241
    /**
242
     * @param Script[] $scripts
243
     * @return Int
244
     */
245
    private function getPaddingSize(array $scripts): Int
246
    {
247
        $maxScriptNameLength = 0;
248
        foreach ($scripts as $script) {
249
            if (strlen($script->getName()) > $maxScriptNameLength) {
250
                $maxScriptNameLength = strlen($script->getName());
251
            }
252
        }
253
        return $maxScriptNameLength + self::MIN_PADDING_SIZE;
254
    }
255
}
256