Completed
Push — master ( 0afdc4...0e57e6 )
by Alexey
04:27
created

Model::afterSave()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

Loading history...
1742
      return new Value($this, $fixedName);
1743
    } elseif (isset($this->_params[$name])) {
1744
      return new Value($this, $name);
1745
    }
1746
    return call_user_func_array([$this, 'loadRelation'], array_merge([$name], $params));
1747
  }
1748
1749
  /**
1750
   * Param and relation getter
1751
   * 
1752
   * @param string $name
1753
   * @return mixed
1754
   */
1755
  public function __get($name) {
1756
    $fixedName = $name;
1757
    static::fixPrefix($fixedName);
1758
    if (isset($this->_params[$fixedName])) {
1759
      return $this->_params[$fixedName];
1760
    }
1761
    if (isset($this->loadedRelations[$name][json_encode([])])) {
1762
      return $this->loadedRelations[$name][json_encode([])];
1763
    }
1764
    return $this->loadRelation($name);
1765
  }
1766
1767
  /**
1768
   * Return model value in object
1769
   * 
1770
   * @param string $name
1771
   * @return \Value|null
1772
   */
1773
  public function value($name) {
1774
    $fixedName = $name;
1775
    static::fixPrefix($fixedName);
1776 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...
1777
      return new Value($this, $fixedName);
1778
    } elseif ($this->_params[$name]) {
1779
      return new Value($this, $name);
1780
    }
1781
    return null;
1782
  }
1783
1784
  /**
1785
   * Return manager filters
1786
   * 
1787
   * @return array
1788
   */
1789
  public static function managerFilters() {
1790
    return [];
1791
  }
1792
1793
  /**
1794
   * Return validators for cols
1795
   * 
1796
   * @return array
1797
   */
1798
  public static function validators() {
1799
    return [];
1800
  }
1801
1802
  /**
1803
   * Return validator by name
1804
   * 
1805
   * @param string $name
1806
   * @return array
1807
   */
1808
  public static function validator($name) {
1809
    $validators = static::validators();
1810
    if (!empty($validators[$name])) {
1811
      return $validators[$name];
1812
    }
1813
    return [];
1814
  }
1815
1816
  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...
1817
    $className = get_class($this);
1818
    $link = substr($className, 0, strpos($className, '\\'));
1819
    $link .= '/view/';
1820
    $link .= str_replace('\\', '%5C', substr($className, strpos($className, '\\') + 1));
1821
    $link .= "/{$this->id}";
1822
    return $link;
1823
  }
1824
1825
  /**
1826
   * Set handler for model params
1827
   * 
1828
   * @param string $name
1829
   * @param mixed $value
1830
   */
1831
  public function __set($name, $value) {
1832
    static::fixPrefix($name);
1833
    $className = get_called_class();
1834
    $shortName = preg_replace('!' . $this->colPrefix() . '!', '', $name);
1835
    if (!empty($className::$cols[$shortName])) {
1836
      switch ($className::$cols[$shortName]['type']) {
1837
        case 'decimal':
1838
          $value = (float) $value;
1839
          break;
1840
        case 'number':
1841
          $value = (int) $value;
1842
          break;
1843
        case 'bool':
1844
          $value = (bool) $value;
1845
          break;
1846
      }
1847
    }
1848
    if ((isset($this->_params[$name]) && $this->_params[$name] != $value) && !isset($this->_changedParams[$name])) {
1849
      $this->_changedParams[$name] = $this->_params[$name];
1850
    }
1851
1852
    $this->_params[$name] = $value;
1853
  }
1854
1855
  /**
1856
   * Isset handler for model params
1857
   * 
1858
   * @param string $name
1859
   * @return boolean
1860
   */
1861
  public function __isset($name) {
1862
    static::fixPrefix($name);
1863
    return isset($this->_params[$name]);
1864
  }
1865
1866
  /**
1867
   * Convert object to string
1868
   * 
1869
   * @return string
1870
   */
1871
  public function __toString() {
1872
    return $this->name();
1873
  }
1874
1875
}
1876