Failed Conditions
Branch master (116909)
by Guilherme
08:28
created

DeployCommand::checkDatabase()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 10
nc 5
nop 1
dl 0
loc 18
ccs 0
cts 14
cp 0
crap 30
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
namespace LoginCidadao\CoreBundle\Command;
4
5
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
6
use Symfony\Component\Console\Output\OutputInterface;
7
use Symfony\Component\Console\Output\BufferedOutput;
8
use Symfony\Component\Console\Input\InputInterface;
9
use Symfony\Component\Console\Input\InputOption;
10
use Symfony\Component\Console\Input\ArrayInput;
11
use Symfony\Component\Console\Style\SymfonyStyle;
12
13
class DeployCommand extends ContainerAwareCommand
14
{
15
    private $updateDb = false;
16
17
    protected function configure()
18
    {
19
        $this
20
            ->setName('lc:deploy')
21
            ->addOption('--update-db', null, InputOption::VALUE_NONE,
22
                'Update database schema without prompting')
23
            ->setDescription('Perform basic deploy commands.');
24
    }
25
26
    protected function execute(InputInterface $input, OutputInterface $output)
27
    {
28
        $this->updateDb = $input->getOption('update-db');
29
30
        $io = new SymfonyStyle($input, $output);
31
        $io->title("Running deploy tasks...");
32
33
        $this->clearMetadata($io);
34
        $this->clearCache($io, 'prod');
35
        $this->checkDatabase($io);
36
        $this->installAssets($io);
37
    }
38
39
    private function clearMetadata(SymfonyStyle $io)
40
    {
41
        $io->section("Clearing Doctrine Metadata...");
42
        $command = $this->getApplication()->find('doctrine:cache:clear-metadata');
43
44
        $envs = $this->getEnvsInput();
45
        $io->progressStart(count($envs));
46
        foreach ($envs as $env => $input) {
47
            $cmdOutput = new BufferedOutput();
48
            $returnCode = $command->run($input, $cmdOutput);
49
50
            if ($returnCode !== 0) {
51
                $io->newLine(2);
52
                $io->error("Couldn't clear metadata cache on $env");
53
54
                return;
55
            }
56
            $io->progressAdvance();
57
        }
58
        $io->progressFinish();
59
    }
60
61
    private function installAssets(SymfonyStyle $io)
62
    {
63
        $io->section("Installing assets...");
64
        $input = $this->getEnvsInput('prod');
65
        $commands = ['assets:install', 'assetic:dump'];
66
        $io->progressStart(count($commands));
67
        foreach ($commands as $command) {
68
            $cmdOutput = new BufferedOutput();
69
            $returnCode = $this->getApplication()
70
                ->find($command)->run($input, $cmdOutput);
71
72
            if ($returnCode !== 0) {
73
                $io->newLine(2);
74
                $io->error("$command failed. Run it separately to find out why.");
75
76
                return;
77
            }
78
            $io->progressAdvance();
79
        }
80
        $io->progressFinish();
81
    }
82
83
    private function clearCache(SymfonyStyle $io, $env)
84
    {
85
        $io->section("Clearing cache ($env)...");
86
        $io->progressStart(1);
87
        $input = $this->getEnvsInput($env);
88
        $command = $this->getApplication()->find('cache:clear');
89
90
        $cmdOutput = new BufferedOutput();
91
        $returnCode = $command->run($input, $cmdOutput);
0 ignored issues
show
Bug introduced by
It seems like $input can also be of type array<string,Symfony\Com...nsole\Input\ArrayInput>; however, parameter $input of Symfony\Component\Console\Command\Command::run() does only seem to accept Symfony\Component\Console\Input\InputInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

91
        $returnCode = $command->run(/** @scrutinizer ignore-type */ $input, $cmdOutput);
Loading history...
92
93
        if ($returnCode !== 0) {
94
            $io->error("cache:clear command failed. You may need to manually delete the cache folders.");
95
96
            return;
97
        }
98
99
        $io->progressFinish();
100
    }
101
102
    private function getEnvsInput($env = null)
103
    {
104
        $envs = [
105
            'prod' => new ArrayInput(['--env' => 'prod']),
106
            'dev' => new ArrayInput(['--env' => 'dev']),
107
        ];
108
109
        if ($env === null) {
110
            return $envs;
111
        } else {
112
            return $envs[$env];
113
        }
114
    }
115
116
    private function checkDatabase(SymfonyStyle $io)
117
    {
118
        $io->section("Checking database schema...");
119
120
        $defaultEm = $this->checkSchemaNeedsUpdate('default');
121
        $logsEm = $this->checkSchemaNeedsUpdate('logs');
122
123
        if (!$defaultEm && !$logsEm) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $defaultEm of type false|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $logsEm of type false|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
124
            $io->success(trim($defaultEm));
0 ignored issues
show
Bug introduced by
It seems like $defaultEm can also be of type false; however, parameter $str of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

124
            $io->success(trim(/** @scrutinizer ignore-type */ $defaultEm));
Loading history...
125
126
            return;
127
        }
128
129
        if ($defaultEm) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $defaultEm of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
130
            $this->updateSchema($io, explode("\n", trim($defaultEm)), 'default');
131
        }
132
        if ($logsEm) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $logsEm of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
133
            $this->updateSchema($io, explode("\n", trim($logsEm)), 'logs');
134
        }
135
    }
136
137
    private function checkSchemaNeedsUpdate($entityManager)
138
    {
139
        $cmdOutput = new BufferedOutput();
140
        $command = $this->getApplication()->find('doctrine:schema:update');
141
        $input = new ArrayInput([
142
            '--env' => 'dev',
143
            '--dump-sql' => true,
144
            '--em' => $entityManager,
145
        ]);
146
147
        $command->run($input, $cmdOutput);
148
149
        $output = $cmdOutput->fetch();
150
        if (strstr($output, 'Nothing to update') !== false) {
151
            return false;
152
        }
153
154
        return $output;
155
    }
156
157
    private function updateSchema(SymfonyStyle $io, $queries, $entityManager)
158
    {
159
        $io->caution("Your database schema needs to be updated. The following queries will be run:");
160
        $io->listing($queries);
161
        if ($this->updateDb === false &&
0 ignored issues
show
introduced by
The condition $this->updateDb === fals...now?', false) === false can never be true.
Loading history...
162
            $io->confirm("Should we run this queries now?", false) === false) {
163
            return;
164
        }
165
166
        $cmdOutput = new BufferedOutput();
167
        $command = $this->getApplication()->find('doctrine:schema:update');
168
        $force = new ArrayInput([
169
            '--env' => 'dev',
170
            '--dump-sql' => true,
171
            '--force' => true,
172
            '--em' => $entityManager,
173
        ]);
174
        $command->run($force, $cmdOutput);
175
176
        $result = $cmdOutput->fetch();
177
        if (strstr($result, 'Database schema updated successfully!') === false) {
178
            $io->error("Couldn't update the schema. Run 'doctrine:schema:update' separately to find out why");
179
        }
180
        $io->success("Database schema updated successfully!");
181
182
        $this->clearMetadata($io);
183
    }
184
}
185