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

ActiveForm::getOptionsList()   D

Complexity

Conditions 22
Paths 220

Size

Total Lines 70
Code Lines 53

Duplication

Lines 3
Ratio 4.29 %

Importance

Changes 0
Metric Value
cc 22
eloc 53
nc 220
nop 5
dl 3
loc 70
rs 4.7435
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Active form
5
 *
6
 * @author Alexey Krupskiy <[email protected]>
7
 * @link http://inji.ru/
8
 * @copyright 2015 Alexey Krupskiy
9
 * @license https://github.com/injitools/cms-Inji/blob/master/LICENSE
10
 */
11
12
namespace Ui;
13
14
class ActiveForm extends \Object {
15
16
  public $model = null;
17
  public $modelName = '';
18
  public $header = "";
19
  public $action = "";
20
  public $form = [];
21
  public $inputs = [];
22
  public $formName = 'noNameForm';
23
  public $requestFormName = '';
24
  public $requestFullFormName = '';
25
  public $parent = null;
26
27
  /**
28
   * 
29
   * @param array|\Model $model
30
   * @param array|string $form
31
   */
32
  public function __construct($model, $form = '') {
33
    if (is_array($model)) {
34
      $this->form = $model;
35
      if (is_string($form)) {
36
        $this->formName = $form;
37
      }
38
    } else {
39
      $this->model = $model;
40
      $this->modelName = get_class($model);
41
      if (is_array($form)) {
42
        if (empty($form)) {
43
          throw new \Exception('empty form');
44
        }
45
        $this->form = $form;
46
      } else {
47
        $this->formName = $form;
48
        $this->form = \App::$cur->ui->getModelForm($this->modelName, $form);
49
        if (empty($this->form)) {
50
          throw new \Exception('empty form ' . $form);
51
        }
52
        $this->inputs = $this->getInputs();
53
      }
54
    }
55
    $this->requestFormName = "ActiveForm_{$this->formName}";
56
    $modeName = $this->modelName;
57
58
    if (!empty($this->form['name'])) {
59
      $this->header = $this->form['name'];
60
    } elseif (!empty($modeName::$objectName)) {
61
      $this->header = $modeName::$objectName;
62
    } else {
63
      $this->header = $this->modelName;
64
    }
65
  }
66
67
  public function getInputs() {
68
    $inputs = !empty($this->form['inputs']) ? $this->form['inputs'] : [];
69
    $modelName = $this->modelName;
70
    foreach ($this->form['map'] as $row) {
71
      foreach ($row as $col) {
72
        if (!$col || !empty($inputs[$col])) {
73
          continue;
74
        }
75
        if (strpos($col, 'form:') === 0) {
76
          $colPath = explode(':', $col);
77
          if ($this->model->{$colPath[1]}) {
78
            $inputs[$col] = new ActiveForm($this->model->{$colPath[1]}, $colPath[2]);
79
          } else {
80
            $relOptions = $modelName::getRelation($colPath[1]);
81
            if (!isset($this->model->_params[$modelName::index()])) {
82
              $this->model->_params[$modelName::index()] = 0;
83
            }
84
            $relOptions['model']::fixPrefix($relOptions['col']);
85
            $inputs[$col] = new ActiveForm(new $relOptions['model']([ $relOptions['col'] => &$this->model->_params[$modelName::index()]]), $colPath[2]);
86
          }
87
          $inputs[$col]->parent = $this;
88
        } elseif (!empty($modelName::$cols[$col])) {
89
          $inputs[$col] = $modelName::$cols[$col];
90
        }
91
      }
92
    }
93
    return $inputs;
94
  }
95
96
  public function checkRequest($params = [], $ajax = false) {
2 ignored issues
show
Coding Style introduced by
checkRequest uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
checkRequest uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
97 View Code Duplication
    if (!$this->checkAccess()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
98
      $this->drawError('you not have access to "' . $this->modelName . '" manager with name: "' . $this->formName . '"');
99
      return [];
100
    }
101
    $successId = 0;
102
    if (!empty($_POST[$this->requestFormName][$this->modelName])) {
103
      $request = $_POST[$this->requestFormName][$this->modelName];
104
      if ($this->model) {
105
        if (!empty($this->form['handler'])) {
106
          $modelName = $this->model;
107
          $modelName::{$this->form['handler']}($request);
108
          $text = 'Новый элемент был успешно добавлен';
109
          \Msg::add($text, 'success');
110
          \Msg::show();
111
        } else {
112
          $presets = !empty($this->form['preset']) ? $this->form['preset'] : [];
113 View Code Duplication
          if (!empty($this->form['userGroupPreset'][\Users\User::$cur->group_id])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
114
            $presets = array_merge($presets, $this->form['userGroupPreset'][\Users\User::$cur->group_id]);
115
          }
116
          $afterSave = [];
117
          $error = false;
118
          foreach ($this->inputs as $col => $param) {
119
            if (!empty($presets[$col])) {
120
              continue;
121
            }
122
            if (is_object($param)) {
123
              $afterSave[] = $param;
124
              continue;
125
            }
126 View Code Duplication
            if (!empty($this->form['userGroupReadonly'][\Users\User::$cur->group_id]) && in_array($col, $this->form['userGroupReadonly'][\Users\User::$cur->group_id])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
127
              continue;
128
            }
129
            $inputClassName = '\Ui\ActiveForm\Input\\' . ucfirst($param['type']);
130
            $input = new $inputClassName();
131
            $input->activeForm = $this;
132
            $input->activeFormParams = $params;
133
            $input->modelName = $this->modelName;
134
            $input->colName = $col;
135
            $input->colParams = $param;
136
            try {
137
              $input->validate($request);
138
              $input->parseRequest($request);
139
            } catch (\Exception $exc) {
140
              \Msg::add($exc->getMessage(), 'danger');
141
              $error = true;
142
            }
143
          }
144
          if (!$error && empty($_GET['notSave'])) {
145
            foreach ($presets as $col => $preset) {
146
              if (!empty($preset['value'])) {
147
                $this->model->$col = $preset['value'];
148
              } elseif (!empty($preset['userCol'])) {
149
                if (strpos($preset['userCol'], ':')) {
150
                  $rel = substr($preset['userCol'], 0, strpos($preset['userCol'], ':'));
151
                  $param = substr($preset['userCol'], strpos($preset['userCol'], ':') + 1);
152
                  $this->model->$col = \Users\User::$cur->$rel->$param;
153
                } else {
154
                  $this->model->$col = \Users\User::$cur->{$preset['userCol']};
155
                }
156
              }
157
            }
158
            if (!$this->parent) {
159
              if (!empty($this->form['successText'])) {
160
                $text = $this->form['successText'];
161
              } else {
162
                $text = $this->model->pk() ? 'Изменения были успешно сохранены' : 'Новый элемент был успешно добавлен';
163
              }
164
              \Msg::add($text, 'success');
165
            }
166
167
            $this->model->save(!empty($params['dataManagerParams']) ? $params['dataManagerParams'] : []);
168
            foreach ($afterSave as $form) {
169
              $form->checkRequest();
170
            }
171
            if ($ajax) {
172
              \Msg::show();
173
            } elseif (!empty($_GET['redirectUrl'])) {
174
              \Tools::redirect($_GET['redirectUrl'] . (!empty($_GET['dataManagerHash']) ? '#' . $_GET['dataManagerHash'] : ''));
175
            }
176
            $successId = $this->model->pk();
177
          }
178
        }
179
      }
180
      if (!is_array($params) && is_callable($params)) {
181
        $params($request);
182
      }
183
    }
184
    return $successId;
185
  }
186
187
  public function draw($params = [], $ajax = false) {
188 View Code Duplication
    if (!$this->checkAccess()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
189
      $this->drawError('you not have access to "' . $this->modelName . '" form with name: "' . $this->formName . '"');
190
      return [];
191
    }
192
    $form = new Form(!empty($this->form['formOptions']) ? $this->form['formOptions'] : []);
193
    \App::$cur->view->widget('Ui\ActiveForm', ['form' => $form, 'activeForm' => $this, 'ajax' => $ajax, 'params' => $params]);
194
  }
195
196
  public function drawCol($colName, $options, $form, $params = []) {
197
    if (is_object($options)) {
198
      $options->draw();
199
    } else {
200
      $inputClassName = '\Ui\ActiveForm\Input\\' . ucfirst($options['type']);
201
      $input = new $inputClassName();
202
      $input->form = $form;
203
      $input->activeForm = $this;
204
      $input->activeFormParams = $params;
205
      $input->modelName = $this->modelName;
206
      $input->colName = $colName;
207
      $input->colParams = $options;
208
      $input->options = !empty($options['options']) ? $options['options'] : [];
209
      $input->draw();
210
    }
211
    return true;
212
  }
213
214
  public static function getOptionsList($inputParams, $params = [], $modelName = '', $aditionalInputNamePrefix = 'aditional', $options = []) {
215
    $values = [];
216
    switch ($inputParams['source']) {
217
      case 'model':
218
        $values = $inputParams['model']::getList(['forSelect' => true]);
219
        break;
220
      case 'array':
221
        $values = $inputParams['sourceArray'];
222
        break;
223
      case 'method':
224
        if (!empty($inputParams['params'])) {
225
          $values = call_user_func_array([\App::$cur->$inputParams['module'], $inputParams['method']], $inputParams['params']);
226
        } else {
227
          $values = \App::$cur->$inputParams['module']->$inputParams['method']();
228
        }
229
        break;
230
      case 'relation':
231
        if (!$modelName) {
232
          return [];
233
        }
234
        $relation = $modelName::getRelation($inputParams['relation']);
235 View Code Duplication
        if (!empty($params['dataManagerParams']['appType'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
236
          $options['appType'] = $params['dataManagerParams']['appType'];
237
        }
238
        $items = [];
239
        if (class_exists($relation['model'])) {
240
          $filters = $relation['model']::managerFilters();
241
          if (!empty($filters['getRows']['where'])) {
242
            $options['where'][] = $filters['getRows']['where'];
243
          }
244
          if (!empty($relation['where'])) {
245
            $options['where'][] = $relation['where'];
246
          }
247
          if (!empty($relation['order'])) {
248
            $options['order'] = $relation['order'];
249
          }
250
          if (!empty($inputParams['itemName'])) {
251
            $options['itemName'] = $inputParams['itemName'];
252
          }
253
          $items = $relation['model']::getList($options);
254
        }
255
        if (!empty($params['noEmptyValue'])) {
256
          $values = [];
257
        } else {
258
          $values = [0 => 'Не задано'];
259
        }
260
        foreach ($items as $key => $item) {
261
          if (!empty($inputParams['showCol'])) {
262
            if (is_array($inputParams['showCol'])) {
263
              switch ($inputParams['showCol']['type']) {
264
                case 'staticMethod':
265
                  $values[$key] = $inputParams['showCol']['class']::{$inputParams['showCol']['method']}($item);
266
                  break;
267
              }
268
            } else {
269
              $values[$key] = $item->$inputParams['showCol'];
270
            }
271
          } else {
272
            $values[$key] = $item->name();
273
          }
274
        }
275
        break;
276
    }
277
    foreach ($values as $key => $value) {
278
      if (is_array($value) && !empty($value['input']) && empty($value['input']['noprefix'])) {
279
        $values[$key]['input']['name'] = $aditionalInputNamePrefix . "[{$value['input']['name']}]";
280
      }
281
    }
282
    return $values;
283
  }
284
285
  /**
286
   * Draw error message
287
   * 
288
   * @param string $errorText
289
   */
290
  public function drawError($errorText) {
291
    echo $errorText;
292
  }
293
294
  /**
295
   * Check access cur user to form with name in param and $model
296
   * 
297
   * @return boolean
298
   */
299
  public function checkAccess() {
300
    if (empty($this->form)) {
301
      $this->drawError('"' . $this->modelName . '" form with name: "' . $this->formName . '" not found');
302
      return false;
303
    }
304
    if (\App::$cur->Access && !\App::$cur->Access->checkAccess($this)) {
305
      return false;
306
    }
307
    if (!empty($this->form['options']['access']['apps']) && !in_array(\App::$cur->name, $this->form['options']['access']['apps'])) {
308
      return false;
309
    }
310 View Code Duplication
    if (!empty($this->form['options']['access']['groups']) && in_array(\Users\User::$cur->group_id, $this->form['options']['access']['groups'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
311
      return true;
312
    }
313
    if ($this->model && !empty($this->form['options']['access']['self']) && \Users\User::$cur->id == $this->model->user_id) {
314
      return true;
315
    }
316
    if ($this->formName == 'manager' && !\Users\User::$cur->isAdmin()) {
317
      return false;
318
    }
319
    return true;
320
  }
321
322
}
323