Passed
Push — v5 ( e348bf...8a8f01 )
by Alexey
06:35
created

DataManager   F

Complexity

Total Complexity 288

Size/Duplication

Total Lines 900
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 900
rs 1.263
c 0
b 0
f 0
wmc 288

14 Methods

Rating   Name   Duplication   Size   Complexity  
F getSummary() 0 142 61
A preDraw() 0 16 3
D getButtons() 0 56 12
A drawError() 0 2 1
A drawCategorys() 0 19 4
F getRows() 0 172 73
C getCols() 0 59 11
D getPages() 0 132 50
A draw() 0 15 3
D drawCol() 0 121 36
B checkAccess() 0 15 8
C getActions() 0 32 15
C __construct() 0 27 8
A rowButtons() 0 15 3

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 Ui;
12
13
class DataManager extends \InjiObject {
0 ignored issues
show
Bug introduced by
The type InjiObject was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
15
    public $modelName = '';
16
    public $managerOptions = [];
17
    public $managerName = 'customManager';
18
    public $name = 'Менеджер данных';
19
    public $limit = 30;
20
    public $page = 1;
21
    public $table = null;
22
    public $joins = [];
23
    public $predraw = false;
24
    public $cols = [];
25
    public $managerId = '';
26
27
    /**
28
     * Construct new data manager
29
     *
30
     * @param string|array $modelNameOrOptions
31
     * @param string $managerName
32
     * @throws Exception
33
     */
34
    public function __construct($modelNameOrOptions, $managerName = 'manager') {
35
        $this->managerName = $managerName;
36
37
        if (!is_array($modelNameOrOptions)) {
38
            if (!class_exists($modelNameOrOptions)) {
39
                throw new \Exception("model {$modelNameOrOptions} not exists");
40
            }
41
            $this->modelName = $modelNameOrOptions;
42
            $this->managerOptions = !empty($modelNameOrOptions::$dataManagers[$managerName]) ? $modelNameOrOptions::$dataManagers[$managerName] : [];
0 ignored issues
show
Bug introduced by
The property dataManagers does not exist on string.
Loading history...
43
            if (isset($modelNameOrOptions::$objectName)) {
0 ignored issues
show
Bug introduced by
The property objectName does not exist on string.
Loading history...
44
                $this->name = $modelNameOrOptions::$objectName;
45
            } else {
46
                $this->name = $modelNameOrOptions;
47
            }
48
        } else {
49
            $this->managerOptions = $modelNameOrOptions;
50
        }
51
52
        if (!$this->managerOptions || !is_array($this->managerOptions)) {
53
            throw new \Exception('empty DataManager');
54
        }
55
56
        if (!empty($this->managerOptions['name'])) {
57
            $this->name = $this->managerOptions['name'];
58
        }
59
60
        $this->managerId = str_replace('\\', '_', 'dataManager_' . $this->modelName . '_' . $this->managerName . '_' . \Tools::randomString());
0 ignored issues
show
Bug introduced by
The type Tools was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
61
    }
62
63
    /**
64
     * Get buttons for manager
65
     *
66
     * @param string $params
67
     * @param object $model
68
     */
69
    public function getButtons($params = [], $model = null) {
70
        $modelName = $this->modelName;
71
72
        $formParams = [
73
            'dataManagerParams' => $params,
74
            'formName' => !empty($this->managerOptions['editForm']) ? $this->managerOptions['editForm'] : 'manager'
75
        ];
76
        if ($model) {
77
            $formModelName = get_class($model);
78
            $relations = $formModelName::relations();
79
            $type = !empty($relations[$params['relation']]['type']) ? $relations[$params['relation']]['type'] : 'to';
80
            switch ($type) {
81
                case 'relModel':
82
                    $formParams['preset'] = [
83
                        $formModelName::index() => $model->pk()
84
                    ];
85
                    break;
86
                default:
87
                    $formParams['preset'] = [
88
                        $relations[$params['relation']]['col'] => $model->pk()
89
                    ];
90
            }
91
        }
92
93
        $buttons = [];
94
        if (!empty($this->managerOptions['sortMode'])) {
95
            $buttons[] = [
96
                'class' => 'modeBtn',
97
                'data-mode' => 'sort',
98
                'text' => 'Сортировать',
99
            ];
100
        }
101
        if (empty($params['noFilters']) && !empty($this->managerOptions['filters'])) {
102
            $buttons[] = [
103
                'text' => 'Фильтры',
104
                'onclick' => '  var modal = $("#' . $this->managerId . '_filters");
105
                modal.modal("show");',
106
            ];
107
        }
108
        if (!empty($modelName::$forms['simpleItem'])) {
0 ignored issues
show
Bug introduced by
The property forms does not exist on string.
Loading history...
109
            $formParams['formName'] = 'simpleItem';
110
            $buttons[] = [
111
                'text' => '<i class = "glyphicon glyphicon-send"></i> Быстрое создание',
112
                'onclick' => 'inji.Ui.dataManagers.get(this).newItem("' . str_replace('\\', '\\\\', $modelName) . '",' . json_encode($formParams) . ');',
113
            ];
114
        }
115
        $formParams['formName'] = !empty($this->managerOptions['editForm']) ? $this->managerOptions['editForm'] : 'manager';
116
        $actions = $this->getActions(false, true);
117
        foreach ($actions as $action) {
118
            $btn = $action['className']::managerButton($this, $formParams, $action);
119
            if ($btn) {
120
                $buttons[] = $btn;
121
            }
122
        }
123
124
        return $buttons;
125
    }
126
127
    public function getActions($groupActions = false, $managerActions = false) {
128
        $actions = [
129
            'Open' => ['className' => 'Open'], 'Create' => ['className' => 'Create'], 'Edit' => ['className' => 'Edit'], 'Delete' => ['className' => 'Delete']
130
        ];
131
        if (isset($this->managerOptions['actions'])) {
132
            $actions = array_merge($actions, $this->managerOptions['actions']);
133
        }
134
        $return = [];
135
        foreach ($actions as $key => $action) {
136
            if ($action === false) {
137
                continue;
138
            }
139
            if (is_array($action)) {
140
                if (!empty($action['access']['groups']) && !in_array(\Users\User::$cur->group_id, $action['access']['groups'])) {
141
                    continue;
142
                }
143
                if (empty($action['className'])) {
144
                    $action['className'] = $key;
145
                }
146
                $return[$key] = $action;
147
            } else {
148
                $key = $action;
149
                $return[$key] = [
150
                    'className' => $action
151
                ];
152
            }
153
            $return[$key]['className'] = strpos($return[$key]['className'], '\\') === false && class_exists('Ui\DataManager\Action\\' . $return[$key]['className']) ? 'Ui\DataManager\Action\\' . $return[$key]['className'] : $return[$key]['className'];
154
            if (!class_exists($return[$key]['className']) || ($groupActions && !$return[$key]['className']::$groupAction) || ($managerActions && !$return[$key]['className']::$managerAction)) {
155
                unset($return[$key]);
156
            }
157
        }
158
        return $return;
159
    }
160
161
    /**
162
     * Get cols for manager
163
     *
164
     * @return string
165
     */
166
    public function getCols() {
167
        $actions = $this->getActions(true);
168
        ob_start();
169
        ?>
170
        <div class="dropdown">
171
            <a id="dLabel" data-target="#" href="" data-toggle="dropdown" role="button" aria-haspopup="true"
172
               aria-expanded="false">
173
                <i class="glyphicon glyphicon-cog"></i>
174
                <span class="caret"></span>
175
            </a>
176
177
            <ul class="dropdown-menu" aria-labelledby="dLabel">
178
                <li><a href='' onclick='inji.Ui.dataManagers.get(this).rowSelection("selectAll");return false;'>Выделить
179
                        все</a></li>
180
                <li><a href='' onclick='inji.Ui.dataManagers.get(this).rowSelection("unSelectAll");return false;'>Снять
181
                        все</a></li>
182
                <li><a href='' onclick='inji.Ui.dataManagers.get(this).rowSelection("inverse");return false;'>Инвертировать</a>
183
                </li>
184
                <li role="separator" class="divider"></li>
185
                <?php
186
                foreach ($actions as $action => $actionParams) {
187
                    if (class_exists($actionParams['className']) && $actionParams['className']::$groupAction) {
188
                        echo "<li><a role='button' href ='#' onclick='inji.Ui.dataManagers.get(this).groupAction(\"" . str_replace('\\', '\\\\', $action) . "\");return false;'>{$actionParams['className']::$name}</a></li>";
189
                    }
190
                }
191
                ?>
192
            </ul>
193
        </div>
194
        <?php
195
        $dropdown = ob_get_contents();
196
        ob_end_clean();
197
198
        $cols = [];
199
        if ($actions) {
200
            $cols[] = ['label' => $dropdown];
201
        }
202
        $cols['id'] = ['label' => '№', 'sortable' => true];
203
204
        $modelName = $this->modelName;
205
        foreach ($this->managerOptions['cols'] as $key => $col) {
206
            if (is_array($col)) {
207
                $colName = $key;
208
                $colOptions = $col;
209
            } else {
210
                $colName = $col;
211
                $colOptions = [];
212
            }
213
            $colInfo = [];
214
            if ($modelName) {
215
                $colInfo = $modelName::getColInfo($colName);
216
            }
217
            if (empty($colOptions['label']) && !empty($colInfo['label'])) {
218
                $colOptions['label'] = $colInfo['label'];
219
            } elseif (empty($colOptions['label'])) {
220
                $colOptions['label'] = $colName;
221
            }
222
            $cols[$colName] = $colOptions;
223
        }
224
        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...
225
    }
226
227
    /**
228
     * Get rows for manager
229
     *
230
     * @param array $params
231
     * @param object $model
232
     * @return array
233
     */
234
    public function getRows($params = [], $model = null) {
235
        $modelName = $this->modelName;
236
        if (!class_exists($modelName)) {
237
            return [];
238
        }
239
        if (!$this->checkAccess()) {
240
            $this->drawError('you not have access to "' . $this->modelName . '" manager with name: "' . $this->managerName . '"');
241
            return [];
242
        }
243
        $modelName = $this->modelName;
244
        $queryParams = [];
245
        if (empty($params['all'])) {
246
            if (!empty($params['limit'])) {
247
                $this->limit = (int) $params['limit'];
248
            }
249
            if (!empty($params['page'])) {
250
                $this->page = (int) $params['page'];
251
            }
252
            $queryParams['limit'] = $this->limit;
253
            $queryParams['start'] = $this->page * $this->limit - $this->limit;
254
        }
255
        if (!empty($params['categoryPath']) && $modelName::$categoryModel) {
0 ignored issues
show
Bug introduced by
The property categoryModel does not exist on string.
Loading history...
256
            $queryParams['where'][] = ['tree_path', $params['categoryPath'] . '%', 'LIKE'];
257
        }
258
        if (!empty($params['appType'])) {
259
            $queryParams['appType'] = $params['appType'];
260
        }
261
        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...
262
            $queryParams['joins'] = $this->joins;
263
        }
264
        if (!empty($this->managerOptions['userGroupFilter'][\Users\User::$cur->group_id]['getRows'])) {
265
            foreach ($this->managerOptions['userGroupFilter'][\Users\User::$cur->group_id]['getRows'] as $colName => $colOptions) {
266
                if (!empty($colOptions['userCol'])) {
267
                    $queryParams['where'][] = [$colName, \Model::getColValue(\Users\User::$cur, $colOptions['userCol'])];
268
                } elseif (isset($colOptions['value'])) {
269
                    if (is_array($colOptions['value'])) {
270
                        foreach ($colOptions['value'] as $key => $value) {
271
                            if ($key === 'userCol') {
272
                                $colOptions['value'][$key] = \Model::getColValue(\Users\User::$cur, $value);
273
                            }
274
                        }
275
                    }
276
                    $queryParams['where'][] = [$colName, $colOptions['value'], is_array($colOptions['value']) ? 'IN' : '='];
277
                }
278
            }
279
        }
280
        if (!empty($this->managerOptions['filters'])) {
281
            foreach ($this->managerOptions['filters'] as $col) {
282
                $colInfo = $modelName::getColInfo($col);
283
                switch ($colInfo['colParams']['type']) {
284
                    case 'select':
285
                        if (empty($params['filters'][$col]['value'])) {
286
                            continue;
287
                        }
288
                        if (is_array($params['filters'][$col]['value'])) {
289
                            foreach ($params['filters'][$col]['value'] as $key => $value) {
290
                                if ($value === '') {
291
                                    unset($params['filters'][$col]['value'][$key]);
292
                                }
293
                            }
294
                        }
295
                        if (!$params['filters'][$col]['value']) {
296
                            continue;
297
                        }
298
                        $queryParams['where'][] = [$col, $params['filters'][$col]['value'], is_array($params['filters'][$col]['value']) ? 'IN' : '='];
299
                        break;
300
                    case 'bool':
301
                        if (!isset($params['filters'][$col]['value']) || $params['filters'][$col]['value'] === '') {
302
                            continue;
303
                        }
304
                        $queryParams['where'][] = [$col, $params['filters'][$col]['value']];
305
                        break;
306
                    case 'dateTime':
307
                    case 'date':
308
                        if (empty($params['filters'][$col]['min']) && empty($params['filters'][$col]['max'])) {
309
                            continue;
310
                        }
311
                        if (!empty($params['filters'][$col]['min'])) {
312
                            $queryParams['where'][] = [$col, $params['filters'][$col]['min'], '>='];
313
                        }
314
                        if (!empty($params['filters'][$col]['max'])) {
315
                            if ($colInfo['colParams']['type'] == 'dateTime' && !strpos($params['filters'][$col]['max'], ' ')) {
316
317
                                $date = $params['filters'][$col]['max'] . ' 23:59:59';
318
                            } else {
319
                                $date = $params['filters'][$col]['max'];
320
                            }
321
                            $queryParams['where'][] = [$col, $date, '<='];
322
                        }
323
                        break;
324
                    case 'number':
325
                        if (empty($params['filters'][$col]['min']) && empty($params['filters'][$col]['max'])) {
326
                            continue;
327
                        }
328
                        if (!empty($params['filters'][$col]['min'])) {
329
                            $queryParams['where'][] = [$col, $params['filters'][$col]['min'], '>='];
330
                        }
331
                        if (!empty($params['filters'][$col]['max'])) {
332
                            $queryParams['where'][] = [$col, $params['filters'][$col]['max'], '<='];
333
                        }
334
                        break;
335
                    case 'email':
336
                    case 'text':
337
                    case 'textarea':
338
                    case 'html':
339
                        if (empty($params['filters'][$col]['value'])) {
340
                            continue;
341
                        }
342
                        switch ($params['filters'][$col]['compareType']) {
343
                            case 'contains':
344
                                $queryParams['where'][] = [$col, '%' . $params['filters'][$col]['value'] . '%', 'LIKE'];
345
                                break;
346
                            case 'equals':
347
                                $queryParams['where'][] = [$col, $params['filters'][$col]['value']];
348
                                break;
349
                            case 'starts_with':
350
                                $queryParams['where'][] = [$col, $params['filters'][$col]['value'] . '%', 'LIKE'];
351
                                break;
352
                            case 'ends_with':
353
                                $queryParams['where'][] = [$col, '%' . $params['filters'][$col]['value'], 'LIKE'];
354
                                break;
355
                        }
356
                        break;
357
                }
358
            }
359
        }
360
        if (!empty($params['mode']) && $params['mode'] == 'sort') {
361
            $queryParams['order'] = ['weight', 'asc'];
362
        } elseif (!empty($params['sortered']) && !empty($this->managerOptions['sortable'])) {
363
            foreach ($params['sortered'] as $colName => $sortType) {
364
                if ($colName && in_array($colName, $this->managerOptions['sortable'])) {
365
                    $sortType = in_array($sortType, ['desc', 'asc']) ? $sortType : 'desc';
366
                    $queryParams['order'][] = [$colName, $sortType];
367
                }
368
            }
369
        }
370
        if ($model && !empty($params['relation'])) {
371
            $relation = $model::getRelation($params['relation']);
372
            $items = $model->{$params['relation']}($queryParams);
373
        } else {
374
            $relation = false;
375
            $items = $modelName::getList($queryParams);
376
        }
377
        $rows = [];
378
        $actions = $this->getActions(true);
379
        foreach ($items as $item) {
380
            if ($relation && !empty($relation['relModel'])) {
381
                $item = $relation['relModel']::get([[$item->index(), $item->id], [$model->index(), $model->id]]);
0 ignored issues
show
Bug introduced by
The method index() 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

381
                $item = $relation['relModel']::get([[$item->index(), $item->id], [$model->/** @scrutinizer ignore-call */ index(), $model->id]]);

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...
382
            }
383
            $row = [];
384
            if (empty($params['download'])) {
385
                if ($actions) {
386
                    $row[] = '<input type ="checkbox" name = "pk[]" value =' . $item->pk() . '>';
387
                }
388
                $redirectUrl = !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/admin/' . str_replace('\\', '%5C', get_class($this));
389
                $row[] = "<a href ='/admin/" . $item->genViewLink() . "?redirectUrl={$redirectUrl}'>{$item->pk()}</a>";
390
            } else {
391
                $row[] = $item->pk();
392
            }
393
            foreach ($this->managerOptions['cols'] as $key => $colName) {
394
                if (!empty($params['download'])) {
395
                    $row[] = \Model::getColValue($item, is_array($colName) ? $key : $colName, true, false);
396
                } else {
397
                    $row[] = DataManager::drawCol($item, is_array($colName) ? $key : $colName, $params, $this);
398
                }
399
            }
400
            if (empty($params['download'])) {
401
                $row[] = $this->rowButtons($item, $params);
402
            }
403
            $rows[] = $row;
404
        }
405
        return $rows;
406
    }
