Passed
Push — master ( 7e6133...d39861 )
by Alexey
11:48
created

Model::get()   F

Complexity

Conditions 19
Paths 2049

Size

Total Lines 69
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 30
CRAP Score 55.1329

Importance

Changes 0
Metric Value
cc 19
eloc 51
nc 2049
nop 3
dl 0
loc 69
rs 2.6059
c 0
b 0
f 0
ccs 30
cts 56
cp 0.5356
crap 55.1329

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 4
    public function __construct($params = []) {
117 4
        $this->setParams($params);
118 4
    }
119
120
    public static $logging = true;
121
122
    /**
123
     * return object name
124
     * 
125
     * @return string
126
     */
127
    public static function objectName() {
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
        if (strpos($valuePath, ':')) {
142
            $rel = substr($valuePath, 0, strpos($valuePath, ':'));
143
            $param = substr($valuePath, strpos($valuePath, ':') + 1);
144
            if (!$object->$rel) {
145
                $modelName = get_class($object);
146
                $relations = $modelName::relations();
147
                if (empty($relations[$rel]['type']) || $relations[$rel]['type'] == 'one') {
148
                    return $object->{$relations[$rel]['col']};
149
                }
150
                return 0;
151
            }
152
            if (strpos($valuePath, ':')) {
153
                return self::getColValue($object->$rel, $param, $convert, $manageHref);
154
            } else {
155
                return $convert ? Model::resloveTypeValue($object->$rel, $param, $manageHref) : $object->$rel->$param;
156
            }
157
        } else {
158
            return $convert ? Model::resloveTypeValue($object, $valuePath, $manageHref) : $object->$valuePath;
159
        }
160
    }
161
162
    /**
163
     * Retrun value for view
164
     * 
165
     * @param Model $item
166
     * @param string $colName
167
     * @param boolean $manageHref
168
     * @return string
169
     */
170
    public static function resloveTypeValue($item, $colName, $manageHref = false) {
171
        $modelName = get_class($item);
172
        $colInfo = $modelName::getColInfo($colName);
173
        $type = !empty($colInfo['colParams']['type']) ? $colInfo['colParams']['type'] : 'string';
174
        $value = '';
175
        switch ($type) {
176
            case 'select':
177
                switch ($colInfo['colParams']['source']) {
178
                    case 'model':
179
                        $sourceValue = '';
180
                        if ($item->$colName) {
181
                            $sourceValue = $colInfo['colParams']['model']::get($item->$colName);
182
                        }
183
                        $value = $sourceValue ? $sourceValue->name() : 'Не задано';
184
                        break;
185
                    case 'array':
186
                        $value = !empty($colInfo['colParams']['sourceArray'][$item->$colName]) ? $colInfo['colParams']['sourceArray'][$item->$colName] : 'Не задано';
187
                        if (is_array($value) && $value['text']) {
188
                            $value = $value['text'];
189
                        }
190
                        break;
191
                    case 'bool':
192
                        return $item->$colName ? 'Да' : 'Нет';
193
                    case 'method':
194 View Code Duplication
                        if (!empty($colInfo['colParams']['params'])) {
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...
195
                            $values = call_user_func_array([App::$cur->$colInfo['colParams']['module'], $colInfo['colParams']['method']], $colInfo['colParams']['params']);
196
                        } else {
197
                            $values = \App::$cur->{$colInfo['colParams']['module']}->$colInfo['colParams']['method']();
198
                        }
199
                        $value = !empty($values[$item->$colName]) ? $values[$item->$colName] : 'Не задано';
200
                        break;
201
                    case 'void':
202
                        if (!empty($modelName::$cols[$colName]['value']['type']) && $modelName::$cols[$colName]['value']['type'] == 'moduleMethod') {
203
                            return \App::$cur->{$modelName::$cols[$colName]['value']['module']}->{$modelName::$cols[$colName]['value']['method']}($item, $colName, $modelName::$cols[$colName]);
204
                        }
205
                        break;
206
                    case 'relation':
207
                        $relations = $colInfo['modelName']::relations();
208
                        $relValue = $relations[$colInfo['colParams']['relation']]['model']::get($item->$colName);
209
                        $relModel = $relations[$colInfo['colParams']['relation']]['model'];
210
                        $relModel = strpos($relModel, '\\') === 0 ? substr($relModel, 1) : $relModel;
211
                        if ($manageHref) {
212
                            $value = $relValue ? "<a href='/admin/" . str_replace('\\', '/view/', $relModel) . "/" . $relValue->pk() . "'>" . $relValue->name() . "</a>" : 'Не задано';
213
                        } else {
214
                            $value = $relValue ? $relValue->name() : 'Не задано';
215
                        }
216
                        break;
217
                }
218
                break;
219
            case 'image':
220
                $file = Files\File::get($item->$colName);
221
                if ($file) {
222
                    $photoId = Tools::randomString();
223
                    $value = '<a href = "' . $file->path . '" id="' . $photoId . '"><img src="' . $file->path . '?resize=60x120" /></a>';
224
                    $value .='<script>inji.onLoad(function(){$("#' . $photoId . '").fancybox();});</script>';
225
                } else {
226
                    $value = '<img src="/static/system/images/no-image.png?resize=60x120" />';
227
                }
228
                break;
229
            case 'file':
230
                $file = Files\File::get($item->$colName);
231
                if ($file) {
232
                    $value = '<a href="' . $file->path . '">' . $file->name . '.' . $file->type->ext . '</a>';
233
                } else {
234
                    $value = 'Файл не загружен';
235
                }
236
                break;
237
            case 'bool':
238
                $value = $item->$colName ? 'Да' : 'Нет';
239
                break;
240
            case 'void':
241
                if (!empty($colInfo['colParams']['value']['type']) && $colInfo['colParams']['value']['type'] == 'moduleMethod') {
242
                    return \App::$cur->{$colInfo['colParams']['value']['module']}->{$colInfo['colParams']['value']['method']}($item, $colName, $colInfo['colParams']);
243
                }
244
                break;
245 View Code Duplication
            case 'map':
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...
246
                if ($item->$colName && json_decode($item->$colName, true)) {
247
                    $addres = json_decode($item->$colName, true);
248
                    $name = $addres['address'] ? $addres['address'] : 'lat:' . $addres['lat'] . ': lng:' . $addres['lng'];
249
                    \App::$cur->libs->loadLib('yandexMap');
250
                    ob_start();
251
                    $uid = Tools::randomString();
252
                    ?>
253
                    <div id='map<?= $uid; ?>_container' style="display:none;"><script>/*
254
                     <div id='map<?= $uid; ?>' style="width: 100%; height: 500px"></div>
255
                     <script>
256
                     var myMap<?= $uid; ?>;
257
                     var myMap<?= $uid; ?>CurPin;
258
                     inji.onLoad(function () {
259
                     ymaps.ready(init<?= $uid; ?>);
260
                     function init<?= $uid; ?>() {
261
                     var myPlacemark;
262
                     myMap<?= $uid; ?> = new ymaps.Map("map<?= $uid; ?>", {
263
                     center: ["<?= $addres['lat'] ?>", "<?= $addres['lng']; ?>"],
264
                     zoom: 13
265
                     });
266
                     myCoords = ["<?= $addres['lat'] ?>", "<?= $addres['lng']; ?>"];
267
                     myMap<?= $uid; ?>CurPin = new ymaps.Placemark(myCoords,
268
                     {iconContent: "<?= $addres['address']; ?>"},
269
                     {preset: 'islands#greenStretchyIcon'}
270
                     );
271
                     myMap<?= $uid; ?>.geoObjects.add(myMap<?= $uid; ?>CurPin, 0);
272
                     }
273
                     window['init<?= $uid; ?>'] = init<?= $uid; ?>;
274
                     });
275
                     */</script>
276
                    </div>
277
                    <?php
278
                    $content = ob_get_contents();
279
                    ob_end_clean();
280
                    $onclick = 'inji.Ui.modals.show("' . addcslashes($addres['address'], '"') . '", $("#map' . $uid . '_container script").html().replace(/^\/\*/g, "").replace(/\*\/$/g, "")+"</script>","mapmodal' . $uid . '","modal-lg");';
281
                    $onclick .= 'return false;';
282
                    $value = "<a href ='#' onclick='{$onclick}' >{$name}</a>";
283
                    $value .= $content;
284
                } else {
285
                    $value = 'Местоположение не заданно';
286
                }
287
288
                break;
289
            case 'dynamicType':
290
                switch ($colInfo['colParams']['typeSource']) {
291
                    case 'selfMethod':
292
                        $type = $item->{$colInfo['colParams']['selfMethod']}();
293
                        if (is_array($type)) {
294 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...
295
                                $relationPath = explode(':', $type['relation']);
296
                                $relationName = array_pop($relationPath);
297
                                $curItem = $item;
298
                                foreach ($relationPath as $path) {
299
                                    $curItem = $curItem->$path;
300
                                }
301
                                $itemModel = get_class($curItem);
302
                                $relation = $itemModel::getRelation($relationName);
303
                                $sourceModel = $relation['model'];
304
                            } else {
305
                                $relation = static::getRelation($type['relation']);
306
                                $sourceModel = $relation['model'];
307
                            }
308
                            $value = $sourceModel::get($item->$colName);
309
                            if ($value) {
310
                                $value = $value->name();
311
                            } else {
312
                                $value = $item->$colName;
313
                            }
314
                        } else {
315
                            switch ($type) {
316 View Code Duplication
                                case 'map':
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...
317
                                    if ($item->$colName && json_decode($item->$colName, true)) {
318
                                        $addres = json_decode($item->$colName, true);
319
                                        $name = $addres['address'] ? $addres['address'] : 'lat:' . $addres['lat'] . ': lng:' . $addres['lng'];
320
                                        \App::$cur->libs->loadLib('yandexMap');
321
                                        ob_start();
322
                                        $uid = Tools::randomString();
323
                                        ?>
324
                                        <div id='map<?= $uid; ?>_container' style="display:none;"><script>/*
325
                                         <div id='map<?= $uid; ?>' style="width: 100%; height: 500px"></div>
326
                                         <script>
327
                                         var myMap<?= $uid; ?>;
328
                                         var myMap<?= $uid; ?>CurPin;
329
                                         inji.onLoad(function () {
330
                                         ymaps.ready(init<?= $uid; ?>);
331
                                         function init<?= $uid; ?>() {
332
                                         var myPlacemark;
333
                                         myMap<?= $uid; ?> = new ymaps.Map("map<?= $uid; ?>", {
334
                                         center: ["<?= $addres['lat'] ?>", "<?= $addres['lng']; ?>"],
335
                                         zoom: 13
336
                                         });
337
                                         myCoords = ["<?= $addres['lat'] ?>", "<?= $addres['lng']; ?>"];
338
                                         myMap<?= $uid; ?>CurPin = new ymaps.Placemark(myCoords,
339
                                         {iconContent: "<?= $addres['address']; ?>"},
340
                                         {preset: 'islands#greenStretchyIcon'}
341
                                         );
342
                                         myMap<?= $uid; ?>.geoObjects.add(myMap<?= $uid; ?>CurPin, 0);
343
                                         }
344
                                         window['init<?= $uid; ?>'] = init<?= $uid; ?>;
345
                                         });
346
                                         */</script>
347
                                        </div>
348
                                        <?php
349
                                        $content = ob_get_contents();
350
                                        ob_end_clean();
351
                                        $onclick = 'inji.Ui.modals.show("' . addcslashes($addres['address'], '"') . '", $("#map' . $uid . '_container script").html().replace(/^\/\*/g, "").replace(/\*\/$/g, "")+"</script>","mapmodal' . $uid . '","modal-lg");';
352
                                        $onclick .= 'return false;';
353
                                        $value = "<a href ='#' onclick='{$onclick}' >{$name}</a>";
354
                                        $value .= $content;
355
                                    } else {
356
                                        $value = 'Местоположение не заданно';
357
                                    }
358
359
                                    break;
360
                                default:
361
                                    $value = $item->$colName;
362
                            }
363
                        }
364
                        break;
365
                }
366
                break;
367
            default:
368
                $value = $item->$colName;
369
                break;
370
        }
