Test Failed
Branch v5 (12d602)
by Alexey
04:51
created

Model::deleteFromModuleStorage()   F

Complexity

Conditions 11
Paths 288

Size

Total Lines 44
Code Lines 32

Duplication

Lines 32
Ratio 72.73 %

Importance

Changes 0
Metric Value
cc 11
eloc 32
nc 288
nop 1
dl 32
loc 44
rs 3.8181
c 0
b 0
f 0

How to fix   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
 * Model
4
 *
5
 * @author Alexey Krupskiy <[email protected]>
6
 * @link http://inji.ru/
7
 * @copyright 2015 Alexey Krupskiy
8
 * @license https://github.com/injitools/cms-Inji/blob/master/LICENSE
9
 */
10
11
namespace Inji;
12
13
use Inji\Model\Builder;
14
15
/**
16
 * Class Model
17
 * @package Inji
18
 *
19
 * @method static Model\Builder connection($connectionName)
20
 */
21
class Model {
22
23
    public static $loaded = [];
24
25
    /**
26
     * Object storage type
27
     *
28
     * @var array
29
     */
30
    public static $storage = ['type' => 'db'];
31
32
    /**
33
     * Object name
34
     *
35
     * @var string
36
     */
37
    public static $objectName = '';
38
39
    /**
40
     * App type for separate data storage
41
     *
42
     * @var string
43
     */
44
    public $appType = 'app';
45
46
    /**
47
     * Object current params
48
     *
49
     * @var array
50
     */
51
    public $_params = [];
52
53
    /**
54
     * List of changed params in current instance
55
     *
56
     * @var array
57
     */
58
    public $_changedParams = [];
59
60
    /**
61
     * Loaded relations
62
     *
63
     * @var array
64
     */
65
    public $loadedRelations = [];
66
67
    /**
68
     * Model name where this model uses as category
69
     *
70
     * @var string
71
     */
72
    public static $treeCategory = '';
73
74
    /**
75
     * Model name who uses as category in this model
76
     *
77
     * @var string
78
     */
79
    public static $categoryModel = '';
80
81
    /**
82
     * Col labels
83
     *
84
     * @var array
85
     */
86
    public static $labels = [];
87
88
    /**
89
     * Model forms
90
     *
91
     * @var array
92
     */
93
    public static $forms = [];
94
95
    /**
96
     * Model cols
97
     *
98
     * @var array
99
     */
100
    public static $cols = [];
101
102
    /**
103
     * Options group for display inforamtion from model
104
     *
105
     * @var array
106
     */
107
    public static $view = [];
108
109
    /**
110
     * List of relations need loaded with item
111
     *
112
     * @var array
113
     */
114
    public static $needJoin = [];
115
116
    /**
117
     * List of joins who need to laod
118
     *
119
     * @var array
120
     */
121
    public static $relJoins = [];
122
123
    public $connectionName = 'default';
124
    public $dbOptions = [];
125
    public $app;
126
127
    /**
128
     * Set params when model create
129
     *
130
     * @param array $params
131
     * @param App $app
132
     */
133
    public function __construct($params = [], $app = null) {
134
        $this->setParams($params);
135
        if (!$app) {
136
            $this->app = App::$primary;
137
        } else {
138
            $this->app = $app;
139
        }
140
    }
141
142
    public static function new($params = [], $app = null) {
143
        return new static($params, $app);
144
    }
145
146
    public static function __callStatic($name, $arguments) {
147
        if (method_exists('Inji\Model\Builder', $name)) {
148
            return call_user_func_array([new Model\Builder(get_called_class()), $name], $arguments);
149
        }
150
        trigger_error('Undefined method in Inji\Model', E_USER_ERROR);
151
    }
152
153
    public static $logging = true;
154
155
    /**
156
     * return object name
157
     *
158
     * @return string
159
     */
160
    public static function objectName() {
161
        return static::$objectName;
162
    }
163
164
    /**
165
     * Retrn col value with col params and relations path
166
     *
167
     * @param Model $object
168
     * @param string $valuePath
169
     * @param boolean $convert
170
     * @param boolean $manageHref
171
     * @return string
172
     */
173
    public static function getColValue($object, $valuePath, $convert = false, $manageHref = false) {
174
        if (is_array($object)) {
175
            $object = array_shift($object);
176
        }
177
        if (strpos($valuePath, ':')) {
178
            $rel = substr($valuePath, 0, strpos($valuePath, ':'));
179
            $param = substr($valuePath, strpos($valuePath, ':') + 1);
180
            if (!$object->$rel) {
181
                $modelName = get_class($object);
182
                $relations = $modelName::relations();
183
                if (empty($relations[$rel]['type']) || $relations[$rel]['type'] == 'one') {
184
                    return $object->{$relations[$rel]['col']};
185
                }
186
                return 0;
187
            }
188
            if (strpos($valuePath, ':')) {
189
                return self::getColValue($object->$rel, $param, $convert, $manageHref);
190
            } else {
191
                return $convert ? Model::resloveTypeValue($object->$rel, $param, $manageHref) : $object->$rel->$param;
192
            }
193
        } else {
194
            return $convert ? Model::resloveTypeValue($object, $valuePath, $manageHref) : $object->$valuePath;
195
        }
196
    }
197
198
    /**
199
     * Retrun value for view
200
     *
201
     * @param Model $item
202
     * @param string $colName
203
     * @param boolean $manageHref
204
     * @param array $params
0 ignored issues
show
Bug introduced by
There is no parameter named $params. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
205
     * @return string
206
     */
207
    public static function resloveTypeValue($item, $colName, $manageHref = false, $colInfo = []) {
208
        $modelName = get_class($item);
209
        if (!$colInfo) {
210
            $colInfo = $modelName::getColInfo($colName);
211
        }
212
        $type = !empty($colInfo['colParams']['type']) ? $colInfo['colParams']['type'] : 'string';
213
        $value = '';
214
        switch ($type) {
215
            case 'autocomplete':
216
                $options = $colInfo['colParams']['options'];
217 View Code Duplication
                if (isset($options['snippet']) && is_string($options['snippet'])) {
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...
218
                    $snippets = \App::$cur->Ui->getSnippets('autocomplete');
219
                    if (isset($snippets[$options['snippet']])) {
220
                        $value = $snippets[$options['snippet']]['getValueText']($item->$colName, $options['snippetParams']);
221
                    }
222
                }
223
                break;
224
            case 'select':
225
                switch ($colInfo['colParams']['source']) {
226
                    case 'model':
227
                        $sourceValue = '';
228
                        if ($item->$colName) {
229
                            $sourceValue = $colInfo['colParams']['model']::get($item->$colName);
230
                        }
231
                        $value = $sourceValue ? $sourceValue->name() : 'Не задано';
232
                        break;
233
                    case 'array':
234
                        $value = !empty($colInfo['colParams']['sourceArray'][$item->$colName]) ? $colInfo['colParams']['sourceArray'][$item->$colName] : 'Не задано';
235
                        if (is_array($value) && $value['text']) {
236
                            $value = $value['text'];
237
                        }
238
                        break;
239
                    case 'bool':
240
                        return $item->$colName ? 'Да' : 'Нет';
241
                    case 'method':
242 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...
243
                            $values = call_user_func_array([App::$cur->{$colInfo['colParams']['module']}, $colInfo['colParams']['method']],
244
                                $colInfo['colParams']['params'] + [$item]
245
                            );
246
                        } else {
247
                            $values = \App::$cur->{$colInfo['colParams']['module']}->{$colInfo['colParams']['method']}($item);
248
                        }
249
                        $value = !empty($values[$item->$colName]) ? $values[$item->$colName] : 'Не задано';
250
                        break;
251
                    case 'void':
252
                        if (!empty($modelName::$cols[$colName]['value']['type']) && $modelName::$cols[$colName]['value']['type'] == 'moduleMethod') {
253
                            return \App::$cur->{$modelName::$cols[$colName]['value']['module']}->{$modelName::$cols[$colName]['value']['method']}($item, $colName, $modelName::$cols[$colName]);
254
                        }
255
                        break;
256
                    case 'relation':
257
                        if (strpos($colInfo['colParams']['relation'], ':')) {
258
                            $relationPath = explode(':', $colInfo['colParams']['relation']);
259
                            $relationName = array_pop($relationPath);
260
                            $curItem = $item;
261
                            foreach ($relationPath as $path) {
262
                                $curItem = $curItem->$path;
263
                            }
264
                            $itemModel = get_class($curItem);
265
                            $relation = $itemModel::getRelation($relationName);
266
                            $relModel = $relation['model'];
267
                        } else {
268
                            $itemModel = get_class($item);
269
                            $relation = $itemModel::getRelation($colInfo['colParams']['relation']);
270
                            $relModel = $relation['model'];
271
                        }
272
                        $relValue = $relModel::get($item->$colName);
273
                        $relModel = strpos($relModel, '\\') === 0 ? substr($relModel, 1) : $relModel;
274
                        if ($manageHref) {
275
                            $value = $relValue ? "<a href='/admin/" . str_replace('\\', '/view/', $relModel) . "/" . $relValue->pk() . "'>" . $relValue->name() . "</a>" : 'Не задано';
276
                        } else {
277
                            $value = $relValue ? $relValue->name() : 'Не задано';
278
                        }
279
                        break;
280
                }
281
                break;
282
            case 'image':
283
                $file = Files\File::get($item->$colName);
284
                if ($file) {
285
                    $photoId = Tools::randomString();
286
                    $value = '<a href = "' . $file->path . '" id="' . $photoId . '" rel="fgall[allimg]"><img src="' . $file->path . '?resize=60x120" /></a>';
287
                    $value .= '<script>inji.onLoad(function(){$("[rel]").fancybox();});</script>';
288
                } else {
289
                    $value = '<img src="/static/system/images/no-image.png?resize=60x120" />';
290
                }
291
                break;
292
            case 'file':
293
                $file = Files\File::get($item->$colName);
294
                if ($file) {
295
                    $value = '<a href="' . $file->path . '">' . $file->name . '.' . $file->type->ext . '</a>';
296
                } else {
297
                    $value = 'Файл не загружен';
298
                }
299
                break;
300
            case 'bool':
301
                $value = $item->$colName ? 'Да' : 'Нет';
302
                break;
303
            case 'void':
304
                if (!empty($colInfo['colParams']['value']['type']) && $colInfo['colParams']['value']['type'] == 'moduleMethod') {
305
                    return \App::$cur->{$colInfo['colParams']['value']['module']}->{$colInfo['colParams']['value']['method']}($item, $colName, $colInfo['colParams']);
306
                }
307
                break;
308
            case 'map':
309
                if ($item->$colName && json_decode($item->$colName, true)) {
310
                    $addres = json_decode($item->$colName, true);
311
                    $name = $addres['address'] ? $addres['address'] : 'lat:' . $addres['lat'] . ': lng:' . $addres['lng'];
312
                    \App::$cur->libs->loadLib('yandexMap');
313
                    ob_start();
314
                    $uid = Tools::randomString();
315
                    ?>
316
                    <div id='map<?= $uid; ?>_container' style="display:none;">
317
                        <script>/*
318
                             <div id='map<?= $uid; ?>' style="width: 100%; height: 500px"></div>
319
                             <script>
320
                             var myMap<?= $uid; ?>;
321
                             var myMap<?= $uid; ?>CurPin;
322
                             inji.onLoad(function () {
323
                             ymaps.ready(init<?= $uid; ?>);
324
                             function init<?= $uid; ?>() {
325
                             var myPlacemark;
326
                             myMap<?= $uid; ?> = new ymaps.Map("map<?= $uid; ?>", {
327
                             center: ["<?= $addres['lat'] ?>", "<?= $addres['lng']; ?>"],
328
                             zoom: 13
329
                             });
330
                             myCoords = ["<?= $addres['lat'] ?>", "<?= $addres['lng']; ?>"];
331
                             myMap<?= $uid; ?>CurPin = new ymaps.Placemark(myCoords,
332
                             {iconContent: "<?= $addres['address']; ?>"},
333
                             {preset: 'islands#greenStretchyIcon'}
334
                             );
335
                             myMap<?= $uid; ?>.geoObjects.add(myMap<?= $uid; ?>CurPin, 0);
336
                             }
337
                             window['init<?= $uid; ?>'] = init<?= $uid; ?>;
338
                             });
339
                             */</script>
340
                    </div>
341
                    <?php
342
                    $content = ob_get_contents();
343
                    ob_end_clean();
344
                    $onclick = 'inji.Ui.modals.show("' . addcslashes($addres['address'], '"') . '", $("#map' . $uid . '_container script").html().replace(/^\/\*/g, "").replace(/\*\/$/g, "")+"</script>","mapmodal' . $uid . '","modal-lg");';
345
                    $onclick .= 'return false;';
346
                    $value = "<a href ='#' onclick='{$onclick}' >{$name}</a>";
347
                    $value .= $content;
348
                } else {
349
                    $value = 'Местоположение не заданно';
350
                }
351
352
                break;
353
            case 'dynamicType':
354
                switch ($colInfo['colParams']['typeSource']) {
355
                    case 'selfMethod':
356
                        $type = $item->{$colInfo['colParams']['selfMethod']}();
357
                        if (is_array($type)) {
358
                            $value = static::resloveTypeValue($item, $colName, $manageHref, ['colParams' => $type]);
359
                        } else {
360
                            $value = static::resloveTypeValue($item, $colName, $manageHref, ['colParams' => ['type' => $type]]);
361
                        }
362
                        break;
363
                }
364
                break;
365
            default:
366
                $value = $item->$colName;
367
        }
368
        return $value;
369
    }