407
408
    public function getSummary($params = [], $model = null) {
409
        $modelName = $this->modelName;
410
        if (!class_exists($modelName)) {
411
            return [];
412
        }
413
        if (empty($this->managerOptions['summary'])) {
414
            return [];
415
        }
416
        if (!$this->checkAccess()) {
417
            $this->drawError('you not have access to "' . $this->modelName . '" manager with name: "' . $this->managerName . '"');
418
            return [];
419
        }
420
        $modelName = $this->modelName;
421
        $queryParams = [];
422
        if (!empty($params['categoryPath']) && $modelName::$categoryModel) {
0 ignored issues
show
Bug introduced by
The property categoryModel does not exist on string.
Loading history...
423
            $queryParams['where'][] = ['tree_path', $params['categoryPath'] . '%', 'LIKE'];
424
        }
425
        if (!empty($params['appType'])) {
426
            $queryParams['appType'] = $params['appType'];
427
        }
428
        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...
429
            $queryParams['joins'] = $this->joins;
430
        }
431
        if (!empty($this->managerOptions['userGroupFilter'][\Users\User::$cur->group_id]['getRows'])) {
432
            foreach ($this->managerOptions['userGroupFilter'][\Users\User::$cur->group_id]['getRows'] as $colName => $colOptions) {
433
                if (!empty($colOptions['userCol'])) {
434
                    $queryParams['where'][] = [$colName, \Model::getColValue(\Users\User::$cur, $colOptions['userCol'])];
435
                } elseif (isset($colOptions['value'])) {
436
                    if (is_array($colOptions['value'])) {
437
                        foreach ($colOptions['value'] as $key => $value) {
438
                            if ($key === 'userCol') {
439
                                $colOptions['value'][$key] = \Model::getColValue(\Users\User::$cur, $value);
440
                            }
441
                        }
442
                    }
443
                    $queryParams['where'][] = [$colName, $colOptions['value'], is_array($colOptions['value']) ? 'IN' : '='];
444
                }
445
            }
446
        }
