Passed
Push — master ( 27b181...baff18 )
by Aleksei
26:54 queued 24:15
created

PrintChanges::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Cycle\Schema\Generator;
6
7
use Cycle\Database\Schema\AbstractTable;
8
use Cycle\Database\Schema\ComparatorInterface;
9
use Cycle\Schema\GeneratorInterface;
10
use Cycle\Schema\Registry;
11
use Symfony\Component\Console\Output\OutputInterface;
12
13
final class PrintChanges implements GeneratorInterface
14
{
15
    private OutputInterface $output;
16
17
    private array $changes = [];
18
19 2
    public function __construct(OutputInterface $output)
20
    {
21 2
        $this->output = $output;
22
    }
23
24
    public function run(Registry $registry): Registry
25
    {
26
        $this->output->writeln('<info>Detecting schema changes:</info>');
27
        $this->changes = [];
28
        foreach ($registry->getIterator() as $entity) {
29
            if ($registry->hasTable($entity)) {
30
                $table = $registry->getTableSchema($entity);
31
                if ($table->getComparator()->hasChanges()) {
32
                    $this->changes[] = [
33
                        'database' => $registry->getDatabase($entity),
34
                        'table' => $registry->getTable($entity),
35
                        'schema' => $table,
36
                    ];
37
                }
38
            }
39
        }
40
        if ($this->changes === []) {
41
            $this->output->writeln('<fg=yellow>no database changes has been detected</fg=yellow>');
42
            return $registry;
43
        }
44
        foreach ($this->changes as $change) {
45
            $this->output->write(sprintf('• <fg=cyan>%s.%s</fg=cyan>', $change['database'], $change['table']));
46
            $this->describeChanges($change['schema']);
47
        }
48
        return $registry;
49
    }
50
51
    public function hasChanges(): bool
52
    {
53
        return $this->changes !== [];
54
    }
55
56
    private function describeChanges(AbstractTable $table): void
57
    {
58
        if (!$this->output->isVerbose()) {
59
            $this->output->writeln(sprintf(
60
                ': <fg=green>%s</fg=green> change(s) detected',
61
                $this->numChanges($table)
62
            ));
63
            return;
64
        }
65
        $this->output->write("\n");
66
        if (!$table->exists()) {
67
            $this->output->writeln('    - create table');
68
        }
69
        if ($table->getStatus() === AbstractTable::STATUS_DECLARED_DROPPED) {
70
            $this->output->writeln('    - drop table');
71
            return;
72
        }
73
        $cmp = $table->getComparator();
74
        $this->describeColumns($cmp);
75
        $this->describeIndexes($cmp);
76
        $this->describeFKs($cmp);
77
    }
78
79
    private function describeColumns(ComparatorInterface $cmp): void
80
    {
81
        foreach ($cmp->addedColumns() as $column) {
82
            $this->output->writeln("    - add column <fg=yellow>{$column->getName()}</fg=yellow>");
83
        }
84
        foreach ($cmp->droppedColumns() as $column) {
85
            $this->output->writeln("    - drop column <fg=yellow>{$column->getName()}</fg=yellow>");
86
        }
87
        foreach ($cmp->alteredColumns() as $column) {
88
            $column = $column[0];
89
            $this->output->writeln("    - alter column <fg=yellow>{$column->getName()}</fg=yellow>");
90
        }
91
    }
92
93
    private function describeIndexes(ComparatorInterface $cmp): void
94
    {
95
        foreach ($cmp->addedIndexes() as $index) {
96
            $index = implode(', ', $index->getColumns());
97
            $this->output->writeln("    - add index on <fg=yellow>[{$index}]</fg=yellow>");
98
        }
99
        foreach ($cmp->droppedIndexes() as $index) {
100
            $index = implode(', ', $index->getColumns());
101
            $this->output->writeln("    - drop index on <fg=yellow>[{$index}]</fg=yellow>");
102
        }
103
        foreach ($cmp->alteredIndexes() as $index) {
104
            $index = $index[0];
105
            $index = implode(', ', $index->getColumns());
106
            $this->output->writeln("    - alter index on <fg=yellow>[{$index}]</fg=yellow>");
107
        }
108
    }
109
110
    private function describeFKs(ComparatorInterface $cmp): void
111
    {
112
        foreach ($cmp->addedForeignKeys() as $fk) {
113
            $fkColumns = implode(', ', $fk->getColumns());
114
            $this->output->writeln("    - add foreign key on <fg=yellow>{$fkColumns}</fg=yellow>");
115
        }
116
        foreach ($cmp->droppedForeignKeys() as $fk) {
117
            $fkColumns = implode(', ', $fk->getColumns());
118
            $this->output->writeln("    - drop foreign key <fg=yellow>{$fkColumns}</fg=yellow>");
119
        }
120
        foreach ($cmp->alteredForeignKeys() as $fk) {
121
            $fk = $fk[0];
122
            $fkColumns = implode(', ', $fk->getColumns());
123
            $this->output->writeln("    - alter foreign key <fg=yellow>{$fkColumns}</fg=yellow>");
124
        }
125
    }
126
127
    private function numChanges(AbstractTable $table): int
128
    {
129
        $cmp = $table->getComparator();
130
        return count($cmp->addedColumns())
131
            + count($cmp->droppedColumns())
132
            + count($cmp->alteredColumns())
133
            + count($cmp->addedIndexes())
134
            + count($cmp->droppedIndexes())
135
            + count($cmp->alteredIndexes())
136
            + count($cmp->addedForeignKeys())
137
            + count($cmp->droppedForeignKeys())
138
            + count($cmp->alteredForeignKeys());
139
    }
140
}
141