Test Setup Failed
Pull Request — master (#15)
by Łukasz
02:08
created

ProvisionDispatcher::deployCandidate()   A

Complexity

Conditions 3
Paths 5

Size

Total Lines 20
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 20
rs 9.4285
cc 3
eloc 15
nc 5
nop 1
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
    public function __construct(
52
        Executor $executor,
53
        CandidateProcessor $processor,
54
        HasSyntaxCorrectCheck $check,
55
        Sql $sqlFormatter
56
    ) {
57
        $this->executor = $executor;
58
        $this->processor = $processor;
59
        $this->syntaxCheck = $check;
60
        $this->sqlFormatter = $sqlFormatter;
61
        $this->startTimestamp = time();
62
    }
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);
1 ignored issue
show
Coding Style Compatibility introduced by
The method finalizeAndExit() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
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
}