447
        if (!empty($this->managerOptions['filters'])) {
448
            foreach ($this->managerOptions['filters'] as $col) {
449
                $colInfo = $modelName::getColInfo($col);
450
                switch ($colInfo['colParams']['type']) {
451
                    case 'select':
452
                        if (empty($params['filters'][$col]['value'])) {
453
                            continue;
454
                        }
455
                        if (is_array($params['filters'][$col]['value'])) {
456
                            foreach ($params['filters'][$col]['value'] as $key => $value) {
457
                                if ($value === '') {
458
                                    unset($params['filters'][$col]['value'][$key]);
459
                                }
460
                            }
461
                        }
462
                        if (!$params['filters'][$col]['value']) {
463
                            continue;
464
                        }
465
                        $queryParams['where'][] = [$col, $params['filters'][$col]['value'], is_array($params['filters'][$col]['value']) ? 'IN' : '='];
466
                        break;
467
                    case 'bool':
468
                        if (!isset($params['filters'][$col]['value']) || $params['filters'][$col]['value'] === '') {
469
                            continue;
470
                        }
471
                        $queryParams['where'][] = [$col, $params['filters'][$col]['value']];
472
                        break;
473
                    case 'dateTime':
474
                    case 'date':
475
                        if (empty($params['filters'][$col]['min']) && empty($params['filters'][$col]['max'])) {
476
                            continue;
477
                        }
478
                        if (!empty($params['filters'][$col]['min'])) {
479
                            $queryParams['where'][] = [$col, $params['filters'][$col]['min'], '>='];
480
                        }
481
                        if (!empty($params['filters'][$col]['max'])) {
482
                            if ($colInfo['colParams']['type'] == 'dateTime' && !strpos($params['filters'][$col]['max'], ' ')) {
483
484
                                $date = $params['filters'][$col]['max'] . ' 23:59:59';
485
                            } else {
486
                                $date = $params['filters'][$col]['max'];
487
                            }
488
                            $queryParams['where'][] = [$col, $date, '<='];
489
                        }
490
                        break;
491
                    case 'number':
492
                        if (empty($params['filters'][$col]['min']) && empty($params['filters'][$col]['max'])) {
493
                            continue;
494
                        }
495
                        if (!empty($params['filters'][$col]['min'])) {
496
                            $queryParams['where'][] = [$col, $params['filters'][$col]['min'], '>='];
497
                        }
498
                        if (!empty($params['filters'][$col]['max'])) {
499
                            $queryParams['where'][] = [$col, $params['filters'][$col]['max'], '<='];
500
                        }
501
                        break;
502
                    case 'email':
503
                    case 'text':
504
                    case 'textarea':
505
                    case 'html':
506
                        if (empty($params['filters'][$col]['value'])) {
507
                            continue;
508
                        }
509
                        switch ($params['filters'][$col]['compareType']) {
510
                            case 'contains':
511
                                $queryParams['where'][] = [$col, '%' . $params['filters'][$col]['value'] . '%', 'LIKE'];
512
                                break;
513
                            case 'equals':
514
                                $queryParams['where'][] = [$col, $params['filters'][$col]['value']];
515
                                break;
516
                            case 'starts_with':
517
                                $queryParams['where'][] = [$col, $params['filters'][$col]['value'] . '%', 'LIKE'];
518
                                break;
519
                            case 'ends_with':
520
                                $queryParams['where'][] = [$col, '%' . $params['filters'][$col]['value'], 'LIKE'];
521
                                break;
522
                        }
523
                        break;
524
                }
525
            }
526
        }
