1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the "RocketORM" package. |
5
|
|
|
* |
6
|
|
|
* https://github.com/RocketORM/ORM |
7
|
|
|
* |
8
|
|
|
* For the full license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Rocket\ORM\Model\Map; |
13
|
|
|
|
14
|
|
|
use Rocket\ORM\Model\Map\Exception\RelationAlreadyExistsException; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* @author Sylvain Lorinet <[email protected]> |
18
|
|
|
*/ |
19
|
|
|
abstract class TableMap implements TableMapInterface |
20
|
|
|
{ |
21
|
|
|
const COLUMN_TYPE_INTEGER = 1; |
22
|
|
|
const COLUMN_TYPE_STRING = 2; |
23
|
|
|
const COLUMN_TYPE_DOUBLE = 3; |
24
|
|
|
const COLUMN_TYPE_BOOLEAN = 4; |
25
|
|
|
const COLUMN_TYPE_FLOAT = 5; |
26
|
|
|
const COLUMN_TYPE_TEXT = 6; |
27
|
|
|
const COLUMN_TYPE_DATE = 7; |
28
|
|
|
const COLUMN_TYPE_DATETIME = 8; |
29
|
|
|
const COLUMN_TYPE_ENUM = 9; |
30
|
|
|
|
31
|
|
|
const RELATION_TYPE_ONE_TO_MANY = 100; |
32
|
|
|
const RELATION_TYPE_MANY_TO_ONE = 101; |
33
|
|
|
const RELATION_TYPE_ONE_TO_ONE = 102; |
34
|
|
|
const RELATION_TYPE_MANY_TO_MANY = 103; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @var string |
38
|
|
|
*/ |
39
|
|
|
protected $connectionName; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @var string |
43
|
|
|
*/ |
44
|
|
|
protected $tableName; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @var string |
48
|
|
|
*/ |
49
|
|
|
protected $className; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* @var string |
53
|
|
|
*/ |
54
|
|
|
protected $classNamespace; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* @var array |
58
|
|
|
*/ |
59
|
|
|
protected $primaryKeys = []; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* @var array |
63
|
|
|
*/ |
64
|
|
|
protected $columns = []; |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* @var array |
68
|
|
|
*/ |
69
|
|
|
protected $relations = []; |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* @var string |
73
|
|
|
*/ |
74
|
|
|
protected $database; |
75
|
|
|
|
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @param string $name |
79
|
|
|
* @param bool $isAutoincrement |
80
|
|
|
*/ |
81
|
4 |
|
public function addPrimaryKey($name, $isAutoincrement = false) |
82
|
|
|
{ |
83
|
4 |
|
$this->primaryKeys[] = [ |
84
|
4 |
|
'name' => $name, |
85
|
|
|
'is_autoincrement' => $isAutoincrement |
86
|
4 |
|
]; |
87
|
4 |
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* @param string $name |
91
|
|
|
* @param string $phpName |
92
|
|
|
* @param int $type |
93
|
|
|
* @param null|int $size |
94
|
|
|
* @param int $decimal |
95
|
|
|
* @param null|array $values |
96
|
|
|
* @param null|bool $default |
97
|
|
|
* @param bool $isRequired |
98
|
|
|
*/ |
99
|
4 |
|
public function addColumn($name, $phpName, $type, $size = null, $decimal = 0, array $values = null, $default = null, $isRequired = false) |
100
|
|
|
{ |
101
|
4 |
|
$this->columns[$name] = [ |
102
|
4 |
|
'name' => $name, |
103
|
4 |
|
'phpName' => $phpName, |
104
|
4 |
|
'type' => $type, |
105
|
4 |
|
'size' => $size, |
106
|
4 |
|
'decimal' => $decimal, |
107
|
4 |
|
'values' => $values, |
108
|
4 |
|
'default' => $default, |
109
|
|
|
'required' => $isRequired |
110
|
4 |
|
]; |
111
|
4 |
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* @param string $classNamespace |
115
|
|
|
* @param string $phpName |
116
|
|
|
* @param int $type |
117
|
|
|
* @param string $local |
118
|
|
|
* @param string $foreign |
119
|
|
|
* |
120
|
|
|
* @throws RelationAlreadyExistsException |
121
|
|
|
*/ |
122
|
4 |
|
public function addRelation($classNamespace, $phpName, $type, $local, $foreign) |
123
|
|
|
{ |
124
|
4 |
|
if (isset($this->relations[$phpName])) { |
125
|
1 |
|
throw new RelationAlreadyExistsException('The relation between ' . str_replace(['TableMap\\', 'TableMap'], '', get_called_class()) . ' and "' . $classNamespace . '" already exists'); |
126
|
|
|
} |
127
|
|
|
|
128
|
4 |
|
$this->relations[$phpName] = [ |
129
|
4 |
|
'namespace' => $classNamespace, |
130
|
4 |
|
'phpName' => $phpName, |
131
|
4 |
|
'type' => $type, |
132
|
4 |
|
'local' => $local, |
133
|
4 |
|
'foreign' => $foreign, |
134
|
4 |
|
'is_many' => self::RELATION_TYPE_MANY_TO_MANY === $type || self::RELATION_TYPE_MANY_TO_ONE === $type |
135
|
|
|
//'table_map_namespace' => constant($classNamespace . 'Query::TABLE_MAP_NAMESPACE') |
|
|
|
|
136
|
4 |
|
]; |
137
|
4 |
|
} |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* @param array $row |
141
|
|
|
* |
142
|
|
|
* @return string |
143
|
|
|
* |
144
|
|
|
* @internal Used by the query class |
145
|
|
|
*/ |
146
|
1 |
|
public function getPrimaryKeysHash(array $row) |
147
|
|
|
{ |
148
|
1 |
|
$hash = ''; |
149
|
1 |
|
foreach ($this->getPrimaryKeys() as $primaryKey) { |
150
|
1 |
|
$hash .= $row[$primaryKey['name']]; |
151
|
1 |
|
} |
152
|
|
|
|
153
|
|
|
// if hash is too long, transform it into MD5 hash |
154
|
1 |
|
if (isset($hash[33])) { |
155
|
1 |
|
return md5($hash); |
156
|
|
|
} |
157
|
|
|
|
158
|
1 |
|
return $hash; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* @return string |
163
|
|
|
*/ |
164
|
1 |
|
public function getClassName() |
165
|
|
|
{ |
166
|
1 |
|
return $this->className; |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* @param string $className |
171
|
|
|
*/ |
172
|
4 |
|
public function setClassName($className) |
173
|
|
|
{ |
174
|
4 |
|
$this->className = $className; |
175
|
4 |
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* @return string |
179
|
|
|
*/ |
180
|
1 |
|
public function getClassNamespace() |
181
|
|
|
{ |
182
|
1 |
|
return $this->classNamespace; |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* @param string $classNamespace |
187
|
|
|
*/ |
188
|
4 |
|
public function setClassNamespace($classNamespace) |
189
|
|
|
{ |
190
|
4 |
|
$this->classNamespace = $classNamespace; |
191
|
4 |
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* @return string |
195
|
|
|
*/ |
196
|
3 |
|
public function getTableName() |
197
|
|
|
{ |
198
|
3 |
|
return $this->tableName; |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* @param string $tableName |
203
|
|
|
*/ |
204
|
4 |
|
public function setTableName($tableName) |
205
|
|
|
{ |
206
|
4 |
|
$this->tableName = $tableName; |
207
|
4 |
|
} |
208
|
|
|
|
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* @return array |
212
|
|
|
*/ |
213
|
1 |
|
public function getColumns() |
214
|
|
|
{ |
215
|
1 |
|
return $this->columns; |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* @return array |
220
|
|
|
*/ |
221
|
2 |
|
public function getPrimaryKeys() |
222
|
|
|
{ |
223
|
2 |
|
return $this->primaryKeys; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* @return array |
228
|
|
|
*/ |
229
|
1 |
|
public function getRelations() |
230
|
|
|
{ |
231
|
1 |
|
return $this->relations; |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
/** |
235
|
|
|
* @param string $name |
236
|
|
|
* |
237
|
|
|
* @return bool |
238
|
|
|
*/ |
239
|
1 |
|
public function hasColumn($name) |
240
|
|
|
{ |
241
|
1 |
|
return isset($this->columns[$name]); |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
/** |
245
|
|
|
* @param string $name |
246
|
|
|
* |
247
|
|
|
* @return bool |
248
|
|
|
*/ |
249
|
1 |
|
public function hasRelation($name) |
250
|
|
|
{ |
251
|
1 |
|
return isset($this->relations[$name]); |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
/** |
255
|
|
|
* @param string $name |
256
|
|
|
* |
257
|
|
|
* @return array |
258
|
|
|
*/ |
259
|
2 |
View Code Duplication |
public function getRelation($name) |
|
|
|
|
260
|
|
|
{ |
261
|
2 |
|
if (!isset($this->relations[$name])) { |
262
|
1 |
|
throw new \InvalidArgumentException('The relation with name "' . $name . '" is not found for table "' . $this->getTableName() . '"'); |
263
|
|
|
} |
264
|
|
|
|
265
|
1 |
|
return $this->relations[$name]; |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
/** |
269
|
|
|
* @param string $name |
270
|
|
|
* |
271
|
|
|
* @return array |
272
|
|
|
*/ |
273
|
2 |
View Code Duplication |
public function getColumn($name) |
|
|
|
|
274
|
|
|
{ |
275
|
2 |
|
if (!isset($this->columns[$name])) { |
276
|
1 |
|
throw new \InvalidArgumentException('The column with name "' . $name . '" is not found for table "' . $this->getTableName() . '"'); |
277
|
|
|
} |
278
|
|
|
|
279
|
1 |
|
return $this->columns[$name]; |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
/** |
283
|
|
|
* @return string |
284
|
|
|
*/ |
285
|
1 |
|
public function getDatabase() |
286
|
|
|
{ |
287
|
1 |
|
return $this->database; |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
/** |
291
|
|
|
* @param string $database |
292
|
|
|
*/ |
293
|
4 |
|
public function setDatabase($database) |
294
|
|
|
{ |
295
|
4 |
|
$this->database = $database; |
296
|
4 |
|
} |
297
|
|
|
|
298
|
|
|
/** |
299
|
|
|
* @return string |
300
|
|
|
*/ |
301
|
1 |
|
public function getConnectionName() |
302
|
|
|
{ |
303
|
1 |
|
return $this->connectionName; |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
/** |
307
|
|
|
* @param string $connectionName |
308
|
|
|
*/ |
309
|
4 |
|
public function setConnectionName($connectionName) |
310
|
|
|
{ |
311
|
4 |
|
$this->connectionName = $connectionName; |
312
|
4 |
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* @param string $stringType |
316
|
|
|
* |
317
|
|
|
* @return int |
318
|
|
|
*/ |
319
|
1 |
|
public static function convertColumnTypeToConstant($stringType) |
320
|
|
|
{ |
321
|
1 |
|
switch (strtolower($stringType)) { |
322
|
1 |
|
case 'boolean': return self::COLUMN_TYPE_BOOLEAN; |
|
|
|
|
323
|
1 |
|
case 'text': return self::COLUMN_TYPE_TEXT; |
|
|
|
|
324
|
1 |
|
case 'varchar': return self::COLUMN_TYPE_STRING; |
|
|
|
|
325
|
1 |
|
case 'integer': return self::COLUMN_TYPE_INTEGER; |
|
|
|
|
326
|
1 |
|
case 'double': return self::COLUMN_TYPE_DOUBLE; |
|
|
|
|
327
|
1 |
|
case 'float': return self::COLUMN_TYPE_FLOAT; |
|
|
|
|
328
|
1 |
|
case 'date': return self::COLUMN_TYPE_DATE; |
|
|
|
|
329
|
1 |
|
case 'datetime': return self::COLUMN_TYPE_DATETIME; |
|
|
|
|
330
|
1 |
|
case 'enum': return self::COLUMN_TYPE_ENUM; |
|
|
|
|
331
|
1 |
|
} |
332
|
|
|
|
333
|
1 |
|
throw new \InvalidArgumentException('Invalid column type for value "' . $stringType . '"'); |
334
|
|
|
} |
335
|
|
|
} |
336
|
|
|
|
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.