371
        return $value;
372
    }
373
374
    /**
375
     * Fix col prefix
376
     * 
377
     * @param mixed $array
378
     * @param string $searchtype
379
     * @param string $rootModel
380
     * @return null
381
     */
382 4
    public static function fixPrefix(&$array, $searchtype = 'key', $rootModel = '') {
383 4
        if (!$rootModel) {
384 4
            $rootModel = get_called_class();
385 4
        }
386 4
        $cols = static::cols();
387 4
        if (!$array) {
388 4
            return;
389
        }
390 4
        if (!is_array($array)) {
391 4 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...
392 2
                static::createCol($array);
393 2
                $cols = static::cols(true);
394 2
            }
395 4
            if (!isset($cols[$array]) && isset($cols[static::colPrefix() . $array])) {
396 4
                $array = static::colPrefix() . $array;
397 4
            } else {
398 4
                static::checkForJoin($array, $rootModel);
399
            }
400 4
            return;
401
        }
402
        switch ($searchtype) {
403 2
            case 'key':
404 2
                foreach ($array as $key => $item) {
405 2 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...
406
                        static::createCol($key);
407
                        $cols = static::cols(true);
408
                    }
409 2
                    if (!isset($cols[$key]) && isset($cols[static::colPrefix() . $key])) {
410 2
                        $array[static::colPrefix() . $key] = $item;
411 2
                        unset($array[$key]);
412 2
                        $key = static::colPrefix() . $key;
413 2
                    }
414 2
                    if (is_array($array[$key])) {
415
                        static::fixPrefix($array[$key], 'key', $rootModel);
416
                    } else {
417 2
                        static::checkForJoin($key, $rootModel);
418
                    }
419 2
                }
420 2
                break;
421 1
            case 'first':
422 1
                if (isset($array[0]) && is_string($array[0])) {
423 1
                    if (!isset($cols[static::colPrefix() . $array[0]]) && isset(static::$cols[$array[0]])) {
424
                        static::createCol($array[0]);
425
                        $cols = static::cols(true);
426
                    }
427 1 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...
428 1
                        $array[0] = static::colPrefix() . $array[0];
429 1
                    } else {
430
                        static::checkForJoin($array[0], $rootModel);
431
                    }
432 1
                } elseif (isset($array[0]) && is_array($array[0])) {
433 1
                    foreach ($array as &$item) {
434 1
                        static::fixPrefix($item, 'first', $rootModel);
435 1
                    }
436 1
                }
437 1
                break;
438
        }
439 2
    }
440
441
    /**
442
     * @param boolean $new
443
     */
444 4
    public function logChanges($new) {
445 4
        if (!App::$cur->db->connect || !App::$cur->dashboard) {
446
            return false;
447
        }
448 4
        $class = get_class($this);
449 4
        if (!$class::$logging) {
450 4
            return false;
451
        }
452 2
        $user_id = class_exists('Users\User') ? \Users\User::$cur->id : 0;
453 2
        if (!$new && !empty($this->_changedParams)) {
454
            $activity = new Dashboard\Activity([
455
                'user_id' => $user_id,
456
                'module' => substr($class, 0, strpos($class, '\\')),
457
                'model' => $class,
458
                'item_id' => $this->pk(),
459
                'type' => 'changes'
460
            ]);
461
            $changes_text = [];
462
            foreach ($this->_changedParams as $fullColName => $oldValue) {
463
                $colName = substr($fullColName, strlen($class::colPrefix()));
464 View Code Duplication
                if (isset($class::$cols[$colName]['logging']) && !$class::$cols[$colName]['logging']) {
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...
465
                    continue;
466
                }
467
                if (strlen($oldValue) + strlen($this->_params[$fullColName]) < 200) {
468
                    $changes_text[] = (!empty($class::$labels[$colName]) ? $class::$labels[$colName] : $colName) . ": \"{$oldValue}\" => \"{$this->$colName}\"";
469
                } else {
470
                    $changes_text[] = !empty($class::$labels[$colName]) ? $class::$labels[$colName] : $colName;
471
                }
472
            }
473
            if (!$changes_text) {
474
                return false;
475
            }
476
            $activity->changes_text = implode(', ', $changes_text);
477
            $activity->save();
478
            foreach ($this->_changedParams as $fullColName => $oldValue) {
479
                $colName = substr($fullColName, strlen($class::colPrefix()));
480 View Code Duplication
                if (isset($class::$cols[$colName]['logging']) && !$class::$cols[$colName]['logging']) {
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...
481
                    continue;
482
                }
483
                $colName = substr($fullColName, strlen($class::colPrefix()));
484
                $change = new Dashboard\Activity\Change([
485
                    'activity_id' => $activity->id,
486
                    'col' => $colName,
487
                    'old' => $oldValue,
488
                    'new' => $this->$colName
489
                ]);
490
                $change->save();
491
            }
492 2
        } elseif ($new) {
493 2
            $activity = new Dashboard\Activity([
494 2
                'user_id' => $user_id,
495 2
                'module' => substr($class, 0, strpos($class, '\\')),
496 2
                'model' => $class,
497 2
                'item_id' => $this->pk(),
498
                'type' => 'new'
499 2
            ]);
500 2
            $activity->save();
501 2
        }
502 2
        return true;
503
    }
