Completed
Push — master ( 1dd400...cdfa80 )
by Alexey
04:26
created

Model::logChanges()   C

Complexity

Conditions 15
Paths 6

Size

Total Lines 55
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 15
eloc 43
nc 6
nop 1
dl 0
loc 55
rs 6.7239
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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

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

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

Loading history...
244
        if ($item->$colName && json_decode($item->$colName, true)) {
245
          $addres = json_decode($item->$colName, true);
246
          $name = $addres['address'] ? $addres['address'] : 'lat:' . $addres['lat'] . ': lng:' . $addres['lng'];
247
          \App::$cur->libs->loadLib('yandexMap');
248
          ob_start();
249
          $uid = Tools::randomString();
250
          ?>
251
          <div id='map<?= $uid; ?>_container' style="display:none;"><script>/*
252
           <div id='map<?= $uid; ?>' style="width: 100%; height: 500px"></div>
253
           <script>
254
           var myMap<?= $uid; ?>;
255
           var myMap<?= $uid; ?>CurPin;
256
           inji.onLoad(function () {
257
           ymaps.ready(init<?= $uid; ?>);
258
           function init<?= $uid; ?>() {
259
           var myPlacemark;
260
           myMap<?= $uid; ?> = new ymaps.Map("map<?= $uid; ?>", {
261
           center: ["<?= $addres['lat'] ?>", "<?= $addres['lng']; ?>"],
262
           zoom: 13
263
           });
264
           myCoords = ["<?= $addres['lat'] ?>", "<?= $addres['lng']; ?>"];
265
           myMap<?= $uid; ?>CurPin = new ymaps.Placemark(myCoords,
266
           {iconContent: "<?= $addres['address']; ?>"},
267
           {preset: 'islands#greenStretchyIcon'}
268
           );
269
           myMap<?= $uid; ?>.geoObjects.add(myMap<?= $uid; ?>CurPin, 0);
270
           }
271
           window['init<?= $uid; ?>'] = init<?= $uid; ?>;
272
           });
273
           */</script>
274
          </div>
275
          <?php
276
          $content = ob_get_contents();
277
          ob_end_clean();
278
          $onclick = 'inji.Ui.modals.show("' . addcslashes($addres['address'], '"') . '", $("#map' . $uid . '_container script").html().replace(/^\/\*/g, "").replace(/\*\/$/g, "")+"</script>","mapmodal' . $uid . '","modal-lg");';
279
          $onclick .= 'return false;';
280
          $value = "<a href ='#' onclick='{$onclick}' >{$name}</a>";
281
          $value .= $content;
282
        } else {
283
          $value = 'Местоположение не заданно';
284
        }
285
286
        break;
287
      case 'dynamicType':
288
        switch ($colInfo['colParams']['typeSource']) {
289
          case'selfMethod':
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

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

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

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

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

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

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

Loading history...
293
                $relationPath = explode(':', $type['relation']);
294
                $relationName = array_pop($relationPath);
295
                $curItem = $item;
296
                foreach ($relationPath as $path) {
297
                  $curItem = $curItem->$path;
298
                }
299
                $itemModel = get_class($curItem);
300
                $relation = $itemModel::getRelation($relationName);
301
                $sourceModel = $relation['model'];
302
              } else {
303
                $relation = static::getRelation($type['relation']);
304
                $sourceModel = $relation['model'];
305
              }
306
              $inputType = 'select';
0 ignored issues
show
Unused Code introduced by
$inputType is not used, you could remove the assignment.

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

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

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

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

Loading history...
307
              $value = $sourceModel::get($item->$colName);
308
              if ($value) {
309
                $value = $value->name();
310
              } else {
311
                $value = $item->$colName;
312
              }
313
            } else {
314
              switch ($type) {
315 View Code Duplication
                case 'map':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
316
                  if ($item->$colName && json_decode($item->$colName, true)) {
317
                    $addres = json_decode($item->$colName, true);
318
                    $name = $addres['address'] ? $addres['address'] : 'lat:' . $addres['lat'] . ': lng:' . $addres['lng'];
319
                    \App::$cur->libs->loadLib('yandexMap');
320
                    ob_start();
321
                    $uid = Tools::randomString();
322
                    ?>
323
                    <div id='map<?= $uid; ?>_container' style="display:none;"><script>/*
324
                     <div id='map<?= $uid; ?>' style="width: 100%; height: 500px"></div>
325
                     <script>
326
                     var myMap<?= $uid; ?>;
327
                     var myMap<?= $uid; ?>CurPin;
328
                     inji.onLoad(function () {
329
                     ymaps.ready(init<?= $uid; ?>);
330
                     function init<?= $uid; ?>() {
331
                     var myPlacemark;
332
                     myMap<?= $uid; ?> = new ymaps.Map("map<?= $uid; ?>", {
333
                     center: ["<?= $addres['lat'] ?>", "<?= $addres['lng']; ?>"],
334
                     zoom: 13
335
                     });
336
                     myCoords = ["<?= $addres['lat'] ?>", "<?= $addres['lng']; ?>"];
337
                     myMap<?= $uid; ?>CurPin = new ymaps.Placemark(myCoords,
338
                     {iconContent: "<?= $addres['address']; ?>"},
339
                     {preset: 'islands#greenStretchyIcon'}
340
                     );
341
                     myMap<?= $uid; ?>.geoObjects.add(myMap<?= $uid; ?>CurPin, 0);
342
                     }
343
                     window['init<?= $uid; ?>'] = init<?= $uid; ?>;
344
                     });
345
                     */</script>
346
                    </div>
347
                    <?php
348
                    $content = ob_get_contents();
349
                    ob_end_clean();
350
                    $onclick = 'inji.Ui.modals.show("' . addcslashes($addres['address'], '"') . '", $("#map' . $uid . '_container script").html().replace(/^\/\*/g, "").replace(/\*\/$/g, "")+"</script>","mapmodal' . $uid . '","modal-lg");';
351
                    $onclick .= 'return false;';
352
                    $value = "<a href ='#' onclick='{$onclick}' >{$name}</a>";
353
                    $value .= $content;
354
                  } else {
355
                    $value = 'Местоположение не заданно';
356
                  }
357
358
                  break;
359
                default:
360
                  $value = $item->$colName;
361
              }
362
            }
