Completed
Push — master ( 3029f1...135fa8 )
by Alexey
05:33
created

Model   D

Complexity

Total Complexity 399

Size/Duplication

Total Lines 1827
Duplicated Lines 13.74 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 8
Bugs 3 Features 1
Metric Value
c 8
b 3
f 1
dl 251
loc 1827
rs 4.4102
wmc 399
lcom 1
cbo 6

56 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A objectName() 0 4 1
C getColValue() 0 22 8
D resloveTypeValue() 30 102 36
C fixPrefix() 13 59 25
C checkForJoin() 10 27 7
A getColInfo() 0 4 1
C parseColRecursion() 15 47 12
B cols() 7 14 5
A indexes() 0 4 1
C genColParams() 0 49 18
A createCol() 0 8 2
C createTable() 0 55 13
A table() 0 4 1
A index() 0 5 1
A colPrefix() 0 6 1
A relations() 0 4 1
A nameCol() 0 4 1
A name() 0 4 2
F get() 0 68 19
F get_list() 35 87 23
B getList() 0 16 5
C getFromModuleStorage() 13 40 12
D getListFromModuleStorage() 22 53 18
C getCountFromModuleStorage() 5 32 8
D checkWhere() 0 28 10
B update() 0 22 5
A pk() 0 4 1
A beforeSave() 0 4 1
D saveModuleStorage() 31 52 13
B changeCategoryTree() 0 26 2
A getCatalogTree() 0 13 4
A changeItemTree() 0 11 2
D save() 0 57 15
A afterSave() 0 4 1
A beforeDelete() 0 4 1
F deleteFromModuleStorage() 32 45 11
A delete() 0 17 4
A deleteList() 0 8 2
A afterDelete() 0 4 1
A findRelation() 0 9 3
B setParams() 0 22 6
A getRelation() 0 5 2
F loadRelation() 0 88 38
A addRelation() 0 16 3
A checkFormAccess() 0 7 3
A checkAccess() 0 7 2
A __call() 5 11 3
A __get() 0 12 3
A value() 5 11 3
A managerFilters() 0 4 1
A validators() 0 4 1
A validator() 0 8 2
C __set() 0 24 8
A __isset() 0 5 1
A __toString() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Model often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Model, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Log
5
 *
6
 * @author Alexey Krupskiy <[email protected]>
7
 * @link http://inji.ru/
8
 * @copyright 2015 Alexey Krupskiy
9
 * @license https://github.com/injitools/cms-Inji/blob/master/LICENSE
10
 */