370
371
    /**
372
     * Fix col prefix
373
     *
374
     * @param mixed $array
375
     * @param string $searchtype
376
     * @param string $rootModel
377
     * @return null
378
     */
379
    public static function fixPrefix(&$array, $searchtype = 'key', $rootModel = '') {
380
        if (!$rootModel) {
381
            $rootModel = get_called_class();
382
        }
383
        $cols = static::cols();
384
        if (!$array) {
385
            return;
386
        }
387
        if (!is_array($array)) {
388 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...
389
                static::createCol($array);
390
                $cols = static::cols();
391
            }
392
            if (!isset($cols[$array]) && isset($cols[static::colPrefix() . $array])) {
393
                $array = static::colPrefix() . $array;
394
            } else {
395
                static::checkForJoin($array, $rootModel);
396
            }
397
            return;
398
        }
399
        switch ($searchtype) {
400
            case 'key':
401
                foreach ($array as $key => $item) {
402 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...
403
                        static::createCol($key);
404
                        $cols = static::cols(true);
405
                    }
406
                    if (!isset($cols[$key]) && isset($cols[static::colPrefix() . $key])) {
407
                        $array[static::colPrefix() . $key] = $item;
408
                        unset($array[$key]);
409
                        $key = static::colPrefix() . $key;
410
                    }
411
                    if (is_array($array[$key])) {
412
                        static::fixPrefix($array[$key], 'key', $rootModel);
413
                    } else {
414
                        static::checkForJoin($key, $rootModel);
415
                    }
416
                }
417
                break;
418
            case 'first':
419
                if (isset($array[0]) && is_string($array[0])) {
420
                    if (!isset($cols[static::colPrefix() . $array[0]]) && isset(static::$cols[$array[0]])) {
421
                        static::createCol($array[0]);
422
                        $cols = static::cols();
423
                    }
424 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...
425
                        $array[0] = static::colPrefix() . $array[0];
426
                    } else {
427
                        static::checkForJoin($array[0], $rootModel);
428
                    }
429
                } elseif (isset($array[0]) && is_array($array[0])) {
430
                    foreach ($array as &$item) {
431
                        static::fixPrefix($item, 'first', $rootModel);
432
                    }
433
                }
434
                break;
435
        }
436
    }
437
438
    /**
439
     * @param boolean $new
440
     */
