DataManager   F
last analyzed

Complexity

Total Complexity 287

Size/Duplication

Total Lines 927
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 927
rs 1.263
c 0
b 0
f 0
wmc 287

16 Methods

Rating   Name   Duplication   Size   Complexity  
A drawError() 0 2 1
A rowButtons() 0 15 3
A modelBuilderFromParams() 0 6 1
A __construct() 0 4 1
D getButtons() 0 56 12
A preDraw() 0 16 3
B checkAccess() 0 15 8
D drawCol() 0 121 36
A draw() 0 15 3
A forModel() 0 7 2
D getRows() 0 187 77
D getPages() 0 137 49
A drawCategorys() 0 19 4
C getCols() 0 59 11
F getSummary() 0 142 61
C getActions() 0 32 15

How to fix   Complexity   

Complex Class

Complex classes like DataManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

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

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

1
<?php
2
/**
3
 * Data manager
4
 *
5
 * @author Alexey Krupskiy <[email protected]>
6
 * @link http://inji.ru/
7
 * @copyright 2015 Alexey Krupskiy
8
 * @license https://github.com/injitools/cms-Inji/blob/master/LICENSE
9
 */
10
11
namespace Inji\Ui;
12
13
use Inji\Model\Builder;
14
use Inji\Users\User;
15
16
class DataManager extends \Inji\InjiObject {
17
18
    public $modelName = '';
19
    public $managerOptions = [];
20
    public $name = 'manager';
21
    public $label = 'Менеджер данных';
22
    public $limit = 30;
23
    public $page = 1;
24
    public $table = null;
25
    public $joins = [];
26
    public $predraw = false;
27
    public $cols = [];
28
    public $managerId = '';
29
    public $connection = 'default';
30
    public $dbOptions = [];
31
32
    /**
33
     * Construct new data manager
34
     *
35
     * @param array $options
36
     */
37
    public function __construct($options = []) {
38
        $this->managerOptions = $options;
39
        $safeName = str_replace('\\', '_', $this->modelName);
40
        $this->managerId = 'dataManager_' . $safeName . '_' . $this->name . '_' . \Inji\Tools::randomString();
41
    }
42
43
    /**
44
     * @param $modelName
45
     * @param string $managerName
46
     * @param array $options
47
     * @return static
48
     */
49
    public static function forModel($modelName, $managerName = 'manager', $options = []) {
50
        if ($managerName !== 'manager') {
51
            $className = $modelName . ucfirst($managerName) . 'DataManager';
52
        } else {
53
            $className = $modelName . 'DataManager';
54
        }
55
        return new $className($options);
56
    }
57
58
    /**
59
     * @param array $params
60
     * @return false|Builder
61
     */
62
    public function modelBuilderFromParams($params = []) {
63
        /**
64
         * @var Builder
65
         */
66
        $builder = $this->modelName::connection($this->connection)->setDbOptions($this->dbOptions);
67
        return $builder;
68
    }
69
70
    public function getPages($params = [], $model = null) {
71
        if (!$this->checkAccess()) {
72
            $this->drawError('you not have access to "' . $this->modelName . '" manager with name: "' . $this->name . '"');
73
            return [];
74
        }
75
        $builder = $this->modelBuilderFromParams($params);
76
        $builder->count('id');
77
        return new Pages([
78
            'limit' => $this->limit,
79
            'page' => $this->page,
80
        ], [
81
            'count' => $builder->get(),
82
            'dataManager' => $this
83
        ]);
84
        if (!empty($params['limit'])) {
0 ignored issues
show
Unused Code introduced by
IfNode is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
85
            $this->limit = (int)$params['limit'];
86
        }
87
        if (!empty($params['page'])) {
88
            $this->page = (int)$params['page'];
89
        }
90
        $queryParams = [
91
            'count' => true
92
        ];
93
        $modelName = $this->modelName;
94
        if (!empty($params['categoryPath']) && $modelName::$categoryModel) {
95
            $queryParams['where'][] = ['tree_path', $params['categoryPath'] . '%', 'LIKE'];
96
        }
97
        if (!empty($this->managerOptions['userGroupFilter'][User::$cur->group_id]['getRows'])) {
98
            foreach ($this->managerOptions['userGroupFilter'][User::$cur->group_id]['getRows'] as $colName => $colOptions) {
99
                if (!empty($colOptions['userCol'])) {
100
                    $queryParams['where'][] = [$colName, \Inji\Model::getColValue(User::$cur, $colOptions['userCol'])];
101
                } elseif (isset($colOptions['value'])) {
102
                    if (is_array($colOptions['value'])) {
103
                        foreach ($colOptions['value'] as $key => $value) {
104
                            if ($key === 'userCol') {
105
                                $colOptions['value'][$key] = \Inji\Model::getColValue(User::$cur, $value);
106
                            }
107
                        }
108
                    }
109
                    $queryParams['where'][] = [$colName, $colOptions['value'], is_array($colOptions['value']) ? 'IN' : '='];
110
                }
111
            }
112
        }
113
        $modelName = $this->modelName;
114
        if (!empty($this->managerOptions['filters'])) {
115
            foreach ($this->managerOptions['filters'] as $col) {
116
                $colInfo = $modelName::getColInfo($col);
117
                switch ($colInfo['colParams']['type']) {
118
                    case 'select':
119
                        if (empty($params['filters'][$col]['value'])) {
120
                            continue;
121
                        }
122
                        if (is_array($params['filters'][$col]['value'])) {
123
                            foreach ($params['filters'][$col]['value'] as $key => $value) {
124
                                if ($value === '') {
125
                                    unset($params['filters'][$col]['value'][$key]);
126
                                }
127
                            }
128
                        }
129
                        if (!$params['filters'][$col]['value']) {
130
                            continue;
131
                        }
132
                        $queryParams['where'][] = [$col, $params['filters'][$col]['value'], is_array($params['filters'][$col]['value']) ? 'IN' : '='];
133
                        break;
134
                    case 'bool':
135
                        if (empty($params['filters'][$col]['value'])) {
136
                            continue;
137
                        }
138
                        $queryParams['where'][] = [$col, '1'];
139
                        break;
140
                    case 'dateTime':
141
                    case 'date':
142
                        if (empty($params['filters'][$col]['min']) && empty($params['filters'][$col]['max'])) {
143
                            continue;
144
                        }
145
                        if (!empty($params['filters'][$col]['min'])) {
146
                            $queryParams['where'][] = [$col, $params['filters'][$col]['min'], '>='];
147
                        }
148
                        if (!empty($params['filters'][$col]['max'])) {
149
                            if ($colInfo['colParams']['type'] == 'dateTime' && !strpos($params['filters'][$col]['max'], ' ')) {
150
151
                                $date = $params['filters'][$col]['max'] . ' 23:59:59';
152
                            } else {
153
                                $date = $params['filters'][$col]['max'];
154
                            }
155
                            $queryParams['where'][] = [$col, $date, '<='];
156
                        }
157
                        break;
158
                    case 'number':
159
                        if (empty($params['filters'][$col]['min']) && empty($params['filters'][$col]['max'])) {
160
                            continue;
161
                        }
162
                        if (!empty($params['filters'][$col]['min'])) {
163
                            $queryParams['where'][] = [$col, $params['filters'][$col]['min'], '>='];
164
                        }
165
                        if (!empty($params['filters'][$col]['max'])) {
166
                            $queryParams['where'][] = [$col, $params['filters'][$col]['max'], '<='];
167
                        }
168
                        break;
169
                    case 'email':
170
                    case 'text':
171
                    case 'textarea':
172
                    case 'html':
173
                        if (empty($params['filters'][$col]['value'])) {
174
                            continue;
175
                        }
176
                        switch ($params['filters'][$col]['compareType']) {
177
                            case 'contains':
178
                                $queryParams['where'][] = [$col, '%' . $params['filters'][$col]['value'] . '%', 'LIKE'];
179
                                break;
180
                            case 'equals':
181
                                $queryParams['where'][] = [$col, $params['filters'][$col]['value']];
182
                                break;
183
                            case 'starts_with':
184
                                $queryParams['where'][] = [$col, $params['filters'][$col]['value'] . '%', 'LIKE'];
185
                                break;
186
                            case 'ends_with':
187
                                $queryParams['where'][] = [$col, '%' . $params['filters'][$col]['value'], 'LIKE'];
188
                                break;
189
                        }
190
                        break;
191
                }
192
            }
193
        }
194
        if ($model && !empty($params['relation'])) {
195
            $count = $model->{$params['relation']}($queryParams);
196
        } else {
197
            $count = $modelName::getCount($queryParams);
198
        }
199
        $pages = new Pages([
200
            'limit' => $this->limit,
201
            'page' => $this->page,
202
        ], [
203
            'count' => $count,
204
            'dataManager' => $this
205
        ]);
206
        return $pages;
207
    }
208
209
    public function getRows($params = [], $model = null) {
210
        if (!$this->checkAccess()) {
211
            $this->drawError('you not have access to "' . $this->modelName . '" manager with name: "' . $this->name . '"');
212
            return [];
213
        }
214
        $builder = $this->modelBuilderFromParams($params);
215
        $items = $builder->getList();
216
        $actions = $this->getActions(true);
217
        $rows = [];
218
        foreach ($items as $item) {
219
            $row = [];
220
            if ($actions) {
221
                $row[] = '<input type ="checkbox" name = "pk[]" value =' . $item->pk() . '>';
222
            }
223
            $redirectUrl = !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/admin/' . str_replace('\\', '%5C', get_class($this));
224
            $row[] = "<a href ='/admin/" . $item->genViewLink() . "?redirectUrl={$redirectUrl}'>{$item->pk()}</a>";
225
226
            foreach ($this->cols as $key => $colName) {
227
                $row[] = DataManager::drawCol($item, is_array($colName) ? $key : $colName, $params, $this);
228
            }
229
            $row[] = $this->rowButtons($item, $params);
230
231
            $rows[] = $row;
232
        }
233
        return $rows;
234
        $queryParams = [];
0 ignored issues
show
Unused Code introduced by
$queryParams = array() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
235
        if (empty($params['all'])) {
236
            if (!empty($params['limit'])) {
237
                $this->limit = (int)$params['limit'];
238
            }
239
            if (!empty($params['page'])) {
240
                $this->page = (int)$params['page'];
241
            }
242
            $queryParams['limit'] = $this->limit;
243
            $queryParams['start'] = $this->page * $this->limit - $this->limit;
244
        }
245
        if (!empty($params['categoryPath']) && $modelName::$categoryModel) {
246
            $queryParams['where'][] = ['tree_path', $params['categoryPath'] . '%', 'LIKE'];
247
        }
248
        if (!empty($params['appType'])) {
249
            $queryParams['appType'] = $params['appType'];
250
        }
251
        if ($this->joins) {
252
            $queryParams['joins'] = $this->joins;
253
        }
254
        if (!empty($this->managerOptions['userGroupFilter'][\Users\User::$cur->group_id]['getRows'])) {
255
            foreach ($this->managerOptions['userGroupFilter'][\Users\User::$cur->group_id]['getRows'] as $colName => $colOptions) {
256
                if (!empty($colOptions['userCol'])) {
257
                    $queryParams['where'][] = [$colName, \Inji\Model::getColValue(\Users\User::$cur, $colOptions['userCol'])];
258
                } elseif (isset($colOptions['value'])) {
259
                    if (is_array($colOptions['value'])) {
260
                        foreach ($colOptions['value'] as $key => $value) {
261
                            if ($key === 'userCol') {
262
                                $colOptions['value'][$key] = \Inji\Model::getColValue(\Users\User::$cur, $value);
263
                            }
264
                        }
265
                    }
266
                    $queryParams['where'][] = [$colName, $colOptions['value'], is_array($colOptions['value']) ? 'IN' : '='];
267
                }
268
            }
269
        }
270
        if (!empty($this->managerOptions['filters'])) {
271
            foreach ($this->managerOptions['filters'] as $col) {
272
                $colInfo = $modelName::getColInfo($col);
273
                switch ($colInfo['colParams']['type']) {
274
                    case 'select':
275
                        if (empty($params['filters'][$col]['value'])) {
276
                            continue;
277
                        }
278
                        if (is_array($params['filters'][$col]['value'])) {
279
                            foreach ($params['filters'][$col]['value'] as $key => $value) {
280
                                if ($value === '') {
281
                                    unset($params['filters'][$col]['value'][$key]);
282
                                }
283
                            }
284
                        }
285
                        if (!$params['filters'][$col]['value']) {
286
                            continue;
287
                        }
288
                        $queryParams['where'][] = [$col, $params['filters'][$col]['value'], is_array($params['filters'][$col]['value']) ? 'IN' : '='];
289
                        break;
290
                    case 'bool':
291
                        if (!isset($params['filters'][$col]['value']) || $params['filters'][$col]['value'] === '') {
292
                            continue;
293
                        }
294
                        $queryParams['where'][] = [$col, $params['filters'][$col]['value']];
295
                        break;
296
                    case 'dateTime':
297
                    case 'date':
298
                        if (empty($params['filters'][$col]['min']) && empty($params['filters'][$col]['max'])) {
299
                            continue;
300
                        }
301
                        if (!empty($params['filters'][$col]['min'])) {
302
                            $queryParams['where'][] = [$col, $params['filters'][$col]['min'], '>='];
303
                        }
304
                        if (!empty($params['filters'][$col]['max'])) {
305
                            if ($colInfo['colParams']['type'] == 'dateTime' && !strpos($params['filters'][$col]['max'], ' ')) {
306
307
                                $date = $params['filters'][$col]['max'] . ' 23:59:59';
308
                            } else {
309
                                $date = $params['filters'][$col]['max'];
310
                            }
311
                            $queryParams['where'][] = [$col, $date, '<='];
312
                        }
313
                        break;
314
                    case 'number':
315
                        if (empty($params['filters'][$col]['min']) && empty($params['filters'][$col]['max'])) {
316
                            continue;
317
                        }
318
                        if (!empty($params['filters'][$col]['min'])) {
319
                            $queryParams['where'][] = [$col, $params['filters'][$col]['min'], '>='];
320
                        }
321
                        if (!empty($params['filters'][$col]['max'])) {
322
                            $queryParams['where'][] = [$col, $params['filters'][$col]['max'], '<='];
323
                        }
324
                        break;
325
                    case 'email':
326
                    case 'text':
327
                    case 'textarea':
328
                    case 'html':
329
                        if (empty($params['filters'][$col]['value'])) {
330
                            continue;
331
                        }
332
                        switch ($params['filters'][$col]['compareType']) {
333
                            case 'contains':
334
                                $queryParams['where'][] = [$col, '%' . $params['filters'][$col]['value'] . '%', 'LIKE'];
335
                                break;
336
                            case 'equals':
337
                                $queryParams['where'][] = [$col, $params['filters'][$col]['value']];
338
                                break;
339
                            case 'starts_with':
340
                                $queryParams['where'][] = [$col, $params['filters'][$col]['value'] . '%', 'LIKE'];
341
                                break;
342
                            case 'ends_with':
343
                                $queryParams['where'][] = [$col, '%' . $params['filters'][$col]['value'], 'LIKE'];
344
                                break;
345
                        }
346
                        break;
347
                }
348
            }
349
        }
350
        if (!empty($params['mode']) && $params['mode'] == 'sort') {
351
            $queryParams['order'] = ['weight', 'asc'];
352
        } elseif (!empty($params['sortered']) && !empty($this->managerOptions['sortable'])) {
353
            foreach ($params['sortered'] as $colName => $sortType) {
354
                if ($colName && in_array($colName, $this->managerOptions['sortable'])) {
355
                    $sortType = in_array($sortType, ['desc', 'asc']) ? $sortType : 'desc';
356
                    $queryParams['order'][] = [$colName, $sortType];
357
                }
358
            }
359
        }
360
        if ($model && !empty($params['relation'])) {
361
            $relation = $model::getRelation($params['relation']);
362
            $items = $model->{$params['relation']}($queryParams);
363
        } else {
364
            $relation = false;
365
            $items = $modelName::getList($queryParams);
366
        }
367
        $rows = [];
368
        $actions = $this->getActions(true);
369
        foreach ($items as $item) {
370
            if ($relation && !empty($relation['relModel'])) {
371
                $item = $relation['relModel']::get([[$item->index(), $item->id], [$model->index(), $model->id]]);
372
            }
373
            $row = [];
374
            if (empty($params['download'])) {
375
                if ($actions) {
376
                    $row[] = '<input type ="checkbox" name = "pk[]" value =' . $item->pk() . '>';
377
                }
378
                $redirectUrl = !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/admin/' . str_replace('\\', '%5C', get_class($this));
379
                $row[] = "<a href ='/admin/" . $item->genViewLink() . "?redirectUrl={$redirectUrl}'>{$item->pk()}</a>";
380
            } else {
381
                $row[] = $item->pk();
382
            }
383
            foreach ($this->managerOptions['cols'] as $key => $colName) {
384
                if (!empty($params['download'])) {
385
                    $row[] = \Inji\Model::getColValue($item, is_array($colName) ? $key : $colName, true, false);
386
                } else {
387
                    $row[] = DataManager::drawCol($item, is_array($colName) ? $key : $colName, $params, $this);
388
                }
389
            }
390
            if (empty($params['download'])) {
391
                $row[] = $this->rowButtons($item, $params);
392
            }
393
            $rows[] = $row;
394
        }
395
        return $rows;
396
    }
397
398
    /**
399
     * Get buttons for manager
400
     *
401
     * @param string $params
402
     * @param object $model
403
     */
404
    public function getButtons($params = [], $model = null) {
405
        $modelName = $this->modelName;
406
407
        $formParams = [
408
            'dataManagerParams' => $params,
409
            'formName' => !empty($this->activeForm) ? $this->activeForm : 'manager'
410
        ];
411
        if ($model) {
412
            $formModelName = get_class($model);
413
            $relations = $formModelName::relations();
414
            $type = !empty($relations[$params['relation']]['type']) ? $relations[$params['relation']]['type'] : 'to';
415
            switch ($type) {
416
                case 'relModel':
417
                    $formParams['preset'] = [
418
                        $formModelName::index() => $model->pk()
419
                    ];
420
                    break;
421
                default:
422
                    $formParams['preset'] = [
423
                        $relations[$params['relation']]['col'] => $model->pk()
424
                    ];
425
            }
426
        }
427
428
        $buttons = [];
429
        if (!empty($this->managerOptions['sortMode'])) {
430
            $buttons[] = [
431
                'class' => 'modeBtn',
432
                'data-mode' => 'sort',
433
                'text' => 'Сортировать',
434
            ];
435
        }
436
        if (empty($params['noFilters']) && !empty($this->managerOptions['filters'])) {
437
            $buttons[] = [
438
                'text' => 'Фильтры',
439
                'onclick' => '  var modal = $("#' . $this->managerId . '_filters");
440
                modal.modal("show");',
441
            ];
442
        }
443
        if (!empty($modelName::$forms['simpleItem'])) {
0 ignored issues
show
Bug introduced by
The property forms does not exist on string.
Loading history...
444
            $formParams['formName'] = 'simpleItem';
445
            $buttons[] = [
446
                'text' => '<i class = "glyphicon glyphicon-send"></i> Быстрое создание',
447
                'onclick' => 'inji.Ui.dataManagers.get(this).newItem("' . str_replace('\\', '\\\\', $modelName) . '",' . json_encode($formParams) . ');',
448
            ];
449
        }
450
        $formParams['formName'] = !empty($this->activeForm) ? $this->activeForm : 'manager';
451
        $actions = $this->getActions(false, true);
452
        foreach ($actions as $action) {
453
            $btn = $action['className']::managerButton($this, $formParams, $action);
454
            if ($btn) {
455
                $buttons[] = $btn;
456
            }
457
        }
458
459
        return $buttons;
460
    }
461
462
    public function getActions($groupActions = false, $managerActions = false) {
463
        $actions = [
464
            'Open' => ['className' => 'Open'], 'Create' => ['className' => 'Create'], 'Edit' => ['className' => 'Edit'], 'Delete' => ['className' => 'Delete']
465
        ];
466
        if (isset($this->actions)) {
467
            $actions = array_merge($actions, $this->actions);
468
        }
469
        $return = [];
470
        foreach ($actions as $key => $action) {
471
            if ($action === false) {
472
                continue;
473
            }
474
            if (is_array($action)) {
475
                if (!empty($action['access']['groups']) && !in_array(\Inji\Users\User::$cur->group_id, $action['access']['groups'])) {
476
                    continue;
477
                }
478
                if (empty($action['className'])) {
479
                    $action['className'] = $key;
480
                }
481
                $return[$key] = $action;
482
            } else {
483
                $key = $action;
484
                $return[$key] = [
485
                    'className' => $action
486
                ];
487
            }
488
            $return[$key]['className'] = strpos($return[$key]['className'], '\\') === false && class_exists('Inji\Ui\DataManager\Action\\' . $return[$key]['className']) ? 'Inji\Ui\DataManager\Action\\' . $return[$key]['className'] : $return[$key]['className'];
489
            if (!class_exists($return[$key]['className']) || ($groupActions && !$return[$key]['className']::$groupAction) || ($managerActions && !$return[$key]['className']::$managerAction)) {
490
                unset($return[$key]);
491
            }
492
        }
493
        return $return;
494
    }
495
496
    /**
497
     * Get cols for manager
498
     *
499
     * @return string
500
     */
501
    public function getCols() {
502
        $actions = $this->getActions(true);
503
        ob_start();
504
        ?>
505
        <div class="dropdown">
506
            <a id="dLabel" data-target="#" href="" data-toggle="dropdown" role="button" aria-haspopup="true"
507
               aria-expanded="false">
508
                <i class="glyphicon glyphicon-cog"></i>
509
                <span class="caret"></span>
510
            </a>
511
512
            <ul class="dropdown-menu" aria-labelledby="dLabel">
513
                <li><a href='' onclick='inji.Ui.dataManagers.get(this).rowSelection("selectAll");return false;'>Выделить
514
                        все</a></li>
515
                <li><a href='' onclick='inji.Ui.dataManagers.get(this).rowSelection("unSelectAll");return false;'>Снять
516
                        все</a></li>
517
                <li><a href='' onclick='inji.Ui.dataManagers.get(this).rowSelection("inverse");return false;'>Инвертировать</a>
518
                </li>
519
                <li role="separator" class="divider"></li>
520
                <?php
521
                foreach ($actions as $action => $actionParams) {
522
                    if (class_exists($actionParams['className']) && $actionParams['className']::$groupAction) {
523
                        echo "<li><a role='button' href ='#' onclick='inji.Ui.dataManagers.get(this).groupAction(\"" . str_replace('\\', '\\\\', $action) . "\");return false;'>{$actionParams['className']::$name}</a></li>";
524
                    }
525
                }
526
                ?>
527
            </ul>
528
        </div>
529
        <?php
530
        $dropdown = ob_get_contents();
531
        ob_end_clean();
532
533
        $cols = [];
534
        if ($actions) {
535
            $cols[] = ['label' => $dropdown];
536
        }
537
        $cols['id'] = ['label' => '№', 'sortable' => true];
538
539
        $modelName = $this->modelName;
540
        foreach ($this->cols as $key => $col) {
541
            if (is_array($col)) {
542
                $colName = $key;
543
                $colOptions = $col;
544
            } else {
545
                $colName = $col;
546
                $colOptions = [];
547
            }
548
            $colInfo = [];
549
            if ($modelName) {
550
                $colInfo = $modelName::getColInfo($colName);
551
            }
552
            if (empty($colOptions['label']) && !empty($colInfo['label'])) {
553
                $colOptions['label'] = $colInfo['label'];
554
            } elseif (empty($colOptions['label'])) {
555
                $colOptions['label'] = $colName;
556
            }
557
            $cols[$colName] = $colOptions;
558
        }
559
        return $cols;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $cols returns the type array<mixed,array<string,string|true>> which is incompatible with the documented return type string.
Loading history...
560
    }
561
562
    /**
563
     * Get rows for manager
564
     *
565
     * @param array $params
566
     * @param object $model
567
     * @return array
568
     */
569
570
571
    public function getSummary($params = [], $model = null) {
572
        $modelName = $this->modelName;
573
        if (!class_exists($modelName)) {
574
            return [];
575
        }
576
        if (empty($this->managerOptions['summary'])) {
577
            return [];
578
        }
579
        if (!$this->checkAccess()) {
580
            $this->drawError('you not have access to "' . $this->modelName . '" manager with name: "' . $this->name . '"');
581
            return [];
582
        }
583
        $modelName = $this->modelName;
584
        $queryParams = [];
585
        if (!empty($params['categoryPath']) && $modelName::$categoryModel) {
0 ignored issues
show
Bug introduced by
The property categoryModel does not exist on string.
Loading history...
586
            $queryParams['where'][] = ['tree_path', $params['categoryPath'] . '%', 'LIKE'];
587
        }
588
        if (!empty($params['appType'])) {
589
            $queryParams['appType'] = $params['appType'];
590
        }
591
        if ($this->joins) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->joins of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
592
            $queryParams['joins'] = $this->joins;
593
        }
594
        if (!empty($this->managerOptions['userGroupFilter'][\Users\User::$cur->group_id]['getRows'])) {
595
            foreach ($this->managerOptions['userGroupFilter'][\Users\User::$cur->group_id]['getRows'] as $colName => $colOptions) {
596
                if (!empty($colOptions['userCol'])) {
597
                    $queryParams['where'][] = [$colName, \Inji\Model::getColValue(\Users\User::$cur, $colOptions['userCol'])];
598
                } elseif (isset($colOptions['value'])) {
599
                    if (is_array($colOptions['value'])) {
600
                        foreach ($colOptions['value'] as $key => $value) {
601
                            if ($key === 'userCol') {
602
                                $colOptions['value'][$key] = \Inji\Model::getColValue(\Users\User::$cur, $value);
603
                            }
604
                        }
605
                    }
606
                    $queryParams['where'][] = [$colName, $colOptions['value'], is_array($colOptions['value']) ? 'IN' : '='];
607
                }
608
            }
609
        }
610
        if (!empty($this->managerOptions['filters'])) {
611
            foreach ($this->managerOptions['filters'] as $col) {
612
                $colInfo = $modelName::getColInfo($col);
613
                switch ($colInfo['colParams']['type']) {
614
                    case 'select':
615
                        if (empty($params['filters'][$col]['value'])) {
616
                            continue;
617
                        }
618
                        if (is_array($params['filters'][$col]['value'])) {
619
                            foreach ($params['filters'][$col]['value'] as $key => $value) {
620
                                if ($value === '') {
621
                                    unset($params['filters'][$col]['value'][$key]);
622
                                }
623
                            }
624
                        }
625
                        if (!$params['filters'][$col]['value']) {
626
                            continue;
627
                        }
628
                        $queryParams['where'][] = [$col, $params['filters'][$col]['value'], is_array($params['filters'][$col]['value']) ? 'IN' : '='];
629
                        break;
630
                    case 'bool':
631
                        if (!isset($params['filters'][$col]['value']) || $params['filters'][$col]['value'] === '') {
632
                            continue;
633
                        }
634
                        $queryParams['where'][] = [$col, $params['filters'][$col]['value']];
635
                        break;
636
                    case 'dateTime':
637
                    case 'date':
638
                        if (empty($params['filters'][$col]['min']) && empty($params['filters'][$col]['max'])) {
639
                            continue;
640
                        }
641
                        if (!empty($params['filters'][$col]['min'])) {
642
                            $queryParams['where'][] = [$col, $params['filters'][$col]['min'], '>='];
643
                        }
644
                        if (!empty($params['filters'][$col]['max'])) {
645
                            if ($colInfo['colParams']['type'] == 'dateTime' && !strpos($params['filters'][$col]['max'], ' ')) {
646
647
                                $date = $params['filters'][$col]['max'] . ' 23:59:59';
648
                            } else {
649
                                $date = $params['filters'][$col]['max'];
650
                            }
651
                            $queryParams['where'][] = [$col, $date, '<='];
652
                        }
653
                        break;
654
                    case 'number':
655
                        if (empty($params['filters'][$col]['min']) && empty($params['filters'][$col]['max'])) {
656
                            continue;
657
                        }
658
                        if (!empty($params['filters'][$col]['min'])) {
659
                            $queryParams['where'][] = [$col, $params['filters'][$col]['min'], '>='];
660
                        }
661
                        if (!empty($params['filters'][$col]['max'])) {
662
                            $queryParams['where'][] = [$col, $params['filters'][$col]['max'], '<='];
663
                        }
664
                        break;
665
                    case 'email':
666
                    case 'text':
667
                    case 'textarea':
668
                    case 'html':
669
                        if (empty($params['filters'][$col]['value'])) {
670
                            continue;
671
                        }
672
                        switch ($params['filters'][$col]['compareType']) {
673
                            case 'contains':
674
                                $queryParams['where'][] = [$col, '%' . $params['filters'][$col]['value'] . '%', 'LIKE'];
675
                                break;
676
                            case 'equals':
677
                                $queryParams['where'][] = [$col, $params['filters'][$col]['value']];
678
                                break;
679
                            case 'starts_with':
680
                                $queryParams['where'][] = [$col, $params['filters'][$col]['value'] . '%', 'LIKE'];
681
                                break;
682
                            case 'ends_with':
683
                                $queryParams['where'][] = [$col, '%' . $params['filters'][$col]['value'], 'LIKE'];
684
                                break;
685
                        }
686
                        break;
687
                }
688
            }
689
        }
690
        if (!empty($params['mode']) && $params['mode'] == 'sort') {
691
            $queryParams['order'] = ['weight', 'asc'];
692
        } elseif (!empty($params['sortered']) && !empty($this->managerOptions['sortable'])) {
693
            foreach ($params['sortered'] as $colName => $sortType) {
694
                if ($colName && in_array($colName, $this->managerOptions['sortable'])) {
695
                    $sortType = in_array($sortType, ['desc', 'asc']) ? $sortType : 'desc';
696
                    $queryParams['order'][] = [$colName, $sortType];
697
                }
698
            }
699
        }
700
        $summarys = [];
701
        foreach ($this->managerOptions['summary'] as $summary) {
702
            $queryParams['cols'] = 'COALESCE(SUM(' . $summary['expression'] . '),0) as summary';
703
            $queryParams['array'] = true;
704
            $queryParams['key'] = false;
705
            if ($model && !empty($params['relation'])) {
706
                $items = $model->{$params['relation']}($queryParams);
707
            } else {
708
                $items = $modelName::getList($queryParams);
709
            }
710
            $summarys[] = ['name' => $summary['name'], 'summary' => $items[0]['summary']];
711
        }
712
        return $summarys;
713
    }
