Completed
Pull Request — master (#41)
by Sven
01:57
created

Application::run()   C

Complexity

Conditions 8
Paths 11

Size

Total Lines 48
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

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