441
    public function logChanges($new) {
442
        if (!App::$cur->db->connect || !App::$cur->dashboard) {
443
            return false;
444
        }
445
        $class = get_class($this);
446
        if (!Model::$logging || !$class::$logging || (is_string($class::$logging) && $class::$logging != ($new ? 'new' : 'changes'))) {
447
            return false;
448
        }
449
        $user_id = class_exists('Users\User') ? \Users\User::$cur->id : 0;
450
        if (!$new && !empty($this->_changedParams)) {
451
            $activity = new Dashboard\Activity([
452
                'user_id' => $user_id,
453
                'module' => substr($class, 0, strpos($class, '\\')),
454
                'model' => $class,
455
                'item_id' => $this->pk(),
456
                'type' => 'changes'
457
            ]);
458
            $changes_text = [];
459
            foreach ($this->_changedParams as $fullColName => $oldValue) {
460
                $colName = substr($fullColName, strlen($class::colPrefix()));
461 View Code Duplication
                if (isset($class::$cols[$colName]['logging']) && $class::$cols[$colName]['logging'] === false) {
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...
462
                    continue;
463
                }
464
                if (!isset($class::$cols[$colName]['logging']) || $class::$cols[$colName]['logging'] !== 'noValue') {
465
                    $oldValueText = $oldValue;
466
                    if (isset($class::$cols[$colName]) && $class::$cols[$colName]['type'] === 'select') {
467
                        switch ($class::$cols[$colName]['source']) {
468
                            case 'array':
469
                                $oldValueText = isset($class::$cols[$colName]['sourceArray'][$oldValue]) ? $class::$cols[$colName]['sourceArray'][$oldValue] : $oldValue;
470
                                break;
471 View Code Duplication
                            case '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...
472
                                $relation = $class::getRelation($class::$cols[$colName]['relation']);
473
                                $relModel = $relation['model'];
474
                                $rel = $relModel::get($oldValue);
475
                                if ($rel) {
476
                                    $oldValueText = $rel->name();
477
                                }
478
                        }
479
                    }
480
                    $newValueText = $this->$colName;
481
                    if (isset($class::$cols[$colName]) && $class::$cols[$colName]['type'] === 'select') {
482
                        switch ($class::$cols[$colName]['source']) {
483
                            case 'array':
484
                                $newValueText = isset($class::$cols[$colName]['sourceArray'][$this->$colName]) ? $class::$cols[$colName]['sourceArray'][$this->$colName] : $this->$colName;
485
                                break;
486 View Code Duplication
                            case '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...
487
                                $relation = $class::getRelation($class::$cols[$colName]['relation']);
488
                                $relModel = $relation['model'];
489
                                $rel = $relModel::get($this->$colName);
490
                                if ($rel) {
491
                                    $newValueText = $rel->name();
492
                                }
493
                        }
494
                    }
495
                }
496
                if ((!isset($class::$cols[$colName]['logging']) || $class::$cols[$colName]['logging'] !== 'noValue') && strlen($oldValueText) + strlen($newValueText) < 200) {
497
                    $changes_text[] = (!empty($class::$labels[$colName]) ? $class::$labels[$colName] : $colName) . ": \"{$oldValueText}\" => \"{$newValueText}\"";
498
                } else {
499
                    $changes_text[] = !empty($class::$labels[$colName]) ? $class::$labels[$colName] : $colName;
500
                }
501
            }
502
            if (!$changes_text) {
503
                return false;
504
            }
505
            $activity->changes_text = implode(', ', $changes_text);
506
            $activity->save();
507
            foreach ($this->_changedParams as $fullColName => $oldValue) {
508
                $colName = substr($fullColName, strlen($class::colPrefix()));
509 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...
510
                    continue;
511
                }
512
                $colName = substr($fullColName, strlen($class::colPrefix()));
513
                $change = new Dashboard\Activity\Change([
514
                    'activity_id' => $activity->id,
515
                    'col' => $colName,
516
                    'old' => $oldValue,
517
                    'new' => $this->$colName
518
                ]);
519
                $change->save();
520
            }
521
        } elseif ($new) {
522
            $activity = new Dashboard\Activity([
523
                'user_id' => $user_id,
524
                'module' => substr($class, 0, strpos($class, '\\')),
525
                'model' => $class,
526
                'item_id' => $this->pk(),
527
                'type' => 'new'
528
            ]);
529
            $activity->save();
530
        }
531
        return true;
532
    }
533
534
    /**
535
     * Check model relations path and load need relations
536
     *
537
     * @param string $col
538
     * @param string $rootModel
539
     */
540
    public static function checkForJoin(&$col, $rootModel) {
541
542
        if (strpos($col, ':') !== false) {
543
            $relations = static::relations();
544
            if (isset($relations[substr($col, 0, strpos($col, ':'))])) {
545
                $rel = substr($col, 0, strpos($col, ':'));
546
                $col = substr($col, strpos($col, ':') + 1);
547
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
548
                $joinName = $relations[$rel]['model'] . '_' . $rel;
549
                switch ($type) {
550 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...
551
                        $relCol = $relations[$rel]['col'];
552
                        static::fixPrefix($relCol);
553
                        $rootModel::$relJoins[$joinName] = [$relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol, 'left', ''];
554
                        break;
555
                    case 'one':
556 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...
557
                        $relCol = $relations[$rel]['col'];
558
                        $relations[$rel]['model']::fixPrefix($relCol);
559
                        $rootModel::$relJoins[$joinName] = [$relations[$rel]['model']::table(), static::index() . ' = ' . $relCol, 'left', ''];
560
                        break;
561
                    case 'relModel':
562
                        $relation = $relations[$rel];
563
                        $fixedCol = $relation['model']::index();
564
                        $relation['relModel']::fixPrefix($fixedCol);
565
                        $joinName = $relations[$rel]['relModel'] . '_' . $rel;
566
                        $rootModel::$relJoins[$joinName] = [$relation['relModel']::table(), $relation['relModel']::colPrefix() . static::index() . ' = ' . static::index(), 'INNER'];
567
                        $joinName = $relations[$rel]['model'] . '_' . $rel;
568
                        $rootModel::$relJoins[$joinName] = [$relation['model']::table(), $relation['relModel']::colPrefix() . $relation['model']::index() . ' = ' . $relation['model']::index(), 'INNER'];
569
                        //$rootModel::$relJoins[$joinName] = [$relations[$rel]['model']::table(), static::index() . ' = ' . $relCol, 'left', ''];
0 ignored issues
show
Unused Code Comprehensibility introduced by
69% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
570
                        break;
571
                }
572
                $relations[$rel]['model']::fixPrefix($col, 'key', $rootModel);
573
            }
574
        }
575
    }
576
577
    /**
578
     * Return full col information
579
     *
580
     * @param string $col
581
     * @return array
582
     */
583
    public static function getColInfo($col) {
584
        return static::parseColRecursion($col);
585
    }
586
587
    /**
588
     * Information extractor for col relations path
589
     *
590
     * @param string $info
591
     * @return array
592
     */
593
    public static function parseColRecursion($info) {
594
        if (is_string($info)) {
595
            $info = ['col' => $info, 'rawCol' => $info, 'rawModel' => get_called_class(), 'modelName' => get_called_class(), 'label' => $info, 'joins' => []];
596
        }
597
        if ($info['col'] === 'id') {
598
            $info['colParams'] = [
599
                'type' => 'number',
600
            ];
601
            return $info;
602
        }
603
        if (strpos($info['col'], ':') !== false) {
604
            $relations = static::relations();
605
            if (isset($relations[substr($info['col'], 0, strpos($info['col'], ':'))])) {
606
                $rel = substr($info['col'], 0, strpos($info['col'], ':'));
607
                $info['col'] = substr($info['col'], strpos($info['col'], ':') + 1);
608
                //$info['modelName'] = $relations[$rel]['model'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
609
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
610
                $joinName = $relations[$rel]['model'] . '_' . $rel;
611
                switch ($type) {
612 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...
613
                        $relCol = $relations[$rel]['col'];
614
                        static::fixPrefix($relCol);
615
                        $info['joins'][$joinName] = [$relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol];
616
                        break;
617 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...
618
                        $relCol = $relations[$rel]['col'];
619
                        $relations[$rel]['model']::fixPrefix($relCol);
620
                        $info['joins'][$joinName] = [$relations[$rel]['model']::table(), static::index() . ' = ' . $relCol];
621
                        break;
622
                }
623
                $info = $relations[$rel]['model']::parseColRecursion($info);
624
            }
625
        } else {
626
            $cols = static::cols();
627 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...
628
                $info['label'] = static::$labels[$info['col']];
629
            }
630
631
            if (isset(static::$cols[$info['col']])) {
632
                $info['colParams'] = static::$cols[$info['col']];
633
            } elseif (isset(static::$cols[str_replace(static::colPrefix(), '', $info['col'])])) {
634
                $info['colParams'] = static::$cols[str_replace(static::colPrefix(), '', $info['col'])];
635
            } else {
636
                $info['colParams'] = [];
637
            }
638 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...
639
                $info['col'] = static::colPrefix() . $info['col'];
640
            }
