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.9.5 |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
namespace Quantum\Libraries\Database\Traits; |
16
|
|
|
|
17
|
|
|
use Quantum\Libraries\Database\Schemas\Column; |
18
|
|
|
use Quantum\Libraries\Database\Constants\Key; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Trait TableTrait |
22
|
|
|
* @package Quantum\Libraries\Database |
23
|
|
|
*/ |
24
|
|
|
trait TableTrait |
25
|
|
|
{ |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Generates create table statement |
29
|
|
|
* @return string |
30
|
|
|
*/ |
31
|
|
|
protected function createTableSql(): string |
32
|
|
|
{ |
33
|
|
|
$tableSchema = array_filter([$this->columnsSql(), $this->indexesSql()]); |
34
|
|
|
$sql = ''; |
35
|
|
|
|
36
|
|
|
if ($tableSchema) { |
|
|
|
|
37
|
|
|
$sql = 'CREATE TABLE `' . $this->name . '` ('; |
38
|
|
|
$sql .= implode(', ', $tableSchema); |
39
|
|
|
$sql .= ');'; |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
return $sql; |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Generates alter table statement |
47
|
|
|
* @return string |
48
|
|
|
*/ |
49
|
|
|
protected function alterTableSql(): string |
50
|
|
|
{ |
51
|
|
|
$tableSchema = array_filter([$this->columnsSql(), $this->indexesSql(), $this->dropIndexesSql()]); |
52
|
|
|
$sql = ''; |
53
|
|
|
|
54
|
|
|
if ($tableSchema) { |
|
|
|
|
55
|
|
|
$sql = 'ALTER TABLE `' . $this->name . '` '; |
56
|
|
|
$sql .= implode(', ', $tableSchema); |
57
|
|
|
$sql .= ';'; |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
return $sql; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Prepares rename table statement |
65
|
|
|
* @return string |
66
|
|
|
*/ |
67
|
|
|
protected function renameTableSql(): string |
68
|
|
|
{ |
69
|
|
|
return 'RENAME TABLE `' . $this->name . '` TO `' . $this->newName . '`;'; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Prepares drop table statement |
74
|
|
|
* @return string |
75
|
|
|
*/ |
76
|
|
|
protected function dropTableSql(): string |
77
|
|
|
{ |
78
|
|
|
return 'DROP TABLE `' . $this->name . '`'; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Prepares columns statements for table |
83
|
|
|
* @return string |
84
|
|
|
*/ |
85
|
|
|
protected function columnsSql(): string |
86
|
|
|
{ |
87
|
|
|
$sql = ''; |
88
|
|
|
|
89
|
|
|
if ($this->columns) { |
90
|
|
|
$columns = []; |
91
|
|
|
|
92
|
|
|
foreach ($this->columns as $entry) { |
93
|
|
|
$columnString = ''; |
94
|
|
|
|
95
|
|
|
if ($entry['action'] != Column::ADD_INDEX && $entry['action'] != Column::DROP_INDEX) { |
96
|
|
|
$columnString .= ($entry['action'] ? $entry['action'] . ' COLUMN ' : ''); |
97
|
|
|
$columnString .= $this->composeColumn($entry['column'], $entry['action']); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
if ($entry['column']->get('indexKey')) { |
101
|
|
|
$this->indexKeys[$entry['column']->get('indexKey')][] = [ |
|
|
|
|
102
|
|
|
'columnName' => $entry['column']->get('name'), |
103
|
|
|
'indexName' => $entry['column']->get('indexName'), |
104
|
|
|
]; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
if ($entry['column']->get('indexDrop')) { |
108
|
|
|
$this->droppedIndexKeys[] = $entry['column']->get('indexDrop'); |
|
|
|
|
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
if ($columnString) { |
112
|
|
|
$columns[] = $columnString; |
113
|
|
|
} |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
$sql = implode(', ', $columns); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
return $sql; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Composes the column |
124
|
|
|
* @param Column $column |
125
|
|
|
* @param string|null $action |
126
|
|
|
* @return string |
127
|
|
|
*/ |
128
|
|
|
protected function composeColumn(Column $column, string $action = null): string |
129
|
|
|
{ |
130
|
|
|
return |
131
|
|
|
$this->columnAttrSql($column->get(Column::NAME), '`', '`') . |
132
|
|
|
$this->columnAttrSql($column->get(Column::NEW_NAME), ' TO `', '`') . |
133
|
|
|
$this->columnAttrSql($column->get(Column::TYPE), ' ') . |
134
|
|
|
$this->columnAttrSql($column->get(Column::CONSTRAINT), '(', ')') . |
135
|
|
|
$this->columnAttrSql($column->get(Column::ATTRIBUTE), ' ') . |
136
|
|
|
$this->columnAttrSql($column->get(Column::NULLABLE, $action), ' ') . |
137
|
|
|
$this->columnAttrSql($column->get(Column::DEFAULT), ' DEFAULT ' . ($column->defaultQuoted() ? '\'' : ''), ($column->defaultQuoted() ? '\'' : '')) . |
138
|
|
|
$this->columnAttrSql($column->get(Column::COMMENT), ' COMMENT \'', '\'') . |
139
|
|
|
$this->columnAttrSql($column->get(Column::AFTER), ' AFTER `', '`') . |
140
|
|
|
$this->columnAttrSql($column->get(Column::AUTO_INCREMENT), ' '); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* Prepares column attributes |
145
|
|
|
* @param mixed $definition |
146
|
|
|
* @param string $before |
147
|
|
|
* @param string $after |
148
|
|
|
* @return string |
149
|
|
|
*/ |
150
|
|
|
protected function columnAttrSql($definition, string $before = '', string $after = ''): string |
151
|
|
|
{ |
152
|
|
|
$sql = ''; |
153
|
|
|
|
154
|
|
|
if (!is_null($definition)) { |
155
|
|
|
|
156
|
|
|
$sql .= $before . (is_array($definition) ? ("'" . implode("', '", $definition) . "'") : $definition) . $after; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
return $sql; |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* Prepares statement for primary key |
164
|
|
|
* @return string |
165
|
|
|
*/ |
166
|
|
|
protected function primaryKeysSql(): string |
167
|
|
|
{ |
168
|
|
|
$sql = ''; |
169
|
|
|
|
170
|
|
|
if (isset($this->indexKeys['primary'])) { |
171
|
|
|
$sql .= ($this->action == self::ALTER ? 'ADD ' : ''); |
|
|
|
|
172
|
|
|
|
173
|
|
|
$sql .= 'PRIMARY KEY ('; |
174
|
|
|
|
175
|
|
|
foreach ($this->indexKeys['primary'] as $key => $primaryKey) { |
176
|
|
|
$sql .= '`' . $primaryKey['columnName'] . '`'; |
177
|
|
|
$sql .= (array_key_last($this->indexKeys['primary']) != $key ? ', ' : ''); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
$sql .= ')'; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
return $sql; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* Prepares statement for index keys |
188
|
|
|
* @param string $type |
189
|
|
|
* @return string |
190
|
|
|
*/ |
191
|
|
|
protected function indexKeysSql(string $type): string |
192
|
|
|
{ |
193
|
|
|
$sql = ''; |
194
|
|
|
|
195
|
|
|
if (isset($this->indexKeys[$type])) { |
196
|
|
|
$indexes = []; |
197
|
|
|
|
198
|
|
|
foreach ($this->indexKeys[$type] as $indexKey) { |
199
|
|
|
$indexString = ($this->action == self::ALTER ? 'ADD ' : ''); |
|
|
|
|
200
|
|
|
$indexString .= strtoupper($type); |
201
|
|
|
$indexString .= ($indexKey['indexName'] ? ' `' . $indexKey['indexName'] . '`' : ''); |
202
|
|
|
$indexString .= ' (`' . $indexKey['columnName'] . '`)'; |
203
|
|
|
|
204
|
|
|
$indexes[] = $indexString; |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
$sql = implode(', ', $indexes); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
return $sql; |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* Builds a complete statement for index keys |
215
|
|
|
* @return string |
216
|
|
|
*/ |
217
|
|
|
protected function indexesSql(): string |
218
|
|
|
{ |
219
|
|
|
$indexes = [ |
220
|
|
|
$this->primaryKeysSql(), |
221
|
|
|
$this->indexKeysSql(Key::INDEX), |
222
|
|
|
$this->indexKeysSql(Key::UNIQUE), |
223
|
|
|
$this->indexKeysSql(Key::FULLTEXT), |
224
|
|
|
$this->indexKeysSql(Key::SPATIAL) |
225
|
|
|
]; |
226
|
|
|
|
227
|
|
|
return implode(', ', array_filter($indexes)); |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
/** |
231
|
|
|
* Builds a statement for drop indexes |
232
|
|
|
* @return string |
233
|
|
|
*/ |
234
|
|
|
protected function dropIndexesSql(): string |
235
|
|
|
{ |
236
|
|
|
$sql = ''; |
237
|
|
|
|
238
|
|
|
if (!empty($this->droppedIndexKeys)) { |
239
|
|
|
$indexes = []; |
240
|
|
|
|
241
|
|
|
foreach ($this->droppedIndexKeys as $index) { |
242
|
|
|
$indexes[] = 'DROP INDEX `' . $index . '`'; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
$sql .= implode(', ', $indexes); |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
return $sql; |
249
|
|
|
} |
250
|
|
|
} |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.