Completed
Pull Request — master (#15)
by Łukasz
01:57
created

ProvisionDispatcher::terminate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

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