1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @author Todd Burry <[email protected]> |
4
|
|
|
* @copyright 2009-2014 Vanilla Forums Inc. |
5
|
|
|
* @license MIT |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace Garden\Db; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* A helper class for creating database tables. |
12
|
|
|
*/ |
13
|
|
|
class TableDef implements \JsonSerializable { |
14
|
|
|
/// Properties /// |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* @var array The columns that need to be set in the table. |
18
|
|
|
*/ |
19
|
|
|
private $columns; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* |
23
|
|
|
* @var string The name of the currently working table. |
24
|
|
|
*/ |
25
|
|
|
private $table; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @var array An array of indexes. |
29
|
|
|
*/ |
30
|
|
|
private $indexes; |
31
|
|
|
|
32
|
|
|
/// Methods /// |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Initialize an instance of the {@link TableDef} class. |
36
|
|
|
* |
37
|
|
|
* @param string $name The name of the table. |
38
|
|
|
*/ |
39
|
32 |
|
public function __construct($name = '') { |
40
|
32 |
|
$this->reset(); |
41
|
32 |
|
$this->table = $name; |
42
|
32 |
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Reset the internal state of this object so that it can be re-used. |
46
|
|
|
* |
47
|
|
|
* @return TableDef Returns $this for fluent calls. |
48
|
|
|
*/ |
49
|
32 |
|
public function reset() { |
50
|
32 |
|
$this->table = ''; |
51
|
32 |
|
$this->columns = []; |
52
|
32 |
|
$this->indexes = []; |
53
|
|
|
// $this->options = []; |
|
|
|
|
54
|
|
|
|
55
|
32 |
|
return $this; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Define a column. |
60
|
|
|
* |
61
|
|
|
* @param string $name The column name. |
62
|
|
|
* @param string $type The column type. |
63
|
|
|
* @param mixed $nullDefault Whether the column is required or it's default. |
64
|
|
|
* |
65
|
|
|
* null|true |
66
|
|
|
* : The column is not required. |
67
|
|
|
* false |
68
|
|
|
* : The column is required. |
69
|
|
|
* Anything else |
70
|
|
|
* : The column is required and this is its default. |
71
|
|
|
* @return TableDef |
72
|
|
|
*/ |
73
|
32 |
|
public function setColumn($name, $type, $nullDefault = false) { |
74
|
32 |
|
$this->columns[$name] = $this->createColumnDef($type, $nullDefault); |
75
|
|
|
|
76
|
32 |
|
return $this; |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Get an array column def from a structured function call. |
81
|
|
|
* |
82
|
|
|
* @param string $dbtype The database type of the column. |
83
|
|
|
* @param mixed $nullDefault Whether or not to allow null or the default value. |
84
|
|
|
* |
85
|
|
|
* null|true |
86
|
|
|
* : The column is not required. |
87
|
|
|
* false |
88
|
|
|
* : The column is required. |
89
|
|
|
* Anything else |
90
|
|
|
* : The column is required and this is its default. |
91
|
|
|
* |
92
|
|
|
* @return array Returns the column def as an array. |
93
|
|
|
*/ |
94
|
32 |
|
private function createColumnDef($dbtype, $nullDefault = false) { |
95
|
32 |
|
$column = Db::typeDef($dbtype); |
96
|
|
|
|
97
|
32 |
|
if ($column === null) { |
98
|
|
|
throw new \InvalidArgumentException("Unknown type '$dbtype'.", 500); |
99
|
|
|
} |
100
|
|
|
|
101
|
32 |
|
if ($column['dbtype'] === 'bool' && in_array($nullDefault, [true, false], true)) { |
102
|
|
|
// Booleans have a special meaning. |
103
|
2 |
|
$column['allowNull'] = false; |
104
|
2 |
|
$column['default'] = $nullDefault; |
105
|
32 |
|
} elseif ($nullDefault === null || $nullDefault === true) { |
106
|
|
|
$column['allowNull'] = true; |
107
|
32 |
|
} elseif ($nullDefault === false) { |
108
|
32 |
|
$column['allowNull'] = false; |
109
|
|
|
} else { |
110
|
28 |
|
$column['allowNull'] = false; |
111
|
28 |
|
$column['default'] = $nullDefault; |
112
|
|
|
} |
113
|
|
|
|
114
|
32 |
|
return $column; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* Define the primary key in the database. |
119
|
|
|
* |
120
|
|
|
* @param string $name The name of the column. |
121
|
|
|
* @param string $type The datatype for the column. |
122
|
|
|
* @return TableDef |
123
|
|
|
*/ |
124
|
20 |
|
public function setPrimaryKey($name, $type = 'int') { |
125
|
20 |
|
$column = $this->createColumnDef($type, false); |
126
|
20 |
|
$column['autoIncrement'] = true; |
127
|
20 |
|
$column['primary'] = true; |
128
|
|
|
|
129
|
20 |
|
$this->columns[$name] = $column; |
130
|
|
|
|
131
|
|
|
// Add the pk index. |
132
|
20 |
|
$this->addIndex(Db::INDEX_PK, $name); |
133
|
|
|
|
134
|
20 |
|
return $this; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* Add or update an index. |
139
|
|
|
* |
140
|
|
|
* @param string $type One of the `Db::INDEX_*` constants. |
141
|
|
|
* @param string ...$columns The columns in the index. |
142
|
|
|
* @return $this |
143
|
|
|
*/ |
|
|
|
|
144
|
32 |
|
public function addIndex($type, ...$columns) { |
145
|
32 |
|
$type = strtolower($type); |
146
|
|
|
|
147
|
|
|
// Look for a current index row. |
148
|
32 |
|
$currentIndex = null; |
149
|
32 |
|
foreach ($this->indexes as $i => $index) { |
150
|
26 |
|
if ($type !== $index['type']) { |
151
|
20 |
|
continue; |
152
|
|
|
} |
153
|
|
|
|
154
|
6 |
|
if ($type === Db::INDEX_PK || array_diff($index['columns'], $columns) == []) { |
155
|
4 |
|
$currentIndex =& $this->indexes[$i]; |
156
|
6 |
|
break; |
157
|
|
|
} |
158
|
|
|
} |
159
|
|
|
|
160
|
32 |
|
if ($currentIndex) { |
161
|
4 |
|
$currentIndex['columns'] = $columns; |
162
|
|
|
} else { |
163
|
|
|
$indexDef = [ |
164
|
32 |
|
'type' => $type, |
165
|
32 |
|
'columns' => $columns, |
166
|
|
|
]; |
167
|
32 |
|
$this->indexes[] = $indexDef; |
168
|
|
|
} |
169
|
|
|
|
170
|
32 |
|
return $this; |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* Get the table. |
175
|
|
|
* |
176
|
|
|
* @return string Returns the table. |
177
|
|
|
*/ |
178
|
|
|
public function getTable() { |
179
|
|
|
return $this->table; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* Set the name of the table. |
184
|
|
|
* |
185
|
|
|
* @param string|null $name The name of the table. |
186
|
|
|
* @return TableDef|string Returns $this for fluent calls. |
187
|
|
|
*/ |
188
|
8 |
|
public function setTable($name) { |
189
|
8 |
|
$this->table = $name; |
190
|
8 |
|
return $this; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Specify data which should be serialized to JSON. |
195
|
|
|
* |
196
|
|
|
* @link http://php.net/manual/en/jsonserializable.jsonserialize.php |
197
|
|
|
* @return mixed data which can be serialized by {@link json_encode()}, |
198
|
|
|
* which is a value of any type other than a resource. |
199
|
|
|
*/ |
200
|
|
|
public function jsonSerialize() { |
201
|
|
|
return $this->toArray(); |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Get the array representation of the table definition. |
206
|
|
|
* |
207
|
|
|
* @return array Returns a definition array. |
208
|
|
|
*/ |
209
|
32 |
|
public function toArray() { |
210
|
|
|
return [ |
211
|
32 |
|
'name' => $this->table, |
212
|
32 |
|
'columns' => $this->columns, |
213
|
32 |
|
'indexes' => $this->indexes |
214
|
|
|
]; |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* Execute this table definition on a database. |
219
|
|
|
* |
220
|
|
|
* @param Db $db The database to query. |
221
|
|
|
* @param array $options Additional options. See {@link Db::defineTable()}. |
222
|
|
|
*/ |
223
|
22 |
|
public function exec(Db $db, array $options = []) { |
224
|
22 |
|
$db->defineTable($this->toArray(), $options); |
225
|
22 |
|
} |
226
|
|
|
} |
227
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.