Passed
Push — master ( 7656d0...dbe1c1 )
by Divine Niiquaye
04:04
created

ShowChanges::describeIndexes()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 10
c 0
b 0
f 0
nc 8
nop 1
dl 0
loc 16
ccs 0
cts 11
cp 0
crap 20
rs 9.9332
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of DivineNii opensource projects.
7
 *
8
 * PHP version 7.4 and above required
9
 *
10
 * @author    Divine Niiquaye Ibok <[email protected]>
11
 * @copyright 2019 DivineNii (https://divinenii.com/)
12
 * @license   https://opensource.org/licenses/BSD-3-Clause License
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 */
17
18
namespace Rade\Database\Cycle\Generator;
19
20
use Cycle\Schema\GeneratorInterface;
0 ignored issues
show
Bug introduced by
The type Cycle\Schema\GeneratorInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
21
use Cycle\Schema\Registry;
0 ignored issues
show
Bug introduced by
The type Cycle\Schema\Registry was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
22
use Cycle\Database\Schema\AbstractTable;
0 ignored issues
show
Bug introduced by
The type Cycle\Database\Schema\AbstractTable was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use Cycle\Database\Schema\Comparator;
0 ignored issues
show
Bug introduced by
The type Cycle\Database\Schema\Comparator was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use Symfony\Component\Console\Output\OutputInterface;
25
26
final class ShowChanges implements GeneratorInterface
27
{
28
    private OutputInterface $output;
29
30
    /** @var array<string,array<string,string|AbstractTable>> */
31
    private array $changes = [];
32
33
    public function __construct(OutputInterface $output)
34
    {
35
        $this->output = $output;
36
    }
37
38
    public function run(Registry $registry): Registry
39
    {
40
        $this->output->writeln('<info>Detecting schema changes:</info>' . "\n");
41
        $this->changes = [];
42
43
        foreach ($registry->getIterator() as $e) {
44
            if ($registry->hasTable($e)) {
45
                $table = $registry->getTableSchema($e);
46
47
                if ($table->getComparator()->hasChanges()) {
48
                    $key = $registry->getDatabase($e) . ':' . $registry->getTable($e);
49
                    $this->changes[$key] = [
50
                        'database' => $registry->getDatabase($e),
51
                        'table' => $registry->getTable($e),
52
                        'schema' => $table,
53
                    ];
54
                }
55
            }
56
        }
57
58
        if ([] === $this->changes) {
59
            $this->output->writeln('<fg=yellow>No database changes has been detected</fg=yellow>');
60
61
            return $registry;
62
        }
63
64
        foreach ($this->changes as $change) {
65
            $this->output->write(\sprintf('• <fg=cyan>%s.%s</fg=cyan>', $change['database'], $change['table']));
66
            $this->describeChanges($change['schema']);
67
        }
68
69
        return $registry;
70
    }
71
72
    public function hasChanges(): bool
73
    {
74
        return [] !== $this->changes;
75
    }
76
77
    protected function describeChanges(AbstractTable $table): void
78
    {
79
        if (!$this->output->isVerbose()) {
80
            $this->output->writeln(
81
                \sprintf(
82
                    ': <fg=green>%s</fg=green> change(s) detected',
83
                    $this->numChanges($table)
84
                )
85
            );
86
87
            return;
88
        }
89
        $this->output->write("\n");
90
91
        if (!$table->exists()) {
92
            $this->output->writeln('    - create table');
93
        }
94
95
        if (AbstractTable::STATUS_DECLARED_DROPPED === $table->getStatus()) {
96
            $this->output->writeln('    - drop table');
97
98
            return;
99
        }
100
101
        $cmp = $table->getComparator();
102
103
        $this->describeColumns($cmp);
104
        $this->describeIndexes($cmp);
105
        $this->describeFKs($cmp);
106
    }
107
108
    protected function describeColumns(Comparator $cmp): void
109
    {
110
        foreach ($cmp->addedColumns() as $column) {
111
            $this->output->writeln("    - add column <fg=yellow>{$column->getName()}</fg=yellow>");
112
        }
113
114
        foreach ($cmp->droppedColumns() as $column) {
115
            $this->output->writeln("    - drop column <fg=yellow>{$column->getName()}</fg=yellow>");
116
        }
117
118
        foreach ($cmp->alteredColumns() as $column) {
119
            $column = $column[0];
120
            $this->output->writeln("    - alter column <fg=yellow>{$column->getName()}</fg=yellow>");
121
        }
122
    }
123
124
    protected function describeIndexes(Comparator $cmp): void
125
    {
126
        foreach ($cmp->addedIndexes() as $index) {
127
            $index = \implode(', ', $index->getColumns());
128
            $this->output->writeln("    - add index on <fg=yellow>[{$index}]</fg=yellow>");
129
        }
130
131
        foreach ($cmp->droppedIndexes() as $index) {
132
            $index = \implode(', ', $index->getColumns());
133
            $this->output->writeln("    - drop index on <fg=yellow>[{$index}]</fg=yellow>");
134
        }
135
136
        foreach ($cmp->alteredIndexes() as $index) {
137
            $index = $index[0];
138
            $index = \implode(', ', $index->getColumns());
139
            $this->output->writeln("    - alter index on <fg=yellow>[{$index}]</fg=yellow>");
140
        }
141
    }
142
143
    protected function describeFKs(Comparator $cmp): void
144
    {
145
        foreach ($cmp->addedForeignKeys() as $fk) {
146
            $fkColumns = \implode(', ', $fk->getColumns());
147
            $this->output->writeln("    - add foreign key on <fg=yellow>{$fkColumns}</fg=yellow>");
148
        }
149
150
        foreach ($cmp->droppedForeignKeys() as $fk) {
151
            $fkColumns = \implode(', ', $fk->getColumns());
152
            $this->output->writeln("    - drop foreign key <fg=yellow>{$fkColumns}</fg=yellow>");
153
        }
154
155
        foreach ($cmp->alteredForeignKeys() as $fk) {
156
            $fk = $fk[0];
157
            $fkColumns = \implode(', ', $fk->getColumns());
158
            $this->output->writeln("    - alter foreign key <fg=yellow>{$fkColumns}</fg=yellow>");
159
        }
160
    }
161
162
    protected function numChanges(AbstractTable $table): int
163
    {
164
        $cmp = $table->getComparator();
165
166
        return \count($cmp->addedColumns())
167
            + \count($cmp->droppedColumns())
168
            + \count($cmp->alteredColumns())
169
            + \count($cmp->addedIndexes())
170
            + \count($cmp->droppedIndexes())
171
            + \count($cmp->alteredIndexes())
172
            + \count($cmp->addedForeignKeys())
173
            + \count($cmp->droppedForeignKeys())
174
            + \count($cmp->alteredForeignKeys());
175
    }
176
}
177