641
        }
642 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...
643
            $info['label'] = static::$labels[$info['rawCol']];
644
        }
645
        return $info;
646
    }
647
648
    /**
649
     * Return actual cols from data base
650
     *
651
     * @param boolean $refresh
652
     * @return array
653
     */
654
    public static function cols($refresh = false) {
655
        if (static::$storage['type'] == 'moduleConfig') {
656
            return [];
657
        }
658 View Code Duplication
        if (empty(\Inji\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...
659
            \Inji\Model::$cols[static::table()] = App::$cur->db->getTableCols(static::table());
660
        }
661 View Code Duplication
        if (!isset(\Inji\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...
662
            static::createTable();
663
            \Inji\Model::$cols[static::table()] = App::$cur->db->getTableCols(static::table());
664
        }
665
        return \Inji\Model::$cols[static::table()];
666
    }
667
668
    /**
669
     * Return cols indexes for create tables
670
     *
671
     * @return array
672
     */
673
    public static function indexes() {
674
        return [];
675
    }
676
677
    /**
678
     * Generate params string for col by name
679
     *
680
     * @param string $colName
681
     * @return false|string
682
     */
683
    public static function genColParams($colName) {
684
        if (empty(static::$cols[$colName]) || static::$storage['type'] == 'moduleConfig') {
685
            return false;
686
        }
687
        $null = ' NULL';
688
        if (empty(static::$cols[$colName]['null'])) {
689
            $null = ' NOT NULL';
690
        }
691
692
        $params = false;
693
        switch (static::$cols[$colName]['type']) {
694
            case 'select':
695
                switch (static::$cols[$colName]['source']) {
696
                    case 'relation':
697
                        $params = 'int(11) UNSIGNED' . $null;
698
                        break;
699
                    default:
700
                        $params = 'varchar(255)' . $null;
701
                }
702
                break;
703
            case 'image':
704
            case 'file':
705
                $params = 'int(11) UNSIGNED' . $null;
706
                break;
707
            case 'number':
708
                $params = 'int(11)' . $null;
709
                break;
710
            case 'text':
711
            case 'email':
712
                $params = 'varchar(255)' . $null;
713
                break;
714
            case 'html':
715
            case 'textarea':
716
            case 'json':
717
            case 'password':
718
            case 'dynamicType':
719
            case 'map':
720
                $params = 'text' . $null;
721
                break;
722
            case 'bool':
723
                $params = 'tinyint(1) UNSIGNED' . $null;
724
                break;
725
            case 'decimal':
726
                $params = 'decimal(8, 2)' . $null;
727
                break;
728
            case 'time':
729
                $params = 'time' . $null;
730
                break;
731
            case 'date':
732
                $params = 'date' . $null;
733
                break;
734
            case 'dateTime':
735
                $params = 'timestamp' . $null;
736
                break;
737
        }
738
        return $params;
739
    }
740
741
    /**
742
     * Create new col in data base
743
     *
744
     * @param string $colName
745
     * @return boolean|integer
746
     */
747
    public static function createCol($colName) {
748
        $cols = static::cols();
749
        if (!empty($cols[static::colPrefix() . $colName])) {
750
            return true;
751
        }
752
        $params = static::genColParams($colName);
753
        if ($params === false) {
754
            return false;
755
        }
756
        $result = App::$cur->db->addCol(static::table(), static::colPrefix() . $colName, $params);
757
        static::cols(true);
758
        return $result;
759
    }
760
761
    public static function createTable() {
762
        if (static::$storage['type'] == 'moduleConfig') {
763
            return true;
764
        }
765
        if (!App::$cur->db) {
766
            return false;
767
        }
768
769
        $query = App::$cur->db->newQuery();
770
        if (!$query) {
771
            return false;
772
        }
773
774
        if (!isset($this)) {
775
            $tableName = static::table();
776
            $colPrefix = static::colPrefix();
777
            $indexes = static::indexes();
778
        } else {
779
            $tableName = $this->table();
780
            $colPrefix = $this->colPrefix();
781
            $indexes = $this->indexes();
782
        }
783
        if (App::$cur->db->tableExist($tableName)) {
784
            return true;
785
        }
786
        $cols = [
787
            $colPrefix . 'id' => 'pk'
788
        ];
789
        $className = get_called_class();
790
        if (!empty($className::$cols)) {
791
            foreach ($className::$cols as $colName => $colParams) {
792
                if ($colName == 'date_create') {
793
                    $cols[$colPrefix . 'date_create'] = 'timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP';
794
                    continue;
795
                }
796
                $params = $className::genColParams($colName);
797
                if ($params) {
798
                    $cols[$colPrefix . $colName] = $params;
799
                }
800
            }
801
        }
802
        if (empty($cols[$colPrefix . 'date_create'])) {
803
            $cols[$colPrefix . 'date_create'] = 'timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP';
804
        }
805
        $tableIndexes = [];
806
        if ($indexes) {
807
            foreach ($indexes as $indexName => $index) {
808
                $tableIndexes[] = $index['type'] . ' ' . App::$cur->db->table_prefix . $indexName . ' (' . implode(',', $index['cols']) . ')';
809
            }
810
        }
811
812
        $query->createTable($tableName, $cols, $tableIndexes);
813
        return true;
814
    }
815
816
    /**
817
     * Return table name
818
     *
819
     * @return string
820
     */
821
    public static function table() {
822
        return strtolower(str_replace('\\', '_', get_called_class()));
823
    }
824
825
    /**
826
     * Return table index col name
827
     *
828
     * @return string
829
     */
830
    public static function index() {
831
        return static::colPrefix() . 'id';
832
    }
833
834
    /**
835
     * Return col prefix
836
     *
837
     * @return string
838
     */
839
    public static function colPrefix() {
840
        $classPath = explode('\\', get_called_class());
841
        $classPath = array_slice($classPath, 2);
842
        return strtolower(implode('_', $classPath)) . '_';
843
    }
844
845
    /**
846
     * return relations list
847
     *
848
     * @return array
849
     */
850
    public static function relations() {
851
        return [];
852
    }
853
854
    /**
855
     * views list
856
     *
857
     * @return array
858
     */
859
    public static $views = [];
860
861
    /**
862
     * Return name of col with object name
863
     *
864
     * @return string
865
     */
866
    public static function nameCol() {
867
        return 'name';
868
    }
869
870
    /**
871
     * Return object name
872
     *
873
     * @return string
874
     */
875
    public function name() {
876
        return $this->{$this->nameCol()} ? $this->{$this->nameCol()} : '№' . $this->pk();
877
    }
878
879
    /**
880
     * Get single object from data base
881
     *
882
     * @param mixed $param
883
     * @param string $col
884
     * @param array $options
885
     * @return boolean|static
886
     */
887
    public static function get($param, $col = null, $options = []) {
888
        if (static::$storage['type'] == 'moduleConfig') {
889
            return static::getFromModuleStorage($param, $col, $options);
890
        }
891
        if (!empty($col)) {
892
            static::fixPrefix($col);
893
        }
894
895
        if (is_array($param)) {
896
            static::fixPrefix($param, 'first');
897
        }
898
        $query = App::$cur->db->newQuery();
899
        foreach (static::$relJoins as $join) {
900
            $query->join($join);
901
        }
902
        static::$relJoins = [];
903
        foreach (static::$needJoin as $rel) {
904
            $relations = static::relations();
905
            if (isset($relations[$rel])) {
906
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
907
                switch ($type) {
908
                    case 'to':
909
                        $relCol = $relations[$rel]['col'];
910
                        static::fixPrefix($relCol);
911
                        $query->join($relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol);
912
                        break;
913
                    case 'one':
914
                        $col = $relations[$rel]['col'];
915
                        $relations[$rel]['model']::fixPrefix($col);
916
                        $query->join($relations[$rel]['model']::table(), static::index() . ' = ' . $col);
917
                        break;
918
                }
919
            }
920
        }
921
        static::$needJoin = [];
922
        if (is_array($param)) {
923
            $query->where($param);
924
        } else {
925
            if ($col === null) {
926
927
                $col = static::index();
928
            }
929
            if ($param !== null) {
930
                $cols = static::cols();
931
                if (!isset($cols[$col]) && isset($cols[static::colPrefix() . $col])) {
932
                    $col = static::colPrefix() . $col;
933
                }
934
                $query->where($col, $param);
935
            } else {
936
                return false;
937
            }
938
        }
939
        if (!$query->where) {
940
            return false;
941
        }
942
        try {
943
            $result = $query->select(static::table());
944
        } catch (\PDOException $exc) {
945
            if ($exc->getCode() == '42S02') {
946
                static::createTable();
947
            } else {
948
                throw $exc;
949
            }
950
            $result = $query->select(static::table());
951
        }
952
        if (!$result) {
953
            return false;
954
        }
955
        return $result->fetch(get_called_class());
956
    }
957
958
    /**
959
     * Old method
960
     *
961
     * @param type $options
962
     * @return Array
963
     */
964
    public static function get_list($options = [], $debug = false) {
965
        $query = App::$cur->db->newQuery();
966
        if (!$query) {
967
            return [];
968
        }
969
        if (!empty($options['where'])) {
970
            $query->where($options['where']);
971
        }
972
        if (!empty($options['cols'])) {
973
            $query->cols = $options['cols'];
974
        }
975
        if (!empty($options['group'])) {
976
            $query->group($options['group']);
977
        }
978
        if (!empty($options['having'])) {
979
            $query->having($options['having']);
980
        }
981
        if (!empty($options['order'])) {
982
            $query->order($options['order']);
983
        }
984
        if (!empty($options['join'])) {
985
            $query->join($options['join']);
986
        }
987
        if (!empty($options['distinct'])) {
988
            $query->distinct = $options['distinct'];
989
        }
990
991 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...
992
            $relations = static::relations();
993
            foreach ($query->join as $item) {
994
                if ($item[0] === $relations[$rel]['model']::table() && $item[3] === '') {
995
                    continue 2;
996
                }
997
            }
998
            if (isset($relations[$rel])) {
999
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
1000
                switch ($type) {
1001
                    case 'to':
1002
                        $relCol = $relations[$rel]['col'];
1003
                        static::fixPrefix($relCol);
1004
                        $query->join($relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol);
1005
                        break;
1006
                    case 'one':
1007
                        $col = $relations[$rel]['col'];
1008
                        $relations[$rel]['model']::fixPrefix($col);
1009
                        $query->join($relations[$rel]['model']::table(), static::index() . ' = ' . $col);
1010
                        break;
1011
                }
1012
            }
1013
        }
1014
        static::$needJoin = [];
1015
1016 View Code Duplication
        foreach (static::$relJoins as $join) {
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...
1017
            foreach ($query->join as $item) {
1018
                if ($item[0] === $join[0] && $item[3] === $join[3]) {
1019
                    continue 2;
1020
                }
1021
            }
1022
            $query->join($join);
1023
        }
1024
        static::$relJoins = [];
1025 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...
1026
            $limit = (int)$options['limit'];
1027
        } else {
1028
            $limit = 0;
1029
        }
1030 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...
1031
            $start = (int)$options['start'];
1032
        } else {
1033
            $start = 0;
1034
        }