714
715
    public static function drawCol($item, $colName, $params = [], $dataManager = null, $originalCol = '', $originalItem = null) {
716
        $modelName = get_class($item);
717
        if (!class_exists($modelName)) {
718
            return false;
719
        }
720
721
        if (!$originalCol) {
722
            $originalCol = $colName;
723
        }
724
        if (!$originalItem) {
725
            $originalItem = $item;
726
        }
727
728
        $relations = $modelName::relations();
729
        if (strpos($colName, ':') !== false && !empty($relations[substr($colName, 0, strpos($colName, ':'))])) {
730
            $rel = substr($colName, 0, strpos($colName, ':'));
731
            $col = substr($colName, strpos($colName, ':') + 1);
732
            if ($item->$rel) {
733
                return DataManager::drawCol($item->$rel, $col, $params, $dataManager, $originalCol, $originalItem);
734
            } else {
735
                return 'Не указано';
736
            }
737
        }
738
        if (!empty($modelName::$cols[$colName]['relation'])) {
0 ignored issues
show
Bug introduced by
The property cols does not exist on string.
Loading history...
739
            $type = !empty($relations[$modelName::$cols[$colName]['relation']]['type']) ? $relations[$modelName::$cols[$colName]['relation']]['type'] : 'to';
740
            switch ($type) {
741
                case 'relModel':
742
                    $managerParams = ['relation' => $modelName::$cols[$colName]['relation']];
743
                    $count = $item->{$modelName::$cols[$colName]['relation']}(array_merge($params, ['count' => 1]));
744
                    $count = $count ? $count : 'Нет';
745
                    return "<a class = 'btn btn-xs btn-primary' onclick = 'inji.Ui.dataManagers.popUp(\"" . str_replace('\\', '\\\\', $modelName) . ":" . $item->pk() . "\"," . json_encode(array_merge($params, $managerParams)) . ")'>{$count}</a>";
746
                case 'many':
747
                    $managerParams = ['relation' => $modelName::$cols[$colName]['relation']];
748
                    if (!empty($modelName::$cols[$colName]['manager'])) {
749
                        $managerParams['managerName'] = $modelName::$cols[$colName]['manager'];
750
                    }
751
                    $count = $item->{$modelName::$cols[$colName]['relation']}(array_merge($params, ['count' => 1]));
752
                    $count = $count ? $count : 'Нет';
753
                    return "<a class = 'btn btn-xs btn-primary' onclick = 'inji.Ui.dataManagers.popUp(\"" . str_replace('\\', '\\\\', $modelName) . ":" . $item->pk() . "\"," . json_encode(array_merge($params, $managerParams)) . ")'>{$count}</a>";
754
                default:
755
                    if ($item->{$modelName::$cols[$colName]['relation']}) {
756
                        if (\Inji\App::$cur->name == 'admin') {
757
                            $href = "<a href ='/admin/" . $item->{$modelName::$cols[$colName]['relation']}->genViewLink() . "'>";
758
                            if (!empty($modelName::$cols[$colName]['showCol'])) {
759
                                $href .= $item->{$modelName::$cols[$colName]['relation']}->{$modelName::$cols[$colName]['showCol']};
760
                            } else {
761
762
                                $href .= $item->{$modelName::$cols[$colName]['relation']}->name();
763
                            }
764
                            $href .= '</a>';
765
                            return $href;
766
                        } else {
767
                            return $item->{$modelName::$cols[$colName]['relation']}->name();
768
                        }
769
                    } else {
770
                        return $item->$colName;
771
                    }
772
            }
773
        } else {
774
            if (!empty($modelName::$cols[$colName]['view']['type'])) {
775
                switch ($modelName::$cols[$colName]['view']['type']) {
776
                    case 'widget':
777
                        ob_start();
778
                        \Inji\App::$cur->view->widget($modelName::$cols[$colName]['view']['widget'], ['item' => $item, 'colName' => $colName, 'colParams' => $modelName::$cols[$colName]]);
0 ignored issues
show
Bug Best Practice introduced by
The property view does not exist on Inji\App. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug introduced by
The method widget() does not exist on Inji\Module. It seems like you code against a sub-type of Inji\Module such as Inji\View or Inji\Db. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

778
                        \Inji\App::$cur->view->/** @scrutinizer ignore-call */ 
779
                                               widget($modelName::$cols[$colName]['view']['widget'], ['item' => $item, 'colName' => $colName, 'colParams' => $modelName::$cols[$colName]]);
Loading history...
Bug introduced by
The method widget() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

778
                        \Inji\App::$cur->view->/** @scrutinizer ignore-call */ 
779
                                               widget($modelName::$cols[$colName]['view']['widget'], ['item' => $item, 'colName' => $colName, 'colParams' => $modelName::$cols[$colName]]);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
779
                        $content = ob_get_contents();
780
                        ob_end_clean();
781
                        return $content;
782
                    case 'moduleMethod':
783
                        return \Inji\App::$cur->{$modelName::$cols[$colName]['view']['module']}->{$modelName::$cols[$colName]['view']['method']}($item, $colName, $modelName::$cols[$colName]);
784
                    case 'many':
785
                        $managerParams = ['relation' => $modelName::$cols[$colName]['relation']];
786
                        if (!empty($modelName::$cols[$colName]['manager'])) {
787
                            $managerParams['managerName'] = $modelName::$cols[$colName]['manager'];
788
                        }
789
                        $count = $item->{$modelName::$cols[$colName]['relation']}(array_merge($params, ['count' => 1]));
790
                        return "<a class = 'btn btn-xs btn-primary' onclick = 'inji.Ui.dataManagers.popUp(\"" . str_replace('\\', '\\\\', $modelName) . ":" . $item->pk() . "\"," . json_encode(array_merge($params, $managerParams)) . ")'>{$count} " . \Inji\Tools::getNumEnding($count, ['Элемент', 'Элемента', 'Элементов']) . "</a>";
791
                    default:
792
                        return $item->$colName;
793
                }
794
            } elseif (!empty($modelName::$cols[$colName]['type'])) {
795
                if (\Inji\App::$cur->name == 'admin' && $originalCol == 'name' || ($dataManager && !empty($dataManager->managerOptions['colToView']) && $dataManager->managerOptions['colToView'] == $originalCol)) {
796
                    $formName = $dataManager && !empty($dataManager->managerOptions['activeForm']) ? $dataManager->managerOptions['activeForm'] : 'manager';
797
                    $redirectUrl = !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/admin/' . str_replace('\\', '/', get_class($originalItem));
798
                    return "<a href ='/admin/{$originalItem->genViewLink()}?formName={$formName}&redirectUrl={$redirectUrl}'>{$item->$colName}</a>";
799
                } elseif (\Inji\App::$cur->name == 'admin' && $colName == 'name') {
800
                    $redirectUrl = !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/admin/' . str_replace('\\', '/', get_class($originalItem));
801
                    return "<a href ='/admin/{$item->genViewLink()}?redirectUrl={$redirectUrl}'>{$item->$colName}</a>";
802
                } elseif ($modelName::$cols[$colName]['type'] == 'html' || $modelName::$cols[$colName]['type'] == 'textarea') {
803
                    $uid = 'text_' . \Inji\Tools::randomString();
804
                    $script = "<script>inji.onLoad(function(){
805
            var el{$uid}=$('#{$uid}');
806
            var height{$uid} = el{$uid}.height();
807
            el{$uid}.css('maxHeight','none');
808
            function el{$uid}Toggle(){
809
              console.log($('#{$uid}').css('height'));
810
                
811
              if( $('#{$uid}').css('height')=='44px'){
812
                $('#{$uid}').css('height','auto');
813
                  var height = $('#{$uid}').height();
814
                  $('#{$uid}').css('height','44px');
815
                  $('#{$uid}').animate({height:height});
816
                  $('#{$uid}').next().text('Свернуть' )
817
                }
818
                else {
819
                  $('#{$uid}').next().text('Развернуть')
820
                  $('#{$uid}').animate({height:'44px'});
821
                }
822
            }
823
            window['el{$uid}Toggle']= el{$uid}Toggle;
824
            if(el{$uid}.height()>height{$uid}){
825
              el{$uid}.css('height','44px');
826
                
827
              el{$uid}.after('<a href=\"#\" onclick=\"el{$uid}Toggle();return false;\">Развернуть</a>');
828
            }
829
            })</script>";
830
                    return "<div id = '{$uid}' style='max-height:44px;overflow:hidden;'>{$item->$colName}</div>" . $script;
831
                } else {
832
                    return \Inji\Model::resloveTypeValue($item, $colName);
833
                }
834
            } else {
835
                return $item->$colName;
836
            }