504
505
    /**
506
     * Check model relations path and load need relations
507
     * 
508
     * @param string $col
509
     * @param string $rootModel
510
     */
511 4
    public static function checkForJoin(&$col, $rootModel) {
512
513 4
        if (strpos($col, ':') !== false) {
514
            $relations = static::relations();
515
            if (isset($relations[substr($col, 0, strpos($col, ':'))])) {
516
                $rel = substr($col, 0, strpos($col, ':'));
517
                $col = substr($col, strpos($col, ':') + 1);
518
519
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
520
                switch ($type) {
521 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...
522
                        $relCol = $relations[$rel]['col'];
523
                        static::fixPrefix($relCol);
524
                        $rootModel::$relJoins[$relations[$rel]['model'] . '_' . $rel] = [$relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol];
525
                        break;
526
                    case 'one':
527 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...
528
                        $relCol = $relations[$rel]['col'];
529
                        $relations[$rel]['model']::fixPrefix($relCol);
530
                        $rootModel::$relJoins[$relations[$rel]['model'] . '_' . $rel] = [$relations[$rel]['model']::table(), static::index() . ' = ' . $relCol];
531
                        break;
532
                }
533
                $relations[$rel]['model']::fixPrefix($col, 'key', $rootModel);
534
            }
535
        }
536 4
    }
537
538
    /**
539
     * Return full col information
540
     * 
541
     * @param string $col
542
     * @return array
543
     */
544
    public static function getColInfo($col) {
545
        return static::parseColRecursion($col);
546
    }
547
548
    /**
549
     * Information extractor for col relations path
550
     * 
551
     * @param string $info
552
     * @return array
553
     */
554
    public static function parseColRecursion($info) {
555
        if (is_string($info)) {
556
            $info = ['col' => $info, 'rawCol' => $info, 'modelName' => '', 'label' => '', 'joins' => []];
557
        }
558
        if (strpos($info['col'], ':') !== false) {
559
            $relations = static::relations();
560
            if (isset($relations[substr($info['col'], 0, strpos($info['col'], ':'))])) {
561
                $rel = substr($info['col'], 0, strpos($info['col'], ':'));
562
                $info['col'] = substr($info['col'], strpos($info['col'], ':') + 1);
563
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
564
                switch ($type) {
565 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...
566
                        $relCol = $relations[$rel]['col'];
567
                        static::fixPrefix($relCol);
568
                        $info['joins'][$relations[$rel]['model'] . '_' . $rel] = [$relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol];
569
                        break;
570 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...
571
                        $relCol = $relations[$rel]['col'];
572
                        $relations[$rel]['model']::fixPrefix($relCol);
573
                        $info['joins'][$relations[$rel]['model'] . '_' . $rel] = [$relations[$rel]['model']::table(), static::index() . ' = ' . $relCol];
574
                        break;
575
                }
576
                $info = $relations[$rel]['model']::parseColRecursion($info);
577
            }
578
        } else {
579
            $cols = static::cols();
580 View Code Duplication
            if (!empty(static::$labels[$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...
581
                $info['label'] = static::$labels[$info['col']];
582
            }
583
584
            if (isset(static::$cols[$info['col']])) {
585
                $info['colParams'] = static::$cols[$info['col']];
586
            } elseif (isset(static::$cols[str_replace(static::colPrefix(), '', $info['col'])])) {
587
                $info['colParams'] = static::$cols[str_replace(static::colPrefix(), '', $info['col'])];
588
            } else {
589
                $info['colParams'] = [];
590
            }
591 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...
592
                $info['col'] = static::colPrefix() . $info['col'];
593
            }
594
            $info['modelName'] = get_called_class();
595
        }
596 View Code Duplication
        if (!empty(static::$labels[$info['rawCol']])) {
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...
597
            $info['label'] = static::$labels[$info['rawCol']];
598
        }
599
        return $info;
600
    }
601
602
    /**
603
     * Return actual cols from data base
604
     * 
605
     * @param boolean $refresh
606
     * @return array
607
     */
608 4
    public static function cols($refresh = false) {
609 4
        if (static::$storage['type'] == 'moduleConfig') {
610 1
            return [];
611
        }
612 4 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...
613 4
            Model::$cols[static::table()] = App::$cur->db->getTableCols(static::table());
614 4
        }
615 4 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...
616
            static::createTable();
617
            Model::$cols[static::table()] = App::$cur->db->getTableCols(static::table());
618
        }
619 4
        return Model::$cols[static::table()];
620
    }
621
622
    /**
623
     * Return cols indexes for create tables
624
     * 
625
     * @return array
626
     */
627 3
    public static function indexes() {
628 3
        return [];
629
    }
630
631
    /**
632
     * Generate params string for col by name
633
     * 
634
     * @param string $colName
635
     * @return false|string
636
     */
637 4
    public static function genColParams($colName) {
638 4
        if (empty(static::$cols[$colName]) || static::$storage['type'] == 'moduleConfig') {
639 1
            return false;
640
        }
641
642 4
        $params = false;
643 4
        switch (static::$cols[$colName]['type']) {
644 4
            case 'select':
645 4
                switch (static::$cols[$colName]['source']) {
646 4
                    case 'relation':
647 4
                        $params = 'int(11) UNSIGNED NOT NULL';
648 4
                        break;
649 1
                    default:
650 1
                        $params = 'varchar(255) NOT NULL';
651 4
                }
652 4
                break;
653 4
            case 'image':
654 4
            case 'file':
655 1
                $params = 'int(11) UNSIGNED NOT NULL';
656 1
                break;
657 4
            case 'number':
658
                $params = 'int(11) NOT NULL';
659
                break;
660 4
            case 'text':
661 4
            case 'email':
662 3
                $params = 'varchar(255) NOT NULL';
663 3
                break;
664 3
            case 'html':
665 3
            case 'textarea':
666 3
            case 'json':
667 3
            case 'password':
668 3
            case 'dynamicType':
669 3
            case 'map':
670 1
                $params = 'text NOT NULL';
671 1
                break;
672 3
            case 'bool':
673 1
                $params = 'tinyint(1) UNSIGNED NOT NULL';
674 1
                break;
675 3
            case 'decimal':
676
                $params = 'decimal(8, 2) NOT NULL';
677
                break;
678 3
            case 'date':
679 1
                $params = 'date NOT NULL DEFAULT 0';
680 1
                break;
681 3
            case 'dateTime':
682 2
                $params = 'timestamp NOT NULL DEFAULT 0';
683 2
                break;
684 4
        }
685 4
        return $params;
686
    }
687
688
    /**
689
     * Create new col in data base
690
     * 
691
     * @param string $colName
692
     * @return boolean|integer
693
     */
694 2
    public static function createCol($colName) {
695 2
        $params = static::genColParams($colName);
696 2
        if ($params === false) {
697 2
            return false;
698
        }
699
        return App::$cur->db->addCol(static::table(), static::colPrefix() . $colName, $params);
700
    }
701
702 4
    public static function createTable() {
703 4
        if (static::$storage['type'] == 'moduleConfig') {
704
            return true;
705
        }
706 4
        if (!App::$cur->db) {
707
            return false;
708
        }
709
710 4
        $query = App::$cur->db->newQuery();
711 4
        if (!$query) {
712
            return false;
713
        }
714
715 4
        if (!isset($this)) {
716 4
            $tableName = static::table();
717 4
            $colPrefix = static::colPrefix();
718 4
            $indexes = static::indexes();
719 4
        } else {
720
            $tableName = $this->table();
721
            $colPrefix = $this->colPrefix();
722
            $indexes = $this->indexes();
723
        }
724 4
        if (App::$cur->db->tableExist($tableName)) {
725
            return true;
726
        }
727
        $cols = [
728 4
            $colPrefix . 'id' => 'pk'
729 4
        ];
730 4
        $className = get_called_class();
731 4
        if (!empty($className::$cols)) {
732 4
            foreach ($className::$cols as $colName => $colParams) {
733 4
                if ($colName == 'date_create') {
734 4
                    $cols[$colPrefix . 'date_create'] = 'timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP';
735 4
                    continue;
736
                }
737 4
                $params = $className::genColParams($colName);
738 4
                if ($params) {
739 4
                    $cols[$colPrefix . $colName] = $params;
740 4
                }
741 4
            }
742 4
        }
743 4
        if (empty($cols[$colPrefix . 'date_create'])) {
744 1
            $cols[$colPrefix . 'date_create'] = 'timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP';
745 1
        }
746 4
        $tableIndexes = [];
747 4
        if ($indexes) {
748 1
            foreach ($indexes as $indexName => $index) {
749 1
                $tableIndexes[] = $index['type'] . ' ' . App::$cur->db->table_prefix . $indexName . ' (' . implode(',', $index['cols']) . ')';
750 1
            }
751 1
        }
752
753 4
        $query->createTable($tableName, $cols, $tableIndexes);
754 4
        return true;
755
    }
