Passed
Pull Request — master (#65)
by Arman
03:48
created

Table::after()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 4
rs 10
1
<?php
2
3
/**
4
 * Quantum PHP Framework
5
 *
6
 * An open source software development framework for PHP
7
 *
8
 * @package Quantum
9
 * @author Arman Ag. <[email protected]>
10
 * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
11
 * @link http://quantum.softberg.org/
12
 * @since 2.7.0
13
 */
14
15
namespace Quantum\Libraries\Database\Schema;
16
17
use Quantum\Libraries\Database\Schema\TableBuilder;
18
use Quantum\Exceptions\MigrationException;
19
use Quantum\Libraries\Database\Database;
20
21
/**
22
 * Class Table
23
 * @package Quantum\Libraries\Database
24
 * 
25
 * @method self autoIncrement()
26
 * @method self primary()
27
 * @method self index(string $name = null)
28
 * @method self unique(string $name = null)
29
 * @method self fulltext(string $name = null)
30
 * @method self spatial(string $name = null)
31
 * @method self nullable(bool $indeed = true)
32
 * @method self default($value, bool $quoted = true)
33
 * @method self defaultQuoted()
34
 * @method self attribute(?string $value)
35
 * @method self comment(?string $value)
36
 * @method self type(string $type, $constraint)
37
 */
38
class Table
39
{
40
41
    use TableBuilder;
42
43
    /**
44
     * Action create
45
     */
46
    const CREATE = 1;
47
48
    /**
49
     * Action alter
50
     */
51
    const ALTER = 2;
52
53
    /**
54
     * Action drop
55
     */
56
    const DROP = 3;
57
58
    /**
59
     * Action rename
60
     */
61
    const RENAME = 4;
62
63
    /**
64
     * @var string
65
     */
66
    private $name;
67
68
    /**
69
     * 
70
     * @var string
71
     */
72
    private $newName;
73
74
    /**
75
     * @var int 
76
     */
77
    private $action = null;
78
79
    /**
80
     * @var array
81
     */
82
    private $columns = [];
83
84
    /**
85
     * @var array
86
     */
87
    private $indexKeys = [];
88
89
    /**
90
     * @var array
91
     */
92
    private $droppedIndexKeys = [];
93
94
    /**
95
     * Table constructor.
96
     * @param string $name
97
     */
98
    public function __construct(string $name)
99
    {
100
        $this->name = $name;
101
    }
102
103
    /**
104
     * Table destructor
105
     * Saves the data before object goes out of scope
106
     */
107
    public function __destruct()
108
    {
109
        $this->save();
110
    }
111
112
    /**
113
     * Renames the table
114
     * @param string $newName
115
     * @return Table
116
     */
117
    public function renameTo(string $newName): Table
118
    {
119
        $this->newName = $newName;
120
        return $this;
121
    }
122
123
    /**
124
     * Sets an action on a table to be performed 
125
     * @param int $action
126
     * @param array|null $data
127
     * @return Table
128
     */
129
    public function setAction(int $action, ?array $data = null): Table
130
    {
131
        $this->action = $action;
132
133
        if ($data) {
134
            $key = key($data);
135
            $this->$key = $data[$key];
136
        }
137
138
        return $this;
139
    }
140
141
    /**
142
     * Adds column to the table
143
     * @param string $name
144
     * @param string $type
145
     * @param mixed $constraint
146
     * @return Table
147
     */
148
    public function addColumn(string $name, string $type, $constraint = null): Table
149
    {
150
        array_push($this->columns, [
151
            'column' => new Column($name, $type, $constraint),
152
            'action' => $this->action == self::ALTER ? Column::ADD : null
153
        ]);
154
155
        return $this;
156
    }
157
158
    /**
159
     * Modifies the column
160
     * @param string $name
161
     * @param string $type
162
     * @param mixed $constraint
163
     * @return Table
164
     */
165
    public function modifyColumn(string $name, string $type = null, $constraint = null): Table
166
    {
167
        if ($this->action == self::ALTER) {
168
            array_push($this->columns, [
169
                'column' => new Column($name, $type, $constraint),
170
                'action' => Column::MODIFY
171
            ]);
172
        }
173
174
        return $this;
175
    }
176
177
    /**
178
     * Renames the column name
179
     * @param string $oldName
180
     * @param string $newName
181
     */
182
    public function renameColumn(string $oldName, string $newName)
183
    {
184
        if ($this->action == self::ALTER) {
185
            array_push($this->columns, [
186
                'column' => (new Column($oldName))->renameTo($newName),
187
                'action' => Column::RENAME
188
            ]);
189
        }
190
    }
191
192
    /**
193
     * Drops the column
194
     * @param string $name
195
     */
196
    public function dropColumn(string $name)
197
    {
198
        if ($this->action == self::ALTER) {
199
            array_push($this->columns, [
200
                'column' => new Column($name),
201
                'action' => Column::DROP
202
            ]);
203
        }
204
    }
205
206
    /**
207
     * Adds new index to column
208
     * @param string $columnName
209
     * @param string $indexType
210
     * @param string $indexName
211
     */
212
    public function addIndex(string $columnName, string $indexType, string $indexName = null)
213
    {
214
        if ($this->action == self::ALTER) {
215
            array_push($this->columns, [
216
                'column' => new Column($columnName),
217
                'action' => Column::ADD_INDEX
218
            ]);
219
220
            $this->$indexType($indexName);
221
        }
222
    }
223
224
    /**
225
     * Drops the column index
226
     * @param string $indexName
227
     */
228
    public function dropIndex(string $indexName)
229
    {
230
        if ($this->action == self::ALTER) {
231
            array_push($this->columns, [
232
                'column' => (new Column('dummy'))->indexDrop($indexName),
233
                'action' => Column::DROP_INDEX
234
            ]);
235
        }
236
    }
237
238
    public function after(string $columnName)
239
    {
240
        $this->columns[$this->columnKey()]['column']->after($columnName);
241
        return $this;
242
    }
243
244
    /**
245
     * Gets the generated query
246
     * @return string
247
     */
248
    public function getSql(): string
249
    {
250
        $sql = '';
251
252
        switch ($this->action) {
253
            case self::CREATE:
254
                $sql = $this->createTableSql();
255
                break;
256
            case self::ALTER:
257
                $sql = $this->alterTableSql();
258
                break;
259
            case self::RENAME:
260
                $sql = $this->renameTableSql();
261
                break;
262
            case self::DROP:
263
                $sql = $this->dropTableSql();
264
                break;
265
        }
266
267
        return $sql;
268
    }
269
270
    /**
271
     * Allows to call methods of Column class 
272
     * @param string $method
273
     * @param array|null $arguments
274
     * @return $this
275
     * @throws Quantum\Exceptions\MigrationException
276
     */
277
    public function __call(string $method, ?array $arguments)
278
    {
279
        if (!method_exists(Column::class, $method)) {
280
            throw MigrationException::methodNotDefined($method);
281
        }
282
283
        $this->columns[$this->columnKey()]['column']->{$method}(...$arguments);
284
        return $this;
285
    }
286
287
    /**
288
     * Saves the query
289
     */
290
    private function save()
291
    {
292
        $sql = $this->getSql();
293
294
        if ($sql) {
295
            Database::execute($sql);
296
        }
297
    }
298
299
    /**
300
     * Checks if column exists on a table 
301
     * @param string $columnName
302
     * @return bool
303
     */
304
    private function checkColumnExists(string $columnName): bool
305
    {
306
        $columnIndex = null;
307
308
        $columns = Database::fetchColumns($this->name);
309
310
        foreach ($columns as $index => $column) {
311
            if ($columnName == $column) {
312
                $columnIndex = $index;
313
                break;
314
            }
315
        }
316
317
        return !is_null($columnIndex);
318
    }
319
320
    /**
321
     * Gets the column key
322
     * @return int
323
     */
324
    private function columnKey(): int
325
    {
326
        return (int) array_key_last($this->columns);
327
    }
328
329
}
330