363
            break;
364
        }
365
        break;
366
      default:
367
        $value = $item->$colName;
368
        break;
369
    }
370
    return $value;
371
  }
372
373
  /**
374
   * Fix col prefix
375
   * 
376
   * @param mixed $array
377
   * @param string $searchtype
378
   * @param string $rootModel
379
   * @return null
380
   */
381
  public static function fixPrefix(&$array, $searchtype = 'key', $rootModel = '') {
382
    if (!$rootModel) {
383
      $rootModel = get_called_class();
384
    }
385
    $cols = static::cols();
386
    if (!$array) {
387
      return;
388
    }
389
    if (!is_array($array)) {
390 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...
391
        static::createCol($array);
392
        $cols = static::cols(true);
393
      }
394
      if (!isset($cols[$array]) && isset($cols[static::colPrefix() . $array])) {
395
        $array = static::colPrefix() . $array;
396
      } else {
397
        static::checkForJoin($array, $rootModel);
398
      }
399
      return;
400
    }
401
    switch ($searchtype) {
402
      case 'key':
403
        foreach ($array as $key => $item) {
404 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...
405
            static::createCol($key);
406
            $cols = static::cols(true);
407
          }
408
          if (!isset($cols[$key]) && isset($cols[static::colPrefix() . $key])) {
409
            $array[static::colPrefix() . $key] = $item;
410
            unset($array[$key]);
411
            $key = static::colPrefix() . $key;
412
          }
413
          if (is_array($array[$key])) {
414
            static::fixPrefix($array[$key], 'key', $rootModel);
415
          } else {
416
            static::checkForJoin($key, $rootModel);
417
          }
418
        }
419
        break;
420
      case 'first':
421
        if (isset($array[0]) && is_string($array[0])) {
422
          if (!isset($cols[static::colPrefix() . $array[0]]) && isset(static::$cols[$array[0]])) {
423
            static::createCol($array[0]);
424
            $cols = static::cols(true);
425
          }
426 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...
427
            $array[0] = static::colPrefix() . $array[0];
428
          } else {
429
            static::checkForJoin($array[0], $rootModel);
430
          }
431
        } elseif (isset($array[0]) && is_array($array[0])) {
432
          foreach ($array as &$item) {
433
            static::fixPrefix($item, 'first', $rootModel);
434
          }
435
        }
436
        break;
437
    }
438
  }
439
440
  public function logChanges($new) {
441
    if (!App::$cur->db->connect || !App::$cur->dashboard) {
442
      return false;
443
    }
444
    $class = get_class($this);
445
    if (!$class::$logging) {
446
      return false;
447
    }
448
    if (!$new && !empty($this->_changedParams)) {
449
      $activity = new Dashboard\Activity([
450
          'user_id' => \Users\User::$cur->id,
451
          'module' => substr($class, 0, strpos($class, '\\')),
452
          'model' => $class,
453
          'item_id' => $this->pk(),
454
          'type' => 'changes'
455
      ]);
456
      $changes_text = [];
457
      foreach ($this->_changedParams as $fullColName => $oldValue) {
458
        $colName = substr($fullColName, strlen($class::colPrefix()));
459
        if(isset($class::$cols[$colName]['logging']) && !$class::$cols[$colName]['logging']){
460
          continue;
461
        }
462
        if (strlen($oldValue) + strlen($this->_params[$fullColName]) < 200) {
463
          $changes_text[] = (!empty($class::$labels[$colName]) ? $class::$labels[$colName] : $colName) . ": \"{$oldValue}\" => \"{$this->$colName}\"";
464
        } else {
465
          $changes_text[] = !empty($class::$labels[$colName]) ? $class::$labels[$colName] : $colName;
466
        }
467
      }
468
      if (!$changes_text) {
469
        return false;
470
      }
471
      $activity->changes_text = implode(', ', $changes_text);
472
      $activity->save();
473
      foreach ($this->_changedParams as $fullColName => $oldValue) {
474
        $colName = substr($fullColName, strlen($class::colPrefix()));
475
        $change = new Dashboard\Activity\Change([
476
            'activity_id' => $activity->id,
477
            'col' => $colName,
478
            'old' => $oldValue,
479
            'new' => $this->$colName
480
        ]);
481
        $change->save();
482
      }
483
    } elseif ($new) {
484
      $activity = new Dashboard\Activity([
485
          'user_id' => \Users\User::$cur->id,
486
          'module' => substr($class, 0, strpos($class, '\\')),
487
          'model' => $class,
488
          'item_id' => $this->pk(),
489
          'type' => 'new'
490
      ]);
491
      $activity->save();
492
    }
493
    return true;
494
  }
495
496
  /**
497
   * Check model relations path and load need relations
498
   * 
499
   * @param string $col
500
   * @param string $rootModel
501
   */
502
  public static function checkForJoin(&$col, $rootModel) {
503
504
    if (strpos($col, ':') !== false) {
505
      $relations = static::relations();
506
      if (isset($relations[substr($col, 0, strpos($col, ':'))])) {
507
        $rel = substr($col, 0, strpos($col, ':'));
508
        $col = substr($col, strpos($col, ':') + 1);
509
510
        $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
511
        switch ($type) {
512 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...
513
            $relCol = $relations[$rel]['col'];
514
            static::fixPrefix($relCol);
515
            $rootModel::$relJoins[$relations[$rel]['model'] . '_' . $rel] = [$relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol];
516
            break;
517
          case 'one':
518 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...
519
            $relCol = $relations[$rel]['col'];
520
            $relations[$rel]['model']::fixPrefix($relCol);
521
            $rootModel::$relJoins[$relations[$rel]['model'] . '_' . $rel] = [$relations[$rel]['model']::table(), static::index() . ' = ' . $relCol];
522
            break;
523
        }
524
        $relations[$rel]['model']::fixPrefix($col, 'key', $rootModel);
525
      }
526
    }
527
  }
528
529
  /**
530
   * Return full col information
531
   * 
532
   * @param string $col
533
   * @return array
534
   */
535
  public static function getColInfo($col) {
536
    return static::parseColRecursion($col);
537
  }