1035
        if ($limit || $start) {
1036
            $query->limit($start, $limit);
1037
        }
1038
        if (isset($options['key'])) {
1039
            $key = $options['key'];
1040
        } else {
1041
            $key = static::index();
1042
        }
1043
1044
        if ($debug) {
1045
            $query->operation = 'SELECT';
1046
            $query->table = static::table();
1047
            return $query->buildQuery();
1048
        }
1049
        try {
1050
            $query->operation = 'SELECT';
1051
            $query->table = static::table();
1052
            $queryArr = $query->buildQuery();
1053
            $result = $query->query($queryArr);
1054
        } catch (PDOException $exc) {
0 ignored issues
show
Bug introduced by
The class Inji\PDOException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1055
            if ($exc->getCode() == '42S02') {
1056
                static::createTable();
1057
                $result = $query->query($queryArr);
1058
            } else {
1059
                throw $exc;
1060
            }
1061
        }
1062
1063
        if (!empty($options['array'])) {
1064
            static::fixPrefix($key);
1065
            return $result->getArray($key);
1066
        }
1067
        $list = $result->getObjects(get_called_class(), $key);
1068
        if (!empty($options['forSelect'])) {
1069
            $return = [];
1070
            foreach ($list as $key => $item) {
1071
                $return[$key] = $item->name();
1072
            }
1073
            return $return;
1074
        }
1075
        return $list;
1076
    }
1077
1078
    /**
1079
     * Return list of objects from data base
1080
     *
1081
     * @param array $options
1082
     * @return static[]
1083
     */
1084
    public static function getList($options = [], $debug = false) {
1085
        if (static::$storage['type'] != 'db') {
1086
            return static::getListFromModuleStorage($options);
1087
        }
1088
        if (!empty($options['where'])) {
1089
            static::fixPrefix($options['where'], 'first');
1090
        }
1091
        if (!empty($options['group'])) {
1092
            static::fixPrefix($options['group'], 'first');
1093
        }
1094
        if (!empty($options['order'])) {
1095
            static::fixPrefix($options['order'], 'first');
1096
        }
1097
        if (!empty($options['having'])) {
1098
            static::fixPrefix($options['having'], 'first');
1099
        }
1100
        return static::get_list($options, $debug);
1101
    }
1102
1103
1104
    /**
1105
     * Return count of records from data base
1106
     *
1107
     * @param array $options
1108
     * @return array|int
1109
     */
1110
    public static function getCount($options = []) {
1111
        if (static::$storage['type'] == 'moduleConfig') {
1112
            return static::getCountFromModuleStorage($options);
1113
        }
1114
        $query = App::$cur->db->newQuery();
1115
        if (!$query) {
1116
            return 0;
1117
        }
1118
        if (!empty($options['where'])) {
1119
            static::fixPrefix($options['where'], 'first');
1120
        }
1121
        if (!empty($options['group'])) {
1122
            static::fixPrefix($options['group'], 'first');
1123
        }
1124
        if (!empty($options['order'])) {
1125
            static::fixPrefix($options['order'], 'first');
1126
        }
1127
        if (!empty($options['where'])) {
1128
            $query->where($options['where']);
1129
        }
1130
        if (!empty($options['join'])) {
1131
            $query->join($options['join']);
1132
        }
1133
        if (!empty($options['order'])) {
1134
            $query->order($options['order']);
1135
        }
1136 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...
1137
            $limit = (int)$options['limit'];
1138
        } else {
1139
            $limit = 0;
1140
        }
1141 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...
1142
            $start = (int)$options['start'];
1143
        } else {
1144
            $start = 0;
1145
        }
1146
        if ($limit || $start) {
1147
            $query->limit($start, $limit);
1148
        }
1149
1150 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...
1151
            $relations = static::relations();
1152
            foreach ($query->join as $item) {
1153
                if ($item[0] === $relations[$rel]['model']::table() && $item[3] === '') {
1154
                    continue 2;
1155
                }
1156
            }
1157
            if (isset($relations[$rel])) {
1158
                $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
1159
                switch ($type) {
1160
                    case 'to':
1161
                        $relCol = $relations[$rel]['col'];
1162
                        static::fixPrefix($relCol);
1163
                        $query->join($relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol);
1164
                        break;
1165
                    case 'one':
1166
                        $col = $relations[$rel]['col'];
1167
                        $relations[$rel]['model']::fixPrefix($col);
1168
                        $query->join($relations[$rel]['model']::table(), static::index() . ' = ' . $col);
1169
                        break;
1170
                }
1171
            }
1172
        }
1173
        static::$needJoin = [];
1174 View Code Duplication
        foreach (static::$relJoins as $join) {
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...
1175
            foreach ($query->join as $item) {
1176
                if ($item[0] === $join[0] && $item[3] === $join[3]) {
1177
                    continue 2;
1178
                }
1179
            }
1180
            $query->join($join);
1181
        }
1182
        static::$relJoins = [];
1183
        $cols = 'COUNT(';
1184
1185
        if (!empty($options['distinct'])) {
1186
            if (is_bool($options['distinct'])) {
1187
                $cols .= 'DISTINCT *';
1188
            } else {
1189
                $cols .= "DISTINCT {$options['distinct']}";
1190
            }
1191
        } else {
1192
            $cols .= '*';
1193
        }
1194
        $cols .= ') as `count`' . (!empty($options['cols']) ? ',' . $options['cols'] : '');
1195
        $query->cols = $cols;