11
class Model
12
{
13
    /**
14
     * Object storage type
15
     * 
16
     * @var array 
17
     */
18
    public static $storage = ['type' => 'db'];
19
20
    /**
21
     * Object name
22
     * 
23
     * @var string 
24
     */
25
    public static $objectName = '';
26
27
    /**
28
     * App type for separate data storage
29
     * 
30
     * @var string
31
     */
32
    public $appType = 'app';
33
34
    /**
35
     * Object current params
36
     * 
37
     * @var array
38
     */
39
    public $_params = [];
40
41
    /**
42
     * List of changed params in current instance
43
     * 
44
     * @var array
45
     */
46
    public $_changedParams = [];
47
48
    /**
49
     * Loaded relations
50
     * 
51
     * @var array 
52
     */
53
    public $loadedRelations = [];
54
55
    /**
56
     * Model name where this model uses as category
57
     * 
58
     * @var string
59
     */
60
    public static $treeCategory = '';
61
62
    /**
63
     * Model name who uses as category in this model
64
     * 
65
     * @var string
66
     */
67
    public static $categoryModel = '';
68
69
    /**
70
     * Col labels
71
     * 
72
     * @var array
73
     */
74
    public static $labels = [];
75
76
    /**
77
     * Model forms
78
     * 
79
     * @var array
80
     */
81
    public static $forms = [];
82
83
    /**
84
     * Model cols
85
     * 
86
     * @var array
87
     */
88
    public static $cols = [];
89
90
    /**
91
     * Options group for display inforamtion from model
92
     * 
93
     * @var array
94
     */
95
    public static $view = [];
96
97
    /**
98
     * List of relations need loaded with item
99
     * 
100
     * @var array 
101
     */
102
    public static $needJoin = [];
103
104
    /**
105
     * List of joins who need to laod
106
     * 
107
     * @var array 
108
     */
109
    public static $relJoins = [];
110
111
    /**
112
     * Set params when model create
113
     * 
114
     * @param array $params
115
     */
116
    public function __construct($params = [])
117
    {
118
        $this->setParams($params);
119
    }
120
121
    /**
122
     * return object name
123
     * 
124
     * @return string
125
     */
126
    public static function objectName()
127
    {
128
        return static::$objectName;
129
    }
130
131
    /**
132
     * Retrn col value with col params and relations path
133
     * 
134
     * @param Model $object
135
     * @param string $valuePath
136
     * @param boolean $convert
137
     * @param boolean $manageHref
138
     * @return string
139
     */
140
    public static function getColValue($object, $valuePath, $convert = false, $manageHref = false)
141
    {
142
        if (strpos($valuePath, ':')) {
143
            $rel = substr($valuePath, 0, strpos($valuePath, ':'));
144
            $param = substr($valuePath, strpos($valuePath, ':') + 1);
145
            if (!$object->$rel) {
146
                $modelName = get_class($object);
147
                $relations = $modelName::relations();
148
                if (empty($relations[$rel]['type']) || $relations[$rel]['type'] == 'one') {
149
                    return $object->{$relations[$rel]['col']};
150
                }
151
                return 0;
152
            }
153
            if (strpos($valuePath, ':')) {
154
                return self::getColValue($object->$rel, $param, $convert, $manageHref);
155
            } else {
156
                return $convert ? Model::resloveTypeValue($object->$rel, $param, $manageHref) : $object->$rel->$param;
157
            }
158
        } else {
159
            return $convert ? Model::resloveTypeValue($object, $valuePath, $manageHref) : $object->$valuePath;
160
        }
161
    }
162
163
    /**
164
     * Retrun value for view
165
     * 
166
     * @param Model $item
167
     * @param string $colName
168
     * @param boolean $manageHref
169
     * @return string
170
     */
171
    public static function resloveTypeValue($item, $colName, $manageHref = false)
172
    {
173
        $modelName = get_class($item);
174
        $colInfo = $modelName::getColInfo($colName);
175
        $type = !empty($colInfo['colParams']['type']) ? $colInfo['colParams']['type'] : 'string';
176
        $value = '';
177
        switch ($type) {
178
            case 'select':
179
                switch ($colInfo['colParams']['source']) {
180
                    case 'model':
181
                        $sourceValue = '';
182
                        if ($item->$colName) {
183
                            $sourceValue = $colInfo['colParams']['model']::get($item->$colName);
184
                        }
185
                        $value = $sourceValue ? $sourceValue->name() : 'Не задано';
186
                        break;
187
                    case 'array':
188
                        $value = !empty($colInfo['colParams']['sourceArray'][$item->$colName]) ? $colInfo['colParams']['sourceArray'][$item->$colName] : 'Не задано';
189
                        if (is_array($value) && $value['text']) {
190
                            $value = $value['text'];
191
                        }
192
                        break;
193
                    case 'bool':
194
                        return $item->$colName ? 'Да' : 'Нет';
195 View Code Duplication
                    case 'method':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
196
                        if (!empty($colInfo['colParams']['params'])) {
197
                            $values = call_user_func_array([App::$cur->$colInfo['colParams']['module'], $colInfo['colParams']['method']], $colInfo['colParams']['params']);
198
                        } else {
199
                            $values = $colInfo['colParams']['module']->$colInfo['colParams']['method']();
200
                        }
201
                        $value = !empty($values[$item->$colName]) ? $values[$item->$colName] : 'Не задано';
202
                        break;
203
                    case 'void':
204
                        if (!empty($modelName::$cols[$colName]['value']['type']) && $modelName::$cols[$colName]['value']['type'] == 'moduleMethod') {
205
                            return \App::$cur->{$modelName::$cols[$colName]['value']['module']}->{$modelName::$cols[$colName]['value']['method']}($item, $colName, $modelName::$cols[$colName]);
206
                        }
207
                        break;
208
                    case 'relation':
209
                        $relations = $colInfo['modelName']::relations();
210
                        $relValue = $relations[$colInfo['colParams']['relation']]['model']::get($item->$colName);
211
                        $relModel = $relations[$colInfo['colParams']['relation']]['model'];
212
                        $relModel = strpos($relModel, '\\') === 0 ? substr($relModel, 1) : $relModel;
213
                        if ($manageHref) {
214
                            $value = $relValue ? "<a href='/admin/" . str_replace('\\', '/view/', $relModel) . "/" . $relValue->pk() . "'>" . $relValue->name() . "</a>" : 'Не задано';
215
                        } else {
216
                            $value = $relValue ? $relValue->name() : 'Не задано';
217
                        }
218
                        break;
219
                }
220
                break;
221 View Code Duplication
            case 'image':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
222
                $file = Files\File::get($item->$colName);
223
                if ($file) {
224
                    $value = '<img src="' . $file->path . '?resize=60x120" />';
225
                } else {
226
                    $value = '<img src="/static/system/images/no-image.png?resize=60x120" />';
227
                }
228
                break;
229
            case 'bool':
230
                $value = $item->$colName ? 'Да' : 'Нет';
231
                break;
232
            case 'void':
233
                if (!empty($colInfo['colParams']['value']['type']) && $colInfo['colParams']['value']['type'] == 'moduleMethod') {
234
                    return \App::$cur->{$colInfo['colParams']['value']['module']}->{$colInfo['colParams']['value']['method']}($item, $colName, $colInfo['colParams']);
235
                }
236
                break;
237
            case 'dynamicType':
238
                switch ($colInfo['colParams']['typeSource']) {
239
                    case'selfMethod':
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
240
                        $type = $item->{$colInfo['colParams']['selfMethod']}();
241
                        if (is_array($type)) {
242 View Code Duplication
                            if (strpos($type['relation'], ':')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
243
                                $relationPath = explode(':', $type['relation']);
244
                                $relationName = array_pop($relationPath);
245
                                $curItem = $item;
246
                                foreach ($relationPath as $path) {
247
                                    $curItem = $curItem->$path;
248
                                }
249
                                $itemModel = get_class($curItem);
250
                                $relation = $itemModel::getRelation($relationName);
251
                                $sourceModel = $relation['model'];
252
                            } else {
253
                                $relation = static::getRelation($type['relation']);
254
                                $sourceModel = $relation['model'];
255
                            }
256
                            $inputType = 'select';
0 ignored issues
show
Unused Code introduced by
$inputType is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
257
                            $value = $sourceModel::get($item->$colName);
258
                            if ($value) {
259
                                $value = $value->name();
260
                            } else {
261
                                $value = $item->$colName;
262
                            }
263
                        }
264
                        break;
265
                }
266
                break;
267
            default:
268
                $value = $item->$colName;
269
                break;
270
        }
271
        return $value;
272
    }
273
274
    /**
275
     * Fix col prefix
276
     * 
277
     * @param mixed $array
278
     * @param string $searchtype
279
     * @param string $rootModel
280
     * @return null
281
     */
282
    public static function fixPrefix(&$array, $searchtype = 'key', $rootModel = '')
283
    {
284
        if (!$rootModel) {
285
            $rootModel = get_called_class();
286
        }
287
        $cols = static::cols();
288
        if (!$array) {
289
            return;
290
        }
291
        if (!is_array($array)) {
292 View Code Duplication
            if (!isset($cols[static::colPrefix() . $array]) && isset(static::$cols[$array])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
293
                static::createCol($array);
294
                $cols = static::cols(true);
295
            }
296
            if (!isset($cols[$array]) && isset($cols[static::colPrefix() . $array])) {
297
                $array = static::colPrefix() . $array;
298
            } else {
299
                static::checkForJoin($array, $rootModel);
300
            }
301
            return;
302
        }
303
        switch ($searchtype) {
304
            case 'key':
305
                foreach ($array as $key => $item) {
306 View Code Duplication
                    if (!isset($cols[static::colPrefix() . $key]) && isset(static::$cols[$key])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
307
                        static::createCol($key);
308
                        $cols = static::cols(true);
309
                    }
310
                    if (!isset($cols[$key]) && isset($cols[static::colPrefix() . $key])) {
311
                        $array[static::colPrefix() . $key] = $item;
312
                        unset($array[$key]);
313
                        $key = static::colPrefix() . $key;
314
                    }
315
                    if (is_array($array[$key])) {
316
                        static::fixPrefix($array[$key], 'key', $rootModel);
317
                    } else {
318
                        static::checkForJoin($key, $rootModel);
319
                    }
320
                }
321
                break;
322
            case 'first':
323
                if (isset($array[0]) && is_string($array[0])) {
324
                    if (!isset($cols[static::colPrefix() . $array[0]]) && isset(static::$cols[$array[0]])) {
325
                        static::createCol($array[0]);
326
                        $cols = static::cols(true);
327
                    }
328 View Code Duplication
                    if (!isset($cols[$array[0]]) && isset($cols[static::colPrefix() . $array[0]])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
329
                        $array[0] = static::colPrefix() . $array[0];
330
                    } else {
331
                        static::checkForJoin($array[0], $rootModel);
332
                    }
333
                } elseif (isset($array[0]) && is_array($array[0])) {
334
                    foreach ($array as &$item) {
335
                        static::fixPrefix($item, 'first', $rootModel);
336
                    }
337
                }
338
                break;
339
        }
340
    }
341
342
    /**
343
     * Check model relations path and load need relations
344
     * 
345
     * @param string $col
346
     * @param string $rootModel
347
     */
348
    public static function checkForJoin(&$col, $rootModel)
349
    {
350
351
        if (strpos($col, ':') !== false) {
352
            $relations = static::relations();
353
            if (isset($relations[substr($col, 0, strpos($col, ':'))])) {
354
                $rel = substr($col, 0, strpos($col, ':'));
355
                $col = substr($col, strpos($col, ':') + 1);
356
357
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
358
                switch ($type) {
359 View Code Duplication
                    case 'to':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
360
                        $relCol = $relations[$rel]['col'];
361
                        static::fixPrefix($relCol);
362
                        $rootModel::$relJoins[$relations[$rel]['model'] . '_' . $rel] = [$relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol];
363
                        break;
364
                    case 'one':
365 View Code Duplication
                    case 'many':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
366
                        $relCol = $relations[$rel]['col'];
367
                        $relations[$rel]['model']::fixPrefix($relCol);
368
                        $rootModel::$relJoins[$relations[$rel]['model'] . '_' . $rel] = [$relations[$rel]['model']::table(), static::index() . ' = ' . $relCol];
369
                        break;
370
                }
371
                $relations[$rel]['model']::fixPrefix($col, 'key', $rootModel);
372
            }
373
        }
374
    }
375
376
    /**
377
     * Return full col information
378
     * 
379
     * @param string $col
380
     * @return array
381
     */
382
    public static function getColInfo($col)
383
    {
384
        return static::parseColRecursion($col);
385
    }
386
387
    /**
388
     * Information extractor for col relations path
389
     * 
390
     * @param string|array $info
391
     * @return array
392
     */
393
    public static function parseColRecursion($info)
394
    {
395
        if (is_string($info)) {
396
            $info = ['col' => $info, 'rawCol' => $info, 'modelName' => '', 'label' => [], 'joins' => []];
397
        }
398
        if (strpos($info['col'], ':') !== false) {
399
            $relations = static::relations();
400
            if (isset($relations[substr($info['col'], 0, strpos($info['col'], ':'))])) {
401
                $rel = substr($info['col'], 0, strpos($info['col'], ':'));
402
                $info['col'] = substr($info['col'], strpos($info['col'], ':') + 1);
403
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
404
                switch ($type) {
405 View Code Duplication
                    case 'to':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
406
                        $relCol = $relations[$rel]['col'];
407
                        static::fixPrefix($relCol);
408
                        //$info['modelName'] = $relations[$rel]['model'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
409
                        $info['joins'][$relations[$rel]['model'] . '_' . $rel] = [$relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol];
410
                        break;
411 View Code Duplication
                    case 'one':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
412
                        $relCol = $relations[$rel]['col'];
413
                        $relations[$rel]['model']::fixPrefix($relCol);
414
                        //$info['modelName'] = $relations[$rel]['model'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
415
                        $info['joins'][$relations[$rel]['model'] . '_' . $rel] = [$relations[$rel]['model']::table(), static::index() . ' = ' . $relCol];
416
                        break;
417
                }
418
                $info = $relations[$rel]['model']::parseColRecursion($info);
419
            }
420
        } else {
421
            $cols = static::cols();
422
            if (!empty(static::$labels[$info['col']])) {
423
                $info['label'] = static::$labels[$info['col']];
424
            }
425
426
            if (isset(static::$cols[$info['col']])) {
427
                $info['colParams'] = static::$cols[$info['col']];
428
            } elseif (isset(static::$cols[str_replace(static::colPrefix(), '', $info['col'])])) {
429
                $info['colParams'] = static::$cols[str_replace(static::colPrefix(), '', $info['col'])];
430
            } else {
431
                $info['colParams'] = [];
432
            }
433 View Code Duplication
            if (!isset($cols[$info['col']]) && isset($cols[static::colPrefix() . $info['col']])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
434
                $info['col'] = static::colPrefix() . $info['col'];
435
            }
436
            $info['modelName'] = get_called_class();
437
        }
438
        return $info;
439
    }
440
441
    /**
442
     * Return actual cols from data base
443
     * 
444
     * @param boolean $refresh
445
     * @return array
446
     */
447
    public static function cols($refresh = false)
448
    {
449
        if (static::$storage['type'] == 'moduleConfig') {
450
            return [];
451
        }
452 View Code Duplication
        if (empty(Model::$cols[static::table()]) || $refresh) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
453
            Model::$cols[static::table()] = App::$cur->db->getTableCols(static::table());
454
        }
455 View Code Duplication
        if (!Model::$cols[static::table()]) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
456
            static::createTable();
457
            Model::$cols[static::table()] = App::$cur->db->getTableCols(static::table());
458
        }