756
757
    /**
758
     * Return table name
759
     * 
760
     * @return string
761
     */
762 4
    public static function table() {
763 4
        return strtolower(str_replace('\\', '_', get_called_class()));
764
    }
765
766
    /**
767
     * Return table index col name
768
     * 
769
     * @return string
770
     */
771 4
    public static function index() {
772
773 4
        return static::colPrefix() . 'id';
774
    }
775
776
    /**
777
     * Return col prefix
778
     * 
779
     * @return string
780
     */
781 4
    public static function colPrefix() {
782 4
        $classPath = explode('\\', get_called_class());
783 4
        $classPath = array_slice($classPath, 1);
784 4
        return strtolower(implode('_', $classPath)) . '_';
785
    }
786
787
    /**
788
     * return relations list
789
     * 
790
     * @return string
791
     */
792 1
    public static function relations() {
793 1
        return [];
794
    }
795
796
    /**
797
     * views list
798
     * 
799
     * @return array
800
     */
801
    public static $views = [];
802
803
    /**
804
     * Return name of col with object name
805
     * 
806
     * @return string
807
     */
808
    public static function nameCol() {
809
        return 'name';
810
    }
811
812
    /**
813
     * Return object name
814
     * 
815
     * @return string
816
     */
817
    public function name() {
818
        return $this->{$this->nameCol()} ? $this->{$this->nameCol()} : '№' . $this->pk();
819
    }
820
821
    /**
822
     * Get single object from data base
823
     * 
824
     * @param mixed $param
825
     * @param string $col
826
     * @param array $options
827
     * @return boolean|\Model
828
     */
829 4
    public static function get($param, $col = null, $options = []) {
830 4
        if (static::$storage['type'] == 'moduleConfig') {
831
            return static::getFromModuleStorage($param, $col, $options);
832
        }
833 4
        if (!empty($col)) {
834 4
            static::fixPrefix($col);
835 4
        }
836
837 4
        if (is_array($param)) {
838 1
            static::fixPrefix($param, 'first');
839 1
        }
840 4
        foreach (static::$relJoins as $join) {
841
            App::$cur->db->join($join[0], $join[1]);
842 4
        }
843 4
        static::$relJoins = [];
844 4
        foreach (static::$needJoin as $rel) {
845
            $relations = static::relations();
846
            if (isset($relations[$rel])) {
847
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
848
                switch ($type) {
849
                    case 'to':
850
                        $relCol = $relations[$rel]['col'];
851
                        static::fixPrefix($relCol);
852
                        App::$cur->db->join($relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol);
853
                        break;
854
                    case 'one':
855
                        $col = $relations[$rel]['col'];
856
                        $relations[$rel]['model']::fixPrefix($col);
857
                        App::$cur->db->join($relations[$rel]['model']::table(), static::index() . ' = ' . $col);
858
                        break;
859
                }
860
            }
861 4
        }
862 4
        static::$needJoin = [];
863 4
        if (is_array($param)) {
864 1
            App::$cur->db->where($param);
865 1
        } else {
866 4
            if ($col === null) {
867
868 3
                $col = static::index();
869 3
            }
870 4
            if ($param !== null) {
871 4
                $cols = static::cols();
872 4
                if (!isset($cols[$col]) && isset($cols[static::colPrefix() . $col])) {
873
                    $col = static::colPrefix() . $col;
874
                }
875 4
                App::$cur->db->where($col, $param);
876 4
            } else {
877
                return false;
878
            }
879
        }
880 4
        if (!App::$cur->db->where) {
881
            return false;
882
        }
883
        try {
884 4
            $result = App::$cur->db->select(static::table());
885 4
        } catch (PDOException $exc) {
886
            if ($exc->getCode() == '42S02') {
887
                static::createTable();
888
            } else {
889
                throw $exc;
890
            }
891
            $result = App::$cur->db->select(static::table());
892
        }
893 4
        if (!$result) {
894
            return false;
895
        }
896 4
        return $result->fetch(get_called_class());
897
    }
898
899
    /**
900
     * Old method
901
     * 
902
     * @param type $options
903
     * @return Array
904
     */
905
    public static function get_list($options = []) {
906
        $query = App::$cur->db->newQuery();
907
        if (!$query) {
908
            return [];
909
        }
910
        if (!empty($options['where'])) {
911
            $query->where($options['where']);
912
        }
913
        if (!empty($options['cols'])) {
914
            $query->cols = $options['cols'];
915
        }
916
        if (!empty($options['group'])) {
917
            $query->group($options['group']);
918
        }
919
        if (!empty($options['having'])) {
920
            $query->having($options['having']);
921
        }
922
        if (!empty($options['order'])) {
923
            $query->order($options['order']);
924
        }
925
        if (!empty($options['join'])) {
926
            $query->join($options['join']);
927
        }
928
        if (!empty($options['distinct'])) {
929
            $query->distinct = $options['distinct'];
930
        }
931
932
        foreach (static::$relJoins as $join) {
933
            $query->join($join[0], $join[1]);
934
        }
935
        static::$relJoins = [];
936 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...
937
            $relations = static::relations();
938
            if (isset($relations[$rel])) {
939
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
940
                switch ($type) {
941
                    case 'to':
942
                        $relCol = $relations[$rel]['col'];
943
                        static::fixPrefix($relCol);
944
                        $query->join($relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol);
945
                        break;
946
                    case 'one':
947
                        $col = $relations[$rel]['col'];
948
                        $relations[$rel]['model']::fixPrefix($col);
949
                        $query->join($relations[$rel]['model']::table(), static::index() . ' = ' . $col);
950
                        break;
951
                }
952
            }
953
        }
954
        static::$needJoin = [];
955
956 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...
957
            $limit = (int) $options['limit'];
958
        } else {
959
            $limit = 0;
960
        }
961 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...
962
            $start = (int) $options['start'];
963
        } else {
964
            $start = 0;
965
        }
966
        if ($limit || $start) {
967
            $query->limit($start, $limit);
968
        }
969
        if (isset($options['key'])) {
970
            $key = $options['key'];
971
        } else {
972
            $key = static::index();
973
        }
974
        try {
975
            $query->operation = 'SELECT';
976
            $query->table = static::table();
977
            $queryArr = $query->buildQuery();
978
            $result = $query->query($queryArr);
979
        } catch (PDOException $exc) {
980
            if ($exc->getCode() == '42S02') {
981
                static::createTable();
982
                $result = $query->query($queryArr);
983
            } else {
984
                throw $exc;
985
            }
986
        }
987
988
        if (!empty($options['array'])) {
989
            return $result->getArray($key);
990
        }
991
        $list = $result->getObjects(get_called_class(), $key);
992 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...
993
            $return = [];
994
            foreach ($list as $key => $item) {
995
                $return[$key] = $item->name();
996
            }
997
            return $return;
998
        }
999
        return $list;
1000
    }
1001
1002
    /**
1003
     * Return list of objects from data base
1004
     * 
1005
     * @param type $options
1006
     * @return type
1007
     */
1008
    public static function getList($options = []) {
1009
        if (static::$storage['type'] != 'db') {
1010
            return static::getListFromModuleStorage($options);
1011
        }
1012
        if (!empty($options['where'])) {
1013
            static::fixPrefix($options['where'], 'first');
1014
        }
1015
        if (!empty($options['group'])) {
1016
            static::fixPrefix($options['group'], 'first');
1017
        }
1018
        if (!empty($options['order'])) {
1019
            static::fixPrefix($options['order'], 'first');
1020
        }
1021
        if (!empty($options['having'])) {
1022
            static::fixPrefix($options['having'], 'first');
1023
        }
1024
        return static::get_list($options);
1025
    }