1196
        if (!empty($options['group'])) {
1197
            $query->group($options['group']);
1198
        }
1199
        try {
1200
            $result = $query->select(static::table());
1201
        } catch (PDOException $exc) {
0 ignored issues
show
Bug introduced by
The class Inji\PDOException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1202
            if ($exc->getCode() == '42S02') {
1203
                static::createTable();
1204
            } else {
1205
                throw $exc;
1206
            }
1207
            $result = $query->select(static::table());
1208
        }
1209
        if (!empty($options['group'])) {
1210
            $count = $result->getArray();
1211
            return $count;
1212
        } else {
1213
            $count = $result->fetch();
1214
            return $count['count'];
1215
        }
1216
    }
1217
1218
    /**
1219
     * Update records in data base
1220
     *
1221
     * @param array $params
1222
     * @param array $where
1223
     * @return false|null
1224
     */
1225
    public static function update($params, $where = []) {
1226
        static::fixPrefix($params);
1227
1228
        $cols = self::cols();
1229
1230
        $values = [];
1231
        foreach ($cols as $col => $param) {
1232
            if (isset($params[$col])) {
1233
                $values[$col] = $params[$col];
1234
            }
1235
        }
1236
        if (empty($values)) {
1237
            return false;
1238
        }
1239
1240
        if (!empty($where)) {
1241
            static::fixPrefix($where, 'first');
1242
1243
            App::$cur->db->where($where);
1244
        }
1245
        App::$cur->db->update(static::table(), $values);
1246
    }
1247
1248
    /**
1249
     * Return primary key of object
1250
     *
1251
     * @return mixed
1252
     */
1253
    public function pk() {
1254
        return $this->{$this->index()};
1255
    }
1256
1257
    /**
1258
     * Before save trigger
1259
     */
1260
    public function beforeSave() {
1261
1262
    }
1263
1264
    /**
1265
     * Save object to module storage
1266
     *
1267
     * @param array $options
1268
     * @return boolean
1269
     */
1270
    public function saveModuleStorage($options) {
1271
1272
        $col = static::index();
1273
        $id = $this->pk();
1274
        $appType = '';
1275
        $classPath = explode('\\', get_called_class());
1276
1277 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...
1278
            $moduleConfig = Config::share($classPath[0]);
1279
        } else {
1280
            $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
0 ignored issues
show
Documentation introduced by
strpos(static::$storage[...'], 'system') !== false is of type boolean, but the function expects a object<Inji\App>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1281
        }
1282
1283 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...
1284
            if (empty($options['appType'])) {
1285
                $appType = App::$cur->type;
1286
            } else {
1287
                $appType = $options['appType'];
1288
            }
1289
            $storage = !empty($moduleConfig['storage'][$appType]) ? $moduleConfig['storage'][$appType] : [];
1290
        } else {
1291
            $storage = !empty($moduleConfig['storage']) ? $moduleConfig['storage'] : [];
1292
        }
1293
        if (empty($storage[$classPath[1]])) {
1294
            $storage[$classPath[1]] = [];
1295
        }
1296
        if ($id) {
1297 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...
1298
                if ($item[$col] == $id) {
1299
                    $storage[$classPath[1]][$key] = $this->_params;
1300
                    break;
1301
                }
1302
            }
1303
        } else {
1304
            $id = !empty($storage['scheme'][$classPath[1]]['ai']) ? $storage['scheme'][$classPath[1]]['ai'] : 1;
1305
            $this->$col = $id;
1306
            $storage['scheme'][$classPath[1]]['ai'] = $id + 1;
1307
            $storage[$classPath[1]][] = $this->_params;
1308
        }
1309 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...
1310
            $moduleConfig['storage'][$appType] = $storage;
1311
        } else {
1312
            $moduleConfig['storage'] = $storage;
1313
        }
1314 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...
1315
            Config::save('module', $moduleConfig, $classPath[0]);
1316
        } else {
1317
            Config::save('share', $moduleConfig, $classPath[0]);
1318
        }
1319
        return true;
1320
    }
1321
1322
    /**
1323
     * Update tree path category
1324
     */
1325
    public function changeCategoryTree() {
1326
        $class = get_class($this);
1327
        $itemModel = $class::$treeCategory;
1328
        $oldPath = $this->tree_path;
1329
        $newPath = $this->getCatalogTree($this);
1330
        $itemsTable = \App::$cur->db->table_prefix . $itemModel::table();
1331
        $itemTreeCol = $itemModel::colPrefix() . 'tree_path';
1332
        $categoryTreeCol = $this->colPrefix() . 'tree_path';
1333
        $categoryTable = \App::$cur->db->table_prefix . $this->table();
1334
        if ($oldPath) {
1335
            \App::$cur->db->query('UPDATE
1336
                ' . $categoryTable . ' 
1337
                    SET 
1338
                        ' . $categoryTreeCol . ' = REPLACE(' . $categoryTreeCol . ', "' . $oldPath . $this->id . '/' . '", "' . $newPath . $this->id . '/' . '") 
1339
                    WHERE ' . $categoryTreeCol . ' LIKE "' . $oldPath . $this->id . '/' . '%"');
1340
1341
            \App::$cur->db->query('UPDATE
1342
                ' . $itemsTable . '
1343
                    SET 
1344
                        ' . $itemTreeCol . ' = REPLACE(' . $itemTreeCol . ', "' . $oldPath . $this->id . '/' . '", "' . $newPath . $this->id . '/' . '") 
1345
                    WHERE ' . $itemTreeCol . ' LIKE "' . $oldPath . $this->id . '/' . '%"');
1346
        }
1347
        $itemModel::update([$itemTreeCol => $newPath . $this->id . '/'], [$itemModel::colPrefix() . $this->index(), $this->id]);
1348
        $this->tree_path = $newPath;
1349
    }
1350
1351
    /**
1352
     * Return tree path
1353
     *
1354
     * @param \Inji\Model $catalog
1355
     * @return string
1356
     */
1357
    public function getCatalogTree($catalog) {
1358
        $catalogClass = get_class($catalog);
1359
        $catalogParent = $catalogClass::get($catalog->parent_id);
1360
        if ($catalog && $catalogParent) {
1361
            if ($catalogParent->tree_path) {
1362
                return $catalogParent->tree_path . $catalogParent->id . '/';
1363
            } else {
1364
                return $this->getCatalogTree($catalogParent) . $catalogParent->id . '/';
1365
            }
1366
        }
1367
        return '/';
1368
    }
1369
1370
    /**
1371
     * Update tree path item
1372
     */
1373
    public function changeItemTree() {
1374
        $class = get_class($this);
1375
        $categoryModel = $class::$categoryModel;
1376
        $category = $categoryModel::get($this->{$categoryModel::index()});
1377
        if ($category) {
1378
            $this->tree_path = $category->tree_path . $category->pk() . '/';
1379
        } else {
1380
            $this->tree_path = '/';
1381
        }
1382
    }
1383
1384
    /**
1385
     * Save object to data base
1386
     *
1387
     * @param array $options
1388
     * @return boolean|int
1389
     */
1390
    public function save($options = []) {
1391
1392
        $builder = new Builder(get_called_class(), $this->app);
1393
        $builder->connection($this->connectionName);
1394
        foreach ($this->dbOptions as $dbOption => $value) {
1395
            $builder->setDbOption($dbOption, $value);
1396
        }
1397
        $class = get_called_class();
1398
        if (!empty($this->_changedParams) && $this->pk()) {
1399
            \Inji::$inst->event('modelItemParamsChanged-' . $class, $this);
1400
        }
1401
        $this->beforeSave();
1402
        $values = [];
1403
1404
        foreach (static::$cols as $col => $param) {
1405
            if (in_array($col, array_keys($this->_params)) && (!$this->pk() || ($this->pk() && in_array($col, array_keys($this->_changedParams))))) {
1406
                $values[$col] = $this->_params[$col];
1407
            }
1408
        }
1409
        if (!$this->pk()) {
1410
            foreach ($class::$cols as $colName => $params) {
1411
                if (isset($params['default']) && !isset($values[$colName])) {
1412
                    $this->_params[$colName] = $values[$colName] = $params['default'];
1413
                }
1414
            }
1415
        }
1416
1417
        if (empty($values) && empty($options['empty'])) {
1418
            return false;
1419
        }
1420
        if (static::$categoryModel) {
1421
            $this->changeItemTree();
1422
        }
1423
        if (static::$treeCategory) {
1424
            $this->changeCategoryTree();
1425
        }
1426
        $new = !$this->pk();
1427
        if ($new) {
1428
            $builder->where(static::index(), $builder->insert($values));
1429
        } else {
1430
            $builder->where(static::index(), $this->pk());
1431
            $builder->update($values);
1432
        }
1433
        $this->logChanges($new);
1434
        $this->_params = $builder->get(['array' => true]);
1435
        if ($new) {
1436
            \Inji::$inst->event('modelCreatedItem-' . get_called_class(), $this);
1437
        }
1438
        $this->afterSave();
1439
        return $this->pk();
1440
    }
1441
1442
    /**
1443
     * After save trigger
1444
     */
1445
    public function afterSave() {
1446
1447
    }
1448
1449
    /**
1450
     * Before delete trigger
1451
     */
1452
    public function beforeDelete() {
1453
1454
    }
1455
1456
    /**
1457
     * Delete item from module storage
1458
     *
1459
     * @param array $options
1460
     * @return boolean
1461
     */
1462
    public function deleteFromModuleStorage($options) {
1463
1464
        $col = static::index();
1465
        $id = $this->pk();
1466
        $appType = '';
1467
        $classPath = explode('\\', get_called_class());
1468 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...
1469
            $moduleConfig = Config::share($classPath[0]);
1470
        } else {
1471
            $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
0 ignored issues
show
Documentation introduced by
strpos(static::$storage[...'], 'system') !== false is of type boolean, but the function expects a object<Inji\App>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1472
        }
1473
1474 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...
1475
            if (empty($options['appType'])) {
1476
                $appType = App::$cur->type;
1477
            } else {
1478
                $appType = $options['appType'];
1479
            }
1480
            $storage = !empty($moduleConfig['storage'][$appType]) ? $moduleConfig['storage'][$appType] : [];
1481
        } else {
1482
            $storage = !empty($moduleConfig['storage']) ? $moduleConfig['storage'] : [];
1483
        }
1484
        if (empty($storage[$classPath[1]])) {
1485
            $storage[$classPath[1]] = [];
1486
        }
1487 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...
1488
1489
            if ($item[$col] == $id) {
1490
                unset($storage[$classPath[1]][$key]);
1491
                break;
1492
            }
1493
        }
1494 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...
1495
            $moduleConfig['storage'][$appType] = $storage;
1496
        } else {
1497
            $moduleConfig['storage'] = $storage;
1498
        }
1499 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...
1500
            Config::save('module', $moduleConfig, $classPath[0]);
1501
        } else {
1502
            Config::save('share', $moduleConfig, $classPath[0]);
1503
        }
