Completed
Push — master ( c9ec76...c066a0 )
by Dominik
01:42
created

SchemaUpdateCommand::update()   C

Complexity

Conditions 8
Paths 80

Size

Total Lines 28
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 14
nc 80
nop 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chubbyphp\Model\Doctrine\DBAL\Command;
6
7
use Doctrine\DBAL\Connection;
8
use Doctrine\DBAL\Schema\Schema;
9
use Symfony\Component\Console\Input\InputInterface;
10
use Symfony\Component\Console\Output\OutputInterface;
11
12
final class SchemaUpdateCommand
13
{
14
    /**
15
     * @var Connection
16
     */
17
    protected $connection;
18
19
    /**
20
     * @var
21
     */
22
    protected $schemaPath;
23
24
    /**
25
     * @param Connection $connection
26
     * @param string     $schemaPath
27
     */
28
    public function __construct(Connection $connection, string $schemaPath)
29
    {
30
        $this->connection = $connection;
31
        $this->schemaPath = $schemaPath;
32
    }
33
34
    /**
35
     * @param InputInterface  $input
36
     * @param OutputInterface $output
37
     *
38
     * @return int|null
39
     */
40
    public function __invoke(InputInterface $input, OutputInterface $output)
41
    {
42
        $dump = true === $input->getOption('dump');
43
        $force = true === $input->getOption('force');
44
45
        if ([] === $statements = $this->getStatements()) {
46
            $output->writeln('<info>No schema changes required</info>');
47
48
            return;
49
        }
50
51
        if (!$dump && !$force) {
52
            $output->writeln('<comment>ATTENTION</comment>: Do not execute in production.');
53
            $output->writeln('    Use the incremental update to detect changes during development and use');
54
            $output->writeln('    the SQL provided to manually update your database in production.');
55
            $output->writeln('');
56
            $output->writeln(sprintf('Would execute <info>"%s"</info> queries.', count($statements)));
57
            $output->writeln('Please run the operation by passing one - or both - of the following options:');
58
            $output->writeln('    <info>--force</info> to execute the command');
59
            $output->writeln('    <info>--dump</info> to dump the SQL statements to the screen');
60
61
            return 1;
62
        }
63
64
        $this->update($output, $statements, $dump, $force);
65
    }
66
67
    /**
68
     * @return array
69
     */
70
    private function getStatements(): array
71
    {
72
        $connection = $this->connection;
73
74
        $schemaManager = $connection->getSchemaManager();
75
        $fromSchema = $schemaManager->createSchema();
76
77
        /** @var Schema $schema */
78
        $schema = require $this->schemaPath;
79
80
        return $fromSchema->getMigrateToSql($schema, $connection->getDatabasePlatform());
81
    }
82
83
    /**
84
     * @param OutputInterface $output
85
     * @param array           $statements
86
     * @param bool            $dump
87
     * @param bool            $force
88
     */
89
    private function update(OutputInterface $output, array $statements, bool $dump, bool $force)
90
    {
91
        if ($dump) {
92
            $output->writeln('<info>Begin transaction</info>');
93
        }
94
95
        if ($force) {
96
            $this->connection->beginTransaction();
97
        }
98
99
        foreach ($statements as $statement) {
100
            if ($dump) {
101
                $output->writeln($statement);
102
            }
103
104
            if ($force) {
105
                $this->connection->exec($statement);
106
            }
107
        }
108
109
        if ($dump) {
110
            $output->writeln('<info>Commit</info>');
111
        }
112
113
        if ($force) {
114
            $this->connection->commit();
115
        }
116
    }
117
}
118