ShowChanges::run()   A
last analyzed

Complexity

Conditions 6
Paths 12

Size

Total Lines 32
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 17
c 1
b 0
f 0
nc 12
nop 1
dl 0
loc 32
rs 9.0777
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Biurad opensource projects.
7
 *
8
 * PHP version 7.2 and above required
9
 *
10
 * @author    Divine Niiquaye Ibok <[email protected]>
11
 * @copyright 2019 Biurad Group (https://biurad.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 Biurad\Cycle\Generators;
19
20
use Cycle\Schema\GeneratorInterface;
21
use Cycle\Schema\Registry;
22
use Spiral\Database\Schema\AbstractTable;
23
use Spiral\Database\Schema\Comparator;
24
use Symfony\Component\Console\Output\OutputInterface;
25
26
final class ShowChanges implements GeneratorInterface
27
{
28
    /** @var OutputInterface */
29
    private $output;
30
31
    /** @var array */
32
    private $changes = [];
33
34
    /**
35
     * @param OutputInterface $output
36
     */
37
    public function __construct(OutputInterface $output)
38
    {
39
        $this->output = $output;
40
    }
41
42
    /**
43
     * @param Registry $registry
44
     *
45
     * @return Registry
46
     */
47
    public function run(Registry $registry): Registry
48
    {
49
        $this->output->writeln('<info>Detecting schema changes:</info>');
50
51
        $this->changes = [];
52
53
        foreach ($registry->getIterator() as $e) {
54
            if ($registry->hasTable($e)) {
55
                $table = $registry->getTableSchema($e);
56
57
                if ($table->getComparator()->hasChanges()) {
58
                    $this->changes[] = [
59
                        'database' => $registry->getDatabase($e),
60
                        'table'    => $registry->getTable($e),
61
                        'schema'   => $table,
62
                    ];
63
                }
64
            }
65
        }
66
67
        if ($this->changes === []) {
68
            $this->output->writeln('<fg=yellow>no database changes has been detected</fg=yellow>');
69
70
            return $registry;
71
        }
72
73
        foreach ($this->changes as $change) {
74
            $this->output->write(\sprintf('• <fg=cyan>%s.%s</fg=cyan>', $change['database'], $change['table']));
75
            $this->describeChanges($change['schema']);
76
        }
77
78
        return $registry;
79
    }
80
81
    /**
82
     * @return bool
83
     */
84
    public function hasChanges(): bool
85
    {
86
        return $this->changes !== [];
87
    }
88
89
    /**
90
     * @param AbstractTable $table
91
     */
92
    protected function describeChanges(AbstractTable $table): void
93
    {
94
        if (!$this->output->isVerbose()) {
95
            $this->output->writeln(
96
                \sprintf(
97
                    ': <fg=green>%s</fg=green> change(s) detected',
98
                    $this->numChanges($table)
99
                )
100
            );
101
102
            return;
103
        }
104
        $this->output->write("\n");
105
106
        if (!$table->exists()) {
107
            $this->output->writeln('    - create table');
108
        }
109
110
        if ($table->getStatus() === AbstractTable::STATUS_DECLARED_DROPPED) {
111
            $this->output->writeln('    - drop table');
112
113
            return;
114
        }
115
116
        $cmp = $table->getComparator();
117
118
        $this->describeColumns($cmp);
119
        $this->describeIndexes($cmp);
120
        $this->describeFKs($cmp);
121
    }
122
123
    /**
124
     * @param Comparator $cmp
125
     */
126
    protected function describeColumns(Comparator $cmp): void
127
    {
128
        foreach ($cmp->addedColumns() as $column) {
129
            $this->output->writeln("    - add column <fg=yellow>{$column->getName()}</fg=yellow>");
130
        }
131
132
        foreach ($cmp->droppedColumns() as $column) {
133
            $this->output->writeln("    - drop column <fg=yellow>{$column->getName()}</fg=yellow>");
134
        }
135
136
        foreach ($cmp->alteredColumns() as $column) {
137
            $column = $column[0];
138
            $this->output->writeln("    - alter column <fg=yellow>{$column->getName()}</fg=yellow>");
139
        }
140
    }
141
142
    /**
143
     * @param Comparator $cmp
144
     */
145
    protected function describeIndexes(Comparator $cmp): void
146
    {
147
        foreach ($cmp->addedIndexes() as $index) {
148
            $index = \implode(', ', $index->getColumns());
149
            $this->output->writeln("    - add index on <fg=yellow>[{$index}]</fg=yellow>");
150
        }
151
152
        foreach ($cmp->droppedIndexes() as $index) {
153
            $index = \implode(', ', $index->getColumns());
154
            $this->output->writeln("    - drop index on <fg=yellow>[{$index}]</fg=yellow>");
155
        }
156
157
        foreach ($cmp->alteredIndexes() as $index) {
158
            $index = $index[0];
159
            $index = \implode(', ', $index->getColumns());
160
            $this->output->writeln("    - alter index on <fg=yellow>[{$index}]</fg=yellow>");
161
        }
162
    }
163
164
    /**
165
     * @param Comparator $cmp
166
     */
167
    protected function describeFKs(Comparator $cmp): void
168
    {
169
        foreach ($cmp->addedForeignKeys() as $fk) {
170
            $fkColumns = \implode(', ', $fk->getColumns());
171
            $this->output->writeln("    - add foreign key on <fg=yellow>{$fkColumns}</fg=yellow>");
172
        }
173
174
        foreach ($cmp->droppedForeignKeys() as $fk) {
175
            $fkColumns = \implode(', ', $fk->getColumns());
176
            $this->output->writeln("    - drop foreign key <fg=yellow>{$fkColumns}</fg=yellow>");
177
        }
178
179
        foreach ($cmp->alteredForeignKeys() as $fk) {
180
            $fk        = $fk[0];
181
            $fkColumns = \implode(', ', $fk->getColumns());
182
            $this->output->writeln("    - alter foreign key <fg=yellow>{$fkColumns}</fg=yellow>");
183
        }
184
    }
185
186
    /**
187
     * @param AbstractTable $table
188
     *
189
     * @return int
190
     */
191
    protected function numChanges(AbstractTable $table): int
192
    {
193
        $cmp = $table->getComparator();
194
195
        return \count($cmp->addedColumns())
196
            + \count($cmp->droppedColumns())
197
            + \count($cmp->alteredColumns())
198
            + \count($cmp->addedIndexes())
199
            + \count($cmp->droppedIndexes())
200
            + \count($cmp->alteredIndexes())
201
            + \count($cmp->addedForeignKeys())
202
            + \count($cmp->droppedForeignKeys())
203
            + \count($cmp->alteredForeignKeys());
204
    }
205
}
206