459
        return Model::$cols[static::table()];
460
    }
461
462
    /**
463
     * Return cols indexes for create tables
464
     * 
465
     * @return array
466
     */
467
    public static function indexes()
468
    {
469
        return [];
470
    }
471
472
    /**
473
     * Generate params string for col by name
474
     * 
475
     * @param string $colName
476
     * @return boolean|string
477
     */
478
    public static function genColParams($colName)
479
    {
480
        if (empty(static::$cols[$colName]) || static::$storage['type'] == 'moduleConfig') {
481
            return false;
482
        }
483
484
        $params = false;
485
        switch (static::$cols[$colName]['type']) {
486
            case 'select':
487
                switch (static::$cols[$colName]['source']) {
488
                    case 'relation':
489
                        $params = 'int(11) UNSIGNED NOT NULL';
490
                        break;
491
                    default:
492
                        $params = 'varchar(255) NOT NULL';
493
                }
494
                break;
495
            case 'image':
496
                $params = 'int(11) UNSIGNED NOT NULL';
497
                break;
498
            case 'number':
499
                $params = 'int(11) NOT NULL';
500
                break;
501
            case 'text':
502
            case 'email':
503
                $params = 'varchar(255) NOT NULL';
504
                break;
505
            case 'html':
506
            case 'textarea':
507
            case 'json':
508
            case 'password':
509
            case 'dynamicType':
510
                $params = 'text NOT NULL';
511
                break;
512
            case 'bool':
513
                $params = 'tinyint(1) UNSIGNED NOT NULL';
514
                break;
515
            case 'decimal':
516
                $params = 'decimal(8, 2) NOT NULL';
517
                break;
518
            case 'date':
519
                $params = 'date NOT NULL DEFAULT 0';
520
                break;
521
            case 'dateTime':
522
                $params = 'timestamp NOT NULL DEFAULT 0';
523
                break;
524
        }
525
        return $params;
526
    }
527
528
    /**
529
     * Create new col in data base
530
     * 
531
     * @param string $colName
532
     * @return boolean|integer
533
     */
534
    public static function createCol($colName)
535
    {
536
        $params = static::genColParams($colName);
537
        if ($params === false) {
538
            return false;
539
        }
540
        return App::$cur->db->addCol(static::table(), static::colPrefix() . $colName, $params);
541
    }
542
543
    public static function createTable()
544
    {
545
        if (static::$storage['type'] == 'moduleConfig') {
546
            return true;
547
        }
548
        if (!App::$cur->db) {
549
            return false;
550
        }
551
552
        $query = App::$cur->db->newQuery();
553
        if (!$query) {
554
            return false;
555
        }
556
557
        if (!isset($this)) {
558
            $tableName = static::table();
559
            $colPrefix = static::colPrefix();
560
            $indexes = static::indexes();
561
        } else {
562
            $tableName = $this->table();
563
            $colPrefix = $this->colPrefix();
564
            $indexes = $this->indexes();
565
        }
566
        if (App::$cur->db->tableExist($tableName)) {
567
            return true;
568
        }
569
        $cols = [
570
            $colPrefix . 'id' => 'pk'
571
        ];
572
        $className = get_called_class();
573
        if (!empty($className::$cols)) {
574
            foreach ($className::$cols as $colName => $colParams) {
575
                if ($colName == 'date_create') {
576
                    $cols[$colPrefix . 'date_create'] = 'timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP';
577
                    continue;
578
                }
579
                $params = $className::genColParams($colName);
580
                if ($params) {
581
                    $cols[$colPrefix . $colName] = $params;
582
                }
583
            }
584
        }
585
        if (empty($cols[$colPrefix . 'date_create'])) {
586
            $cols[$colPrefix . 'date_create'] = 'timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP';
587
        }
588
        $tableIndexes = [];
589
        if ($indexes) {
590
            foreach ($indexes as $indexName => $index) {
591
                $tableIndexes[] = $index['type'] . ' ' . App::$cur->db->table_prefix . $indexName . ' (' . implode(',', $index['cols']) . ')';
592
            }
593
        }
594
595
        $query->createTable($tableName, $cols, $tableIndexes);
596
        return true;
597
    }
598
599
    /**
600
     * Return table name
601
     * 
602
     * @return string
603
     */
604
    public static function table()
605
    {
606
        return strtolower(str_replace('\\', '_', get_called_class()));
607
    }
608
609
    /**
610
     * Return table index col name
611
     * 
612
     * @return string
613
     */
614
    public static function index()
615
    {
616
617
        return static::colPrefix() . 'id';
618
    }
619
620
    /**
621
     * Return col prefix
622
     * 
623
     * @return string
624
     */
625
    public static function colPrefix()
626
    {
627
        $classPath = explode('\\', get_called_class());
628
        $classPath = array_slice($classPath, 1);
629
        return strtolower(implode('_', $classPath)) . '_';
630
    }
631
632
    /**
633
     * return relations list
634
     * 
635
     * @return array
636
     */
637
    public static function relations()
638
    {
639
        return [];
640
    }
641
642
    /**
643
     * Return name of col with object name
644
     * 
645
     * @return string
646
     */
647
    public static function nameCol()
648
    {
649
        return 'name';
650
    }
651
652
    /**
653
     * Return object name
654
     * 
655
     * @return string
656
     */