538
539
  /**
540
   * Information extractor for col relations path
541
   * 
542
   * @param string|array $info
543
   * @return array
544
   */
545
  public static function parseColRecursion($info) {
546
    if (is_string($info)) {
547
      $info = ['col' => $info, 'rawCol' => $info, 'modelName' => '', 'label' => '', 'joins' => []];
548
    }
549
    if (strpos($info['col'], ':') !== false) {
550
      $relations = static::relations();
551
      if (isset($relations[substr($info['col'], 0, strpos($info['col'], ':'))])) {
552
        $rel = substr($info['col'], 0, strpos($info['col'], ':'));
553
        $info['col'] = substr($info['col'], strpos($info['col'], ':') + 1);
554
        $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
555
        switch ($type) {
556 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...
557
            $relCol = $relations[$rel]['col'];
558
            static::fixPrefix($relCol);
559
            //$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...
560
            $info['joins'][$relations[$rel]['model'] . '_' . $rel] = [$relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol];
561
            break;
562 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...
563
            $relCol = $relations[$rel]['col'];
564
            $relations[$rel]['model']::fixPrefix($relCol);
565
            //$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...
566
            $info['joins'][$relations[$rel]['model'] . '_' . $rel] = [$relations[$rel]['model']::table(), static::index() . ' = ' . $relCol];
567
            break;
568
        }
569
        $info = $relations[$rel]['model']::parseColRecursion($info);
570
      }
571
    } else {
572
      $cols = static::cols();
573 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...
574
        $info['label'] = static::$labels[$info['col']];
575
      }
576
577
      if (isset(static::$cols[$info['col']])) {
578
        $info['colParams'] = static::$cols[$info['col']];
579
      } elseif (isset(static::$cols[str_replace(static::colPrefix(), '', $info['col'])])) {
580
        $info['colParams'] = static::$cols[str_replace(static::colPrefix(), '', $info['col'])];
581
      } else {
582
        $info['colParams'] = [];
583
      }
584 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...
585
        $info['col'] = static::colPrefix() . $info['col'];
586
      }
587
      $info['modelName'] = get_called_class();
588
    }
589 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...
590
      $info['label'] = static::$labels[$info['rawCol']];
591
    }
592
    return $info;
593
  }
594
595
  /**
596
   * Return actual cols from data base
597
   * 
598
   * @param boolean $refresh
599
   * @return array
600
   */
601
  public static function cols($refresh = false) {
602
    if (static::$storage['type'] == 'moduleConfig') {
603
      return [];
604
    }
605 View Code Duplication
    if (empty(Model::$cols[static::table()]) || $refresh) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

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

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

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

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

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

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

Loading history...
979
      $return = [];
980
      foreach ($list as $key => $item) {
981
        $return[$key] = $item->name();
982
      }
983
      return $return;
984
    }
985
    return $list;
986
  }
987
988
  /**
989
   * Return list of objects from data base
990
   * 
991
   * @param type $options
992
   * @return type
993
   */
994
  public static function getList($options = []) {
995
    if (static::$storage['type'] != 'db') {
996
      return static::getListFromModuleStorage($options);
997
    }
998
    if (!empty($options['where'])) {
999
      static::fixPrefix($options['where'], 'first');
1000
    }
1001
    if (!empty($options['group'])) {
1002
      static::fixPrefix($options['group'], 'first');
1003
    }
1004
    if (!empty($options['order'])) {
1005
      static::fixPrefix($options['order'], 'first');
1006
    }
1007
    if (!empty($options['having'])) {
1008
      static::fixPrefix($options['having'], 'first');
1009
    }
1010
    return static::get_list($options);
1011
  }
1012
1013
  /**
1014
   * Get single item from module storage
1015
   * 
1016
   * @param array $param
1017
   * @param string $col
1018
   * @param array $options
1019
   * @return boolean|\Model
1020
   */
1021
  public static function getFromModuleStorage($param = null, $col = null, $options = []) {
1022
    if ($col === null) {
1023
1024
      $col = static::index();
1025
    }
1026
    if ($param == null) {
1027
      return false;
1028
    }
1029
    $classPath = explode('\\', get_called_class());
1030 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...
1031
      $moduleConfig = Config::share($classPath[0]);
1032
    } else {
1033
      $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
1034
    }
1035
    $appType = App::$cur->type;
1036 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...
1037
      if (!empty($options['appType'])) {
1038
        $appType = $options['appType'];
1039
      }
1040
      $storage = !empty($moduleConfig['storage'][$appType]) ? $moduleConfig['storage'][$appType] : [];
1041
    } else {
1042
      $storage = !empty($moduleConfig['storage']) ? $moduleConfig['storage'] : [];
1043
    }
1044
    if (!empty($storage[$classPath[1]])) {
1045
      $items = $storage[$classPath[1]];
1046
      $class = get_called_class();
1047
      $where = is_array($param) ? $param : [$col, $param];
1048
      foreach ($items as $key => $item) {
1049
        if (!Model::checkWhere($item, $where)) {
1050
          continue;
1051
        }
1052
        if (!empty($options['array'])) {
1053
          return $item;
1054
        }
1055
        $item = new $class($item);
1056
        $item->appType = $appType;
1057
        return $item;
1058
      }
1059
    }
1060
    return false;
1061
  }
1062
1063
  /**
1064
   * Return list items from module storage
1065
   * 
1066
   * @param array $options
1067
   * @return array
1068
   */
1069
  public static function getListFromModuleStorage($options = []) {
1070
    $classPath = explode('\\', get_called_class());
1071 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...
1072
      $moduleConfig = Config::share($classPath[0]);
1073
    } else {
1074
      $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
1075
    }
1076 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...
1077
      if (empty($options['appType'])) {
1078
        $appType = App::$cur->type;
1079
      } else {
1080
        $appType = $options['appType'];
1081
      }
1082
      $storage = !empty($moduleConfig['storage'][$appType]) ? $moduleConfig['storage'][$appType] : [];
1083
    } else {
1084
      $storage = !empty($moduleConfig['storage']) ? $moduleConfig['storage'] : [];
1085
    }