1026
1027
    /**
1028
     * Get single item from module storage
1029
     * 
1030
     * @param array $param
1031
     * @param string $col
1032
     * @param array $options
1033
     * @return boolean|\Model
1034
     */
1035
    public static function getFromModuleStorage($param = null, $col = null, $options = []) {
1036
        if ($col === null) {
1037
1038
            $col = static::index();
1039
        }
1040
        if ($param == null) {
1041
            return false;
1042
        }
1043
        $classPath = explode('\\', get_called_class());
1044 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...
1045
            $moduleConfig = Config::share($classPath[0]);
1046
        } else {
1047
            $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
1048
        }
1049
        $appType = App::$cur->type;
1050 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...
1051
            if (!empty($options['appType'])) {
1052
                $appType = $options['appType'];
1053
            }
1054
            $storage = !empty($moduleConfig['storage'][$appType]) ? $moduleConfig['storage'][$appType] : [];
1055
        } else {
1056
            $storage = !empty($moduleConfig['storage']) ? $moduleConfig['storage'] : [];
1057
        }
1058
        if (!empty($storage[$classPath[1]])) {
1059
            $items = $storage[$classPath[1]];
1060
            $class = get_called_class();
1061
            $where = is_array($param) ? $param : [$col, $param];
1062
            foreach ($items as $key => $item) {
1063
                if (!Model::checkWhere($item, $where)) {
1064
                    continue;
1065
                }
1066
                if (!empty($options['array'])) {
1067
                    return $item;
1068
                }
1069
                $item = new $class($item);
1070
                $item->appType = $appType;
1071
                return $item;
1072
            }
1073
        }
1074
        return false;
1075
    }
1076
1077
    /**
1078
     * Return list items from module storage
1079
     * 
1080
     * @param array $options
1081
     * @return array
1082
     */
1083
    public static function getListFromModuleStorage($options = []) {
1084
        $classPath = explode('\\', get_called_class());
1085 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...
1086
            $moduleConfig = Config::share($classPath[0]);
1087
        } else {
1088
            $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
1089
        }
1090 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...
1091
            if (empty($options['appType'])) {
1092
                $appType = App::$cur->type;
1093
            } else {
1094
                $appType = $options['appType'];
1095
            }
1096
            $storage = !empty($moduleConfig['storage'][$appType]) ? $moduleConfig['storage'][$appType] : [];
1097
        } else {
1098
            $storage = !empty($moduleConfig['storage']) ? $moduleConfig['storage'] : [];
1099
        }
1100
        if (!empty($storage[$classPath[1]])) {
1101
            $items = [];
1102
            $class = get_called_class();
1103
            if (isset($options['key'])) {
1104
                $arrayKey = $options['key'];
1105
            } else {
1106
                $arrayKey = static::index();
1107
            }
1108
            foreach ($storage[$classPath[1]] as $key => $item) {
1109
                if (!empty($options['where']) && !Model::checkWhere($item, $options['where'])) {
1110
                    continue;
1111
                }
1112
                $items[$item[$arrayKey]] = new $class($item);
1113
            }
1114
            if (!empty($options['order'])) {
1115
                usort($items, function($a, $b) use($options) {
1116
                    if ($a->{$options['order'][0]} > $b->{$options['order'][0]} && $options['order'][1] = 'asc') {
1117
                        return 1;
1118
                    } elseif ($a->{$options['order'][0]} < $b->{$options['order'][0]} && $options['order'][1] = 'asc') {
1119
                        return -1;
1120
                    }
1121
                    return 0;
1122
                });
1123
            }
1124 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...
1125
                $return = [];
1126
                foreach ($items as $key => $item) {
1127
                    $return[$key] = $item->name();
1128
                }
1129
                return $return;
1130
            }
1131
            return $items;
1132
        }
1133
        return [];
1134
    }
1135
1136
    /**
1137
     * Return count of records from module storage
1138
     * 
1139
     * @param array $options
1140
     * @return int
1141
     */
1142
    public static function getCountFromModuleStorage($options = []) {
1143
1144
        $classPath = explode('\\', get_called_class());
1145
        $count = 0;
1146
        if (empty($options['appType'])) {
1147
            $appType = App::$cur->type;
1148
        } else {
1149
            $appType = $options['appType'];
1150
        }
1151 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...
1152
            $moduleConfig = Config::share($classPath[0]);
1153
        } else {
1154
            $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
1155
        }
1156
        if (!empty($moduleConfig['storage'][$appType][$classPath[1]])) {
1157
            $items = $moduleConfig['storage'][$appType][$classPath[1]];
1158
            if (empty($options['where'])) {
1159
                return count($items);
1160
            }
1161
            foreach ($items as $key => $item) {
1162
                if (!empty($options['where'])) {
1163
                    if (Model::checkWhere($item, $options['where'])) {
1164
                        $count++;
1165
                    }
1166
                } else {
1167
                    $count++;
1168
                }
1169
            }
1170
        }
1171
        return $count;
1172
    }
1173
1174
    /**
1175
     * Check where for module storage query
1176
     * 
1177
     * @param array $item
1178
     * @param array|string $where
1179
     * @param string $value
1180
     * @param string $operation
1181
     * @param string $concatenation
1182
     * @return boolean
1183
     */
1184
    public static function checkWhere($item = [], $where = '', $value = '', $operation = '=', $concatenation = 'AND') {
1185
1186
        if (is_array($where)) {
1187
            if (is_array($where[0])) {
1188
                $result = true;
1189
                foreach ($where as $key => $whereItem) {
1190
                    $concatenation = empty($whereItem[3]) ? 'AND' : strtoupper($whereItem[3]);
1191
                    switch ($concatenation) {
1192 View Code Duplication
                        case 'AND':
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...
1193
                            $result = $result && forward_static_call_array(['Model', 'checkWhere'], [$item, $whereItem]);
1194
                            break;
1195 View Code Duplication
                        case 'OR':
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...
1196
                            $result = $result || forward_static_call_array(['Model', 'checkWhere'], [$item, $whereItem]);
1197
                            break;
1198
                    }
1199
                }
1200
1201
                return $result;
1202
            } else {
1203
                return forward_static_call_array(['Model', 'checkWhere'], array_merge([$item], $where));
1204
            }
1205
        }
1206
        if (!isset($item[$where]) && !$value) {
1207
            return true;
1208
        }
1209
        if (!isset($item[$where]) && $value) {
1210
            return false;
1211
        }
1212
        if ($item[$where] == $value) {
1213
            return true;
1214
        }
1215
        return false;
1216
    }
1217
1218
    /**
1219
     * Return count of records from data base
1220
     * 
1221
     * @param array $options
1222
     * @return array|int
1223
     */
1224
    public static function getCount($options = []) {
1225
        if (static::$storage['type'] == 'moduleConfig') {
1226
            return static::getCountFromModuleStorage($options);
1227
        }
1228
        $query = App::$cur->db->newQuery();
1229
        if (!$query) {
1230
            return 0;
1231
        }
1232
        if (!empty($options['where'])) {
1233
            static::fixPrefix($options['where'], 'first');
1234
        }
1235
        if (!empty($options['group'])) {
1236
            static::fixPrefix($options['group'], 'first');
1237
        }
1238
        if (!empty($options['order'])) {
1239
            static::fixPrefix($options['order'], 'first');
1240
        }
1241
        if (!empty($options['where'])) {
1242
            $query->where($options['where']);
1243
        }
1244
        if (!empty($options['join'])) {
1245
            $query->join($options['join']);
1246
        }
1247
        if (!empty($options['order'])) {
1248
            $query->order($options['order']);
1249
        }
1250 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...
1251
            $limit = (int) $options['limit'];
1252
        } else {
1253
            $limit = 0;
1254
        }
1255 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...
1256
            $start = (int) $options['start'];
1257
        } else {
1258
            $start = 0;
1259
        }
1260
        if ($limit || $start) {
1261
            $query->limit($start, $limit);
1262
        }
1263
1264
        foreach (static::$relJoins as $join) {
1265
            $query->join($join[0], $join[1]);
1266
        }
1267
        static::$relJoins = [];
1268 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...
1269
            $relations = static::relations();
1270
            if (isset($relations[$rel])) {
1271
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
1272
                switch ($type) {
1273
                    case 'to':
1274
                        $relCol = $relations[$rel]['col'];
1275
                        static::fixPrefix($relCol);
1276
                        $query->join($relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol);
1277
                        break;
1278
                    case 'one':
1279
                        $col = $relations[$rel]['col'];
1280
                        $relations[$rel]['model']::fixPrefix($col);
1281
                        $query->join($relations[$rel]['model']::table(), static::index() . ' = ' . $col);
1282
                        break;
1283
                }
1284
            }