837
        }
838
    }
839
840
    public function rowButtons($item, $params) {
841
        $modelName = $this->modelName;
842
        if (!class_exists($modelName)) {
843
            return false;
844
        }
845
        ob_start();
846
        $widgetName = !empty($this->managerOptions['rowButtonsWidget']) ? $this->managerOptions['rowButtonsWidget'] : 'Ui\DataManager/rowButtons';
847
        \Inji\App::$cur->view->widget($widgetName, [
0 ignored issues
show
Bug Best Practice introduced by
The property view does not exist on Inji\App. Since you implemented __get, consider adding a @property annotation.
Loading history...
848
            'dataManager' => $this,
849
            'item' => $item,
850
            'params' => $params
851
        ]);
852
        $buttons = ob_get_contents();
853
        ob_end_clean();
854
        return $buttons;
855
    }
856
857
858
    public function preDraw($params = [], $model = null) {
859
        $this->predraw = true;
860
861
        $cols = $this->getCols();
862
863
        $this->table = new Table();
864
        $tableCols = [];
865
        foreach ($cols as $colName => $colOptions) {
0 ignored issues
show
Bug introduced by
The expression $cols of type string is not traversable.
Loading history...
866
            $tableCols[] = [
867
                'attributes' => ['class' => $this->managerId . '_colname_' . $colName, 'data-colname' => $colName],
868
                'text' => !empty($colOptions['label']) ? $colOptions['label'] : $colName
869
            ];
870
        }
871
        $tableCols[] = '';
872
        $this->table->class .= ' datamanagertable';
873
        $this->table->setCols($tableCols);
874
    }