1086
    if (!empty($storage[$classPath[1]])) {
1087
      $items = [];
1088
      $class = get_called_class();
1089
      if (isset($options['key'])) {
1090
        $arrayKey = $options['key'];
1091
      } else {
1092
        $arrayKey = static::index();
1093
      }
1094
      foreach ($storage[$classPath[1]] as $key => $item) {
1095
        if (!empty($options['where']) && !Model::checkWhere($item, $options['where'])) {
1096
          continue;
1097
        }
1098
        $items[$item[$arrayKey]] = new $class($item);
1099
      }
1100
      if (!empty($options['order'])) {
1101
        usort($items, function($a, $b) use($options) {
1102
          if ($a->{$options['order'][0]} > $b->{$options['order'][0]} && $options['order'][1] = 'asc') {
1103
            return 1;
1104
          } elseif ($a->{$options['order'][0]} < $b->{$options['order'][0]} && $options['order'][1] = 'asc') {
1105
            return -1;
1106
          }
1107
          return 0;
1108
        });
1109
      }
1110 View Code Duplication
      if (!empty($options['forSelect'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1111
        $return = [];
1112
        foreach ($items as $key => $item) {
1113
          $return[$key] = $item->name();
1114
        }
1115
        return $return;
1116
      }
1117
      return $items;
1118
    }
1119
    return [];
1120
  }
1121
1122
  /**
1123
   * Return count of records from module storage
1124
   * 
1125
   * @param array $options
1126
   * @return int
1127
   */
1128
  public static function getCountFromModuleStorage($options = []) {
1129
1130
    $classPath = explode('\\', get_called_class());
1131
    $count = 0;
1132
    if (empty($options['appType'])) {
1133
      $appType = App::$cur->type;
1134
    } else {
1135
      $appType = $options['appType'];
1136
    }
1137 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...
1138
      $moduleConfig = Config::share($classPath[0]);
1139
    } else {
1140
      $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
1141
    }
1142
    if (!empty($moduleConfig['storage'][$appType][$classPath[1]])) {
1143
      $items = $moduleConfig['storage'][$appType][$classPath[1]];
1144
      if (empty($options['where'])) {
1145
        return count($items);
1146
      }
1147
      foreach ($items as $key => $item) {
1148
        if (!empty($options['where'])) {
1149
          if (Model::checkWhere($item, $options['where'])) {
1150
            $count++;
1151
          }
1152
        } else {
1153
          $count++;
1154
        }
1155
      }
1156
    }
1157
    return $count;
1158
  }
1159
1160
  /**
1161
   * Check where for module storage query
1162
   * 
1163
   * @param array $item
1164
   * @param array|string $where
1165
   * @param string $value
1166
   * @param string $operation
1167
   * @param string $concatenation
1168
   * @return boolean
1169
   */
1170
  public static function checkWhere($item = [], $where = '', $value = '', $operation = '=', $concatenation = 'AND') {
1171
1172
    if (is_array($where)) {
1173
      if (is_array($where[0])) {
1174
        $result = true;
1175
        foreach ($where as $key => $whereItem) {
1176
          $concatenation = empty($whereItem[3]) ? 'AND' : strtoupper($whereItem[3]);
1177
          switch ($concatenation) {
1178 View Code Duplication
            case 'AND':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1179
              $result = $result && forward_static_call_array(['Model', 'checkWhere'], [$item, $whereItem]);
1180
              break;
1181 View Code Duplication
            case 'OR':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1182
              $result = $result || forward_static_call_array(['Model', 'checkWhere'], [$item, $whereItem]);
1183
              break;
1184
          }
1185
        }
1186
1187
        return $result;
1188
      } else {
1189
        return forward_static_call_array(['Model', 'checkWhere'], array_merge([$item], $where));
1190
      }
1191
    }
1192
    if (!isset($item[$where]) && !$value) {
1193
      return true;
1194
    }
1195
    if (!isset($item[$where]) && $value) {
1196
      return false;
1197
    }
1198
    if ($item[$where] == $value) {
1199
      return true;
1200
    }
1201
    return false;
1202
  }
1203
1204
  /**
1205
   * Return count of records from data base
1206
   * 
1207
   * @param array $options
1208
   * @return array|int
1209
   */
1210
  public static function getCount($options = []) {
1211
    if (static::$storage['type'] == 'moduleConfig') {
1212
      return static::getCountFromModuleStorage($options);
1213
    }
1214
    $query = App::$cur->db->newQuery();
1215
    if (!$query) {
1216
      return 0;
1217
    }
1218
    if (!empty($options['where'])) {
1219
      static::fixPrefix($options['where'], 'first');
1220
    }
1221
    if (!empty($options['group'])) {
1222
      static::fixPrefix($options['group'], 'first');
1223
    }
1224
    if (!empty($options['where']))
1225
      $query->where($options['where']);
1226
    if (!empty($options['join']))
1227
      $query->join($options['join']);
1228
    if (!empty($options['order'])) {
1229
      $query->order($options['order']);
1230
    }
1231 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...
1232
      $limit = (int) $options['limit'];
1233
    else {
1234
      $limit = 0;
1235
    }
1236 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...
1237
      $start = (int) $options['start'];
1238
    else {
1239
      $start = 0;
1240
    }
1241
    if ($limit || $start) {
1242
      $query->limit($start, $limit);
1243
    }
1244
1245
    foreach (static::$relJoins as $join) {
1246
      $query->join($join[0], $join[1]);
1247
    }
1248
    static::$relJoins = [];
1249 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...
1250
      $relations = static::relations();
1251
      if (isset($relations[$rel])) {
1252
        $type = empty($relations[$rel]['type']) ? 'to' : $relations[$rel]['type'];
1253
        switch ($type) {
1254
          case 'to':
1255
            $relCol = $relations[$rel]['col'];
1256
            static::fixPrefix($relCol);
1257
            $query->join($relations[$rel]['model']::table(), $relations[$rel]['model']::index() . ' = ' . $relCol);
1258
            break;
1259
          case 'one':
1260
            $col = $relations[$rel]['col'];
1261
            $relations[$rel]['model']::fixPrefix($col);
1262
            $query->join($relations[$rel]['model']::table(), static::index() . ' = ' . $col);
1263
            break;
1264
        }
1265
      }
1266
    }
1267
    static::$needJoin = [];