1285
        }
1286
        static::$needJoin = [];
1287
        $cols = 'COUNT(';
1288
1289
        if (!empty($options['distinct'])) {
1290
            if (is_bool($options['distinct'])) {
1291
                $cols .= 'DISTINCT *';
1292
            } else {
1293
                $cols .= "DISTINCT {$options['distinct']}";
1294
            }
1295
        } else {
1296
            $cols .= '*';
1297
        }
1298
        $cols .=') as `count`' . (!empty($options['cols']) ? ',' . $options['cols'] : '');
1299
        $query->cols = $cols;
1300
        if (!empty($options['group'])) {
1301
            $query->group($options['group']);
1302
        }
1303
        try {
1304
            $result = $query->select(static::table());
1305
        } catch (PDOException $exc) {
1306
            if ($exc->getCode() == '42S02') {
1307
                static::createTable();
1308
            } else {
1309
                throw $exc;
1310
            }
1311
            $result = $query->select(static::table());
1312
        }
1313
        if (!empty($options['group'])) {
1314
            $count = $result->getArray();
1315
            return $count;
1316
        } else {
1317
            $count = $result->fetch();
1318
            return $count['count'];
1319
        }
1320
    }
1321
1322
    /**
1323
     * Update records in data base
1324
     * 
1325
     * @param array $params
1326
     * @param array $where
1327
     * @return false|null
1328
     */
1329
    public static function update($params, $where = []) {
1330
        static::fixPrefix($params);
1331
1332
        $cols = self::cols();
1333
1334
        $values = [];
1335
        foreach ($cols as $col => $param) {
1336
            if (isset($params[$col])) {
1337
                $values[$col] = $params[$col];
1338
            }
1339
        }
1340
        if (empty($values)) {
1341
            return false;
1342
        }
1343
1344
        if (!empty($where)) {
1345
            static::fixPrefix($where, 'first');
1346
1347
            App::$cur->db->where($where);
1348
        }
1349
        App::$cur->db->update(static::table(), $values);
1350
    }
1351
1352
    /**
1353
     * Return primary key of object
1354
     * 
1355
     * @return mixed
1356
     */
1357 4
    public function pk() {
1358 4
        return $this->{$this->index()};
1359
    }
1360
1361
    /**
1362
     * Before save trigger
1363
     */
1364 4
    public function beforeSave() {
1365
        
1366 4
    }
1367
1368
    /**
1369
     * Save object to module storage
1370
     * 
1371
     * @param array $options
1372
     * @return boolean
1373
     */
1374 1
    public function saveModuleStorage($options) {
1375
1376 1
        $col = static::index();
1377 1
        $id = $this->pk();
1378 1
        $appType = '';
1379 1
        $classPath = explode('\\', get_called_class());
1380
1381 1 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...
1382
            $moduleConfig = Config::share($classPath[0]);
1383
        } else {
1384 1
            $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
1385
        }
1386
1387 1 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...
1388 1
            if (empty($options['appType'])) {
1389
                $appType = App::$cur->type;
1390
            } else {
1391 1
                $appType = $options['appType'];
1392
            }
1393 1
            $storage = !empty($moduleConfig['storage'][$appType]) ? $moduleConfig['storage'][$appType] : [];
1394 1
        } else {
1395
            $storage = !empty($moduleConfig['storage']) ? $moduleConfig['storage'] : [];
1396
        }
1397 1
        if (empty($storage[$classPath[1]])) {
1398
            $storage[$classPath[1]] = [];
1399
        }
1400 1
        if ($id) {
1401 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...
1402
                if ($item[$col] == $id) {
1403
                    $storage[$classPath[1]][$key] = $this->_params;
1404
                    break;
1405
                }
1406
            }
1407
        } else {
1408 1
            $id = !empty($storage['scheme'][$classPath[1]]['ai']) ? $storage['scheme'][$classPath[1]]['ai'] : 1;
1409 1
            $this->$col = $id;
1410 1
            $storage['scheme'][$classPath[1]]['ai'] = $id + 1;
1411 1
            $storage[$classPath[1]][] = $this->_params;
1412
        }
1413 1 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...
1414 1
            $moduleConfig['storage'][$appType] = $storage;
1415 1
        } else {
1416
            $moduleConfig['storage'] = $storage;
1417
        }
1418 1 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...
1419 1
            Config::save('module', $moduleConfig, $classPath[0]);
1420 1
        } else {
1421
            Config::save('share', $moduleConfig, $classPath[0]);
1422
        }
1423 1
        return true;
1424
    }
1425
1426
    /**
1427
     * Update tree path category
1428
     */
1429
    public function changeCategoryTree() {
1430
        $class = get_class($this);
1431
        $itemModel = $class::$treeCategory;
1432
        $oldPath = $this->tree_path;
1433
        $this->tree_path = $this->getCatalogTree($this);
1434
        $itemsTable = \App::$cur->db->table_prefix . $itemModel::table();
1435
        $itemTreeCol = $itemModel::colPrefix() . 'tree_path';
1436
1437
        $categoryTreeCol = $this->colPrefix() . 'tree_path';
1438
        $categoryTable = \App::$cur->db->table_prefix . $this->table();
1439
        if ($oldPath) {
1440
            \App::$cur->db->query('UPDATE
1441
                ' . $categoryTable . ' 
1442
                    SET 
1443
                        ' . $categoryTreeCol . ' = REPLACE(' . $categoryTreeCol . ', "' . $oldPath . $this->id . '/' . '", "' . $this->tree_path . $this->id . '/' . '") 
1444
                    WHERE ' . $categoryTreeCol . ' LIKE "' . $oldPath . $this->id . '/' . '%"');
1445
1446
            \App::$cur->db->query('UPDATE
1447
                ' . $itemsTable . '
1448
                    SET 
1449
                        ' . $itemTreeCol . ' = REPLACE(' . $itemTreeCol . ', "' . $oldPath . $this->id . '/' . '", "' . $this->tree_path . $this->id . '/' . '") 
1450
                    WHERE ' . $itemTreeCol . ' LIKE "' . $oldPath . $this->id . '/' . '%"');
1451
        }
1452
        $itemModel::update([$itemTreeCol => $this->tree_path . $this->id . '/'], [$itemModel::colPrefix() . $this->index(), $this->id]);
1453
    }
1454
1455
    /**
1456
     * Return tree path
1457
     * 
1458
     * @param \Model $catalog
1459
     * @return string
1460
     */
1461
    public function getCatalogTree($catalog) {
1462
        $catalogClass = get_class($catalog);
1463
        $catalogParent = $catalogClass::get($catalog->parent_id);
1464
        if ($catalog && $catalogParent) {
1465
            if ($catalogParent->tree_path) {
1466
                return $catalogParent->tree_path . $catalogParent->id . '/';
1467
            } else {
1468
                return $this->getCatalogTree($catalogParent) . $catalogParent->id . '/';
1469
            }
1470
        }
1471
        return '/';
1472
    }
1473
1474
    /**
1475
     * Update tree path item
1476
     */
1477
    public function changeItemTree() {
1478
        $class = get_class($this);
1479
        $categoryModel = $class::$categoryModel;
1480
        $category = $categoryModel::get($this->{$categoryModel::index()});
1481
        if ($category) {
1482
            $this->tree_path = $category->tree_path . $category->pk() . '/';
1483
        } else {
1484
            $this->tree_path = '/';
1485
        }
1486
    }
1487
1488
    /**
1489
     * Save object to data base
1490
     * 
1491
     * @param array $options
1492
     * @return boolean|int
1493
     */
1494 4
    public function save($options = []) {
1495
1496 4
        if (static::$storage['type'] == 'moduleConfig') {
1497 1
            return static::saveModuleStorage($options);
1498
        }
1499 4
        $class = get_class($this);
1500 4
        if ($class::$categoryModel) {
1501
            $this->changeItemTree();
1502
        }
1503 4
        if ($class::$treeCategory) {
1504
            $this->changeCategoryTree();
1505
        }
1506 4
        if (!empty($this->_changedParams) && $this->pk()) {
1507 3
            Inji::$inst->event('modelItemParamsChanged-' . get_called_class(), $this);
1508 3
        }
1509 4
        $this->beforeSave();
1510 4
        $values = [];
1511
1512 4
        foreach ($this->cols() as $col => $param) {
1513 4
            if (isset($this->_params[$col])) {
1514 4
                $values[$col] = $this->_params[$col];
1515 4
            }
1516 4
        }
1517 4
        foreach ($class::$cols as $colName => $params) {
1518 4
            $class::fixPrefix($colName);
1519 4
            if (isset($params['default']) && !isset($values[$colName])) {
1520
                $this->_params[$colName] = $values[$colName] = $params['default'];
1521
            }
1522 4
        }
1523 4
        if (empty($values) && empty($options['empty'])) {
1524
            return false;
1525
        }
1526
1527 4
        if ($this->pk()) {
1528 3
            $new = false;
1529 3
            if ($this->get($this->_params[$this->index()])) {
1530 3
                App::$cur->db->where($this->index(), $this->_params[$this->index()]);
1531 3
                App::$cur->db->update($this->table(), $values);
1532 3
            } else {
1533
1534
                $this->_params[$this->index()] = App::$cur->db->insert($this->table(), $values);
1535
            }
1536 3
        } else {
1537 4
            $new = true;
1538 4
            $this->_params[$this->index()] = App::$cur->db->insert($this->table(), $values);
1539
        }
1540 4
        $this->logChanges($new);
1541 4
        App::$cur->db->where($this->index(), $this->_params[$this->index()]);
1542
        try {
1543 4
            $result = App::$cur->db->select($this->table());
1544 4
        } catch (PDOException $exc) {
1545
            if ($exc->getCode() == '42S02') {
1546
                $this->createTable();
1547
            }
1548
            $result = App::$cur->db->select($this->table());
1549
        }
1550 4
        $this->_params = $result->fetch();
1551 4
        if ($new) {
1552 4
            Inji::$inst->event('modelCreatedItem-' . get_called_class(), $this);
1553 4
        }
1554 4
        $this->afterSave();
1555 4
        return $this->{$this->index()};
1556
    }
1557
1558
    /**
1559
     * After save trigger
1560
     */
1561 4
    public function afterSave() {
1562
        
1563 4
    }
1564
1565
    /**
1566
     * Before delete trigger
1567
     */
1568 1
    public function beforeDelete() {
1569
        
1570 1
    }
1571
1572
    /**
1573
     * Delete item from module storage
1574
     * 
1575
     * @param array $options
1576
     * @return boolean
1577
     */
1578
    public function deleteFromModuleStorage($options) {
1579
1580
        $col = static::index();
1581
        $id = $this->pk();
1582
        $appType = '';
1583
        $classPath = explode('\\', get_called_class());
1584 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...
1585
            $moduleConfig = Config::share($classPath[0]);
1586
        } else {
1587
            $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
1588
        }
1589
1590 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...
1591
            if (empty($options['appType'])) {
1592
                $appType = App::$cur->type;
1593
            } else {
1594
                $appType = $options['appType'];
1595
            }
1596
            $storage = !empty($moduleConfig['storage'][$appType]) ? $moduleConfig['storage'][$appType] : [];
1597
        } else {
1598
            $storage = !empty($moduleConfig['storage']) ? $moduleConfig['storage'] : [];
1599
        }
1600
        if (empty($storage[$classPath[1]])) {
1601
            $storage[$classPath[1]] = [];
1602
        }
1603 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...
1604
1605
            if ($item[$col] == $id) {
1606
                unset($storage[$classPath[1]][$key]);
1607
                break;
1608
            }
1609
        }
