ShowChanges   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 76
dl 0
loc 149
ccs 0
cts 79
cp 0
rs 10
c 0
b 0
f 0
wmc 25

8 Methods

Rating   Name   Duplication   Size   Complexity  
A numChanges() 0 13 1
A describeColumns() 0 13 4
A __construct() 0 3 1
A describeFKs() 0 16 4
A run() 0 32 6
A describeIndexes() 0 16 4
A hasChanges() 0 3 1
A describeChanges() 0 29 4
1
<?php declare(strict_types=1);
2
3
/*
4
 * This file is part of Biurad opensource projects.
5
 *
6
 * @copyright 2019 Biurad Group (https://biurad.com/)
7
 * @license   https://opensource.org/licenses/BSD-3-Clause License
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
namespace Flange\Database\Cycle\Generator;
14
15
use Cycle\Database\Schema\AbstractTable;
16
use Cycle\Database\Schema\Comparator;
17
use Cycle\Schema\GeneratorInterface;
18
use Cycle\Schema\Registry;
19
use Symfony\Component\Console\Output\OutputInterface;
20
21
final class ShowChanges implements GeneratorInterface
22
{
23
    private OutputInterface $output;
24
25
    /** @var array<string,array<string,string|AbstractTable>> */
26
    private array $changes = [];
27
28
    public function __construct(OutputInterface $output)
29
    {
30
        $this->output = $output;
31
    }
32
33
    public function run(Registry $registry): Registry
34
    {
35
        $this->output->writeln('<info>Detecting schema changes:</info>'."\n");
36
        $this->changes = [];
37
38
        foreach ($registry->getIterator() as $e) {
39
            if ($registry->hasTable($e)) {
40
                $table = $registry->getTableSchema($e);
41
42
                if ($table->getComparator()->hasChanges()) {
43
                    $key = $registry->getDatabase($e).':'.$registry->getTable($e);
44
                    $this->changes[$key] = [
45
                        'database' => $registry->getDatabase($e),
46
                        'table' => $registry->getTable($e),
47
                        'schema' => $table,
48
                    ];
49
                }
50
            }
51
        }
52
53
        if ([] === $this->changes) {
54
            $this->output->writeln('<fg=yellow>No database changes has been detected</fg=yellow>');
55
56
            return $registry;
57
        }
58
59
        foreach ($this->changes as $change) {
60
            $this->output->write(\sprintf('• <fg=cyan>%s.%s</fg=cyan>', $change['database'], $change['table']));
61
            $this->describeChanges($change['schema']);
62
        }
63
64
        return $registry;
65
    }
66
67
    public function hasChanges(): bool
68
    {
69
        return [] !== $this->changes;
70
    }
71
72
    protected function describeChanges(AbstractTable $table): void
73
    {
74
        if (!$this->output->isVerbose()) {
75
            $this->output->writeln(
76
                \sprintf(
77
                    ': <fg=green>%s</fg=green> change(s) detected',
78
                    $this->numChanges($table)
79
                )
80
            );
81
82
            return;
83
        }
84
        $this->output->write("\n");
85
86
        if (!$table->exists()) {
87
            $this->output->writeln('    - create table');
88
        }
89
90
        if (AbstractTable::STATUS_DECLARED_DROPPED === $table->getStatus()) {
91
            $this->output->writeln('    - drop table');
92
93
            return;
94
        }
95
96
        $cmp = $table->getComparator();
97
98
        $this->describeColumns($cmp);
99
        $this->describeIndexes($cmp);
100
        $this->describeFKs($cmp);
101
    }
102
103
    protected function describeColumns(Comparator $cmp): void
104
    {
105
        foreach ($cmp->addedColumns() as $column) {
106
            $this->output->writeln("    - add column <fg=yellow>{$column->getName()}</fg=yellow>");
107
        }
108
109
        foreach ($cmp->droppedColumns() as $column) {
110
            $this->output->writeln("    - drop column <fg=yellow>{$column->getName()}</fg=yellow>");
111
        }
112
113
        foreach ($cmp->alteredColumns() as $column) {
114
            $column = $column[0];
115
            $this->output->writeln("    - alter column <fg=yellow>{$column->getName()}</fg=yellow>");
116
        }
117
    }
118
119
    protected function describeIndexes(Comparator $cmp): void
120
    {
121
        foreach ($cmp->addedIndexes() as $index) {
122
            $index = \implode(', ', $index->getColumns());
123
            $this->output->writeln("    - add index on <fg=yellow>[{$index}]</fg=yellow>");
124
        }
125
126
        foreach ($cmp->droppedIndexes() as $index) {
127
            $index = \implode(', ', $index->getColumns());
128
            $this->output->writeln("    - drop index on <fg=yellow>[{$index}]</fg=yellow>");
129
        }
130
131
        foreach ($cmp->alteredIndexes() as $index) {
132
            $index = $index[0];
133
            $index = \implode(', ', $index->getColumns());
134
            $this->output->writeln("    - alter index on <fg=yellow>[{$index}]</fg=yellow>");
135
        }
136
    }
137
138
    protected function describeFKs(Comparator $cmp): void
139
    {
140
        foreach ($cmp->addedForeignKeys() as $fk) {
141
            $fkColumns = \implode(', ', $fk->getColumns());
142
            $this->output->writeln("    - add foreign key on <fg=yellow>{$fkColumns}</fg=yellow>");
143
        }
144
145
        foreach ($cmp->droppedForeignKeys() as $fk) {
146
            $fkColumns = \implode(', ', $fk->getColumns());
147
            $this->output->writeln("    - drop foreign key <fg=yellow>{$fkColumns}</fg=yellow>");
148
        }
149
150
        foreach ($cmp->alteredForeignKeys() as $fk) {
151
            $fk = $fk[0];
152
            $fkColumns = \implode(', ', $fk->getColumns());
153
            $this->output->writeln("    - alter foreign key <fg=yellow>{$fkColumns}</fg=yellow>");
154
        }
155
    }
156
157
    protected function numChanges(AbstractTable $table): int
158
    {
159
        $cmp = $table->getComparator();
160
161
        return \count($cmp->addedColumns())
162
            + \count($cmp->droppedColumns())
163
            + \count($cmp->alteredColumns())
164
            + \count($cmp->addedIndexes())
165
            + \count($cmp->droppedIndexes())
166
            + \count($cmp->alteredIndexes())
167
            + \count($cmp->addedForeignKeys())
168
            + \count($cmp->droppedForeignKeys())
169
            + \count($cmp->alteredForeignKeys());
170
    }
171
}
172