1268
    $cols = 'COUNT(';
1269
1270
    if (!empty($options['distinct'])) {
1271
      if (is_bool($options['distinct'])) {
1272
        $cols .= 'DISTINCT *';
1273
      } else {
1274
        $cols .= "DISTINCT {$options['distinct']}";
1275
      }
1276
    } else {
1277
      $cols .= '*';
1278
    }
1279
    $cols .=') as `count`' . (!empty($options['cols']) ? ',' . $options['cols'] : '');
1280
    $query->cols = $cols;
1281
    if (!empty($options['group'])) {
1282
      $query->group($options['group']);
1283
    }
1284
    try {
1285
      $result = $query->select(static::table());
1286
    } catch (PDOException $exc) {
1287
      if ($exc->getCode() == '42S02') {
1288
        static::createTable();
1289
      }
1290
      $result = $query->select(static::table());
1291
    }
1292
    if (!empty($options['group'])) {
1293
      $count = $result->getArray();
1294
      return $count;
1295
    } else {
1296
      $count = $result->fetch();
1297
      return $count['count'];
1298
    }
1299
  }
1300
1301
  /**
1302
   * Update records in data base
1303
   * 
1304
   * @param array $params
1305
   * @param array $where
1306
   * @return boolean
1307
   */
1308
  public static function update($params, $where = []) {
1309
    static::fixPrefix($params);
1310
1311
    $cols = self::cols();
1312
1313
    $values = [];
1314
    foreach ($cols as $col => $param) {
1315
      if (isset($params[$col]))
1316
        $values[$col] = $params[$col];
1317
    }
1318
    if (empty($values)) {
1319
      return false;
1320
    }
1321
1322
    if (!empty($where)) {
1323
      static::fixPrefix($where, 'first');
1324
1325
      App::$cur->db->where($where);
1326
    }
1327
    App::$cur->db->update(static::table(), $values);
1328
  }
1329
1330
  /**
1331
   * Return primary key of object
1332
   * 
1333
   * @return mixed
1334
   */
1335
  public function pk() {
1336
    return $this->{$this->index()};
1337
  }
1338
1339
  /**
1340
   * Before save trigger
1341
   */
1342
  public function beforeSave() {
1343
    
1344
  }
1345
1346
  /**
1347
   * Save object to module storage
1348
   * 
1349
   * @param array $options
1350
   * @return boolean
1351
   */
1352
  public function saveModuleStorage($options) {
1353
1354
    $col = static::index();
1355
    $id = $this->pk();
1356
    $appType = '';
1357
    $classPath = explode('\\', get_called_class());
1358
1359 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...
1360
      $moduleConfig = Config::share($classPath[0]);
1361
    } else {
1362
      $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
1363
    }
1364
1365 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...
1366
      if (empty($options['appType'])) {
1367
        $appType = App::$cur->type;
1368
      } else {
1369
        $appType = $options['appType'];
1370
      }
1371
      $storage = !empty($moduleConfig['storage'][$appType]) ? $moduleConfig['storage'][$appType] : [];
1372
    } else {
1373
      $storage = !empty($moduleConfig['storage']) ? $moduleConfig['storage'] : [];
1374
    }
1375
    if (empty($storage[$classPath[1]])) {
1376
      $storage[$classPath[1]] = [];
1377
    }
1378
    if ($id) {
1379 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...
1380
        if ($item[$col] == $id) {
1381
          $storage[$classPath[1]][$key] = $this->_params;
1382
          break;
1383
        }
1384
      }
1385
    } else {
1386
      $id = !empty($storage['scheme'][$classPath[1]]['ai']) ? $storage['scheme'][$classPath[1]]['ai'] : 1;
1387
      $this->$col = $id;
1388
      $storage['scheme'][$classPath[1]]['ai'] = $id + 1;
1389
      $storage[$classPath[1]][] = $this->_params;
1390
    }
1391 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...
1392
      $moduleConfig['storage'][$appType] = $storage;
1393
    } else {
1394
      $moduleConfig['storage'] = $storage;
1395
    }
1396 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...
1397
      Config::save('module', $moduleConfig, $classPath[0]);
1398
    } else {
1399
      Config::save('share', $moduleConfig, $classPath[0]);
1400
    }
1401
    return true;
1402
  }
1403
1404
  /**
1405
   * Update tree path category
1406
   */
