UpdateSchemaCommand   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 128
Duplicated Lines 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 14
eloc 59
c 2
b 1
f 0
dl 0
loc 128
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A unlock() 0 3 1
A setContainer() 0 3 1
A configure() 0 7 1
B execute() 0 97 11
1
<?php
2
3
namespace DH\DoctrineAuditBundle\Command;
4
5
use DH\DoctrineAuditBundle\Reader\Reader;
6
use DH\DoctrineAuditBundle\Transaction\TransactionManager;
7
use DH\DoctrineAuditBundle\Updater\UpdateManager;
8
use Symfony\Component\Console\Command\Command;
9
use Symfony\Component\Console\Command\LockableTrait;
10
use Symfony\Component\Console\Exception\RuntimeException;
11
use Symfony\Component\Console\Helper\ProgressBar;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Input\InputOption;
14
use Symfony\Component\Console\Output\OutputInterface;
15
use Symfony\Component\Console\Style\SymfonyStyle;
16
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
17
use Symfony\Component\DependencyInjection\ContainerInterface;
18
19
class UpdateSchemaCommand extends Command implements ContainerAwareInterface
20
{
21
    use LockableTrait;
22
23
    protected static $defaultName = 'audit:schema:update';
24
25
    /**
26
     * @var null|ContainerInterface
27
     */
28
    private $container;
29
30
    public function setContainer(?ContainerInterface $container = null): void
31
    {
32
        $this->container = $container;
33
    }
34
35
    public function unlock(): void
36
    {
37
        $this->release();
38
    }
39
40
    protected function configure(): void
41
    {
42
        $this
43
            ->setDescription('Update audit tables structure')
44
            ->addOption('dump-sql', null, InputOption::VALUE_NONE, 'Dumps the generated SQL statements to the screen (does not execute them).')
45
            ->addOption('force', 'f', InputOption::VALUE_NONE, 'Causes the generated SQL statements to be physically executed against your database.')
46
            ->setName(self::$defaultName)
47
        ;
48
    }
49
50
    protected function execute(InputInterface $input, OutputInterface $output)
51
    {
52
        if (null === $this->container) {
53
            throw new RuntimeException('No container.');
54
        }
55
56
        if (!$this->lock()) {
57
            $output->writeln('The command is already running in another process.');
58
59
            return 0;
60
        }
61
62
        $io = new SymfonyStyle($input, $output);
63
64
        $dumpSql = true === $input->getOption('dump-sql');
65
        $force = true === $input->getOption('force');
66
67
        /**
68
         * @var TransactionManager
69
         */
70
        $manager = $this->container->get('dh_doctrine_audit.manager');
71
72
        /**
73
         * @var Reader
74
         */
75
        $reader = $this->container->get('dh_doctrine_audit.reader');
76
77
        /**
78
         * @var \DH\DoctrineAuditBundle\Updater\UpdateManager
79
         */
80
        $updater = new UpdateManager($manager, $reader);
0 ignored issues
show
Bug introduced by
It seems like $manager can also be of type null; however, parameter $transactionManager of DH\DoctrineAuditBundle\U...eManager::__construct() does only seem to accept DH\DoctrineAuditBundle\T...tion\TransactionManager, 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

80
        $updater = new UpdateManager(/** @scrutinizer ignore-type */ $manager, $reader);
Loading history...
Bug introduced by
It seems like $reader can also be of type null; however, parameter $reader of DH\DoctrineAuditBundle\U...eManager::__construct() does only seem to accept DH\DoctrineAuditBundle\Reader\Reader, 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

80
        $updater = new UpdateManager($manager, /** @scrutinizer ignore-type */ $reader);
Loading history...
81
82
        $sqls = $updater->getUpdateAuditSchemaSql();
83
84
        if (empty($sqls)) {
85
            $io->success('Nothing to update.');
86
87
            $this->release();
88
89
            return 0;
90
        }
91
92
        if ($dumpSql) {
93
            $io->text('The following SQL statements will be executed:');
94
            $io->newLine();
95
96
            foreach ($sqls as $sql) {
97
                $io->text(sprintf('    %s;', $sql));
98
            }
99
        }
100
101
        if ($force) {
102
            if ($dumpSql) {
103
                $io->newLine();
104
            }
105
            $io->text('Updating database schema...');
106
            $io->newLine();
107
108
            $progressBar = new ProgressBar($output, \count($sqls));
109
            $progressBar->start();
110
111
            $updater->updateAuditSchema($sqls, static function (array $progress) use ($progressBar): void {
112
                $progressBar->advance();
113
            });
114
115
            $progressBar->finish();
116
117
            $io->newLine(2);
118
119
            $pluralization = (1 === \count($sqls)) ? 'query was' : 'queries were';
120
121
            $io->text(sprintf('    <info>%s</info> %s executed', \count($sqls), $pluralization));
122
            $io->success('Database schema updated successfully!');
123
        }
124
125
        if ($dumpSql || $force) {
126
            $this->release();
127
128
            return 0;
129
        }
130
131
        $io->caution('This operation should not be executed in a production environment!');
132
133
        $io->text(
134
            [
135
                sprintf('The Schema-Tool would execute <info>"%s"</info> queries to update the database.', \count($sqls)),
136
                '',
137
                'Please run the operation by passing one - or both - of the following options:',
138
                '',
139
                sprintf('    <info>%s --force</info> to execute the command', $this->getName()),
140
                sprintf('    <info>%s --dump-sql</info> to dump the SQL statements to the screen', $this->getName()),
141
            ]
142
        );
143
144
        $this->release();
145
146
        return 1;
147
    }
148
}
149