1610 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...
1611
            $moduleConfig['storage'][$appType] = $storage;
1612
        } else {
1613
            $moduleConfig['storage'] = $storage;
1614
        }
1615 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...
1616
            Config::save('module', $moduleConfig, $classPath[0]);
1617
        } else {
1618
            Config::save('share', $moduleConfig, $classPath[0]);
1619
        }
1620
        return true;
1621
    }
1622
1623
    /**
1624
     * Delete item from data base
1625
     * 
1626
     * @param array $options
1627
     * @return boolean
1628
     */
1629 1
    public function delete($options = []) {
1630 1
        $this->beforeDelete();
1631
1632 1
        if (static::$storage['type'] == 'moduleConfig') {
1633
            return static::deleteFromModuleStorage($options);
1634
        }
1635 1
        if (!empty($this->_params[$this->index()])) {
1636 1
            App::$cur->db->where($this->index(), $this->_params[$this->index()]);
1637 1
            $result = App::$cur->db->delete($this->table());
1638 1
            if ($result) {
1639 1
                $this->afterDelete();
1640 1
                return $result;
1641
            }
1642
        }
1643
        return false;
1644
    }
1645
1646
    /**
1647
     * Delete items from data base
1648
     * 
1649
     * @param array $where
1650
     */
1651 4
    public static function deleteList($where = []) {
1652 4
        if (!empty($where)) {
1653
            static::fixPrefix($where, 'first');
1654
            App::$cur->db->where($where);
1655
        }
1656 4
        App::$cur->db->delete(static::table());
1657 4
    }
1658
1659
    /**
1660
     * After delete trigger
1661
     */
1662 1
    public function afterDelete() {
1663
        
1664 1
    }
1665
1666
    /**
1667
     * find relation for col name
1668
     * 
1669
     * @param string $col
1670
     * @return array|null
1671
     */
1672
    public static function findRelation($col) {
1673
1674
        foreach (static::relations() as $relName => $rel) {
1675
            if ($rel['col'] == $col) {
1676
                return $relName;
1677
            }
1678
        }
1679
        return null;
1680
    }
1681
1682
    /**
1683
     * Set params for model
1684
     * 
1685
     * @param array $params
1686
     */
1687 4
    public function setParams($params) {
1688 4
        static::fixPrefix($params);
1689 4
        $className = get_called_class();
1690 4
        foreach ($params as $paramName => $value) {
1691 2
            $shortName = preg_replace('!' . $this->colPrefix() . '!', '', $paramName);
1692 2
            if (!empty($className::$cols[$shortName])) {
1693 2
                switch ($className::$cols[$shortName]['type']) {
1694 2
                    case 'decimal':
1695
                        $params[$paramName] = (float) $value;
1696
                        break;
1697 2
                    case 'number':
1698 2
                        $params[$paramName] = (int) $value;
1699 2
                        break;
1700 2
                    case 'bool':
1701 1
                        $params[$paramName] = (bool) $value;
1702 1
                        break;
1703 2
                }
1704 2
            }
1705 4
        }
1706 4
        $this->_params = array_merge($this->_params, $params);
1707 4
    }
1708
1709
    /**
1710
     * Return relation
1711
     * 
1712
     * @param string $relName
1713
     * @return array|boolean
1714
     */
1715 4
    public static function getRelation($relName) {
1716 4
        $relations = static::relations();
1717 4
        return !empty($relations[$relName]) ? $relations[$relName] : false;
1718
    }
1719
1720
    /**
1721
     * Load relation
1722
     * 
1723
     * @param string $name
1724
     * @param array $params
1725
     * @return null|array|integer|\Model
1726
     */