1407
  public function changeCategoryTree() {
1408
    $class = get_class($this);
1409
    $itemModel = $class::$treeCategory;
1410
    $oldPath = $this->tree_path;
1411
    $this->tree_path = $this->getCatalogTree($this);
1412
    $itemsTable = \App::$cur->db->table_prefix . $itemModel::table();
1413
    $itemTreeCol = $itemModel::colPrefix() . 'tree_path';
1414
1415
    $categoryTreeCol = $this->colPrefix() . 'tree_path';
1416
    $categoryTable = \App::$cur->db->table_prefix . $this->table();
1417
    if ($oldPath) {
1418
      \App::$cur->db->query('UPDATE
1419
                ' . $categoryTable . ' 
1420
                    SET 
1421
                        ' . $categoryTreeCol . ' = REPLACE(' . $categoryTreeCol . ', "' . $oldPath . $this->id . '/' . '", "' . $this->tree_path . $this->id . '/' . '") 
1422
                    WHERE ' . $categoryTreeCol . ' LIKE "' . $oldPath . $this->id . '/' . '%"');
1423
1424
      \App::$cur->db->query('UPDATE
1425
                ' . $itemsTable . '
1426
                    SET 
1427
                        ' . $itemTreeCol . ' = REPLACE(' . $itemTreeCol . ', "' . $oldPath . $this->id . '/' . '", "' . $this->tree_path . $this->id . '/' . '") 
1428
                    WHERE ' . $itemTreeCol . ' LIKE "' . $oldPath . $this->id . '/' . '%"');
1429
    }
1430
    $itemModel::update([$itemTreeCol => $this->tree_path . $this->id . '/'], [$itemModel::colPrefix() . $this->index(), $this->id]);
1431
  }
1432
1433
  /**
1434
   * Return tree path
1435
   * 
1436
   * @param \Model $catalog
1437
   * @return string
1438
   */
1439
  public function getCatalogTree($catalog) {
1440
    $catalogClass = get_class($catalog);
1441
    $catalogParent = $catalogClass::get($catalog->parent_id);
1442
    if ($catalog && $catalogParent) {
1443
      if ($catalogParent->tree_path) {
1444
        return $catalogParent->tree_path . $catalogParent->id . '/';
1445
      } else {
1446
        return $this->getCatalogTree($catalogParent) . $catalogParent->id . '/';
1447
      }
1448
    }
1449
    return '/';
1450
  }
1451
1452
  /**
1453
   * Update tree path item
1454
   */
1455
  public function changeItemTree() {
1456
    $class = get_class($this);
1457
    $categoryModel = $class::$categoryModel;
1458
    $category = $categoryModel::get($this->{$categoryModel::index()});
1459
    if ($category) {
1460
      $this->tree_path = $category->tree_path . $category->pk() . '/';
1461
    } else {
1462
      $this->tree_path = '/';
1463
    }
1464
  }
1465
1466
  /**
1467
   * Save object to data base
1468
   * 
1469
   * @param array $options
1470
   * @return boolean|int
1471
   */
1472
  public function save($options = []) {
1473
1474
    if (static::$storage['type'] == 'moduleConfig') {
1475
      return static::saveModuleStorage($options);
1476
    }
1477
    $class = get_class($this);
1478
    if ($class::$categoryModel) {
1479
      $this->changeItemTree();
1480
    }
1481
    if ($class::$treeCategory) {
1482
      $this->changeCategoryTree();
1483
    }
1484
    if (!empty($this->_changedParams) && $this->pk()) {
1485
      Inji::$inst->event('modelItemParamsChanged-' . get_called_class(), $this);
1486
    }
1487
    $this->beforeSave();
1488
    $values = [];
1489
1490
    foreach ($this->cols() as $col => $param) {
1491
      if (isset($this->_params[$col])) {
1492
        $values[$col] = $this->_params[$col];
1493
      }
1494
    }
1495
    foreach ($class::$cols as $colName => $params) {
1496
      $class::fixPrefix($colName);
1497
      if (isset($params['default']) && !isset($values[$colName])) {
1498
        $this->_params[$colName] = $values[$colName] = $params['default'];
1499
      }
1500
    }
1501
    if (empty($values) && empty($options['empty'])) {
1502
      return false;
1503
    }
1504
1505
    if ($this->pk()) {
1506
      $new = false;
1507
      if ($this->get($this->_params[$this->index()])) {
1508
        App::$cur->db->where($this->index(), $this->_params[$this->index()]);
1509
        App::$cur->db->update($this->table(), $values);
1510
      } else {
1511
1512
        $this->_params[$this->index()] = App::$cur->db->insert($this->table(), $values);
1513
      }
1514
    } else {
1515
      $new = true;
1516
      $this->_params[$this->index()] = App::$cur->db->insert($this->table(), $values);
1517
    }
1518
    $this->logChanges($new);
1519
    App::$cur->db->where($this->index(), $this->_params[$this->index()]);
1520
    try {
1521
      $result = App::$cur->db->select($this->table());
1522
    } catch (PDOException $exc) {
1523
      if ($exc->getCode() == '42S02') {
1524
        $this->createTable();
1525
      }
1526
      $result = App::$cur->db->select($this->table());
1527
    }
1528
    $this->_params = $result->fetch();
1529
    if ($new) {
1530
      Inji::$inst->event('modelCreatedItem-' . get_called_class(), $this);
1531
    }
1532
    $this->afterSave();
1533
    return $this->{$this->index()};
1534
  }
1535
1536
  /**
1537
   * After save trigger
1538
   */
1539
  public function afterSave() {
1540
    
1541
  }
1542
1543
  /**
1544
   * Before delete trigger
1545
   */
1546
  public function beforeDelete() {
1547
    
1548
  }
1549
1550
  /**
1551
   * Delete item from module storage
1552
   * 
1553
   * @param array $options
1554
   * @return boolean
1555
   */
1556
  public function deleteFromModuleStorage($options) {
1557
1558
    $col = static::index();
1559
    $id = $this->pk();
1560
    $appType = '';
1561
    $classPath = explode('\\', get_called_class());
1562 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...
1563
      $moduleConfig = Config::share($classPath[0]);
1564
    } else {
1565
      $moduleConfig = Config::module($classPath[0], strpos(static::$storage['type'], 'system') !== false);
1566
    }
1567
1568 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...
1569
      if (empty($options['appType'])) {
1570
        $appType = App::$cur->type;
1571
      } else {
1572
        $appType = $options['appType'];
1573
      }
1574
      $storage = !empty($moduleConfig['storage'][$appType]) ? $moduleConfig['storage'][$appType] : [];
1575
    } else {
1576
      $storage = !empty($moduleConfig['storage']) ? $moduleConfig['storage'] : [];
1577
    }
1578
    if (empty($storage[$classPath[1]])) {
1579
      $storage[$classPath[1]] = [];
1580
    }
1581 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...
1582
1583
      if ($item[$col] == $id) {
1584
        unset($storage[$classPath[1]][$key]);
1585
        break;
1586
      }
1587
    }
1588 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...
1589
      $moduleConfig['storage'][$appType] = $storage;
1590
    } else {
1591
      $moduleConfig['storage'] = $storage;
1592
    }
1593 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...
1594
      Config::save('module', $moduleConfig, $classPath[0]);
1595
    } else {
1596
      Config::save('share', $moduleConfig, $classPath[0]);
1597
    }
1598
    return true;
1599
  }
1600
1601
  /**
1602
   * Delete item from data base
1603
   * 
1604
   * @param array $options
1605
   * @return boolean
1606
   */
1607
  public function delete($options = []) {
1608
    $this->beforeDelete();
1609
1610
    if (static::$storage['type'] == 'moduleConfig') {
1611
      return static::deleteFromModuleStorage($options);
1612
    }
1613
    if (!empty($this->_params[$this->index()])) {
1614
      App::$cur->db->where($this->index(), $this->_params[$this->index()]);
1615
      $result = App::$cur->db->delete($this->table());
1616
      if ($result) {
1617
        $this->afterDelete();
1618
        return $result;
1619
      }
1620
    }
1621
    return false;
1622
  }