527
        if (!empty($params['mode']) && $params['mode'] == 'sort') {
528
            $queryParams['order'] = ['weight', 'asc'];
529
        } elseif (!empty($params['sortered']) && !empty($this->managerOptions['sortable'])) {
530
            foreach ($params['sortered'] as $colName => $sortType) {
531
                if ($colName && in_array($colName, $this->managerOptions['sortable'])) {
532
                    $sortType = in_array($sortType, ['desc', 'asc']) ? $sortType : 'desc';
533
                    $queryParams['order'][] = [$colName, $sortType];
534
                }
535
            }
536
        }
537
        $summarys = [];
538
        foreach ($this->managerOptions['summary'] as $summary) {
539
            $queryParams['cols'] = 'COALESCE(SUM(' . $summary['expression'] . '),0) as summary';
540
            $queryParams['array'] = true;
541
            $queryParams['key'] = false;
542
            if ($model && !empty($params['relation'])) {
543
                $items = $model->{$params['relation']}($queryParams);
544
            } else {
545
                $items = $modelName::getList($queryParams);
546
            }
547
            $summarys[] = ['name' => $summary['name'], 'summary' => $items[0]['summary']];
548
        }
549
        return $summarys;
550
    }
551
552
    public static function drawCol($item, $colName, $params = [], $dataManager = null, $originalCol = '', $originalItem = null) {
553
        $modelName = get_class($item);
554
        if (!class_exists($modelName)) {
555
            return false;
556
        }
557
558
        if (!$originalCol) {
559
            $originalCol = $colName;
560
        }
561
        if (!$originalItem) {
562
            $originalItem = $item;
563
        }
564
565
        $relations = $modelName::relations();
566
        if (strpos($colName, ':') !== false && !empty($relations[substr($colName, 0, strpos($colName, ':'))])) {
567
            $rel = substr($colName, 0, strpos($colName, ':'));
568
            $col = substr($colName, strpos($colName, ':') + 1);
569
            if ($item->$rel) {
570
                return DataManager::drawCol($item->$rel, $col, $params, $dataManager, $originalCol, $originalItem);
571
            } else {
572
                return 'Не указано';
573
            }
574
        }
575
        if (!empty($modelName::$cols[$colName]['relation'])) {
0 ignored issues
show
Bug introduced by
The property cols does not exist on string.
Loading history...
576
            $type = !empty($relations[$modelName::$cols[$colName]['relation']]['type']) ? $relations[$modelName::$cols[$colName]['relation']]['type'] : 'to';
577
            switch ($type) {
578
                case 'relModel':
579
                    $managerParams = ['relation' => $modelName::$cols[$colName]['relation']];
580
                    $count = $item->{$modelName::$cols[$colName]['relation']}(array_merge($params, ['count' => 1]));
581
                    $count = $count ? $count : 'Нет';
582
                    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>";
583
                case 'many':
584
                    $managerParams = ['relation' => $modelName::$cols[$colName]['relation']];
585
                    if (!empty($modelName::$cols[$colName]['manager'])) {
586
                        $managerParams['managerName'] = $modelName::$cols[$colName]['manager'];
587
                    }
588
                    $count = $item->{$modelName::$cols[$colName]['relation']}(array_merge($params, ['count' => 1]));
589
                    $count = $count ? $count : 'Нет';
590
                    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>";
591
                default:
592
                    if ($item->{$modelName::$cols[$colName]['relation']}) {
593
                        if (\App::$cur->name == 'admin') {
594
                            $href = "<a href ='/admin/" . $item->{$modelName::$cols[$colName]['relation']}->genViewLink() . "'>";
595
                            if (!empty($modelName::$cols[$colName]['showCol'])) {
596
                                $href .= $item->{$modelName::$cols[$colName]['relation']}->{$modelName::$cols[$colName]['showCol']};
597
                            } else {
598
599
                                $href .= $item->{$modelName::$cols[$colName]['relation']}->name();
600
                            }
601
                            $href .= '</a>';
602
                            return $href;
603
                        } else {
604
                            return $item->{$modelName::$cols[$colName]['relation']}->name();
605
                        }
606
                    } else {
607
                        return $item->$colName;
608
                    }
609
            }
610
        } else {
611
            if (!empty($modelName::$cols[$colName]['view']['type'])) {
612
                switch ($modelName::$cols[$colName]['view']['type']) {
613
                    case 'widget':
614
                        ob_start();
615
                        \App::$cur->view->widget($modelName::$cols[$colName]['view']['widget'], ['item' => $item, 'colName' => $colName, 'colParams' => $modelName::$cols[$colName]]);
616
                        $content = ob_get_contents();
617
                        ob_end_clean();
618
                        return $content;
619
                    case 'moduleMethod':
620
                        return \App::$cur->{$modelName::$cols[$colName]['view']['module']}->{$modelName::$cols[$colName]['view']['method']}($item, $colName, $modelName::$cols[$colName]);
621
                    case 'many':
622
                        $managerParams = ['relation' => $modelName::$cols[$colName]['relation']];
623
                        if (!empty($modelName::$cols[$colName]['manager'])) {
624
                            $managerParams['managerName'] = $modelName::$cols[$colName]['manager'];
625
                        }
626
                        $count = $item->{$modelName::$cols[$colName]['relation']}(array_merge($params, ['count' => 1]));
627
                        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} " . \Tools::getNumEnding($count, ['Элемент', 'Элемента', 'Элементов']) . "</a>";
628
                    default:
629
                        return $item->$colName;
630
                }
631
            } elseif (!empty($modelName::$cols[$colName]['type'])) {
632
                if (\App::$cur->name == 'admin' && $originalCol == 'name' || ($dataManager && !empty($dataManager->managerOptions['colToView']) && $dataManager->managerOptions['colToView'] == $originalCol)) {
633
                    $formName = $dataManager && !empty($dataManager->managerOptions['editForm']) ? $dataManager->managerOptions['editForm'] : 'manager';
634
                    $redirectUrl = !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/admin/' . str_replace('\\', '/', get_class($originalItem));
635
                    return "<a href ='/admin/{$originalItem->genViewLink()}?formName={$formName}&redirectUrl={$redirectUrl}'>{$item->$colName}</a>";
636
                } elseif (\App::$cur->name == 'admin' && $colName == 'name') {
637
                    $redirectUrl = !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/admin/' . str_replace('\\', '/', get_class($originalItem));
638
                    return "<a href ='/admin/{$item->genViewLink()}?redirectUrl={$redirectUrl}'>{$item->$colName}</a>";
639
                } elseif ($modelName::$cols[$colName]['type'] == 'html' || $modelName::$cols[$colName]['type'] == 'textarea') {
640
                    $uid = 'text_' . \Tools::randomString();
641
                    $script = "<script>inji.onLoad(function(){
642
            var el{$uid}=$('#{$uid}');
643
            var height{$uid} = el{$uid}.height();
644
            el{$uid}.css('maxHeight','none');
645
            function el{$uid}Toggle(){
646
              console.log($('#{$uid}').css('height'));
647
                
648
              if( $('#{$uid}').css('height')=='44px'){
649
                $('#{$uid}').css('height','auto');
650
                  var height = $('#{$uid}').height();
651
                  $('#{$uid}').css('height','44px');
652
                  $('#{$uid}').animate({height:height});
653
                  $('#{$uid}').next().text('Свернуть' )
654
                }
655
                else {
656
                  $('#{$uid}').next().text('Развернуть')
657
                  $('#{$uid}').animate({height:'44px'});
658
                }
659
            }
660
            window['el{$uid}Toggle']= el{$uid}Toggle;
661
            if(el{$uid}.height()>height{$uid}){
662
              el{$uid}.css('height','44px');
663
                
664
              el{$uid}.after('<a href=\"#\" onclick=\"el{$uid}Toggle();return false;\">Развернуть</a>');
665
            }
666
            })</script>";
667
                    return "<div id = '{$uid}' style='max-height:44px;overflow:hidden;'>{$item->$colName}</div>" . $script;
668
                } else {
669
                    return \Model::resloveTypeValue($item, $colName);
670
                }