875
876
    public function draw($params = [], $model = null) {
877
        if (!$this->predraw) {
878
            $this->preDraw($params, $model);
879
        }
880
        if (!$this->checkAccess()) {
881
            $this->drawError('you not have access to "' . $this->modelName . '" manager with name: "' . $this->name . '"');
882
            return false;
883
        }
884
        \Inji\App::$cur->view->widget('Ui\DataManager/DataManager', [
0 ignored issues
show
Bug Best Practice introduced by
The property view does not exist on Inji\App. Since you implemented __get, consider adding a @property annotation.
Loading history...
885
            'dataManager' => $this,
886
            'model' => $model,
887
            'table' => $this->table,
888
            'params' => $params
889
        ]);
890
        return true;
891
    }
892
893
    public function drawCategorys() {
894
        if (!class_exists($this->modelName)) {
895
            return false;
896
        }
897
        if (!$this->checkAccess()) {
898
            $this->drawError('you not have access to "' . $this->modelName . '" manager with name: "' . $this->name . '"');
899
            return [];
900
        }
901
        $tree = new Tree();
902
        $tree->ul($this->managerOptions['categorys']['model'], 0, function ($category) {
0 ignored issues
show
Bug introduced by
function(...) { /* ... */ } of type callable is incompatible with the type null|Inji\Ui\closure expected by parameter $hrefFunc of Inji\Ui\Tree::ul(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

902
        $tree->ul($this->managerOptions['categorys']['model'], 0, /** @scrutinizer ignore-type */ function ($category) {
Loading history...
903
            $path = $category->tree_path . ($category->pk() ? $category->pk() . "/" : '');
904
            $cleanClassName = str_replace('\\', '\\\\', get_class($category));
905
            return "<a href='#' onclick='inji.Ui.dataManagers.get(this).switchCategory(this);return false;' data-index='{$category->index()}' data-path ='{$path}' data-id='{$category->pk()}' data-model='{$this->managerOptions['categorys']['model']}'> {$category->name}</a> 
906
                
907
                    <a href = '#' class ='glyphicon glyphicon-edit'   onclick = 'inji.Ui.forms.popUp(\"{$cleanClassName}:{$category->pk()}\")'></a>&nbsp;
908
                    <a href = '#' class ='glyphicon glyphicon-remove' onclick = 'inji.Ui.dataManagers.get(this).delCategory({$category->pk()});return false;'></a>";
909
        });
910
        ?>
911
        <?php
912
    }
913
914
    /**
915
     * Draw error message
916
     *
917
     * @param string $errorText
918
     */
919
    public function drawError($errorText) {
920
        echo $errorText;
921
    }
922
923
    /**
924
     * Check access cur user to manager with name in param
925
     *
926
     * @return boolean
927
     */
928
    public function checkAccess() {
929
        if (\Inji\App::$cur->Access && !\Inji\App::$cur->Access->checkAccess($this)) {
0 ignored issues
show
Bug introduced by
The method checkAccess() does not exist on Inji\Module. It seems like you code against a sub-type of Inji\Module such as Inji\Access or Inji\Db. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

929
        if (\Inji\App::$cur->Access && !\Inji\App::$cur->Access->/** @scrutinizer ignore-call */ checkAccess($this)) {
Loading history...
Bug Best Practice introduced by
The property Access does not exist on Inji\App. Since you implemented __get, consider adding a @property annotation.
Loading history...
930
            return false;
931
        }
932
933
        if (!empty($this->managerOptions['options']['access']['apps']) && !in_array(\Inji\App::$cur->name, $this->managerOptions['options']['access']['apps'])) {
934
            return false;
935
        }
936
        if (!empty($this->managerOptions['options']['access']['groups'])) {
937
            return in_array(\Inji\Users\User::$cur->group_id, $this->managerOptions['options']['access']['groups']);
938
        }
939
        if ($this->name == 'manager' && !\Inji\Users\User::$cur->isAdmin()) {
940
            return false;
941
        }
942
        return true;
943
    }
944
}