Passed
Push — master ( 10a192...087136 )
by Aleksei
07:38 queued 05:42
created

Atomizer   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 115
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 16
eloc 32
c 1
b 0
f 1
dl 0
loc 115
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getTables() 0 3 1
A sortedTables() 0 13 3
A declareChanges() 0 14 4
A addTable() 0 5 1
A revertChanges() 0 14 4
A __construct() 0 3 1
1
<?php
2
3
/**
4
 * Spiral Framework.
5
 *
6
 * @license MIT
7
 * @author  Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Cycle\Migrations\Atomizer;
13
14
use Cycle\Database\Schema\AbstractTable;
15
use Cycle\Database\Schema\Reflector;
16
use Spiral\Reactor\Partial\Source;
17
18
/**
19
 * Atomizer provides ability to convert given AbstractTables and their changes into set of
20
 * migration commands.
21
 */
22
final class Atomizer
23
{
24
    /** @var AbstractTable[] */
25
    protected $tables = [];
26
    /** @var RendererInterface */
27
    private $renderer;
28
29
    /**
30
     * @param RendererInterface $renderer
31
     */
32
    public function __construct(RendererInterface $renderer)
33
    {
34
        $this->renderer = $renderer;
35
    }
36
37
    /**
38
     * Add new table into atomizer.
39
     *
40
     * @param AbstractTable $table
41
     *
42
     * @return Atomizer
43
     */
44
    public function addTable(AbstractTable $table): self
45
    {
46
        $this->tables[] = $table;
47
48
        return $this;
49
    }
50
51
    /**
52
     * Get all atomizer tables.
53
     *
54
     * @return AbstractTable[]
55
     */
56
    public function getTables(): array
57
    {
58
        return $this->tables;
59
    }
60
61
    /**
62
     * Generate set of commands needed to describe migration (up command).
63
     *
64
     * @param Source $source
65
     */
66
    public function declareChanges(Source $source): void
67
    {
68
        foreach ($this->sortedTables() as $table) {
69
            if (!$table->getComparator()->hasChanges()) {
70
                continue;
71
            }
72
73
            //New operations block
74
            $this->declareBlock($source);
75
76
            if (!$table->exists()) {
77
                $this->renderer->createTable($source, $table);
78
            } else {
79
                $this->renderer->updateTable($source, $table);
80
            }
81
        }
82
    }
83
84
    /**
85
     * Generate set of lines needed to rollback migration (down command).
86
     *
87
     * @param Source $source
88
     */
89
    public function revertChanges(Source $source): void
90
    {
91
        foreach ($this->sortedTables(true) as $table) {
92
            if (!$table->getComparator()->hasChanges()) {
93
                continue;
94
            }
95
96
            //New operations block
97
            $this->declareBlock($source);
98
99
            if (!$table->exists()) {
100
                $this->renderer->dropTable($source, $table);
101
            } else {
102
                $this->renderer->revertTable($source, $table);
103
            }
104
        }
105
    }
106
107
    /**
108
     * Tables sorted in order of their dependencies.
109
     *
110
     * @param bool $reverse
111
     *
112
     * @return AbstractTable[]
113
     */
114
    protected function sortedTables($reverse = false): array
115
    {
116
        $reflector = new Reflector();
117
        foreach ($this->tables as $table) {
118
            $reflector->addTable($table);
119
        }
120
121
        $sorted = $reflector->sortedTables();
122
        if ($reverse) {
123
            return array_reverse($sorted);
124
        }
125
126
        return $sorted;
127
    }
128
129
    /**
130
     * Add spacing between commands, only if required.
131
     *
132
     * @param Source $source
133
     */
134
    private function declareBlock(Source $source): void
135
    {
136
        if ($source->getLines() !== []) {
137
            $source->addLine('');
138
        }
139
    }
140
}
141