671
            } else {
672
                return $item->$colName;
673
            }
674
        }
675
    }
676
677
    public function rowButtons($item, $params) {
678
        $modelName = $this->modelName;
679
        if (!class_exists($modelName)) {
680
            return false;
681
        }
682
        ob_start();
683
        $widgetName = !empty($this->managerOptions['rowButtonsWidget']) ? $this->managerOptions['rowButtonsWidget'] : 'Ui\DataManager/rowButtons';
684
        \App::$cur->view->widget($widgetName, [
685
            'dataManager' => $this,
686
            'item' => $item,
687
            'params' => $params
688
        ]);
689
        $buttons = ob_get_contents();
690
        ob_end_clean();
691
        return $buttons;
692
    }
693
694
    public function getPages($params = [], $model = null) {
695
        $modelName = $this->modelName;
696
        if (!class_exists($modelName)) {
697
            return [];
698
        }
699
        if (!$this->checkAccess()) {
700
            $this->drawError('you not have access to "' . $this->modelName . '" manager with name: "' . $this->managerName . '"');
701
            return [];
702
        }
703
        if (!empty($params['limit'])) {
704
            $this->limit = (int) $params['limit'];
705
        }
706
        if (!empty($params['page'])) {
707
            $this->page = (int) $params['page'];
708
        }
709
        $queryParams = [
710
            'count' => true
711
        ];
712
        $modelName = $this->modelName;
713
        if (!empty($params['categoryPath']) && $modelName::$categoryModel) {
0 ignored issues
show
Bug introduced by
The property categoryModel does not exist on string.
Loading history...
714
            $queryParams['where'][] = ['tree_path', $params['categoryPath'] . '%', 'LIKE'];
715
        }
716
        if (!empty($this->managerOptions['userGroupFilter'][\Users\User::$cur->group_id]['getRows'])) {
717
            foreach ($this->managerOptions['userGroupFilter'][\Users\User::$cur->group_id]['getRows'] as $colName => $colOptions) {
718
                if (!empty($colOptions['userCol'])) {
719
                    $queryParams['where'][] = [$colName, \Model::getColValue(\Users\User::$cur, $colOptions['userCol'])];
720
                } elseif (isset($colOptions['value'])) {
721
                    if (is_array($colOptions['value'])) {
722
                        foreach ($colOptions['value'] as $key => $value) {
723
                            if ($key === 'userCol') {
724
                                $colOptions['value'][$key] = \Model::getColValue(\Users\User::$cur, $value);
725
                            }
726
                        }
727
                    }
728
                    $queryParams['where'][] = [$colName, $colOptions['value'], is_array($colOptions['value']) ? 'IN' : '='];
729
                }
730
            }
731
        }
732
        $modelName = $this->modelName;
733
        if (!empty($this->managerOptions['filters'])) {
734
            foreach ($this->managerOptions['filters'] as $col) {
735
                $colInfo = $modelName::getColInfo($col);
736
                switch ($colInfo['colParams']['type']) {
737
                    case 'select':
738
                        if (empty($params['filters'][$col]['value'])) {
739
                            continue;
740
                        }
741
                        if (is_array($params['filters'][$col]['value'])) {
742
                            foreach ($params['filters'][$col]['value'] as $key => $value) {
743
                                if ($value === '') {
744
                                    unset($params['filters'][$col]['value'][$key]);
745
                                }
746
                            }
747
                        }
748
                        if (!$params['filters'][$col]['value']) {
749
                            continue;
750
                        }
751
                        $queryParams['where'][] = [$col, $params['filters'][$col]['value'], is_array($params['filters'][$col]['value']) ? 'IN' : '='];
752
                        break;
753
                    case 'bool':
754
                        if (empty($params['filters'][$col]['value'])) {
755
                            continue;
756
                        }
757
                        $queryParams['where'][] = [$col, '1'];
758
                        break;
759
                    case 'dateTime':
760
                    case 'date':
761
                        if (empty($params['filters'][$col]['min']) && empty($params['filters'][$col]['max'])) {
762
                            continue;
763
                        }
764
                        if (!empty($params['filters'][$col]['min'])) {
765
                            $queryParams['where'][] = [$col, $params['filters'][$col]['min'], '>='];
766
                        }
767
                        if (!empty($params['filters'][$col]['max'])) {
768
                            if ($colInfo['colParams']['type'] == 'dateTime' && !strpos($params['filters'][$col]['max'], ' ')) {
769
770
                                $date = $params['filters'][$col]['max'] . ' 23:59:59';
771
                            } else {
772
                                $date = $params['filters'][$col]['max'];
773
                            }
774
                            $queryParams['where'][] = [$col, $date, '<='];
775
                        }
776
                        break;
777
                    case 'number':
778
                        if (empty($params['filters'][$col]['min']) && empty($params['filters'][$col]['max'])) {
779
                            continue;
780
                        }
781
                        if (!empty($params['filters'][$col]['min'])) {
782
                            $queryParams['where'][] = [$col, $params['filters'][$col]['min'], '>='];
783
                        }
784
                        if (!empty($params['filters'][$col]['max'])) {
785
                            $queryParams['where'][] = [$col, $params['filters'][$col]['max'], '<='];
786
                        }
787
                        break;
788
                    case 'email':
789
                    case 'text':
790
                    case 'textarea':
791
                    case 'html':
792
                        if (empty($params['filters'][$col]['value'])) {
793
                            continue;
794
                        }
795
                        switch ($params['filters'][$col]['compareType']) {
796
                            case 'contains':
797
                                $queryParams['where'][] = [$col, '%' . $params['filters'][$col]['value'] . '%', 'LIKE'];
798
                                break;
799
                            case 'equals':
800
                                $queryParams['where'][] = [$col, $params['filters'][$col]['value']];
801
                                break;
802
                            case 'starts_with':
803
                                $queryParams['where'][] = [$col, $params['filters'][$col]['value'] . '%', 'LIKE'];
804
                                break;
805
                            case 'ends_with':
806
                                $queryParams['where'][] = [$col, '%' . $params['filters'][$col]['value'], 'LIKE'];
807
                                break;
808
                        }
809
                        break;
810
                }
811
            }
812
        }
813
        if ($model && !empty($params['relation'])) {
814
            $count = $model->{$params['relation']}($queryParams);
815
        } else {
816
            $count = $modelName::getCount($queryParams);
817
        }
818
        $pages = new Pages([
819
            'limit' => $this->limit,
820
            'page' => $this->page,
821
        ], [
822
            'count' => $count,
823
            'dataManager' => $this
824
        ]);
825
        return $pages;
826
    }
