UpdateSchemaCommand   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 15
eloc 59
c 1
b 0
f 0
dl 0
loc 110
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A setAuditor() 0 5 1
A configure() 0 7 1
C execute() 0 87 13
1
<?php
2
3
declare(strict_types=1);
4
5
namespace DH\Auditor\Provider\Doctrine\Persistence\Command;
6
7
use DH\Auditor\Auditor;
8
use DH\Auditor\Provider\Doctrine\DoctrineProvider;
9
use DH\Auditor\Provider\Doctrine\Persistence\Schema\SchemaManager;
10
use Symfony\Component\Console\Command\Command;
11
use Symfony\Component\Console\Command\LockableTrait;
12
use Symfony\Component\Console\Helper\ProgressBar;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Input\InputOption;
15
use Symfony\Component\Console\Output\OutputInterface;
16
use Symfony\Component\Console\Style\SymfonyStyle;
17
18
/**
19
 * @see \DH\Auditor\Tests\Provider\Doctrine\Persistence\Command\UpdateSchemaCommandTest
20
 */
21
final class UpdateSchemaCommand extends Command
22
{
23
    use LockableTrait;
24
25
    private Auditor $auditor;
26
27
    public function setAuditor(Auditor $auditor): self
28
    {
29
        $this->auditor = $auditor;
30
31
        return $this;
32
    }
33
34
    protected function configure(): void
35
    {
36
        $this
37
            ->setDescription('Update audit tables structure')
38
            ->setName('audit:schema:update')
39
            ->addOption('dump-sql', null, InputOption::VALUE_NONE, 'Dumps the generated SQL statements to the screen (does not execute them).')
40
            ->addOption('force', 'f', InputOption::VALUE_NONE, 'Causes the generated SQL statements to be physically executed against your database.')
41
        ;
42
    }
43
44
    protected function execute(InputInterface $input, OutputInterface $output): int
45
    {
46
        if (!$this->lock()) {
47
            $output->writeln('The command is already running in another process.');
48
49
            return Command::SUCCESS;
50
        }
51
52
        $io = new SymfonyStyle($input, $output);
53
54
        $dumpSql = true === $input->getOption('dump-sql');
55
        $force = true === $input->getOption('force');
56
57
        /** @var DoctrineProvider $provider */
58
        $provider = $this->auditor->getProvider(DoctrineProvider::class);
59
        $updateManager = new SchemaManager($provider);
60
61
        $sqls = $updateManager->getUpdateAuditSchemaSql();
62
63
        $count = 0;
64
        foreach ($sqls as $queries) {
65
            $count += is_countable($queries) ? \count($queries) : 0;
66
        }
67
68
        if (0 === $count) {
69
            $io->success('Nothing to update.');
70
            $this->release();
71
72
            return Command::SUCCESS;
73
        }
74
75
        if ($dumpSql) {
76
            $io->text('The following SQL statements will be executed:');
77
            $io->newLine();
78
79
            foreach ($sqls as $queries) {
80
                foreach ($queries as $sql) {
81
                    $io->text(sprintf('    %s;', $sql));
82
                }
83
            }
84
        }
85
86
        if ($force) {
87
            if ($dumpSql) {
88
                $io->newLine();
89
            }
90
91
            $io->text('Updating database schema...');
92
            $io->newLine();
93
94
            $progressBar = new ProgressBar($output, \count($sqls));
95
            $progressBar->start();
96
97
            $updateManager->updateAuditSchema($sqls, static function (array $progress) use ($progressBar): void {
98
                $progressBar->advance();
99
            });
100
101
            $progressBar->finish();
102
            $io->newLine(2);
103
104
            $pluralization = (1 === $count) ? 'query was' : 'queries were';
105
106
            $io->text(sprintf('    <info>%s</info> %s executed', $count, $pluralization));
107
            $io->success('Database schema updated successfully!');
108
        }
109
110
        if ($dumpSql || $force) {
111
            $this->release();
112
113
            return Command::SUCCESS;
114
        }
115
116
        $io->caution('This operation should not be executed in a production environment!');
117
        $io->text(
118
            [
119
                sprintf('The Schema-Tool would execute <info>"%s"</info> queries to update the database.', $count),
120
                '',
121
                'Please run the operation by passing one - or both - of the following options:',
122
                '',
123
                sprintf('    <info>%s --force</info> to execute the command', $this->getName()),
124
                sprintf('    <info>%s --dump-sql</info> to dump the SQL statements to the screen', $this->getName()),
125
            ]
126
        );
127
128
        $this->release();
129
130
        return Command::FAILURE;
131
    }
132
}
133