Completed
Push — master ( 8873c6...682113 )
by Łukasz
02:14
created

ProvisionDispatcher::finalizeAndExit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 13
ccs 0
cts 11
cp 0
rs 9.4285
cc 1
eloc 9
nc 1
nop 0
crap 2
1
<?php
2
3
namespace Tworzenieweb\SqlProvisioner\Controller;
4
5
use RuntimeException;
6
use Symfony\Component\Console\Style\SymfonyStyle;
7
use Tworzenieweb\SqlProvisioner\Check\HasSyntaxCorrectCheck;
8
use Tworzenieweb\SqlProvisioner\Database\Exception;
9
use Tworzenieweb\SqlProvisioner\Database\Executor;
10
use Tworzenieweb\SqlProvisioner\Formatter\Sql;
11
use Tworzenieweb\SqlProvisioner\Model\Candidate;
12
use Tworzenieweb\SqlProvisioner\Processor\CandidateProcessor;
13
14
/**
15
 * Class ActionDispatcher
16
 *
17
 * @package Tworzenieweb\SqlProvisioner\Controller
18
 */
19
class ProvisionDispatcher
20
{
21
    const ACTION_DEPLOY = 'DEPLOY';
22
    const ACTION_SKIP = 'SKIP';
23
    const ACTION_QUIT = 'QUIT';
24
25
    /** @var Executor */
26
    private $executor;
27
28
    /** @var CandidateProcessor */
29
    private $processor;
30
31
    /** @var HasSyntaxCorrectCheck */
32
    private $syntaxCheck;
33
34
    /** @var Sql */
35
    private $sqlFormatter;
36
37
    /** @var SymfonyStyle */
38
    private $input;
39
40
    /** @var int */
41
    private $startTimestamp;
42
43
    /** @var int */
44
    private $candidateIndexValue = 1;
45
46
47
48
    /**
49
     * ActionDispatcher constructor.
50
     *
51
     * @param Executor $executor
52
     * @param CandidateProcessor $processor
53
     * @param HasSyntaxCorrectCheck $check
54
     * @param Sql $sqlFormatter
55
     */
56 1
    public function __construct(
57
        Executor $executor,
58
        CandidateProcessor $processor,
59
        HasSyntaxCorrectCheck $check,
60
        Sql $sqlFormatter
61
    ) {
62 1
        $this->executor = $executor;
63 1
        $this->processor = $processor;
64 1
        $this->syntaxCheck = $check;
65 1
        $this->sqlFormatter = $sqlFormatter;
66 1
        $this->startTimestamp = time();
67 1
    }
68
69
70
71
    /**
72
     * @param SymfonyStyle $io
73
     */
74
    public function setInputOutput(SymfonyStyle $io)
75
    {
76
        $this->input = $io;
77
    }
78
79
80
81
    /**
82
     * @param Candidate[] $workingDirectoryCandidates
83
     * @param int $queuedCandidatesCount
84
     */
85
    public function deploy(array $workingDirectoryCandidates, $queuedCandidatesCount)
86
    {
87
        while (!empty($workingDirectoryCandidates)) {
88
            $candidate = array_shift($workingDirectoryCandidates);
89
90
            if ($candidate->isQueued()) {
91
                $this->executeCandidateScript($candidate, $queuedCandidatesCount);
92
            }
93
        }
94
        $this->input->writeln('<info>All candidates scripts were executed</info>');
95
        $this->finalizeAndExit();
96
    }
97
98
99
100
    /**
101
     * @param Candidate $candidate
102
     */
103
    public function validate(Candidate $candidate)
104
    {
105
        if ($this->processor->isValid($candidate)) {
106
            $candidate->markAsQueued();
107
            $candidate->setIndex($this->candidateIndexValue++);
108
109
            return;
110
        }
111
112
        $this->ignoreCandidateHavingError($candidate);
113
    }
114
115
116
117
    public function skipSyntaxCheck()
118
    {
119
        $this->input->warning('SQL parsing disabled. This could lead to executing invalid queries.');
120
        $this->processor->removeCheck($this->syntaxCheck);
121
    }
122
123
124
125
    /**
126
     * @param Candidate $candidate
127
     */
128
    private function ignoreCandidateHavingError(Candidate $candidate)
129
    {
130
        $candidate->markAsIgnored($this->processor->getLastError());
131
        $lastErrorMessage = $this->processor->getLastErrorMessage();
132
133
        if (null !== $lastErrorMessage) {
134
            throw new RuntimeException($lastErrorMessage);
135
        }
136
    }
137
138
139
140
    /**
141
     * @param Candidate $candidate
142
     * @param int $queuedCandidatesCount
143
     */
144
    private function executeCandidateScript(Candidate $candidate, $queuedCandidatesCount)
145
    {
146
        $this->input->warning(
147
            sprintf(
148
                'PROCESSING [%d/%d] %s',
149
                $candidate->getIndex(),
150
                $queuedCandidatesCount,
151
                $candidate->getName()
152
            )
153
        );
154
        $this->input->text($this->sqlFormatter->format($candidate->getContent()));
155
        $action = $this->input->choice(
156
            sprintf('What action to perform for "%s"', $candidate->getName()),
157
            [self::ACTION_DEPLOY, self::ACTION_SKIP, self::ACTION_QUIT]
158
        );
159
160
        $this->dispatchAction($candidate, $action);
161
    }
162
163
164
165
    /**
166
     * @param Candidate $candidate
167
     */
168
    private function deployCandidate(Candidate $candidate)
169
    {
170
        try {
171
            $this->executor->execute($candidate);
172
            $this->processor->postValidate($candidate);
173
        } catch (Exception $databaseException) {
174
            $this->input->error($databaseException->getMessage());
175
            $this->input->writeln(
176
                sprintf(
177
                    "<bg=yellow>%s\n\r%s</>",
178
                    $databaseException->getPrevious()->getMessage(),
179
                    $candidate->getContent()
180
                )
181
            );
182
            $this->terminate();
183
        } catch (RuntimeException $runtimeException) {
184
            $this->input->error($runtimeException->getMessage());
185
            $this->terminate();
186
        }
187
    }
188
189
190
191
    public function finalizeAndExit()
192
    {
193
        $this->input->text(sprintf('Provisioning ended at %s', date('Y-m-d H:i:s')));
194
        $this->input->writeln(str_repeat('=', 120));
195
        $this->input->writeln(
196
            sprintf(
197
                '<info>Memory used: %s MB. Total Time of provisioning: %s seconds</info>',
198
                memory_get_peak_usage(true) / (pow(1024, 2)),
199
                time() - $this->startTimestamp
200
            )
201
        );
202
        die(0);
203
    }
204
205
206
207
    private function terminate()
208
    {
209
        $this->input->text(sprintf('Provisioning ended with error at %s', date('Y-m-d H:i:s')));
210
        die(1);
211
    }
212
213
214
215
    /**
216
     * @param Candidate $candidate
217
     * @param string $action
218
     */
219
    private function dispatchAction(Candidate $candidate, $action)
220
    {
221
        switch ($action) {
222
            case self::ACTION_DEPLOY:
223
                $this->deployCandidate($candidate);
224
                break;
225
            case self::ACTION_QUIT:
226
                $this->finalizeAndExit();
227
                break;
228
        }
229
    }
230
}
231