1623
1624
  /**
1625
   * Delete items from data base
1626
   * 
1627
   * @param array $where
1628
   */
1629
  public static function deleteList($where) {
1630
    if (!empty($where)) {
1631
      static::fixPrefix($where, 'first');
1632
      App::$cur->db->where($where);
1633
    }
1634
    App::$cur->db->delete(static::table());
1635
  }
1636
1637
  /**
1638
   * After delete trigger
1639
   */
1640
  public function afterDelete() {
1641
    
1642
  }
1643
1644
  /**
1645
   * find relation for col name
1646
   * 
1647
   * @param string $col
1648
   * @return array|null
1649
   */
1650
  public static function findRelation($col) {
1651
1652
    foreach (static::relations() as $relName => $rel) {
1653
      if ($rel['col'] == $col)
1654
        return $relName;
1655
    }
1656
    return NULL;
1657
  }
1658
1659
  /**
1660
   * Set params for model
1661
   * 
1662
   * @param array $params
1663
   */
1664
  public function setParams($params) {
1665
    static::fixPrefix($params);
1666
    $className = get_called_class();
1667
    foreach ($params as $paramName => $value) {
1668
      $shortName = preg_replace('!' . $this->colPrefix() . '!', '', $paramName);
1669
      if (!empty($className::$cols[$shortName])) {
1670
        switch ($className::$cols[$shortName]['type']) {
1671
          case 'decimal':
1672
            $params[$paramName] = (float) $value;
1673
            break;
1674
          case 'number':
1675
            $params[$paramName] = (int) $value;
1676
            break;
1677
          case 'bool':
1678
            $params[$paramName] = (bool) $value;
1679
            break;
1680
        }
1681
      }
1682
    }
1683
    $this->_params = array_merge($this->_params, $params);
1684
  }
1685
1686
  /**
1687
   * Return relation
1688
   * 
1689
   * @param string $relName
1690
   * @return array|boolean
1691
   */
1692
  public static function getRelation($relName) {
1693
    $relations = static::relations();
1694
    return !empty($relations[$relName]) ? $relations[$relName] : false;
1695
  }
1696
1697
  /**
1698
   * Load relation
1699
   * 
1700
   * @param string $name
1701
   * @param array $params
1702
   * @return null|array|integer|\Model
1703
   */
1704
  public function loadRelation($name, $params = []) {
1705
    $relation = static::getRelation($name);
1706
    if ($relation) {
1707
      if (!isset($relation['type'])) {
1708
        $type = 'to';
1709
      } else {
1710
        $type = $relation['type'];
1711
      }
1712
      $getCol = null;
1713
      $getParams = [];
1714
      switch ($type) {
1715
        case 'relModel':
1716
          if (!$this->pk()) {
1717
            return [];
1718
          }
1719
          $fixedCol = $relation['model']::index();
1720
          $relation['relModel']::fixPrefix($fixedCol);
1721
          $ids = array_keys($relation['relModel']::getList(['where' => [$this->index(), $this->pk()], 'array' => true, 'key' => $fixedCol]));
1722
          if (empty($ids)) {
1723
            if (empty($params['count'])) {
1724
              return [];
1725
            } else {
1726
              return 0;
1727
            }
1728
          }
1729
          $getType = 'getList';
1730
          $options = [
1731
              'where' => [$relation['model']::index(), implode(',', $ids), 'IN'],
1732
              'array' => (!empty($params['array'])) ? true : false,
1733
              'key' => (isset($params['key'])) ? $params['key'] : ((isset($relation['resultKey'])) ? $relation['resultKey'] : null),
1734
              'start' => (isset($params['start'])) ? $params['start'] : ((isset($relation['start'])) ? $relation['start'] : null),
1735
              'order' => (isset($params['order'])) ? $params['order'] : ((isset($relation['order'])) ? $relation['order'] : null),
1736
              'limit' => (isset($params['limit'])) ? $params['limit'] : ((isset($relation['limit'])) ? $relation['limit'] : null),
1737
          ];
1738
          break;
1739
        case 'many':
1740
          if (!$this->{$this->index()}) {
1741
            return [];
1742
          }
1743
          $getType = 'getList';
1744
          $options = [
1745
              'join' => (isset($relation['join'])) ? $relation['join'] : null,
1746
              'key' => (isset($params['key'])) ? $params['key'] : ((isset($relation['resultKey'])) ? $relation['resultKey'] : null),
1747
              'array' => (!empty($params['array'])) ? true : false,
1748
              'forSelect' => (!empty($params['forSelect'])) ? true : false,
1749
              'order' => (isset($params['order'])) ? $params['order'] : ((isset($relation['order'])) ? $relation['order'] : null),
1750
              'start' => (isset($params['start'])) ? $params['start'] : ((isset($relation['start'])) ? $relation['start'] : null),
1751
              'limit' => (isset($params['limit'])) ? $params['limit'] : ((isset($relation['limit'])) ? $relation['limit'] : null),
1752
              'appType' => (isset($params['appType'])) ? $params['appType'] : ((isset($relation['appType'])) ? $relation['appType'] : null),
1753
              'where' => []
1754
          ];
1755
          $options['where'][] = [$relation['col'], $this->{$this->index()}];
1756
          if (!empty($relation['where'])) {
1757
            $options['where'] = array_merge($options['where'], [$relation['where']]);
1758
          }
1759
          if (!empty($params['where'])) {
1760
            $options['where'] = array_merge($options['where'], [$params['where']]);
1761
          }
1762
          break;
1763
        case 'one':
1764
          $getType = 'get';
1765
          $options = [$relation['col'], $this->pk()];
1766
          break;
1767
        default:
1768
          if ($this->$relation['col'] === NULL) {
1769
            return null;
1770
          }
1771
          $getType = 'get';
1772
          $options = $this->$relation['col'];
1773
          $getParams['appType'] = $this->appType;
1774
      }
1775
      if (!empty($params['count'])) {
1776
        if (class_exists($relation['model'])) {
1777
          return $relation['model']::getCount($options);
1778
        }
1779
        return 0;
1780
      } else {
1781
        if (class_exists($relation['model'])) {
1782
          $this->loadedRelations[$name][json_encode($params)] = $relation['model']::$getType($options, $getCol, $getParams);
1783
        } else {
1784
          $this->loadedRelations[$name][json_encode($params)] = [];
1785
        }
1786
      }
1787
      return $this->loadedRelations[$name][json_encode($params)];
1788
    }
1789
    return NULL;
1790
  }