657
    public function name()
658
    {
659
        return $this->{$this->nameCol()} ? $this->{$this->nameCol()} : $this->pk();
660
    }
661
662
    /**
663
     * Get single object from data base
664
     * 
665
     * @param mixed $param
666
     * @param string $col
667
     * @param array $options
668
     * @return boolean|\Model
669
     */
670
    public static function get($param, $col = null, $options = [])
671
    {
672
        if (static::$storage['type'] == 'moduleConfig') {
673
            return static::getFromModuleStorage($param, $col, $options);
674
        }
675
        if (!empty($col)) {
676
            static::fixPrefix($col);
677
        }
678
679
        if (is_array($param)) {
680
            static::fixPrefix($param, 'first');
681
        }
682
        foreach (static::$relJoins as $join) {
683
            App::$cur->db->join($join[0], $join[1]);
684
        }
685
        static::$relJoins = [];
686
        foreach (static::$needJoin as $rel) {
687
            $relations = static::relations();
688
            if (isset($relations[$rel])) {
689
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
690
                switch ($type) {
691
                    case 'to':
692
                        $relCol = $relations[$rel]['col'];
693
                        static::fixPrefix($relCol);
694
                        App::$cur->db->join($relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol);
695
                        break;
696
                    case 'one':
697
                        $col = $relations[$rel]['col'];
698
                        $relations[$rel]['model']::fixPrefix($col);
699
                        App::$cur->db->join($relations[$rel]['model']::table(), static::index() . ' = ' . $col);
700
                        break;
701
                }
702
            }
703
        }
704
        static::$needJoin = [];
705
        if (is_array($param)) {
706
            App::$cur->db->where($param);
707
        } else {
708
            if ($col === null) {
709
710
                $col = static::index();
711
            }
712
            if ($param !== null) {
713
                $cols = static::cols();
714
                if (!isset($cols[$col]) && isset($cols[static::colPrefix() . $col])) {
715
                    $col = static::colPrefix() . $col;
716
                }
717
                App::$cur->db->where($col, $param);
718
            } else {
719
                return false;
720
            }
721
        }
722
        if (!App::$cur->db->where) {
723
            return false;
724
        }
725
        try {
726
            $result = App::$cur->db->select(static::table());
727
        } catch (PDOException $exc) {
728
            if ($exc->getCode() == '42S02') {
729
                static::createTable();
730
            }
731
            $result = App::$cur->db->select(static::table());
732
        }
733
        if (!$result) {
734
            return false;
735
        }
736
        return $result->fetch(get_called_class());
737
    }
738
739
    /**
740
     * Old method
741
     * 
742
     * @param type $options
743
     * @return Array
744
     */
745
    public static function get_list($options = [])
746
    {
747
        $query = App::$cur->db->newQuery();
748
        if (!$query) {
749
            return [];
750
        }
751
        if (!empty($options['where']))
752
            $query->where($options['where']);
753
        if (!empty($options['group'])) {
754
            $query->group($options['group']);
755
        }
756
        if (!empty($options['order']))
757
            $query->order($options['order']);
758
        if (!empty($options['join']))
759
            $query->join($options['join']);
760
        if (!empty($options['distinct']))
761
            $query->distinct = $options['distinct'];
762
763
        foreach (static::$relJoins as $join) {
764
            $query->join($join[0], $join[1]);
765
        }
766
        static::$relJoins = [];
767 View Code Duplication
        foreach (static::$needJoin as $rel) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
768
            $relations = static::relations();
769
            if (isset($relations[$rel])) {
770
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
771
                switch ($type) {
772
                    case 'to':
773
                        $relCol = $relations[$rel]['col'];
774
                        static::fixPrefix($relCol);
775
                        $query->join($relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol);
776
                        break;
777
                    case 'one':
778
                        $col = $relations[$rel]['col'];
779
                        $relations[$rel]['model']::fixPrefix($col);
780
                        $query->join($relations[$rel]['model']::table(), static::index() . ' = ' . $col);
781
                        break;
782
                }
783
            }
784
        }
785
        static::$needJoin = [];