1504
        return true;
1505
    }
1506
1507
    /**
1508
     * Delete item from data base
1509
     *
1510
     * @param array $options
1511
     * @return boolean
1512
     */
1513
    public function delete($options = []) {
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1514
        $this->beforeDelete();
1515
        if (!empty($this->pk())) {
1516
            $builder = new Builder(get_called_class(), $this->app);
1517
            $builder->connection($this->connectionName);
1518
            foreach ($this->dbOptions as $dbOption => $value) {
1519
                $builder->setDbOption($dbOption, $value);
1520
            }
1521
            $builder->where($this->index(), $this->pk());
1522
            $result = $builder->delete();
1523
            if ($result) {
1524
                $this->afterDelete();
1525
                return $result;
1526
            }
1527
        }
1528
        return false;
1529
    }
1530
1531
    /**
1532
     * Delete items from data base
1533
     *
1534
     * @param array $where
1535
     */
1536
    public static function deleteList($where = []) {
1537
        if (!empty($where)) {
1538
            static::fixPrefix($where, 'first');
1539
            App::$cur->db->where($where);
1540
        }
1541
        App::$cur->db->delete(static::table());
1542
    }
1543
1544
    /**
1545
     * After delete trigger
1546
     */
1547
    public function afterDelete() {
1548
1549
    }
1550
1551
    /**
1552
     * find relation for col name
1553
     *
1554
     * @param string $col
1555
     * @return array|null
1556
     */
1557
    public static function findRelation($col) {
1558
1559
        foreach (static::relations() as $relName => $rel) {
1560
            if ($rel['col'] == $col) {
1561
                return $relName;
1562
            }
1563
        }
1564
        return null;
1565
    }
1566
1567
    /**
1568
     * Set params for model
1569
     *
1570
     * @param array $params
1571
     */
1572
    public function setParams($params) {
1573
        foreach ($params as $paramName => $value) {
1574
            $this->$paramName = $value;
1575
        }
1576
    }
1577
1578
    /**
1579
     * Return relation
1580
     *
1581
     * @param string $relName
1582
     * @return array|boolean
1583
     */
1584
    public static function getRelation($relName) {
1585
        $relations = static::relations();
1586
        return !empty($relations[$relName]) ? $relations[$relName] : false;
1587
    }
1588
1589
    /**
1590
     * Load relation
1591
     *
1592
     * @param string $name
1593
     * @param array $params
1594
     * @return null|array|integer|\Model
1595
     */
1596
    public function loadRelation($name, $params = []) {
1597
        $relation = static::getRelation($name);
1598
        if ($relation) {
1599
            if (!isset($relation['type'])) {
1600
                $type = 'to';
1601
            } else {
1602
                $type = $relation['type'];
1603
            }
1604
            $getCol = null;
1605
            $getParams = [];
1606
            switch ($type) {
1607
                case 'relModel':
1608
                    if (!$this->pk()) {
1609
                        return [];
1610
                    }
1611
                    $fixedCol = $relation['model']::index();
1612
                    $relation['relModel']::fixPrefix($fixedCol);
1613
                    $join = [$relation['relModel']::table(), $relation['relModel']::colPrefix() . $this->index() . ' = ' . $this->pk() . ' and ' . $relation['relModel']::colPrefix() . $relation['model']::index() . ' = ' . $relation['model']::index(), 'INNER'];
1614
                    $getType = 'getList';
1615
                    $options = [
1616
                        'cols' => (isset($params['cols'])) ? $params['cols'] : ((isset($relation['cols'])) ? $relation['cols'] : null),
1617
                        'join' => [$join],
1618
                        'where' => (isset($params['where'])) ? $params['where'] : ((isset($relation['where'])) ? $relation['where'] : null),
1619
                        'array' => (!empty($params['array'])) ? true : false,
1620
                        'key' => (isset($params['key'])) ? $params['key'] : ((isset($relation['resultKey'])) ? $relation['resultKey'] : null),
1621
                        'start' => (isset($params['start'])) ? $params['start'] : ((isset($relation['start'])) ? $relation['start'] : null),
1622
                        'order' => (isset($params['order'])) ? $params['order'] : ((isset($relation['order'])) ? $relation['order'] : null),
1623
                        'limit' => (isset($params['limit'])) ? $params['limit'] : ((isset($relation['limit'])) ? $relation['limit'] : null),
1624
                    ];
1625
                    break;
1626
                case 'many':
1627
                    if (!$this->{$this->index()}) {
1628
                        return [];
1629
                    }
1630
                    $getType = 'getList';
1631
                    $options = [
1632
                        'cols' => (isset($params['cols'])) ? $params['cols'] : ((isset($relation['cols'])) ? $relation['cols'] : null),
1633
                        'join' => (isset($relation['join'])) ? $relation['join'] : null,
1634
                        'key' => (isset($params['key'])) ? $params['key'] : ((isset($relation['resultKey'])) ? $relation['resultKey'] : null),
1635
                        'array' => (!empty($params['array'])) ? true : false,
1636
                        'forSelect' => !empty($params['forSelect']),
1637
                        'order' => (isset($params['order'])) ? $params['order'] : ((isset($relation['order'])) ? $relation['order'] : null),
1638
                        'start' => (isset($params['start'])) ? $params['start'] : ((isset($relation['start'])) ? $relation['start'] : null),
1639
                        'limit' => (isset($params['limit'])) ? $params['limit'] : ((isset($relation['limit'])) ? $relation['limit'] : null),
1640
                        'appType' => (isset($params['appType'])) ? $params['appType'] : ((isset($relation['appType'])) ? $relation['appType'] : null),
1641
                        'where' => []
1642
                    ];
1643
                    $options['where'][] = [$relation['col'], $this->{$this->index()}];
1644
                    if (!empty($relation['where'])) {
1645
                        $options['where'] = array_merge($options['where'], [$relation['where']]);
1646
                    }
1647
                    if (!empty($params['where'])) {
1648
                        $options['where'] = array_merge($options['where'], [$params['where']]);
1649
                    }
1650
                    break;
1651
                case 'one':
1652
                    $getType = 'get';
1653
                    $options = [$relation['col'], $this->pk()];
1654
                    break;
1655
                default:
1656
                    if ($this->{$relation['col']} === null) {
1657
                        return null;
1658
                    }
1659
                    $getType = 'get';
1660
                    $options = $this->{$relation['col']};
1661
                    $getParams['appType'] = $this->appType;
1662
            }
1663
            if (!empty($params['count'])) {
1664
                if (class_exists($relation['model'])) {
1665
                    return $relation['model']::getCount($options);
1666
                }
1667
                return 0;
1668
            } else {
1669
                if (class_exists($relation['model'])) {
1670
                    $this->loadedRelations[$name][json_encode($params)] = $relation['model']::$getType($options, $getCol, $getParams);
1671
                } else {
1672
                    $this->loadedRelations[$name][json_encode($params)] = [];
1673
                }
1674
            }
1675
            return $this->loadedRelations[$name][json_encode($params)];
1676
        }
1677
        return null;
1678
    }