827
828
    public function preDraw($params = [], $model = null) {
829
        $this->predraw = true;
830
831
        $cols = $this->getCols();
832
833
        $this->table = new Table();
834
        $tableCols = [];
835
        foreach ($cols as $colName => $colOptions) {
0 ignored issues
show
Bug introduced by
The expression $cols of type string is not traversable.
Loading history...
836
            $tableCols[] = [
837
                'attributes' => ['class' => $this->managerId . '_colname_' . $colName, 'data-colname' => $colName],
838
                'text' => !empty($colOptions['label']) ? $colOptions['label'] : $colName
839
            ];
840
        }
841
        $tableCols[] = '';
842
        $this->table->class .= ' datamanagertable';
843
        $this->table->setCols($tableCols);
844
    }
845
846
    public function draw($params = [], $model = null) {
847
        if (!$this->predraw) {
848
            $this->preDraw($params, $model);
849
        }
850
        if (!$this->checkAccess()) {
851
            $this->drawError('you not have access to "' . $this->modelName . '" manager with name: "' . $this->managerName . '"');
852
            return false;
853
        }
854
        \App::$cur->view->widget('Ui\DataManager/DataManager', [
855
            'dataManager' => $this,
856
            'model' => $model,
857
            'table' => $this->table,
858
            'params' => $params
859
        ]);
860
        return true;
861
    }
