1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Created by Gorlum 12.07.2017 10:27 |
4
|
|
|
*/ |
5
|
|
|
|
6
|
|
|
namespace DBAL; |
7
|
|
|
|
8
|
|
|
use Common\AccessLogged; |
9
|
|
|
use Common\GlobalContainer; |
10
|
|
|
use Exceptions\DbalFieldInvalidException; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Class ActiveRecordAbstract |
14
|
|
|
* @package DBAL |
15
|
|
|
* |
16
|
|
|
* Adds some DB functionality |
17
|
|
|
*/ |
18
|
|
|
abstract class ActiveRecordAbstract extends AccessLogged { |
19
|
|
|
const FIELDS_TO_PROPERTIES = true; |
20
|
|
|
const PROPERTIES_TO_FIELDS = false; |
21
|
|
|
|
22
|
|
|
const IGNORE_PREFIX = 'Record'; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @var \db_mysql $db |
26
|
|
|
*/ |
27
|
|
|
protected static $db; |
28
|
|
|
/** |
29
|
|
|
* Table name for current Active Record |
30
|
|
|
* |
31
|
|
|
* Can be predefined in class or calculated in run-time |
32
|
|
|
* |
33
|
|
|
* ALWAYS SHOULD BE OVERRIDEN IN CHILD CLASSES! |
34
|
|
|
* |
35
|
|
|
* @var string $_tableName |
36
|
|
|
*/ |
37
|
|
|
protected static $_tableName = ''; |
38
|
|
|
/** |
39
|
|
|
* Field name translations to property names |
40
|
|
|
* |
41
|
|
|
* @var string[] $_fieldsToProperties |
42
|
|
|
*/ |
43
|
|
|
protected static $_fieldsToProperties = []; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @var bool $_forUpdate |
47
|
|
|
*/ |
48
|
|
|
protected static $_forUpdate = DbQuery::DB_SHARED; |
49
|
|
|
|
50
|
|
|
// AR's service fields |
51
|
|
|
/** |
52
|
|
|
* Is this field - new field? |
53
|
|
|
* |
54
|
|
|
* @var bool $_isNew |
55
|
|
|
*/ |
56
|
|
|
protected $_isNew = true; |
57
|
|
|
|
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Get table name |
61
|
|
|
* |
62
|
|
|
* @return string |
63
|
|
|
*/ |
64
|
1 |
|
public static function tableName() { |
65
|
1 |
|
empty(static::$_tableName) ? static::$_tableName = static::calcTableName() : false; |
66
|
|
|
|
67
|
1 |
|
return static::$_tableName; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* @param \db_mysql $db |
72
|
|
|
*/ |
73
|
1 |
|
public static function setDb(\db_mysql $db) { |
74
|
1 |
|
static::$db = $db; |
75
|
1 |
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Get DB |
79
|
|
|
* |
80
|
|
|
* @return \db_mysql |
81
|
|
|
*/ |
82
|
1 |
|
public static function db() { |
83
|
1 |
|
empty(static::$db) ? static::$db = \classSupernova::services()->db : false; |
84
|
|
|
|
85
|
1 |
|
return static::$db; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Instate ActiveRecord from array of field values - even if it is empty |
90
|
|
|
* |
91
|
|
|
* @param array $properties List of field values [$propertyName => $propertyValue] |
92
|
|
|
* |
93
|
|
|
* @return static |
94
|
|
|
*/ |
95
|
1 |
|
public static function buildEvenEmpty(array $properties = []) { |
96
|
1 |
|
$record = new static(); |
97
|
1 |
|
$record->fromProperties($properties); |
98
|
|
|
|
99
|
1 |
|
return $record; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* Instate ActiveRecord from array of field values |
104
|
|
|
* |
105
|
|
|
* @param array $properties List of field values [$propertyName => $propertyValue] |
106
|
|
|
* |
107
|
|
|
* @return static|bool |
108
|
|
|
*/ |
109
|
1 |
|
public static function build(array $properties = []) { |
110
|
1 |
|
if (!is_array($properties) || empty($properties)) { |
111
|
1 |
|
return false; |
112
|
|
|
} |
113
|
|
|
|
114
|
1 |
|
return static::buildEvenEmpty($properties); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* Set flag "for update" |
119
|
|
|
* |
120
|
|
|
* @param bool $forUpdate - DbQuery::DB_FOR_UPDATE | DbQuery::DB_SHARED |
121
|
|
|
*/ |
122
|
|
|
public static function setForUpdate($forUpdate = DbQuery::DB_FOR_UPDATE) { |
123
|
|
|
static::$_forUpdate = $forUpdate; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Finds records by property - equivalent of SELECT ... WHERE ... AND ... |
128
|
|
|
* |
129
|
|
|
* @param array $propertyFilter - [$propertyName => $propertyValue]. Pass [] to find all records in table |
130
|
|
|
* |
131
|
|
|
* @return bool|\mysqli_result |
132
|
|
|
*/ |
133
|
|
|
public static function find($propertyFilter) { |
134
|
|
|
$dbq = static::dbPrepareQuery(); |
135
|
|
|
if (!empty($propertyFilter)) { |
136
|
|
|
$dbq->setWhereArray(static::translateNames($propertyFilter, static::PROPERTIES_TO_FIELDS)); |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
if(static::$_forUpdate == DbQuery::DB_FOR_UPDATE) { |
140
|
|
|
$dbq->setForUpdate(); |
141
|
|
|
static::$_forUpdate = DbQuery::DB_SHARED; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
return $dbq->doSelect(); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Gets first record by $where |
149
|
|
|
* |
150
|
|
|
* @param array $propertyFilter - [$propertyName => $propertyValue]. Pass [] to find all records in table |
151
|
|
|
* |
152
|
|
|
* @return string[] - [$field_name => $field_value] |
153
|
|
|
*/ |
154
|
|
|
public static function findRecordFirst($propertyFilter) { |
155
|
|
|
$result = empty($mysqliResult = static::find($propertyFilter)) ? [] : $mysqliResult->fetch_assoc(); |
156
|
|
|
|
157
|
|
|
// Secondary check - for fetch_assoc() result |
158
|
|
|
return empty($result) ? [] : $result; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* Gets all records by $where |
163
|
|
|
* |
164
|
|
|
* @param array $propertyFilter - [$propertyName => $propertyValue]. Pass [] to find all records in table |
165
|
|
|
* |
166
|
|
|
* @return array[] - [(int) => [$field_name => $field_value]] |
167
|
|
|
*/ |
168
|
|
|
public static function findRecordsAll($propertyFilter) { |
169
|
|
|
return empty($mysqliResult = static::find($propertyFilter)) ? [] : $mysqliResult->fetch_all(MYSQLI_ASSOC); |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
/** |
173
|
|
|
* Gets first ActiveRecord by $where |
174
|
|
|
* |
175
|
|
|
* @param array $propertyFilter - [$propertyName => $propertyValue]. Pass [] to find all records in table |
176
|
|
|
* |
177
|
|
|
* @return static|bool |
178
|
|
|
*/ |
179
|
|
|
public static function findFirst($propertyFilter) { |
180
|
|
|
$record = false; |
181
|
|
|
$fields = static::findRecordFirst($propertyFilter); |
182
|
|
|
if (!empty($fields)) { |
183
|
|
|
$record = static::build(static::translateNames($fields, self::FIELDS_TO_PROPERTIES)); |
184
|
|
|
if (is_object($record)) { |
185
|
|
|
$record->_isNew = false; |
186
|
|
|
} |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
return $record; |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* Gets all ActiveRecords by $where |
194
|
|
|
* |
195
|
|
|
* @param array $propertyFilter - [$propertyName => $propertyValue]. Pass [] to find all records in table |
196
|
|
|
* |
197
|
|
|
* @return array|static[] - [(int) => static] |
198
|
|
|
*/ |
199
|
|
|
public static function findAll($propertyFilter) { |
200
|
|
|
return static::fromRecordList(static::findRecordsAll($propertyFilter)); |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* ActiveRecord constructor. |
206
|
|
|
* |
207
|
|
|
* @param GlobalContainer|null $services |
208
|
|
|
*/ |
209
|
1 |
|
public function __construct(GlobalContainer $services = null) { |
210
|
1 |
|
parent::__construct($services); |
211
|
1 |
|
} |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* @return bool |
215
|
|
|
*/ |
216
|
|
|
// TODO - do a check that all fields present in stored data. I.e. no empty fields with no defaults |
217
|
|
|
public function insert() { |
218
|
|
|
if ($this->isEmpty()) { |
219
|
|
|
return false; |
220
|
|
|
} |
221
|
|
|
if (!$this->_isNew) { |
222
|
|
|
return false; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
$this->defaultValues(); |
226
|
|
|
|
227
|
|
|
if (!$this->dbInsert()) { |
228
|
|
|
return false; |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
$this->acceptChanges(); |
232
|
|
|
$this->_isNew = false; |
233
|
|
|
|
234
|
|
|
return true; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
/** |
238
|
|
|
* Normalize array |
239
|
|
|
* |
240
|
|
|
* Basically - uppercase all field names to make it use in PTL |
241
|
|
|
* Can be override by descendants to make more convinient, clear and robust indexes |
242
|
|
|
* |
243
|
|
|
* @return array |
244
|
|
|
*/ |
245
|
|
|
public function ptlArray() { |
246
|
|
|
$result = []; |
247
|
|
|
foreach ($this->values as $key => $value) { |
248
|
|
|
$result[strtoupper(\HelperString::camelToUnderscore($key))] = $value; |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
return $result; |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
/** |
255
|
|
|
* Get default value for field |
256
|
|
|
* |
257
|
|
|
* @param string $propertyName |
258
|
|
|
* |
259
|
|
|
* @return mixed |
260
|
|
|
*/ |
261
|
2 |
|
public function getDefault($propertyName) { |
262
|
2 |
|
$fieldName = self::getFieldName($propertyName); |
263
|
|
|
|
264
|
|
|
return |
265
|
2 |
|
isset(static::dbGetFieldsDescription()[$fieldName]->Default) |
266
|
2 |
|
? static::dbGetFieldsDescription()[$fieldName]->Default |
267
|
2 |
|
: null; |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* Returns default value if original value not set |
272
|
|
|
* |
273
|
|
|
* @param string $propertyName |
274
|
|
|
* |
275
|
|
|
* @return mixed |
276
|
|
|
*/ |
277
|
1 |
|
public function __get($propertyName) { |
278
|
1 |
|
return $this->__isset($propertyName) ? parent::__get($propertyName) : $this->getDefault($propertyName); |
279
|
|
|
} |
280
|
|
|
|
281
|
1 |
|
public function __set($propertyName, $value) { |
282
|
1 |
|
$this->shieldName($propertyName); |
283
|
1 |
|
parent::__set($propertyName, $value); |
284
|
1 |
|
} |
285
|
|
|
|
286
|
|
|
|
287
|
|
|
/** |
288
|
|
|
* Calculate table name by class name and fills internal property |
289
|
|
|
* |
290
|
|
|
* Namespaces does not count - only class name taken into account |
291
|
|
|
* Class name converted from CamelCase to underscore_name |
292
|
|
|
* Prefix "Record" is ignored - can be override |
293
|
|
|
* |
294
|
|
|
* Examples: |
295
|
|
|
* Class \Namespace\ClassName will map to table `class_name` |
296
|
|
|
* Class \NameSpace\RecordLongName will map to table `long_name` |
297
|
|
|
* |
298
|
|
|
* Can be overriden to provide different name |
299
|
|
|
* |
300
|
|
|
* @return string - table name in DB |
301
|
|
|
* |
302
|
|
|
*/ |
303
|
1 |
|
protected static function calcTableName() { |
304
|
1 |
|
$temp = explode('\\', get_called_class()); |
305
|
1 |
|
$className = end($temp); |
306
|
1 |
|
if (strpos($className, static::IGNORE_PREFIX) === 0) { |
307
|
1 |
|
$className = substr($className, strlen(static::IGNORE_PREFIX)); |
308
|
1 |
|
} |
309
|
|
|
|
310
|
1 |
|
return \HelperString::camelToUnderscore($className); |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
/** |
314
|
|
|
* Get table fields description |
315
|
|
|
* |
316
|
|
|
* @return DbFieldDescription[] |
317
|
|
|
*/ |
318
|
|
|
protected static function dbGetFieldsDescription() { |
319
|
|
|
return static::db()->schema()->getTableSchema(static::tableName())->fieldsObject; |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
/** |
323
|
|
|
* Prepares DbQuery object for further operations |
324
|
|
|
* |
325
|
|
|
* @return DbQuery |
326
|
|
|
*/ |
327
|
1 |
|
protected static function dbPrepareQuery() { |
328
|
1 |
|
return DbQuery::build(static::db())->setTable(static::tableName()); |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
/** |
332
|
|
|
* Is there translation for this field name to property name |
333
|
|
|
* |
334
|
|
|
* @param string $fieldName |
335
|
|
|
* |
336
|
|
|
* @return bool |
337
|
|
|
*/ |
338
|
1 |
|
protected static function haveTranslationToProperty($fieldName) { |
339
|
1 |
|
return !empty(static::$_fieldsToProperties[$fieldName]); |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
/** |
343
|
|
|
* Check if field exists |
344
|
|
|
* |
345
|
|
|
* @param string $fieldName |
346
|
|
|
* |
347
|
|
|
* @return bool |
348
|
|
|
*/ |
349
|
1 |
|
protected static function haveField($fieldName) { |
350
|
1 |
|
return !empty(static::dbGetFieldsDescription()[$fieldName]); |
351
|
|
|
} |
352
|
|
|
|
353
|
|
|
/** |
354
|
|
|
* Returns field name by property name |
355
|
|
|
* |
356
|
|
|
* @param string $propertyName |
357
|
|
|
* |
358
|
|
|
* @return string Field name for property or '' if not field |
359
|
|
|
*/ |
360
|
4 |
|
protected static function getFieldName($propertyName) { |
361
|
4 |
|
$fieldName = array_search($propertyName, static::$_fieldsToProperties); |
362
|
|
|
if ( |
363
|
|
|
// No translation found for property name |
364
|
|
|
$fieldName === false |
365
|
4 |
|
&& |
366
|
|
|
// AND Property name is not among translatable field names |
367
|
3 |
|
!static::haveTranslationToProperty($propertyName) |
368
|
4 |
|
&& |
369
|
|
|
// AND field name exists |
370
|
2 |
|
static::haveField($propertyName) |
371
|
4 |
|
) { |
372
|
|
|
// Returning property name as field name |
373
|
1 |
|
$fieldName = $propertyName; |
374
|
1 |
|
} |
375
|
|
|
|
376
|
4 |
|
return $fieldName === false ? '' : $fieldName; |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
/** |
380
|
|
|
* Does property exists? |
381
|
|
|
* |
382
|
|
|
* @param string $propertyName |
383
|
|
|
* |
384
|
|
|
* @return bool |
385
|
|
|
*/ |
386
|
1 |
|
protected static function haveProperty($propertyName) { |
387
|
1 |
|
return !empty(static::getFieldName($propertyName)); |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
/** |
391
|
|
|
* Translate field name to property name |
392
|
|
|
* |
393
|
|
|
* @param string $fieldName |
394
|
|
|
* |
395
|
|
|
* @return string Property name for field if field exists or '' otherwise |
396
|
|
|
*/ |
397
|
4 |
|
protected static function getPropertyName($fieldName) { |
398
|
|
|
return |
399
|
|
|
// If there translation of field name = returning translation result |
400
|
4 |
|
static::haveTranslationToProperty($fieldName) |
401
|
4 |
|
? static::$_fieldsToProperties[$fieldName] |
402
|
|
|
// No, there is no translation |
403
|
|
|
// Is field exists in table? If yes - returning field name as property name |
404
|
4 |
|
: (static::haveField($fieldName) ? $fieldName : ''); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
/** |
408
|
|
|
* Converts property-indexed value array to field-indexed via translation table |
409
|
|
|
* |
410
|
|
|
* @param array $names |
411
|
|
|
* @param bool $fieldToProperties - translation direction: |
412
|
|
|
* - self::FIELDS_TO_PROPERTIES - field to props. |
413
|
|
|
* - self::PROPERTIES_TO_FIELDS - prop to fields |
414
|
|
|
* |
415
|
|
|
* @return array |
416
|
|
|
*/ |
417
|
|
|
// TODO - Throw exception on incorrect field |
418
|
1 |
|
protected static function translateNames(array $names, $fieldToProperties = self::FIELDS_TO_PROPERTIES) { |
419
|
1 |
|
$result = []; |
420
|
1 |
|
foreach ($names as $name => $value) { |
421
|
1 |
|
$exists = $fieldToProperties == self::FIELDS_TO_PROPERTIES ? static::haveField($name) : static::haveProperty($name); |
422
|
1 |
|
if (!$exists) { |
423
|
1 |
|
continue; |
424
|
|
|
} |
425
|
|
|
|
426
|
|
|
$name = |
427
|
|
|
$fieldToProperties == self::FIELDS_TO_PROPERTIES |
428
|
1 |
|
? static::getPropertyName($name) |
429
|
1 |
|
: static::getFieldName($name); |
430
|
1 |
|
$result[$name] = $value; |
431
|
1 |
|
} |
432
|
|
|
|
433
|
1 |
|
return $result; |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
/** |
437
|
|
|
* Makes array of object from field/property list array |
438
|
|
|
* |
439
|
|
|
* Empty records and non-records (non-subarrays) are ignored |
440
|
|
|
* Function maintains record indexes |
441
|
|
|
* |
442
|
|
|
* @param array[] $records - array of DB records [(int) => [$name => $value]] |
443
|
|
|
* @param bool $fieldToProperties - should names be translated (true - for field records, false - for property records) |
444
|
|
|
* |
445
|
|
|
* @return array|static[] |
446
|
|
|
*/ |
447
|
1 |
|
protected static function fromRecordList($records, $fieldToProperties = self::FIELDS_TO_PROPERTIES) { |
448
|
1 |
|
$result = []; |
449
|
1 |
|
if (is_array($records) && !empty($records)) { |
450
|
1 |
|
foreach ($records as $key => $recordArray) { |
451
|
1 |
|
if (!is_array($recordArray) || empty($recordArray)) { |
452
|
1 |
|
continue; |
453
|
|
|
} |
454
|
|
|
|
455
|
|
|
$fieldToProperties === self::FIELDS_TO_PROPERTIES |
456
|
1 |
|
? $recordArray = static::translateNames($recordArray, self::FIELDS_TO_PROPERTIES) |
457
|
1 |
|
: false; |
458
|
|
|
|
459
|
1 |
|
$theRecord = static::build($recordArray); |
460
|
1 |
|
if (is_object($theRecord)) { |
461
|
1 |
|
$theRecord->_isNew = false; |
462
|
|
|
// if(!empty($theRecord->id)) { |
|
|
|
|
463
|
|
|
// $key = $theRecord->id; |
464
|
|
|
// } |
465
|
1 |
|
$result[$key] = $theRecord; |
466
|
1 |
|
} |
467
|
1 |
|
} |
468
|
1 |
|
} |
469
|
|
|
|
470
|
1 |
|
return $result; |
471
|
|
|
} |
472
|
|
|
|
473
|
1 |
|
protected function defaultValues() { |
474
|
1 |
|
foreach (static::dbGetFieldsDescription() as $fieldName => $fieldData) { |
475
|
1 |
|
if (array_key_exists($propertyName = static::getPropertyName($fieldName), $this->values)) { |
476
|
1 |
|
continue; |
477
|
|
|
} |
478
|
|
|
|
479
|
|
|
// Skipping auto increment fields |
480
|
1 |
|
if (strpos($fieldData->Extra, SN_SQL_EXTRA_AUTO_INCREMENT) !== false) { |
481
|
1 |
|
continue; |
482
|
|
|
} |
483
|
|
|
|
484
|
1 |
|
if ($fieldData->Type == SN_SQL_TYPE_NAME_TIMESTAMP && $fieldData->Default == SN_SQL_DEFAULT_CURRENT_TIMESTAMP) { |
485
|
1 |
|
$this->__set($propertyName, SN_TIME_SQL); |
486
|
1 |
|
continue; |
487
|
|
|
} |
488
|
|
|
|
489
|
1 |
|
$this->__set($propertyName, $fieldData->Default); |
490
|
1 |
|
} |
491
|
1 |
|
} |
492
|
|
|
|
493
|
|
|
/** |
494
|
|
|
* Set AR properties from array of PROPERTIES |
495
|
|
|
* |
496
|
|
|
* DOES NOT override existing values |
497
|
|
|
* DOES set default values for empty fields |
498
|
|
|
* |
499
|
|
|
* @param array $properties |
500
|
|
|
*/ |
501
|
1 |
|
protected function fromProperties(array $properties) { |
502
|
1 |
|
foreach ($properties as $name => $value) { |
503
|
1 |
|
$this->__set($name, $value); |
504
|
1 |
|
} |
505
|
|
|
|
506
|
1 |
|
$this->defaultValues(); |
507
|
1 |
|
} |
508
|
|
|
|
509
|
|
|
/** |
510
|
|
|
* Set AR properties from array of FIELDS |
511
|
|
|
* |
512
|
|
|
* DOES NOT override existing values |
513
|
|
|
* DOES set default values for empty fields |
514
|
|
|
* |
515
|
|
|
* @param array $fields List of field values [$fieldName => $fieldValue] |
516
|
|
|
*/ |
517
|
1 |
|
protected function fromFields(array $fields) { |
518
|
1 |
|
$this->fromProperties(static::translateNames($fields, self::FIELDS_TO_PROPERTIES)); |
519
|
1 |
|
} |
520
|
|
|
|
521
|
|
|
/** |
522
|
|
|
* @return bool |
523
|
|
|
*/ |
524
|
|
|
protected function dbInsert() { |
525
|
|
|
return |
526
|
|
|
static::dbPrepareQuery() |
527
|
|
|
->setValues(static::translateNames($this->values, self::PROPERTIES_TO_FIELDS)) |
528
|
|
|
->doInsert(); |
529
|
|
|
} |
530
|
|
|
|
531
|
|
|
/** |
532
|
|
|
* Protects object from setting non-existing property |
533
|
|
|
* |
534
|
|
|
* @param string $propertyName |
535
|
|
|
* |
536
|
|
|
* @throws DbalFieldInvalidException |
537
|
|
|
*/ |
538
|
2 |
|
protected function shieldName($propertyName) { |
539
|
2 |
|
if (!self::haveProperty($propertyName)) { |
540
|
1 |
|
throw new DbalFieldInvalidException(sprintf( |
541
|
1 |
|
'{{{ Свойство \'%1$s\' не существует в ActiveRecord \'%2$s\' }}}', $propertyName, get_called_class() |
542
|
1 |
|
)); |
543
|
|
|
} |
544
|
2 |
|
} |
545
|
|
|
|
546
|
|
|
} |
547
|
|
|
|
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.