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

TableBlueprint::addOperation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 5
c 0
b 0
f 0
rs 10
cc 1
nc 1
nop 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;
13
14
use Cycle\Database\Schema\AbstractTable;
15
use Cycle\Migrations\Exception\BlueprintException;
16
17
/**
18
 * TableBlueprint is abstraction wrapper at top of AbstractTable which converts command based
19
 * definitions into declarative.
20
 */
21
final class TableBlueprint
22
{
23
    /** @var CapsuleInterface */
24
    private $capsule = null;
25
26
    /** @var bool */
27
    private $executed = false;
28
29
    /** @var array */
30
    private $operations = [];
31
32
    /** @var string */
33
    private $table = '';
34
35
    /**
36
     * @param CapsuleInterface $capsule
37
     * @param string           $table
38
     */
39
    public function __construct(CapsuleInterface $capsule, string $table)
40
    {
41
        $this->capsule = $capsule;
42
        $this->table = $table;
43
    }
44
45
    /**
46
     * Get associated table schema.
47
     *
48
     * @return AbstractTable
49
     */
50
    public function getSchema(): AbstractTable
51
    {
52
        return $this->capsule->getSchema($this->table);
53
    }
54
55
    /**
56
     * Example:
57
     * $table->addColumn('name', 'string', ['length' => 64]);
58
     * $table->addColumn('status', 'enum', [
59
     *      'values' => ['active', 'disabled']
60
     * ]);
61
     *
62
     * @param string $name
63
     * @param string $type
64
     * @param array  $options
65
     *
66
     * @return TableBlueprint
67
     */
68
    public function addColumn(string $name, string $type, array $options = []): self
69
    {
70
        return $this->addOperation(
71
            new Operation\Column\Add($this->table, $name, $type, $options)
72
        );
73
    }
74
75
    /**
76
     * Example:
77
     * $table->alterColumn('name', 'string', ['length' => 128]);
78
     *
79
     * @param string $name
80
     * @param string $type
81
     * @param array  $options
82
     *
83
     * @return TableBlueprint
84
     */
85
    public function alterColumn(string $name, string $type, array $options = []): self
86
    {
87
        return $this->addOperation(
88
            new Operation\Column\Alter($this->table, $name, $type, $options)
89
        );
90
    }
91
92
    /**
93
     * Example:
94
     * $table->renameColumn('column', 'new_name');
95
     *
96
     * @param string $name
97
     * @param string $newName
98
     *
99
     * @return TableBlueprint
100
     */
101
    public function renameColumn(string $name, string $newName): self
102
    {
103
        return $this->addOperation(
104
            new Operation\Column\Rename($this->table, $name, $newName)
105
        );
106
    }
107
108
    /**
109
     * Example:
110
     * $table->dropColumn('email');
111
     *
112
     * @param string $name
113
     *
114
     * @return TableBlueprint
115
     */
116
    public function dropColumn(string $name): self
117
    {
118
        return $this->addOperation(
119
            new Operation\Column\Drop($this->table, $name)
120
        );
121
    }
122
123
    /**
124
     * Example:
125
     * $table->addIndex(['email'], ['unique' => true]);
126
     *
127
     * @param array $columns
128
     * @param array $options
129
     *
130
     * @return TableBlueprint
131
     */
132
    public function addIndex(array $columns, array $options = []): self
133
    {
134
        return $this->addOperation(
135
            new Operation\Index\Add($this->table, $columns, $options)
136
        );
137
    }
138
139
    /**
140
     * Example:
141
     * $table->alterIndex(['email'], ['unique' => false]);
142
     *
143
     * @param array $columns
144
     * @param array $options
145
     *
146
     * @return TableBlueprint
147
     */
148
    public function alterIndex(array $columns, array $options): self
149
    {
150
        return $this->addOperation(
151
            new Operation\Index\Alter($this->table, $columns, $options)
152
        );
153
    }
154
155
    /**
156
     * Example:
157
     * $table->dropIndex(['email']);
158
     *
159
     * @param array $columns
160
     *
161
     * @return TableBlueprint
162
     */
163
    public function dropIndex(array $columns): self
164
    {
165
        return $this->addOperation(
166
            new Operation\Index\Drop($this->table, $columns)
167
        );
168
    }
169
170
    /**
171
     * Example:
172
     * $table->addForeignKey('user_id', 'users', 'id', ['delete' => 'CASCADE']);
173
     *
174
     * @param array  $columns
175
     * @param string $foreignTable Database isolation prefix will be automatically added.
176
     * @param array  $foreignKeys
177
     * @param array  $options
178
     *
179
     * @return TableBlueprint
180
     */
181
    public function addForeignKey(
182
        array $columns,
183
        string $foreignTable,
184
        array $foreignKeys,
185
        array $options = []
186
    ): self {
187
        return $this->addOperation(
188
            new Operation\ForeignKey\Add(
189
                $this->table,
190
                $columns,
191
                $foreignTable,
192
                $foreignKeys,
193
                $options
194
            )
195
        );
196
    }
197
198
    /**
199
     * Example:
200
     * $table->alterForeignKey('user_id', 'users', 'id', ['delete' => 'NO ACTION']);
201
     *
202
     * @param array  $columns
203
     * @param string $foreignTable
204
     * @param array  $foreignKeys
205
     * @param array  $options
206
     *
207
     * @return TableBlueprint
208
     */
209
    public function alterForeignKey(
210
        array $columns,
211
        string $foreignTable,
212
        array $foreignKeys,
213
        array $options = []
214
    ): self {
215
        return $this->addOperation(
216
            new Operation\ForeignKey\Alter(
217
                $this->table,
218
                $columns,
219
                $foreignTable,
220
                $foreignKeys,
221
                $options
222
            )
223
        );
224
    }
225
226
    /**
227
     * Example:
228
     * $table->dropForeignKey('user_id');
229
     *
230
     * @param array $columns
231
     *
232
     * @return TableBlueprint
233
     */
234
    public function dropForeignKey(array $columns): self
235
    {
236
        return $this->addOperation(
237
            new Operation\ForeignKey\Drop($this->table, $columns)
238
        );
239
    }
240
241
    /**
242
     * Set table primary keys index. Attention, you can only call it when table being created.
243
     *
244
     * @param array $keys
245
     *
246
     * @return TableBlueprint
247
     */
248
    public function setPrimaryKeys(array $keys): self
249
    {
250
        return $this->addOperation(
251
            new Operation\Table\PrimaryKeys($this->table, $keys)
252
        );
253
    }
254
255
    /**
256
     * Create table schema. Must be last operation in the sequence.
257
     */
258
    public function create(): void
259
    {
260
        $this->addOperation(
261
            new Operation\Table\Create($this->table)
262
        );
263
264
        $this->execute();
265
    }
266
267
    /**
268
     * Update table schema. Must be last operation in the sequence.
269
     */
270
    public function update(): void
271
    {
272
        $this->addOperation(
273
            new Operation\Table\Update($this->table)
274
        );
275
276
        $this->execute();
277
    }
278
279
    /**
280
     * Drop table. Must be last operation in the sequence.
281
     */
282
    public function drop(): void
283
    {
284
        $this->addOperation(
285
            new Operation\Table\Drop($this->table)
286
        );
287
288
        $this->execute();
289
    }
290
291
    /**
292
     * Rename table. Must be last operation in the sequence.
293
     *
294
     * @param string $newName
295
     */
296
    public function rename(string $newName): void
297
    {
298
        $this->addOperation(
299
            new Operation\Table\Rename($this->table, $newName)
300
        );
301
302
        $this->execute();
303
    }
304
305
    /**
306
     * Register new operation.
307
     *
308
     * @param OperationInterface $operation
309
     *
310
     * @return TableBlueprint
311
     */
312
    public function addOperation(OperationInterface $operation): self
313
    {
314
        $this->operations[] = $operation;
315
316
        return $this;
317
    }
318
319
    /**
320
     * Execute blueprint operations.
321
     */
322
    private function execute(): void
323
    {
324
        if ($this->executed) {
325
            throw new BlueprintException('Only one create/update/rename/drop is allowed per blueprint.');
326
        }
327
328
        $this->capsule->execute($this->operations);
329
        $this->executed = true;
330
    }
331
}
332