1727 4
    public function loadRelation($name, $params = []) {
1728 4
        $relation = static::getRelation($name);
1729 4
        if ($relation) {
1730 2
            if (!isset($relation['type'])) {
1731 2
                $type = 'to';
1732 2
            } else {
1733
                $type = $relation['type'];
1734
            }
1735 2
            $getCol = null;
1736 2
            $getParams = [];
1737
            switch ($type) {
1738 2
                case 'relModel':
1739
                    if (!$this->pk()) {
1740
                        return [];
1741
                    }
1742
                    $fixedCol = $relation['model']::index();
1743
                    $relation['relModel']::fixPrefix($fixedCol);
1744
                    $ids = array_keys($relation['relModel']::getList(['where' => [$this->index(), $this->pk()], 'array' => true, 'key' => $fixedCol]));
1745
                    if (empty($ids)) {
1746
                        if (empty($params['count'])) {
1747
                            return [];
1748
                        } else {
1749
                            return 0;
1750
                        }
1751
                    }
1752
                    $getType = 'getList';
1753
                    $options = [
1754
                        'where' => [$relation['model']::index(), implode(',', $ids), 'IN'],
1755
                        'array' => (!empty($params['array'])) ? true : false,
1756
                        'key' => (isset($params['key'])) ? $params['key'] : ((isset($relation['resultKey'])) ? $relation['resultKey'] : null),
1757
                        'start' => (isset($params['start'])) ? $params['start'] : ((isset($relation['start'])) ? $relation['start'] : null),
1758
                        'order' => (isset($params['order'])) ? $params['order'] : ((isset($relation['order'])) ? $relation['order'] : null),
1759
                        'limit' => (isset($params['limit'])) ? $params['limit'] : ((isset($relation['limit'])) ? $relation['limit'] : null),
1760
                    ];
1761
                    break;
1762 2
                case 'many':
1763
                    if (!$this->{$this->index()}) {
1764
                        return [];
1765
                    }
1766
                    $getType = 'getList';
1767
                    $options = [
1768
                        'join' => (isset($relation['join'])) ? $relation['join'] : null,
1769
                        'key' => (isset($params['key'])) ? $params['key'] : ((isset($relation['resultKey'])) ? $relation['resultKey'] : null),
1770
                        'array' => (!empty($params['array'])) ? true : false,
1771
                        'forSelect' => (!empty($params['forSelect'])) ? true : false,
1772
                        'order' => (isset($params['order'])) ? $params['order'] : ((isset($relation['order'])) ? $relation['order'] : null),
1773
                        'start' => (isset($params['start'])) ? $params['start'] : ((isset($relation['start'])) ? $relation['start'] : null),
1774
                        'limit' => (isset($params['limit'])) ? $params['limit'] : ((isset($relation['limit'])) ? $relation['limit'] : null),
1775
                        'appType' => (isset($params['appType'])) ? $params['appType'] : ((isset($relation['appType'])) ? $relation['appType'] : null),
1776
                        'where' => []
1777
                    ];
1778
                    $options['where'][] = [$relation['col'], $this->{$this->index()}];
1779
                    if (!empty($relation['where'])) {
1780
                        $options['where'] = array_merge($options['where'], [$relation['where']]);
1781
                    }
1782
                    if (!empty($params['where'])) {
1783
                        $options['where'] = array_merge($options['where'], [$params['where']]);
1784
                    }
1785
                    break;
1786 2
                case 'one':
1787
                    $getType = 'get';
1788
                    $options = [$relation['col'], $this->pk()];
1789
                    break;
1790 2
                default:
1791 2
                    if ($this->$relation['col'] === null) {
1792
                        return null;
1793
                    }
1794 2
                    $getType = 'get';
1795 2
                    $options = $this->$relation['col'];
1796 2
                    $getParams['appType'] = $this->appType;
1797 2
            }
1798 2
            if (!empty($params['count'])) {
1799
                if (class_exists($relation['model'])) {
1800
                    return $relation['model']::getCount($options);
1801
                }
1802
                return 0;
1803
            } else {
1804 2
                if (class_exists($relation['model'])) {
1805 2
                    $this->loadedRelations[$name][json_encode($params)] = $relation['model']::$getType($options, $getCol, $getParams);
1806 2
                } else {
1807
                    $this->loadedRelations[$name][json_encode($params)] = [];
1808
                }
1809
            }
1810 2
            return $this->loadedRelations[$name][json_encode($params)];
1811
        }
1812 4
        return null;
1813
    }
1814
1815
    /**
1816
     * Add relation item
1817
     * 
1818
     * @param string $relName
1819
     * @param \Model $objectId
1820
     * @return \Model|boolean
1821
     */
1822
    public function addRelation($relName, $objectId) {
1823
        $relation = $this->getRelation($relName);
1824
        if ($relation) {
1825
            $rel = $relation['relModel']::get([[$relation['model']::index(), $objectId], [$this->index(), $this->pk()]]);
1826
            if (!$rel) {
1827
                $rel = new $relation['relModel']([
1828
                    $relation['model']::index() => $objectId,
1829
                    $this->index() => $this->pk()
1830
                ]);
1831
                $rel->save();
1832
            }
1833
            return $rel;
1834
        }
1835
        return false;
1836
    }
1837
1838
    /**
1839
     * Check user access for form
1840
     * 
1841
     * @param string $formName
1842
     * @return boolean
1843
     */
1844
    public function checkFormAccess($formName) {
1845
        if ($formName == 'manage' && !Users\User::$cur->isAdmin()) {
1846
            return false;
1847
        }
1848
        return true;
1849
    }
1850
1851
    /**
1852
     * Check access for model
1853
     * 
1854
     * @param string $mode
1855
     * @param \Users\User $user
1856
     * @return boolean
1857
     */
1858
    public function checkAccess($mode = 'write', $user = null) {
1859
        if (!$user) {
1860
            $user = \Users\User::$cur;
1861
        }
1862
        return $user->isAdmin();
1863
    }
1864
1865
    /**
1866
     * Param and relation with params getter
1867
     * 
1868
     * @param string $name
1869
     * @param array $params
1870
     * @return \Value|mixed
1871
     */
1872
    public function __call($name, $params) {
1873
        $fixedName = $name;
1874
        static::fixPrefix($fixedName);
1875 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...
1876
            return new Value($this, $fixedName);
1877
        } elseif (isset($this->_params[$name])) {
1878
            return new Value($this, $name);
1879
        }
1880
        return call_user_func_array([$this, 'loadRelation'], array_merge([$name], $params));
1881
    }
1882
1883
    /**
1884
     * Param and relation getter
1885
     * 
1886
     * @param string $name
1887
     * @return mixed
1888
     */
1889 4
    public function __get($name) {
1890 4
        $fixedName = $name;
1891 4
        static::fixPrefix($fixedName);
1892 4
        if (isset($this->_params[$fixedName])) {
1893 4
            return $this->_params[$fixedName];
1894
        }
1895 4
        if (isset($this->loadedRelations[$name][json_encode([])])) {
1896 2
            return $this->loadedRelations[$name][json_encode([])];
1897
        }
1898 4
        return $this->loadRelation($name);
1899
    }
1900
1901
    /**
1902
     * Return model value in object
1903
     * 
1904
     * @param string $name
1905
     * @return \Value|null
1906
     */
1907
    public function value($name) {
1908
        $fixedName = $name;
1909
        static::fixPrefix($fixedName);
1910 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...
1911
            return new Value($this, $fixedName);
1912
        } elseif ($this->_params[$name]) {
1913
            return new Value($this, $name);
1914
        }
1915
        return null;
1916
    }
1917
1918
    /**
1919
     * Return manager filters
1920
     * 
1921
     * @return array
1922
     */
1923
    public static function managerFilters() {
1924
        return [];
1925
    }
1926
1927
    /**
1928
     * Return validators for cols
1929
     * 
1930
     * @return array
1931
     */
1932
    public static function validators() {
1933
        return [];
1934
    }
1935
1936
    /**
1937
     * Return validator by name
1938
     * 
1939
     * @param string $name
1940
     * @return array
1941
     */
1942
    public static function validator($name) {
1943
        $validators = static::validators();
1944
        if (!empty($validators[$name])) {
1945
            return $validators[$name];
1946
        }
1947
        return [];
1948
    }
1949
1950
    public function genViewLink() {
1951
        $className = get_class($this);
1952
        $link = substr($className, 0, strpos($className, '\\'));
1953
        $link .= '/view/';
1954
        $link .= str_replace('\\', '%5C', substr($className, strpos($className, '\\') + 1));
1955
        $link .= "/{$this->id}";
1956
        return $link;
1957
    }
1958
1959
    /**
1960
     * Set handler for model params
1961
     * 
1962
     * @param string $name
1963
     * @param mixed $value
1964
     */
1965 4
    public function __set($name, $value) {
1966 4
        static::fixPrefix($name);
1967 4
        $className = get_called_class();
1968 4
        $shortName = preg_replace('!' . $this->colPrefix() . '!', '', $name);
1969 4
        if (!empty($className::$cols[$shortName])) {
1970 4
            switch ($className::$cols[$shortName]['type']) {
1971 4
                case 'decimal':
1972
                    $value = (float) $value;
1973
                    break;
1974 4
                case 'number':
1975
                    $value = (int) $value;
1976
                    break;
1977 4
                case 'bool':
1978
                    $value = (bool) $value;
1979
                    break;
1980 4
            }
1981 4
        }
1982 4
        if ((isset($this->_params[$name]) && $this->_params[$name] != $value) && !isset($this->_changedParams[$name])) {
1983 3
            $this->_changedParams[$name] = $this->_params[$name];
1984 3
        }
1985
1986 4
        $this->_params[$name] = $value;
1987 4
    }
1988
1989
    /**
1990
     * Isset handler for model params
1991
     * 
1992
     * @param string $name
1993
     * @return boolean
1994
     */
1995
    public function __isset($name) {
1996
        static::fixPrefix($name);
1997
        return isset($this->_params[$name]);
1998
    }
1999
2000
    /**
2001
     * Convert object to string
2002
     * 
2003
     * @return string
2004
     */
2005
    public function __toString() {
2006
        return $this->name();
2007
    }
2008
}