TableBlueprint   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 231
Duplicated Lines 0 %

Test Coverage

Coverage 98.39%

Importance

Changes 0
Metric Value
wmc 20
eloc 54
dl 0
loc 231
ccs 61
cts 62
cp 0.9839
rs 10
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A addColumn() 0 4 1
A alterForeignKey() 0 13 1
A rename() 0 7 1
A drop() 0 7 1
A __construct() 0 2 1
A addIndex() 0 4 1
A execute() 0 8 2
A alterColumn() 0 4 1
A renameColumn() 0 4 1
A dropForeignKey() 0 4 1
A getSchema() 0 3 1
A setPrimaryKeys() 0 4 1
A addOperation() 0 5 1
A update() 0 7 1
A alterIndex() 0 4 1
A addForeignKey() 0 13 1
A dropIndex() 0 4 1
A dropColumn() 0 4 1
A create() 0 7 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cycle\Migrations;
6
7
use Cycle\Database\Schema\AbstractTable;
8
use Cycle\Migrations\Exception\BlueprintException;
9
10
/**
11
 * TableBlueprint is abstraction wrapper at top of AbstractTable which converts command based
12
 * definitions into declarative.
13
 */
14
final class TableBlueprint
15
{
16
    private bool $executed = false;
17
    private array $operations = [];
18
19 408
    public function __construct(private CapsuleInterface $capsule, private string $table)
20
    {
21
    }
22
23
    /**
24
     * Get associated table schema.
25
     */
26 96
    public function getSchema(): AbstractTable
27
    {
28 96
        return $this->capsule->getSchema($this->table);
29
    }
30
31
    /**
32
     * Example:
33
     * $table->addColumn('name', 'string', ['length' => 64]);
34
     * $table->addColumn('status', 'enum', [
35
     *      'values' => ['active', 'disabled']
36
     * ]);
37
     */
38 280
    public function addColumn(string $name, string $type, array $options = []): self
39
    {
40 280
        return $this->addOperation(
41 280
            new Operation\Column\Add($this->table, $name, $type, $options)
42
        );
43
    }
44
45
    /**
46
     * Example:
47
     * $table->alterColumn('name', 'string', ['length' => 128]);
48
     */
49 56
    public function alterColumn(string $name, string $type, array $options = []): self
50
    {
51 56
        return $this->addOperation(
52 56
            new Operation\Column\Alter($this->table, $name, $type, $options)
53
        );
54
    }
55
56
    /**
57
     * Example:
58
     * $table->renameColumn('column', 'new_name');
59
     */
60 32
    public function renameColumn(string $name, string $newName): self
61
    {
62 32
        return $this->addOperation(
63 32
            new Operation\Column\Rename($this->table, $name, $newName)
64
        );
65
    }
66
67
    /**
68
     * Example:
69
     * $table->dropColumn('email');
70
     */
71 40
    public function dropColumn(string $name): self
72
    {
73 40
        return $this->addOperation(
74 40
            new Operation\Column\Drop($this->table, $name)
75
        );
76
    }
77
78
    /**
79
     * Example:
80
     * $table->addIndex(['email'], ['unique' => true]);
81
     */
82 192
    public function addIndex(array $columns, array $options = []): self
83
    {
84 192
        return $this->addOperation(
85 192
            new Operation\Index\Add($this->table, $columns, $options)
86
        );
87
    }
88
89
    /**
90
     * Example:
91
     * $table->alterIndex(['email'], ['unique' => false]);
92
     */
93 24
    public function alterIndex(array $columns, array $options): self
94
    {
95 24
        return $this->addOperation(
96 24
            new Operation\Index\Alter($this->table, $columns, $options)
97
        );
98
    }
99
100
    /**
101
     * Example:
102
     * $table->dropIndex(['email']);
103
     */
104 40
    public function dropIndex(array $columns): self
105
    {
106 40
        return $this->addOperation(
107 40
            new Operation\Index\Drop($this->table, $columns)
108
        );
109
    }
110
111
    /**
112
     * Example:
113
     * $table->addForeignKey('user_id', 'users', 'id', ['delete' => 'CASCADE']);
114
     *
115
     * @param string $foreignTable Database isolation prefix will be automatically added.
116
     */
117 80
    public function addForeignKey(
118
        array $columns,
119
        string $foreignTable,
120
        array $foreignKeys,
121
        array $options = []
122
    ): self {
123 80
        return $this->addOperation(
124 80
            new Operation\ForeignKey\Add(
125 80
                $this->table,
126
                $columns,
127
                $foreignTable,
128
                $foreignKeys,
129
                $options
130
            )
131
        );
132
    }
133
134
    /**
135
     * Example:
136
     * $table->alterForeignKey('user_id', 'users', 'id', ['delete' => 'NO ACTION']);
137
     */
138 32
    public function alterForeignKey(
139
        array $columns,
140
        string $foreignTable,
141
        array $foreignKeys,
142
        array $options = []
143
    ): self {
144 32
        return $this->addOperation(
145 32
            new Operation\ForeignKey\Alter(
146 32
                $this->table,
147
                $columns,
148
                $foreignTable,
149
                $foreignKeys,
150
                $options
151
            )
152
        );
153
    }
154
155
    /**
156
     * Example:
157
     * $table->dropForeignKey('user_id');
158
     */
159 24
    public function dropForeignKey(array $columns): self
160
    {
161 24
        return $this->addOperation(
162 24
            new Operation\ForeignKey\Drop($this->table, $columns)
163
        );
164
    }
165
166
    /**
167
     * Set table primary keys index. Attention, you can only call it when table being created.
168
     */
169 136
    public function setPrimaryKeys(array $keys): self
170
    {
171 136
        return $this->addOperation(
172 136
            new Operation\Table\PrimaryKeys($this->table, $keys)
173
        );
174
    }
175
176
    /**
177
     * Create table schema. Must be last operation in the sequence.
178
     */
179 304
    public function create(): void
180
    {
181 304
        $this->addOperation(
182 304
            new Operation\Table\Create($this->table)
183
        );
184
185 304
        $this->execute();
186
    }
187
188
    /**
189
     * Update table schema. Must be last operation in the sequence.
190
     */
191 208
    public function update(): void
192
    {
193 208
        $this->addOperation(
194 208
            new Operation\Table\Update($this->table)
195
        );
196
197 208
        $this->execute();
198
    }
199
200
    /**
201
     * Drop table. Must be last operation in the sequence.
202
     */
203 144
    public function drop(): void
204
    {
205 144
        $this->addOperation(
206 144
            new Operation\Table\Drop($this->table)
207
        );
208
209 144
        $this->execute();
210
    }
211
212
    /**
213
     * Rename table. Must be last operation in the sequence.
214
     */
215 24
    public function rename(string $newName): void
216
    {
217 24
        $this->addOperation(
218 24
            new Operation\Table\Rename($this->table, $newName)
219
        );
220
221 24
        $this->execute();
222
    }
223
224
    /**
225
     * Register new operation.
226
     */
227 408
    public function addOperation(OperationInterface $operation): self
228
    {
229 408
        $this->operations[] = $operation;
230
231 408
        return $this;
232
    }
233
234
    /**
235
     * Execute blueprint operations.
236
     */
237 400
    private function execute(): void
238
    {
239 400
        if ($this->executed) {
240
            throw new BlueprintException('Only one create/update/rename/drop is allowed per blueprint.');
241
        }
242
243 400
        $this->capsule->execute($this->operations);
244 240
        $this->executed = true;
245
    }
246
}
247