786
787 View Code Duplication
        if (!empty($options['limit']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
788
            $limit = (int) $options['limit'];
789
        else {
790
            $limit = 0;
791
        }
792 View Code Duplication
        if (!empty($options['start']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
793
            $start = (int) $options['start'];
794
        else {
795
            $start = 0;
796
        }
797
        if ($limit || $start) {
798
            $query->limit($start, $limit);
799
        }
800
        if (isset($options['key'])) {
801
            $key = $options['key'];
802
        } else {
803
            $key = static::index();
804
        }
805
        try {
806
            $query->operation = 'SELECT';
807
            $query->table = static::table();
808
            $queryArr = $query->buildQuery();
809
            $result = $query->query($queryArr);
810
        } catch (PDOException $exc) {
811
            if ($exc->getCode() == '42S02') {
812
                static::createTable();
813
                $result = $query->query($queryArr);
814
            } else {
815
                throw $exc;
816
            }
817
        }
818
819
        if (!empty($options['array'])) {
820
            return $result->getArray($key);
821
        }
822
        $list = $result->getObjects(get_called_class(), $key);
823 View Code Duplication
        if (!empty($options['forSelect'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
824
            $return = [];
825
            foreach ($list as $key => $item) {
826
                $return[$key] = $item->name();
827
            }
828
            return $return;
829
        }
830
        return $list;
831
    }
832
833
    /**
834
     * Return list of objects from data base
835
     * 
836
     * @param type $options
837
     * @return type
838
     */
839
    public static function getList($options = [])
840
    {
841
        if (static::$storage['type'] != 'db') {
842
            return static::getListFromModuleStorage($options);
843
        }
844
        if (!empty($options['where'])) {
845
            static::fixPrefix($options['where'], 'first');
846
        }
847
        if (!empty($options['group'])) {
848
            static::fixPrefix($options['group'], 'first');
849
        }
850
        if (!empty($options['order'])) {
851
            static::fixPrefix($options['order'], 'first');
852
        }
853
        return static::get_list($options);
854
    }
855
856
    /**
857
     * Get single item from module storage
858
     * 
859
     * @param array $param
860
     * @param string $col
861
     * @param array $options
862
     * @return boolean|\Model
863
     */
864
    public static function getFromModuleStorage($param = null, $col = null, $options = [])
865
    {
866
        if ($col === null) {
867
868
            $col = static::index();
869
        }
870
        if ($param == null) {
871
            return false;
872
        }
873
        $classPath = explode('\\', get_called_class());
874 View Code Duplication
        if (!empty(static::$storage['options']['share'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
875
            $moduleConfig = Config::share($classPath[0]);
876
        } else {
877
            $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
878
        }
879
        $appType = App::$cur->type;
880 View Code Duplication
        if (!empty($moduleConfig['storage']['appTypeSplit'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
881
            if (!empty($options['appType'])) {
882
                $appType = $options['appType'];
883
            }
884
            $storage = !empty($moduleConfig['storage'][$appType]) ? $moduleConfig['storage'][$appType] : [];
885
        } else {
886
            $storage = !empty($moduleConfig['storage']) ? $moduleConfig['storage'] : [];
887
        }
888
        if (!empty($storage[$classPath[1]])) {
889
            $items = $storage[$classPath[1]];
890
            $class = get_called_class();
891
            foreach ($items as $key => $item) {
892
                if ($item[$col] == $param) {
893
                    if (!empty($options['array'])) {
894
                        return $item;
895
                    }
896
                    $item = new $class($item);
897
                    $item->appType = $appType;
898
                    return $item;
899
                }
900
            }
901
        }
902
        return false;
903
    }
904
905
    /**
906
     * Return list items from module storage
907
     * 
908
     * @param array $options
909
     * @return array
910
     */
911
    public static function getListFromModuleStorage($options = [])
912
    {
913
        $classPath = explode('\\', get_called_class());
914 View Code Duplication
        if (!empty(static::$storage['options']['share'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
915
            $moduleConfig = Config::share($classPath[0]);
916
        } else {
917
            $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
918
        }
919 View Code Duplication
        if (!empty($moduleConfig['storage']['appTypeSplit'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
920
            if (empty($options['appType'])) {
921
                $appType = App::$cur->type;
922
            } else {
923
                $appType = $options['appType'];
924
            }
925
            $storage = !empty($moduleConfig['storage'][$appType]) ? $moduleConfig['storage'][$appType] : [];
926
        } else {
927
            $storage = !empty($moduleConfig['storage']) ? $moduleConfig['storage'] : [];
928
        }
929
        if (!empty($storage[$classPath[1]])) {
930
            $items = [];
931
            $class = get_called_class();
932
            if (isset($options['key'])) {
933
                $arrayKey = $options['key'];
934
            } else {
935
                $arrayKey = static::index();
936
            }
937
            foreach ($storage[$classPath[1]] as $key => $item) {
938
                if (!empty($options['where']) && !Model::checkWhere($item, $options['where'])) {
939
                    continue;
940
                }
941
                $items[$item[$arrayKey]] = new $class($item);
942
            }
943
            if (!empty($options['order'])) {
944
                usort($items, function($a, $b) use($options) {
945
                    if ($a->{$options['order'][0]} > $b->{$options['order'][0]} && $options['order'][1] = 'asc') {
946
                        return 1;
947
                    } elseif ($a->{$options['order'][0]} < $b->{$options['order'][0]} && $options['order'][1] = 'asc') {
948
                        return -1;
949
                    }
950
                    return 0;
951
                });
952
            }
953 View Code Duplication
            if (!empty($options['forSelect'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
954
                $return = [];
955
                foreach ($items as $key => $item) {
956
                    $return[$key] = $item->name();
957
                }
958
                return $return;
959
            }
960
            return $items;
961
        }
962
        return [];
963
    }
964
965
    /**
966
     * Return count of records from module storage
967
     * 
968
     * @param array $options
969
     * @return int
970
     */
971
    public static function getCountFromModuleStorage($options = [])
972
    {
973
974
        $classPath = explode('\\', get_called_class());
975
        $count = 0;
976
        if (empty($options['appType'])) {
977
            $appType = App::$cur->type;
978
        } else {
979
            $appType = $options['appType'];
980
        }
981 View Code Duplication
        if (!empty(static::$storage['options']['share'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
982
            $moduleConfig = Config::share($classPath[0]);
983
        } else {
984
            $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
985
        }
986
        if (!empty($moduleConfig['storage'][$appType][$classPath[1]])) {
987
            $items = $moduleConfig['storage'][$appType][$classPath[1]];
988
            if (empty($options['where'])) {
989
                return count($items);
990
            }
991
            foreach ($items as $key => $item) {
992
                if (!empty($options['where'])) {
993
                    if (Model::checkWhere($item, $options['where'])) {
994
                        $count++;
995
                    }
996
                } else {
997
                    $count++;
998
                }
999
            }
1000
        }
1001
        return $count;
1002
    }
1003
1004
    /**
1005
     * Check where for module storage query
1006
     * 
1007
     * @param array $item
1008
     * @param array|string $where
1009
     * @param string $value
1010
     * @param string $operation
1011
     * @param string $concatenation
1012
     * @return boolean
1013
     */
1014
    public static function checkWhere($item = [], $where = '', $value = '', $operation = '=', $concatenation = 'AND')
1015
    {
1016
1017
        if (is_array($where)) {
1018
            if (is_array($where[0])) {
1019
                foreach ($where as $whereItem) {
1020
                    $result = forward_static_call_array(['Model', 'checkWhere'], array_merge([$item], $whereItem));
1021
                    if (!$result) {
1022
                        return false;
1023
                    }
1024
                }
1025
                return true;
1026
            } else {
1027
                return forward_static_call_array(['Model', 'checkWhere'], array_merge([$item], $where));
1028
            }
1029
        }
1030
1031
        if (!isset($item[$where]) && !$value) {
1032
            return true;
1033
        }
1034
        if (!isset($item[$where]) && $value) {
1035
            return false;
1036
        }
1037
        if ($item[$where] == $value) {
1038
            return true;
1039
        }
1040
        return false;
1041
    }
1042
1043
    /**
1044
     * Return count of records from data base
1045
     * 
1046
     * @param array $options
1047
     * @return array|int
1048
     */
1049
    public static function getCount($options = [])
1050
    {
1051
        if (static::$storage['type'] == 'moduleConfig') {
1052
            return static::getCountFromModuleStorage($options);
1053
        }
1054
        $query = App::$cur->db->newQuery();
1055
        if (!$query) {
1056
            return 0;
1057
        }
1058
        if (!empty($options['where'])) {
1059
            static::fixPrefix($options['where'], 'first');
1060
        }
1061
        if (!empty($options['where']))
1062
            $query->where($options['where']);
1063
        if (!empty($options['join']))
1064
            $query->join($options['join']);
1065
        if (!empty($options['order'])) {
1066
            $query->order($options['order']);
1067
        }
1068 View Code Duplication
        if (!empty($options['limit']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1069
            $limit = (int) $options['limit'];
1070
        else {
1071
            $limit = 0;
1072
        }
1073 View Code Duplication
        if (!empty($options['start']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1074
            $start = (int) $options['start'];
1075
        else {
1076
            $start = 0;
1077
        }
1078
        if ($limit || $start) {
1079
            $query->limit($start, $limit);
1080
        }
1081
1082
        foreach (static::$relJoins as $join) {
1083
            $query->join($join[0], $join[1]);
1084
        }
1085
        static::$relJoins = [];
1086 View Code Duplication
        foreach (static::$needJoin as $rel) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1087
            $relations = static::relations();
1088
            if (isset($relations[$rel])) {
1089
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
1090
                switch ($type) {
1091
                    case 'to':
1092
                        $relCol = $relations[$rel]['col'];
1093
                        static::fixPrefix($relCol);
1094
                        $query->join($relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol);
1095
                        break;
1096
                    case 'one':
1097
                        $col = $relations[$rel]['col'];
1098
                        $relations[$rel]['model']::fixPrefix($col);
1099
                        $query->join($relations[$rel]['model']::table(), static::index() . ' = ' . $col);
1100
                        break;
1101
                }
1102
            }
1103
        }
1104
        static::$needJoin = [];
1105
        $cols = 'COUNT(';
1106
1107
        if (!empty($options['distinct'])) {
1108
            if (is_bool($options['distinct'])) {
1109
                $cols .= 'DISTINCT *';
1110
            } else {
1111
                $cols .= "DISTINCT {$options['distinct']}";
1112
            }
1113
        } else {
1114
            $cols .= '*';
1115
        }
1116
        $cols .=') as `count`' . (!empty($options['cols']) ? ',' . $options['cols'] : '');
1117
        $query->cols = $cols;
1118
        if (!empty($options['group'])) {
1119
            $query->group($options['group']);
1120
        }
1121
        try {
1122
            $result = $query->select(static::table());
1123
        } catch (PDOException $exc) {
1124
            if ($exc->getCode() == '42S02') {
1125
                static::createTable();
1126
            }
1127
            $result = $query->select(static::table());
1128
        }
1129
        if (!empty($options['group'])) {
1130
            $count = $result->getArray();
1131
            return $count;
1132
        } else {
1133
            $count = $result->fetch();
1134
            return $count['count'];
1135
        }
1136
    }
1137
1138
    /**
1139
     * Update records in data base
1140
     * 
1141
     * @param array $params
1142
     * @param array $where
1143
     * @return boolean
1144
     */
1145
    public static function update($params, $where = [])
1146
    {
1147
        static::fixPrefix($params);
1148
1149
        $cols = self::cols();
1150
1151
        $values = [];
1152
        foreach ($cols as $col => $param) {
1153
            if (isset($params[$col]))
1154
                $values[$col] = $params[$col];
1155
        }
1156
        if (empty($values)) {
1157
            return false;
1158
        }
1159
1160
        if (!empty($where)) {
1161
            static::fixPrefix($where, 'first');
1162
1163
            App::$cur->db->where($where);
1164
        }
1165
        App::$cur->db->update(static::table(), $values);
1166
    }
1167
1168
    /**
1169
     * Return primary key of object
1170
     * 
1171
     * @return mixed
1172
     */
1173
    public function pk()
1174
    {
1175
        return $this->{$this->index()};
1176
    }
1177
1178
    /**
1179
     * Before save trigger
1180
     */
1181
    public function beforeSave()
1182
    {
1183
        
1184
    }
1185
1186
    /**
1187
     * Save object to module storage
1188
     * 
1189
     * @param array $options
1190
     * @return boolean
1191
     */
1192
    public function saveModuleStorage($options)
1193
    {
1194
1195
        $col = static::index();
1196
        $id = $this->pk();
1197
        $appType = '';
1198
        $classPath = explode('\\', get_called_class());
1199
1200 View Code Duplication
        if (!empty(static::$storage['options']['share'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1201
            $moduleConfig = Config::share($classPath[0]);
1202
        } else {
1203
            $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
1204
        }
1205
1206 View Code Duplication
        if (!empty($moduleConfig['storage']['appTypeSplit'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1207
            if (empty($options['appType'])) {
1208
                $appType = App::$cur->type;
1209
            } else {
1210
                $appType = $options['appType'];
1211
            }
1212
            $storage = !empty($moduleConfig['storage'][$appType]) ? $moduleConfig['storage'][$appType] : [];
1213
        } else {
1214
            $storage = !empty($moduleConfig['storage']) ? $moduleConfig['storage'] : [];
1215
        }
1216
        if (empty($storage[$classPath[1]])) {
1217
            $storage[$classPath[1]] = [];
1218
        }
1219
        if ($id) {
1220 View Code Duplication
            foreach ($storage[$classPath[1]] as $key => $item) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1221
                if ($item[$col] == $id) {
1222
                    $storage[$classPath[1]][$key] = $this->_params;
1223
                    break;
1224
                }
1225
            }
1226
        } else {
1227
            $id = !empty($storage['scheme'][$classPath[1]]['ai']) ? $storage['scheme'][$classPath[1]]['ai'] : 1;
1228
            $this->$col = $id;
1229
            $storage['scheme'][$classPath[1]]['ai'] = $id + 1;
1230
            $storage[$classPath[1]][] = $this->_params;
1231
        }
1232 View Code Duplication
        if (!empty($moduleConfig['storage']['appTypeSplit'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1233
            $moduleConfig['storage'][$appType] = $storage;
1234
        } else {
1235
            $moduleConfig['storage'] = $storage;
1236
        }
1237 View Code Duplication
        if (empty(static::$storage['options']['share'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1238
            Config::save('module', $moduleConfig, $classPath[0]);
1239
        } else {
1240
            Config::save('share', $moduleConfig, $classPath[0]);
1241
        }
1242
        return true;
1243
    }
1244
1245
    /**
1246
     * Update tree path category
1247
     */
1248
    public function changeCategoryTree()
1249
    {
1250
        $class = get_class($this);
1251
        $itemModel = $class::$treeCategory;
1252
        $oldPath = $this->tree_path;
1253
        $this->tree_path = $this->getCatalogTree($this);
1254
        $itemsTable = \App::$cur->db->table_prefix . $itemModel::table();
1255
        $itemTreeCol = $itemModel::colPrefix() . 'tree_path';
1256
1257
        $categoryTreeCol = $this->colPrefix() . 'tree_path';
1258
        $categoryTable = \App::$cur->db->table_prefix . $this->table();
1259
        if ($oldPath) {
1260
            \App::$cur->db->query('UPDATE
1261
                ' . $categoryTable . ' 
1262
                    SET 
1263
                        ' . $categoryTreeCol . ' = REPLACE(' . $categoryTreeCol . ', "' . $oldPath . $this->id . '/' . '", "' . $this->tree_path . $this->id . '/' . '") 
1264
                    WHERE ' . $categoryTreeCol . ' LIKE "' . $oldPath . $this->id . '/' . '%"');
1265
1266
            \App::$cur->db->query('UPDATE
1267
                ' . $itemsTable . '
1268
                    SET 
1269
                        ' . $itemTreeCol . ' = REPLACE(' . $itemTreeCol . ', "' . $oldPath . $this->id . '/' . '", "' . $this->tree_path . $this->id . '/' . '") 
1270
                    WHERE ' . $itemTreeCol . ' LIKE "' . $oldPath . $this->id . '/' . '%"');
1271
        }
1272
        $itemModel::update([$itemTreeCol => $this->tree_path . $this->id . '/'], [$itemModel::colPrefix() . $this->index(), $this->id]);
1273
    }
1274
1275
    /**
1276
     * Return tree path
1277
     * 
1278
     * @param \Model $catalog
1279
     * @return string
1280
     */
1281
    public function getCatalogTree($catalog)
1282
    {
1283
        $catalogClass = get_class($catalog);
1284
        $catalogParent = $catalogClass::get($catalog->parent_id);
1285
        if ($catalog && $catalogParent) {
1286
            if ($catalogParent->tree_path) {
1287
                return $catalogParent->tree_path . $catalogParent->id . '/';
1288
            } else {
1289
                return $this->getCatalogTree($catalogParent) . $catalogParent->id . '/';
1290
            }
1291
        }
1292
        return '/';
1293
    }
1294
1295
    /**
1296
     * Update tree path item
1297
     */
1298
    public function changeItemTree()
1299
    {
1300
        $class = get_class($this);
1301
        $categoryModel = $class::$categoryModel;
1302
        $category = $categoryModel::get($this->{$categoryModel::index()});
1303
        if ($category) {
1304
            $this->tree_path = $category->tree_path . $category->pk() . '/';
1305
        } else {
1306
            $this->tree_path = '/';
1307
        }
1308
    }
1309
1310
    /**
1311
     * Save object to data base
1312
     * 
1313
     * @param array $options
1314
     * @return boolean|int
1315
     */
1316
    public function save($options = [])
1317
    {
1318
1319
        if (static::$storage['type'] == 'moduleConfig') {
1320
            return static::saveModuleStorage($options);
1321
        }
1322
        $class = get_class($this);
1323
        if ($class::$categoryModel) {
1324
            $this->changeItemTree();
1325
        }
1326
        if ($class::$treeCategory) {
1327
            $this->changeCategoryTree();
1328
        }
1329
        if (!empty($this->_changedParams) && $this->pk()) {
1330
            Inji::$inst->event('modelItemParamsChanged-' . get_called_class(), $this);
1331
        }
1332
        $this->beforeSave();
1333
1334
        $values = [];
1335
1336
        foreach ($this->cols() as $col => $param) {
1337
            if (isset($this->_params[$col]))
1338
                $values[$col] = $this->_params[$col];
1339
        }
1340
        if (empty($values) && empty($options['empty'])) {
1341
            return false;
1342
        }
1343
1344
        if ($this->pk()) {
1345
            $new = false;
1346
            if ($this->get($this->_params[$this->index()])) {
1347
                App::$cur->db->where($this->index(), $this->_params[$this->index()]);
1348
                App::$cur->db->update($this->table(), $values);
1349
            } else {
1350
1351
                $this->_params[$this->index()] = App::$cur->db->insert($this->table(), $values);
1352
            }
1353
        } else {
1354
            $new = true;
1355
            $this->_params[$this->index()] = App::$cur->db->insert($this->table(), $values);
1356
        }
1357
        App::$cur->db->where($this->index(), $this->_params[$this->index()]);
1358
        try {
1359
            $result = App::$cur->db->select($this->table());
1360
        } catch (PDOException $exc) {
1361
            if ($exc->getCode() == '42S02') {
1362
                $this->createTable();
1363
            }
1364
            $result = App::$cur->db->select($this->table());
1365
        }
1366
        $this->_params = $result->fetch();
1367
        if ($new) {
1368
            Inji::$inst->event('modelCreatedItem-' . get_called_class(), $this);
1369
        }
1370
        $this->afterSave();
1371
        return $this->{$this->index()};
1372
    }
1373
1374
    /**
1375
     * After save trigger
1376
     */
1377
    public function afterSave()
1378
    {
1379
        
1380
    }
1381
1382
    /**
1383
     * Before delete trigger
1384
     */
1385
    public function beforeDelete()
1386
    {
1387
        
1388
    }
1389
1390
    /**
1391
     * Delete item from module storage
1392
     * 
1393
     * @param array $options
1394
     * @return boolean
1395
     */
1396
    public function deleteFromModuleStorage($options)
1397
    {
1398
1399
        $col = static::index();
1400
        $id = $this->pk();
1401
        $appType = '';
1402
        $classPath = explode('\\', get_called_class());
1403 View Code Duplication
        if (!empty(static::$storage['options']['share'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1404
            $moduleConfig = Config::share($classPath[0]);
1405
        } else {
1406
            $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
1407
        }
1408
1409 View Code Duplication
        if (!empty($moduleConfig['storage']['appTypeSplit'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1410
            if (empty($options['appType'])) {
1411
                $appType = App::$cur->type;
1412
            } else {
1413
                $appType = $options['appType'];
1414
            }
1415
            $storage = !empty($moduleConfig['storage'][$appType]) ? $moduleConfig['storage'][$appType] : [];
1416
        } else {
1417
            $storage = !empty($moduleConfig['storage']) ? $moduleConfig['storage'] : [];
1418
        }
1419
        if (empty($storage[$classPath[1]])) {
1420
            $storage[$classPath[1]] = [];
1421
        }
1422 View Code Duplication
        foreach ($storage[$classPath[1]] as $key => $item) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1423
1424
            if ($item[$col] == $id) {
1425
                unset($storage[$classPath[1]][$key]);
1426
                break;
1427
            }
1428
        }
1429 View Code Duplication
        if (!empty($moduleConfig['storage']['appTypeSplit'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1430
            $moduleConfig['storage'][$appType] = $storage;
1431
        } else {
1432
            $moduleConfig['storage'] = $storage;
1433
        }
1434 View Code Duplication
        if (empty(static::$storage['options']['share'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1435
            Config::save('module', $moduleConfig, $classPath[0]);
1436
        } else {
1437
            Config::save('share', $moduleConfig, $classPath[0]);
1438
        }
1439
        return true;
1440
    }
1441
1442
    /**
1443
     * Delete item from data base
1444
     * 
1445
     * @param array $options
1446
     * @return boolean
1447
     */
1448
    public function delete($options = [])
1449
    {
1450
        $this->beforeDelete();
1451
1452
        if (static::$storage['type'] == 'moduleConfig') {
1453
            return static::deleteFromModuleStorage($options);
1454
        }
1455
        if (!empty($this->_params[$this->index()])) {
1456
            App::$cur->db->where($this->index(), $this->_params[$this->index()]);
1457
            $result = App::$cur->db->delete($this->table());
1458
            if ($result) {
1459
                $this->afterDelete();
1460
                return $result;
1461
            }
1462
        }
1463
        return false;
1464
    }
1465
1466
    /**
1467
     * Delete items from data base
1468
     * 
1469
     * @param array $where
1470
     */
1471
    public static function deleteList($where)
1472
    {
1473
        if (!empty($where)) {
1474
            static::fixPrefix($where, 'first');
1475
            App::$cur->db->where($where);
1476
        }
1477
        App::$cur->db->delete(static::table());
1478
    }
1479
1480
    /**
1481
     * After delete trigger
1482
     */
1483
    public function afterDelete()
1484
    {
1485
        
1486
    }
1487
1488
    /**
1489
     * find relation for col name
1490
     * 
1491
     * @param string $col
1492
     * @return array|null
1493
     */
1494
    public static function findRelation($col)
1495
    {
1496
1497
        foreach (static::relations() as $relName => $rel) {
1498
            if ($rel['col'] == $col)
1499
                return $relName;
1500
        }
1501
        return NULL;
1502
    }
1503
1504
    /**
1505
     * Set params for model
1506
     * 
1507
     * @param array $params
1508
     */
1509
    public function setParams($params)
1510
    {
1511
        static::fixPrefix($params);
1512
        $className = get_called_class();
1513
        foreach ($params as $paramName => $value) {
1514
            $shortName = preg_replace('!' . $this->colPrefix() . '!', '', $paramName);
1515
            if (!empty($className::$cols[$shortName])) {
1516
                switch ($className::$cols[$shortName]['type']) {
1517
                    case 'decimal':
1518
                        $params[$paramName] = (float) $value;
1519
                        break;
1520
                    case 'number':
1521
                        $params[$paramName] = (int) $value;
1522
                        break;
1523
                    case 'bool':
1524
                        $params[$paramName] = (bool) $value;
1525
                        break;
1526
                }
1527
            }
1528
        }
1529
        $this->_params = array_merge($this->_params, $params);
1530
    }
1531
1532
    /**
1533
     * Return relation
1534
     * 
1535
     * @param string $relName
1536
     * @return array|boolean
1537
     */
1538
    public static function getRelation($relName)
1539
    {
1540
        $relations = static::relations();
1541
        return !empty($relations[$relName]) ? $relations[$relName] : false;
1542
    }
1543
1544
    /**
1545
     * Load relation
1546
     * 
1547
     * @param string $name
1548
     * @param array $params
1549
     * @return null|array|integer|\Model
1550
     */
1551
    public function loadRelation($name, $params = [])
1552
    {
1553
        $relation = static::getRelation($name);
1554
        if ($relation) {
1555
            if (!isset($relation['type'])) {
1556
                $type = 'to';
1557
            } else {
1558
                $type = $relation['type'];
1559
            }
1560
            $getCol = null;
1561
            $getParams = [];
1562
            switch ($type) {
1563
                case 'relModel':
1564
                    if (!$this->pk()) {
1565
                        return [];
1566
                    }
1567
                    $fixedCol = $relation['model']::index();
1568
                    $relation['relModel']::fixPrefix($fixedCol);
1569
                    $ids = array_keys($relation['relModel']::getList(['where' => [$this->index(), $this->pk()], 'array' => true, 'key' => $fixedCol]));
1570
                    if (empty($ids)) {
1571
                        if (empty($params['count'])) {
1572
                            return [];
1573
                        } else {
1574
                            return 0;
1575
                        }
1576
                    }
1577
                    $getType = 'getList';
1578
                    $options = [
1579
                        'where' => [$relation['model']::index(), implode(',', $ids), 'IN'],
1580
                        'array' => (!empty($params['array'])) ? true : false,
1581
                        'key' => (isset($params['key'])) ? $params['key'] : ((isset($relation['resultKey'])) ? $relation['resultKey'] : null),
1582
                        'start' => (isset($params['start'])) ? $params['start'] : ((isset($relation['start'])) ? $relation['start'] : null),
1583
                        'order' => (isset($params['order'])) ? $params['order'] : ((isset($relation['order'])) ? $relation['order'] : null),
1584
                        'limit' => (isset($params['limit'])) ? $params['limit'] : ((isset($relation['limit'])) ? $relation['limit'] : null),
1585
                    ];
1586
                    break;
1587
                case 'many':
1588
                    if (!$this->{$this->index()}) {
1589
                        return [];
1590
                    }
1591
                    $getType = 'getList';
1592
                    $options = [
1593
                        'join' => (isset($relation['join'])) ? $relation['join'] : null,
1594
                        'key' => (isset($params['key'])) ? $params['key'] : ((isset($relation['resultKey'])) ? $relation['resultKey'] : null),
1595
                        'array' => (!empty($params['array'])) ? true : false,
1596
                        'forSelect' => (!empty($params['forSelect'])) ? true : false,
1597
                        'order' => (isset($params['order'])) ? $params['order'] : ((isset($relation['order'])) ? $relation['order'] : null),
1598
                        'start' => (isset($params['start'])) ? $params['start'] : ((isset($relation['start'])) ? $relation['start'] : null),
1599
                        'limit' => (isset($params['limit'])) ? $params['limit'] : ((isset($relation['limit'])) ? $relation['limit'] : null),
1600
                        'appType' => (isset($params['appType'])) ? $params['appType'] : ((isset($relation['appType'])) ? $relation['appType'] : null),
1601
                        'where' => []
1602
                    ];
1603
                    $options['where'][] = [$relation['col'], $this->{$this->index()}];
1604
                    if (!empty($relation['where'])) {
1605
                        $options['where'] = array_merge($options['where'], [$relation['where']]);
1606
                    }
1607
                    if (!empty($params['where'])) {
1608
                        $options['where'] = array_merge($options['where'], [$params['where']]);
1609
                    }
1610
                    break;
1611
                case 'one':
1612
                    $getType = 'get';
1613
                    $options = [$relation['col'], $this->pk()];
1614
                    break;
1615
                default:
1616
                    if ($this->$relation['col'] === NULL) {
1617
                        return null;
1618
                    }
1619
                    $getType = 'get';
1620
                    $options = $this->$relation['col'];
1621
                    $getParams['appType'] = $this->appType;
1622
            }
1623
            if (!empty($params['count'])) {
1624
                if (class_exists($relation['model'])) {
1625
                    return $relation['model']::getCount($options);
1626
                }
1627
                return 0;
1628
            } else {
1629
                if (class_exists($relation['model'])) {
1630
                    $this->loadedRelations[$name][json_encode($params)] = $relation['model']::$getType($options, $getCol, $getParams);
1631
                } else {
1632
                    $this->loadedRelations[$name][json_encode($params)] = [];
1633
                }
1634
            }
1635
            return $this->loadedRelations[$name][json_encode($params)];
1636
        }
1637
        return NULL;
1638
    }
1639
1640
    /**
1641
     * Add relation item
1642
     * 
1643
     * @param string $relName
1644
     * @param \Model $objectId
1645
     * @return \Model|boolean
1646
     */
1647
    public function addRelation($relName, $objectId)
1648
    {
1649
        $relation = $this->getRelation($relName);
1650
        if ($relation) {
1651
            $rel = $relation['relModel']::get([[$relation['model']::index(), $objectId], [$this->index(), $this->pk()]]);
1652
            if (!$rel) {
1653
                $rel = new $relation['relModel']([
1654
                    $relation['model']::index() => $objectId,
1655
                    $this->index() => $this->pk()
1656
                ]);
1657
                $rel->save();
1658
            }
1659
            return $rel;
1660
        }
1661
        return false;
1662
    }
1663
1664
    /**
1665
     * Check user access for form
1666
     * 
1667
     * @param string $formName
1668
     * @return boolean
1669
     */
1670
    public function checkFormAccess($formName)
1671
    {
1672
        if ($formName == 'manage' && !Users\User::$cur->isAdmin()) {
1673
            return false;
1674
        }
1675
        return true;
1676
    }
1677
1678
    /**
1679
     * Check access for model
1680
     * 
1681
     * @param string $mode
1682
     * @param \Users\User $user
1683
     * @return boolean
1684
     */
1685
    public function checkAccess($mode = 'write', $user = null)
1686
    {
1687
        if (!$user) {
1688
            $user = \Users\User::$cur;
1689
        }
1690
        return $user->isAdmin();
1691
    }
1692
1693
    /**
1694
     * Param and relation with params getter
1695
     * 
1696
     * @param string $name
1697
     * @param array $params
1698
     * @return \Value|mixed
1699
     */
1700
    public function __call($name, $params)
1701
    {
1702
        $fixedName = $name;
1703
        static::fixPrefix($fixedName);
1704 View Code Duplication
        if (isset($this->_params[$fixedName])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1705
            return new Value($this, $fixedName);
1706
        } elseif (isset($this->_params[$name])) {
1707
            return new Value($this, $name);
1708
        }
1709
        return call_user_func_array([$this, 'loadRelation'], array_merge([$name], $params));
1710
    }
1711
1712
    /**
1713
     * Param and relation getter
1714
     * 
1715
     * @param string $name
1716
     * @return mixed
1717
     */
1718
    public function __get($name)
1719
    {
1720
        $fixedName = $name;
1721
        static::fixPrefix($fixedName);
1722
        if (isset($this->_params[$fixedName])) {
1723
            return $this->_params[$fixedName];
1724
        }
1725
        if (isset($this->loadedRelations[$name][json_encode([])])) {
1726
            return $this->loadedRelations[$name][json_encode([])];
1727
        }
1728
        return $this->loadRelation($name);
1729
    }
1730
1731
    /**
1732
     * Return model value in object
1733
     * 
1734
     * @param string $name
1735
     * @return \Value|null
1736
     */
1737
    public function value($name)
1738
    {
1739
        $fixedName = $name;
1740
        static::fixPrefix($fixedName);
1741 View Code Duplication
        if (isset($this->_params[$fixedName])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1742
            return new Value($this, $fixedName);
1743
        } elseif ($this->_params[$name]) {
1744
            return new Value($this, $name);
1745
        }
1746
        return null;
1747
    }
1748
1749
    /**
1750
     * Return manager filters
1751
     * 
1752
     * @return array
1753
     */
1754
    public static function managerFilters()
1755
    {
1756
        return [];
1757
    }
1758
1759
    /**
1760
     * Return validators for cols
1761
     * 
1762
     * @return array
1763
     */
1764
    public static function validators()
1765
    {
1766
        return [];
1767
    }
1768
1769
    /**
1770
     * Return validator by name
1771
     * 
1772
     * @param string $name
1773
     * @return array
1774
     */
1775
    public static function validator($name)
1776
    {
1777
        $validators = static::validators();
1778
        if (!empty($validators[$name])) {
1779
            return $validators[$name];
1780
        }
1781
        return [];
1782
    }
1783
1784
    /**
1785
     * Set handler for model params
1786
     * 
1787
     * @param string $name
1788
     * @param mixed $value
1789
     */
1790
    public function __set($name, $value)
1791
    {
1792
        static::fixPrefix($name);
1793
        $className = get_called_class();
1794
        $shortName = preg_replace('!' . $this->colPrefix() . '!', '', $name);
1795
        if (!empty($className::$cols[$shortName])) {
1796
            switch ($className::$cols[$shortName]['type']) {
1797
                case 'decimal':
1798
                    $value = (float) $value;
1799
                    break;
1800
                case 'number':
1801
                    $value = (int) $value;
1802
                    break;
1803
                case 'bool':
1804
                    $value = (bool) $value;
1805
                    break;
1806
            }
1807
        }
1808
        if ((isset($this->_params[$name]) && $this->_params[$name] != $value) && !isset($this->_changedParams[$name])) {
1809
            $this->_changedParams[$name] = $this->_params[$name];
1810
        }
1811
1812
        $this->_params[$name] = $value;
1813
    }
1814
1815
    /**
1816
     * Isset handler for model params
1817
     * 
1818
     * @param string $name
1819
     * @return boolean
1820
     */
1821
    public function __isset($name)
1822
    {
1823
        static::fixPrefix($name);
1824
        return isset($this->_params[$name]);
1825
    }
1826
1827
    /**
1828
     * Convert object to string
1829
     * 
1830
     * @return string
1831
     */
1832
    public function __toString()
1833
    {
1834
        return $this->name();
1835
    }
1836
1837
}
1838