1791
1792
  /**
1793
   * Add relation item
1794
   * 
1795
   * @param string $relName
1796
   * @param \Model $objectId
1797
   * @return \Model|boolean
1798
   */
1799
  public function addRelation($relName, $objectId) {
1800
    $relation = $this->getRelation($relName);
1801
    if ($relation) {
1802
      $rel = $relation['relModel']::get([[$relation['model']::index(), $objectId], [$this->index(), $this->pk()]]);
1803
      if (!$rel) {
1804
        $rel = new $relation['relModel']([
1805
            $relation['model']::index() => $objectId,
1806
            $this->index() => $this->pk()
1807
        ]);
1808
        $rel->save();
1809
      }
1810
      return $rel;
1811
    }
1812
    return false;
1813
  }
1814
1815
  /**
1816
   * Check user access for form
1817
   * 
1818
   * @param string $formName
1819
   * @return boolean
1820
   */
1821
  public function checkFormAccess($formName) {
1822
    if ($formName == 'manage' && !Users\User::$cur->isAdmin()) {
1823
      return false;
1824
    }
1825
    return true;
1826
  }
1827
1828
  /**
1829
   * Check access for model
1830
   * 
1831
   * @param string $mode
1832
   * @param \Users\User $user
1833
   * @return boolean
1834
   */
1835
  public function checkAccess($mode = 'write', $user = null) {
1836
    if (!$user) {
1837
      $user = \Users\User::$cur;
1838
    }
1839
    return $user->isAdmin();
1840
  }
1841
1842
  /**
1843
   * Param and relation with params getter
1844
   * 
1845
   * @param string $name
1846
   * @param array $params
1847
   * @return \Value|mixed
1848
   */
1849
  public function __call($name, $params) {
1850
    $fixedName = $name;
1851
    static::fixPrefix($fixedName);
1852 View Code Duplication
    if (isset($this->_params[$fixedName])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1853
      return new Value($this, $fixedName);
1854
    } elseif (isset($this->_params[$name])) {
1855
      return new Value($this, $name);
1856
    }
1857
    return call_user_func_array([$this, 'loadRelation'], array_merge([$name], $params));
1858
  }
1859
1860
  /**
1861
   * Param and relation getter
1862
   * 
1863
   * @param string $name
1864
   * @return mixed
1865
   */
1866
  public function __get($name) {
1867
    $fixedName = $name;
1868
    static::fixPrefix($fixedName);
1869
    if (isset($this->_params[$fixedName])) {
1870
      return $this->_params[$fixedName];
1871
    }
1872
    if (isset($this->loadedRelations[$name][json_encode([])])) {
1873
      return $this->loadedRelations[$name][json_encode([])];
1874
    }
1875
    return $this->loadRelation($name);
1876
  }
1877
1878
  /**
1879
   * Return model value in object
1880
   * 
1881
   * @param string $name
1882
   * @return \Value|null
1883
   */
1884
  public function value($name) {
1885
    $fixedName = $name;
1886
    static::fixPrefix($fixedName);
1887 View Code Duplication
    if (isset($this->_params[$fixedName])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1888
      return new Value($this, $fixedName);
1889
    } elseif ($this->_params[$name]) {
1890
      return new Value($this, $name);
1891
    }
1892
    return null;
1893
  }
1894
1895
  /**
1896
   * Return manager filters
1897
   * 
1898
   * @return array
1899
   */
1900
  public static function managerFilters() {
1901
    return [];
1902
  }
1903
1904
  /**
1905
   * Return validators for cols
1906
   * 
1907
   * @return array
1908
   */
1909
  public static function validators() {
1910
    return [];
1911
  }
1912
1913
  /**
1914
   * Return validator by name
1915
   * 
1916
   * @param string $name
1917
   * @return array
1918
   */
1919
  public static function validator($name) {
1920
    $validators = static::validators();
1921
    if (!empty($validators[$name])) {
1922
      return $validators[$name];
1923
    }
1924
    return [];
1925
  }
1926
1927
  function genViewLink() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1928
    $className = get_class($this);
1929
    $link = substr($className, 0, strpos($className, '\\'));
1930
    $link .= '/view/';
1931
    $link .= str_replace('\\', '%5C', substr($className, strpos($className, '\\') + 1));
1932
    $link .= "/{$this->id}";
1933
    return $link;
1934
  }
1935
1936
  /**
1937
   * Set handler for model params
1938
   * 
1939
   * @param string $name
1940
   * @param mixed $value
1941
   */
1942
  public function __set($name, $value) {
1943
    static::fixPrefix($name);
1944
    $className = get_called_class();
1945
    $shortName = preg_replace('!' . $this->colPrefix() . '!', '', $name);
1946
    if (!empty($className::$cols[$shortName])) {
1947
      switch ($className::$cols[$shortName]['type']) {
1948
        case 'decimal':
1949
          $value = (float) $value;
1950
          break;
1951
        case 'number':
1952
          $value = (int) $value;
1953
          break;
1954
        case 'bool':
1955
          $value = (bool) $value;
1956
          break;
1957
      }
1958
    }
1959
    if ((isset($this->_params[$name]) && $this->_params[$name] != $value) && !isset($this->_changedParams[$name])) {
1960
      $this->_changedParams[$name] = $this->_params[$name];
1961
    }
1962
1963
    $this->_params[$name] = $value;
1964
  }
1965
1966
  /**
1967
   * Isset handler for model params
1968
   * 
1969
   * @param string $name
1970
   * @return boolean
1971
   */
1972
  public function __isset($name) {
1973
    static::fixPrefix($name);
1974
    return isset($this->_params[$name]);
1975
  }
1976
1977
  /**
1978
   * Convert object to string
1979
   * 
1980
   * @return string
1981
   */
1982
  public function __toString() {
1983
    return $this->name();
1984
  }
1985
1986
}
1987