862
863
    public function drawCategorys() {
864
        if (!class_exists($this->modelName)) {
865
            return false;
866
        }
867
        if (!$this->checkAccess()) {
868
            $this->drawError('you not have access to "' . $this->modelName . '" manager with name: "' . $this->managerName . '"');
869
            return [];
870
        }
871
        $tree = new Tree();
872
        $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|Ui\closure expected by parameter $hrefFunc of 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

872
        $tree->ul($this->managerOptions['categorys']['model'], 0, /** @scrutinizer ignore-type */ function ($category) {
Loading history...
873
            $path = $category->tree_path . ($category->pk() ? $category->pk() . "/" : '');
874
            $cleanClassName = str_replace('\\', '\\\\', get_class($category));
875
            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> 
876
                
877
                    <a href = '#' class ='glyphicon glyphicon-edit'   onclick = 'inji.Ui.forms.popUp(\"{$cleanClassName}:{$category->pk()}\")'></a>&nbsp;
878
                    <a href = '#' class ='glyphicon glyphicon-remove' onclick = 'inji.Ui.dataManagers.get(this).delCategory({$category->pk()});return false;'></a>";
879
        });
880
        ?>
881
        <?php
882
    }
883
884
    /**
885
     * Draw error message
886
     *
887
     * @param string $errorText
888
     */
889
    public function drawError($errorText) {
890
        echo $errorText;
891
    }
892
893
    /**
894
     * Check access cur user to manager with name in param
895
     *
896
     * @return boolean
897
     */
898
    public function checkAccess() {
899
        if (\App::$cur->Access && !\App::$cur->Access->checkAccess($this)) {
900
            return false;
901
        }
902
903
        if (!empty($this->managerOptions['options']['access']['apps']) && !in_array(\App::$cur->name, $this->managerOptions['options']['access']['apps'])) {
904
            return false;
905
        }
906
        if (!empty($this->managerOptions['options']['access']['groups'])) {
907
            return in_array(\Users\User::$cur->group_id, $this->managerOptions['options']['access']['groups']);
908
        }
909
        if ($this->managerName == 'manager' && !\Users\User::$cur->isAdmin()) {
910
            return false;
911
        }
912
        return true;
913
    }
914
}