1679
1680
    /**
1681
     * Add relation item
1682
     *
1683
     * @param string $relName
1684
     * @param \Inji\Model $objectId
1685
     * @return \Inji\Model|boolean
1686
     */
1687
    public function addRelation($relName, $objectId) {
1688
        $relation = $this->getRelation($relName);
1689
        if ($relation) {
1690
            $rel = $relation['relModel']::get([[$relation['model']::index(), $objectId], [$this->index(), $this->pk()]]);
1691
            if (!$rel) {
1692
                $rel = new $relation['relModel']([
1693
                    $relation['model']::index() => $objectId,
1694
                    $this->index() => $this->pk()
1695
                ]);
1696
                $rel->save();
1697
            }
1698
            return $rel;
1699
        }
1700
        return false;
1701
    }
1702
1703
    /**
1704
     * Check user access for form
1705
     *
1706
     * @param string $formName
1707
     * @return boolean
1708
     */
1709
    public function checkFormAccess($formName) {
1710
        if ($formName == 'manage' && !Users\User::$cur->isAdmin()) {
1711
            return false;
1712
        }
1713
        return true;
1714
    }
1715
1716
    /**
1717
     * Check access for model
1718
     *
1719
     * @param string $mode
1720
     * @param \Users\User $user
1721
     * @return boolean
1722
     */
1723
    public function checkAccess($mode = 'write', $user = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $mode is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1724
        if (!$user) {
1725
            $user = \Users\User::$cur;
1726
        }
1727
        return $user->isAdmin();
1728
    }
1729
1730
    /**
1731
     * Param and relation with params getter
1732
     *
1733
     * @param string $name
1734
     * @param array $params
1735
     * @return \Value|mixed
1736
     */
1737
    public function __call($name, $params) {
1738
        $fixedName = $name;
1739
        static::fixPrefix($fixedName);
1740
        if (isset($this->_params[$fixedName])) {
1741
            return new Value($this, $fixedName);
1742
        } elseif (isset($this->_params[$name])) {
1743
            return new Value($this, $name);
1744
        } elseif (!empty($params[0]) && isset($this->loadedRelations[$name][json_encode($params[0])])) {
1745
            return $this->loadedRelations[$name][json_encode($params[0])];
1746
        }
1747
        return call_user_func_array([$this, 'loadRelation'], array_merge([$name], $params));
1748
    }
1749
1750
    /**
1751
     * Param and relation getter
1752
     *
1753
     * @param string $name
1754
     * @return mixed
1755
     */
1756
    public function __get($name) {
1757
        if (isset($this->_params[$name])) {
1758
            return $this->_params[$name];
1759
        }
1760
        if (isset($this->loadedRelations[$name][json_encode([])])) {
1761
            return $this->loadedRelations[$name][json_encode([])];
1762
        }
1763
        return $this->loadRelation($name);
1764
    }
1765
1766
    /**
1767
     * Return model value in object
1768
     *
1769
     * @param string $name
1770
     * @return \Value|null
1771
     */
1772
    public function value($name) {
1773
        $fixedName = $name;
1774
        static::fixPrefix($fixedName);
1775
        if (isset($this->_params[$fixedName])) {
1776
            return new Value($this, $fixedName);
1777
        } elseif ($this->_params[$name]) {
1778
            return new Value($this, $name);
1779
        }
1780
        return null;
1781
    }
1782
1783
    /**
1784
     * Return manager filters
1785
     *
1786
     * @return array
1787
     */
1788
    public static function managerFilters() {
1789
        return [];
1790
    }
1791
1792
    /**
1793
     * Return validators for cols
1794
     *
1795
     * @return array
1796
     */
1797
    public static function validators() {
1798
        return [];
1799
    }
1800
1801
    /**
1802
     * Return validator by name
1803
     *
1804
     * @param string $name
1805
     * @return array
1806
     */
1807
    public static function validator($name) {
1808
        $validators = static::validators();
1809
        if (!empty($validators[$name])) {
1810
            return $validators[$name];
1811
        }
1812
        return [];
1813
    }
1814
1815
    public function genViewLink() {
1816
        $className = get_class($this);
1817
        $link = substr($className, 0, strpos($className, '\\'));
1818
        $link .= '/view/';
1819
        $link .= str_replace('\\', '%5C', substr($className, strpos($className, '\\') + 1));
1820
        $link .= "/{$this->id}";
1821
        return $link;
1822
    }
1823
1824
    public function extract($model) {
1825
        $params = [];
1826
        if (empty($this->_params[$model::index()])) {
1827
            return false;
1828
        }
1829
        $params['id'] = $this->_params[$model::index()];
1830
        $indexes = array_keys($this->_params);
1831
        foreach ($model::$cols as $colName => $colParams) {
1832
            if (in_array($model::colPrefix() . $colName, $indexes)) {
1833
                $params[$model::colPrefix() . $colName] = $this->_params[$model::colPrefix() . $colName];
1834
            }
1835
        }
1836
        if (!$params) {
1837
            return FALSE;
1838
        }
1839
        return new $model($params);
1840
    }
1841
1842
    /**
1843
     * Set handler for model params
1844
     *
1845
     * @param string $name
1846
     * @param mixed $value
1847
     */
1848
    public function __set($name, $value) {
1849
        //static::fixPrefix($name);
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1850
        $className = get_called_class();
1851
        $shortName = $name;
1852
        if (!$value && !empty(static::$cols[$shortName]) && in_array('emptyValue', array_keys(static::$cols[$shortName]))) {
1853
            $value = static::$cols[$shortName]['emptyValue'];
1854
        }
1855
        if (is_null($value) && empty(static::$cols[$shortName]['null'])) {
1856
            $value = '';
1857
        }
1858
        if (!empty($className::$cols[$shortName])) {
1859
            switch ($className::$cols[$shortName]['type']) {
1860
                case 'decimal':
1861
                    $value = (float)$value;
1862
                    break;
1863
                case 'number':
1864
                    $value = (int)$value;
1865
                    break;
1866
                case 'bool':
1867
                    $value = (bool)$value;
1868
                    break;
1869
            }
1870
        }
1871 View Code Duplication
        if (in_array($name, array_keys($this->_params)) && $this->_params[$name] != $value && !in_array($name, array_keys($this->_changedParams))) {
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...
1872
            $this->_changedParams[$name] = $this->_params[$name];
1873
        }
1874
        $this->_params[$name] = $value;
1875 View Code Duplication
        if (in_array($name, array_keys($this->_params)) && in_array($name, array_keys($this->_changedParams)) && $this->_changedParams[$name] == $value) {
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
            unset($this->_changedParams[$name]);
1877
        }
1878
    }
1879
1880
    /**
1881
     * Isset handler for model params
1882
     *
1883
     * @param string $name
1884
     * @return boolean
1885
     */
1886
    public function __isset($name) {
1887
        static::fixPrefix($name);
1888
        return isset($this->_params[$name]);
1889
    }
1890
1891
    /**
1892
     * Convert object to string
1893
     *
1894
     * @return string
1895
     */
1896
    public function __toString() {
1897
        return $this->name();
1898
    }
1899
}