Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like ActiveForm 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
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 ActiveForm, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 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 = '') |
||
| 67 | |||
| 68 | public function getInputs() |
||
| 97 | |||
| 98 | public function checkRequest($params = [], $ajax = false) |
||
| 181 | |||
| 182 | public function draw($params = [], $ajax = false) |
||
| 191 | |||
| 192 | public function drawCol($colName, $options, $form, $params = []) |
||
| 209 | |||
| 210 | public static function getOptionsList($inputParams, $params = [], $modelName = '', $aditionalInputNamePrefix = 'aditional', $options = []) |
||
| 211 | { |
||
| 212 | $values = []; |
||
| 213 | switch ($inputParams['source']) { |
||
| 214 | case 'model': |
||
| 215 | $values = $inputParams['model']::getList(['forSelect' => true]); |
||
| 216 | break; |
||
| 217 | case 'array': |
||
| 218 | $values = $inputParams['sourceArray']; |
||
| 219 | break; |
||
| 220 | case 'method': |
||
| 221 | if (!empty($inputParams['params'])) { |
||
| 222 | $values = call_user_func_array([\App::$cur->$inputParams['module'], $inputParams['method']], $inputParams['params']); |
||
| 223 | } else { |
||
| 224 | $values = \App::$cur->$inputParams['module']->$inputParams['method'](); |
||
| 225 | } |
||
| 226 | break; |
||
| 227 | case 'relation': |
||
| 228 | if (!$modelName) { |
||
| 229 | return []; |
||
| 230 | } |
||
| 231 | $relation = $modelName::getRelation($inputParams['relation']); |
||
| 232 | View Code Duplication | if (!empty($params['dataManagerParams']['appType'])) { |
|
| 233 | $options['appType'] = $params['dataManagerParams']['appType']; |
||
| 234 | } |
||
| 235 | $items = []; |
||
| 236 | if (class_exists($relation['model'])) { |
||
| 237 | $filters = $relation['model']::managerFilters(); |
||
| 238 | if (!empty($filters['getRows']['where'])) { |
||
| 239 | $options['where'][] = $filters['getRows']['where']; |
||
| 240 | } |
||
| 241 | if (!empty($relation['order'])) { |
||
| 242 | $options['order'] = $relation['order']; |
||
| 243 | } |
||
| 244 | if (!empty($inputParams['itemName'])) { |
||
| 245 | $options['itemName'] = $inputParams['itemName']; |
||
| 246 | } |
||
| 247 | $items = $relation['model']::getList($options); |
||
| 248 | } |
||
| 249 | if (!empty($params['noEmptyValue'])) { |
||
| 250 | $values = []; |
||
| 251 | } else { |
||
| 252 | $values = [0 => 'Не задано']; |
||
| 253 | } |
||
| 254 | foreach ($items as $key => $item) { |
||
| 255 | if (!empty($inputParams['showCol'])) { |
||
| 256 | if (is_array($inputParams['showCol'])) { |
||
| 257 | switch ($inputParams['showCol']['type']) { |
||
| 258 | case 'staticMethod': |
||
| 259 | $values[$key] = $inputParams['showCol']['class']::{$inputParams['showCol']['method']}($item); |
||
| 260 | break; |
||
| 261 | } |
||
| 262 | } else { |
||
| 263 | $values[$key] = $item->$inputParams['showCol']; |
||
| 264 | } |
||
| 265 | } else { |
||
| 266 | $values[$key] = $item->name(); |
||
| 267 | } |
||
| 268 | } |
||
| 269 | break; |
||
| 270 | } |
||
| 271 | foreach ($values as $key => $value) { |
||
| 272 | if (is_array($value) && !empty($value['input']) && empty($value['input']['noprefix'])) { |
||
| 273 | $values[$key]['input']['name'] = $aditionalInputNamePrefix . "[{$value['input']['name']}]"; |
||
| 274 | } |
||
| 275 | } |
||
| 276 | return $values; |
||
| 277 | } |
||
| 278 | |||
| 279 | /** |
||
| 280 | * Draw error message |
||
| 281 | * |
||
| 282 | * @param string $errorText |
||
| 283 | */ |
||
| 284 | public function drawError($errorText) |
||
| 288 | |||
| 289 | /** |
||
| 290 | * Check access cur user to form with name in param and $model |
||
| 291 | * |
||
| 292 | * @return boolean |
||
| 293 | */ |
||
| 294 | public function checkAccess() |
||
| 317 | |||
| 318 | } |
||
| 319 |
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: