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 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. 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 DataManager, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 13 | class DataManager extends \Object |
||
| 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 $modelName |
||
| 31 | * @param string|array $dataManager |
||
| 32 | * @throws Exception |
||
| 33 | */ |
||
| 34 | public function __construct($modelName, $dataManager = 'manager') |
||
| 62 | |||
| 63 | /** |
||
| 64 | * Get buttons for manager |
||
| 65 | * |
||
| 66 | * @param string $params |
||
| 67 | * @param object $model |
||
| 68 | */ |
||
| 69 | public function getButtons($params = [], $model = null) |
||
| 115 | |||
| 116 | function getActions() |
||
| 138 | |||
| 139 | /** |
||
| 140 | * Get cols for manager |
||
| 141 | * |
||
| 142 | * @return string |
||
| 143 | */ |
||
| 144 | public function getCols() |
||
| 145 | { |
||
| 146 | $modelName = $this->modelName; |
||
| 147 | if (!class_exists($modelName)) { |
||
| 148 | return []; |
||
| 149 | } |
||
| 150 | $modelName = $this->modelName; |
||
| 151 | $cols = []; |
||
| 152 | $actions = $this->getActions(); |
||
| 153 | ob_start(); |
||
| 154 | ?> |
||
| 155 | <div class="dropdown"> |
||
| 156 | <a id="dLabel" data-target="#" href="" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"> |
||
| 157 | <i class="glyphicon glyphicon-cog"></i> |
||
| 158 | <span class="caret"></span> |
||
| 159 | </a> |
||
| 160 | |||
| 161 | <ul class="dropdown-menu" aria-labelledby="dLabel"> |
||
| 162 | <li><a href ='' onclick='inji.Ui.dataManagers.get(this).rowSelection("selectAll");return false;'>Выделить все</a></li> |
||
| 163 | <li><a href ='' onclick='inji.Ui.dataManagers.get(this).rowSelection("unSelectAll");return false;'>Снять все</a></li> |
||
| 164 | <li><a href ='' onclick='inji.Ui.dataManagers.get(this).rowSelection("inverse");return false;'>Инвертировать</a></li> |
||
| 165 | <li role="separator" class="divider"></li> |
||
| 166 | <?php |
||
| 167 | foreach ($actions as $action => $actionParams) { |
||
| 168 | if (class_exists($actionParams['className']) && $actionParams['className']::$groupAction) { |
||
| 169 | echo "<li><a href ='' onclick='inji.Ui.dataManagers.get(this).groupAction(\"" . str_replace('\\', '\\\\', $action) . "\");return false;'>{$actionParams['className']::$name}</a></li>"; |
||
| 170 | } |
||
| 171 | } |
||
| 172 | ?> |
||
| 173 | </ul> |
||
| 174 | </div> |
||
| 175 | <?php |
||
| 176 | $dropdown = ob_get_contents(); |
||
| 177 | ob_end_clean(); |
||
| 178 | $cols[] = ['label' => $dropdown]; |
||
| 179 | |||
| 180 | $cols['id'] = ['label' => '№', 'sortable' => true]; |
||
| 181 | foreach ($this->managerOptions['cols'] as $key => $col) { |
||
| 182 | if (is_array($col)) { |
||
| 183 | $colName = $key; |
||
| 184 | $colOptions = $col; |
||
| 185 | } else { |
||
| 186 | $colName = $col; |
||
| 187 | $colOptions = []; |
||
| 188 | } |
||
| 189 | $colInfo = []; |
||
| 190 | if ($modelName) { |
||
| 191 | $colInfo = $modelName::getColInfo($colName); |
||
| 192 | } |
||
| 193 | if (empty($colOptions['label']) && !empty($colInfo['label'])) { |
||
| 194 | $colOptions['label'] = $colInfo['label']; |
||
| 195 | } elseif (empty($colOptions['label'])) { |
||
| 196 | $colOptions['label'] = $colName; |
||
| 197 | } |
||
| 198 | $cols[$colName] = $colOptions; |
||
| 199 | } |
||
| 200 | return $cols; |
||
| 201 | } |
||
| 202 | |||
| 203 | /** |
||
| 204 | * Get rows for manager |
||
| 205 | * |
||
| 206 | * @param array $params |
||
| 207 | * @param object $model |
||
| 208 | * @return type |
||
| 209 | */ |
||
| 210 | public function getRows($params = [], $model = null) |
||
| 379 | |||
| 380 | public static function drawCol($item, $colName, $params = [], $dataManager = null, $originalCol = '', $originalItem = null) |
||
|
1 ignored issue
–
show
|
|||
| 381 | { |
||
| 382 | $modelName = get_class($item); |
||
| 383 | if (!class_exists($modelName)) { |
||
| 384 | return false; |
||
| 385 | } |
||
| 386 | |||
| 387 | if (!$originalCol) { |
||
| 388 | $originalCol = $colName; |
||
| 389 | } |
||
| 390 | if (!$originalItem) { |
||
| 391 | $originalItem = $item; |
||
| 392 | } |
||
| 393 | |||
| 394 | $relations = $modelName::relations(); |
||
| 395 | if (strpos($colName, ':') !== false && !empty($relations[substr($colName, 0, strpos($colName, ':'))])) { |
||
| 396 | $rel = substr($colName, 0, strpos($colName, ':')); |
||
| 397 | $col = substr($colName, strpos($colName, ':') + 1); |
||
| 398 | if ($item->$rel) { |
||
| 399 | return DataManager::drawCol($item->$rel, $col, $params, $dataManager, $originalCol, $originalItem); |
||
| 400 | } else { |
||
| 401 | return 'Не указано'; |
||
| 402 | } |
||
| 403 | } |
||
| 404 | if (!empty($modelName::$cols[$colName]['relation'])) { |
||
| 405 | $type = !empty($relations[$modelName::$cols[$colName]['relation']]['type']) ? $relations[$modelName::$cols[$colName]['relation']]['type'] : 'to'; |
||
| 406 | switch ($type) { |
||
| 407 | View Code Duplication | case 'relModel': |
|
| 408 | $managerParams = ['relation' => $modelName::$cols[$colName]['relation']]; |
||
| 409 | $count = $item->{$modelName::$cols[$colName]['relation']}(array_merge($params, ['count' => 1])); |
||
| 410 | 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>"; |
||
| 411 | View Code Duplication | case 'many': |
|
| 412 | $managerParams = ['relation' => $modelName::$cols[$colName]['relation']]; |
||
| 413 | $count = $item->{$modelName::$cols[$colName]['relation']}(array_merge($params, ['count' => 1])); |
||
| 414 | 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>"; |
||
| 415 | default : |
||
| 416 | if ($item->{$modelName::$cols[$colName]['relation']}) { |
||
| 417 | if (\App::$cur->name == 'admin') { |
||
| 418 | $href = "<a href ='/admin/" . str_replace('\\', '/view/', $relations[$modelName::$cols[$colName]['relation']]['model']) . "/" . $item->{$modelName::$cols[$colName]['relation']}->pk() . "'>"; |
||
| 419 | if (!empty($modelName::$cols[$colName]['showCol'])) { |
||
| 420 | $href .= $item->{$modelName::$cols[$colName]['relation']}->{$modelName::$cols[$colName]['showCol']}; |
||
| 421 | } else { |
||
| 422 | |||
| 423 | $href .= $item->{$modelName::$cols[$colName]['relation']}->name(); |
||
| 424 | } |
||
| 425 | $href .= '</a>'; |
||
| 426 | return $href; |
||
| 427 | } else { |
||
| 428 | return $item->{$modelName::$cols[$colName]['relation']}->name(); |
||
| 429 | } |
||
| 430 | } else { |
||
| 431 | return $item->$colName; |
||
| 432 | } |
||
| 433 | } |
||
| 434 | } else { |
||
| 435 | if (!empty($modelName::$cols[$colName]['view']['type'])) { |
||
| 436 | switch ($modelName::$cols[$colName]['view']['type']) { |
||
| 437 | case 'widget': |
||
| 438 | ob_start(); |
||
| 439 | \App::$cur->view->widget($modelName::$cols[$colName]['view']['widget'], ['item' => $item, 'colName' => $colName, 'colParams' => $modelName::$cols[$colName]]); |
||
| 440 | $content = ob_get_contents(); |
||
| 441 | ob_end_clean(); |
||
| 442 | return $content; |
||
| 443 | case 'moduleMethod': |
||
| 444 | return \App::$cur->{$modelName::$cols[$colName]['view']['module']}->{$modelName::$cols[$colName]['view']['method']}($item, $colName, $modelName::$cols[$colName]); |
||
| 445 | View Code Duplication | case'many': |
|
| 446 | $managerParams = ['relation' => $modelName::$cols[$colName]['relation']]; |
||
| 447 | $count = $item->{$modelName::$cols[$colName]['relation']}(array_merge($params, ['count' => 1])); |
||
| 448 | 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>"; |
||
| 449 | default: |
||
| 450 | return $item->$colName; |
||
| 451 | } |
||
| 452 | } elseif (!empty($modelName::$cols[$colName]['type'])) { |
||
| 453 | if (\App::$cur->name == 'admin' && $originalCol == 'name' || ( $dataManager && !empty($dataManager->managerOptions['colToView']) && $dataManager->managerOptions['colToView'] == $originalCol)) { |
||
| 454 | $formName = $dataManager && !empty($dataManager->managerOptions['editForm']) ? $dataManager->managerOptions['editForm'] : 'manager'; |
||
| 455 | $redirectUrl = !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/admin/' . str_replace('\\', '/', get_class($originalItem)); |
||
| 456 | return "<a href ='/admin/" . str_replace('\\', '/view/', get_class($originalItem)) . "/{$originalItem->id}?formName={$formName}&redirectUrl={$redirectUrl}'>{$item->$colName}</a>"; |
||
| 457 | } elseif (\App::$cur->name == 'admin' && $colName == 'name') { |
||
| 458 | $redirectUrl = !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/admin/' . str_replace('\\', '/', get_class($originalItem)); |
||
| 459 | return "<a href ='/admin/" . str_replace('\\', '/view/', get_class($item)) . "/{$item->id}?redirectUrl={$redirectUrl}'>{$item->$colName}</a>"; |
||
| 460 | } else { |
||
| 461 | return \Model::resloveTypeValue($item, $colName); |
||
| 462 | } |
||
| 463 | } else { |
||
| 464 | return $item->$colName; |
||
| 465 | } |
||
| 466 | } |
||
| 467 | } |
||
| 468 | |||
| 469 | public function rowButtons($item, $params) |
||
| 486 | |||
| 487 | public function getPages($params = [], $model = null) |
||
| 617 | |||
| 618 | public function preDraw($params = [], $model = null) |
||
| 635 | |||
| 636 | public function draw($params = [], $model = null) |
||
| 651 | |||
| 652 | public function drawCategorys() |
||
| 653 | { |
||
| 670 | |||
| 671 | /** |
||
| 672 | * Draw error message |
||
| 673 | * |
||
| 674 | * @param string $errorText |
||
| 675 | */ |
||
| 676 | public function drawError($errorText) |
||
| 680 | |||
| 681 | /** |
||
| 682 | * Check access cur user to manager with name in param |
||
| 683 | * |
||
| 684 | * @return boolean |
||
| 685 | */ |
||
| 686 | public function checkAccess() |
||
| 702 | |||
| 703 | } |
||
| 704 |
Adding explicit visibility (
private,protected, orpublic) is generally recommend to communicate to other developers how, and from where this method is intended to be used.