| Total Complexity | 40 |
| Total Lines | 392 |
| Duplicated Lines | 0 % |
| Changes | 4 | ||
| Bugs | 0 | Features | 0 |
Complex classes like DashboardView 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 DashboardView, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 17 | class DashboardView extends ModuleView |
||
| 18 | { |
||
| 19 | protected $label = 'Dashboard'; |
||
| 20 | |||
| 21 | protected $dashboard; |
||
| 22 | protected $columns; |
||
| 23 | protected $admin = false; |
||
| 24 | protected $locked = false; |
||
| 25 | |||
| 26 | public function body() |
||
| 27 | { |
||
| 28 | if (! $this->isSingleDashboard()) { |
||
| 29 | $this->location($this->dashboard()['name']); |
||
| 30 | } |
||
| 31 | |||
| 32 | // initiate the dashboard first |
||
| 33 | $this->dashboard(); |
||
| 34 | |||
| 35 | $this->addMenu(); |
||
| 36 | |||
| 37 | $this->showDashboard(); |
||
| 38 | } |
||
| 39 | |||
| 40 | public function showDashboard() |
||
| 41 | { |
||
| 42 | $dashboard = $this->dashboard(); |
||
| 43 | |||
| 44 | $this->requireJS('sortable.jquery-ui.js'); |
||
| 45 | |||
| 46 | $applets = $dashboard->ref('applets')->setOrder(['column', 'row']); |
||
| 47 | |||
| 48 | $columns = $this->add(['Columns', 'id' => 'dashboard', 'ui' => 'three stackable grid' . ($this->isLocked()? ' locked': '')]); |
||
| 49 | |||
| 50 | foreach ([1, 2, 3] as $columnId) { |
||
| 51 | $columnApplets = clone $applets; |
||
| 52 | |||
| 53 | /** @scrutinizer ignore-call */ |
||
| 54 | $col = $columns->addColumn([ |
||
| 55 | '', |
||
| 56 | 'ui' => 'sortable', |
||
| 57 | 'attr' => [ |
||
| 58 | 'dashboard-id' => $dashboard->id, |
||
| 59 | 'column-id' => $columnId |
||
| 60 | ] |
||
| 61 | ]); |
||
| 62 | |||
| 63 | foreach ($columnApplets->addCondition('column', $columnId) as $applet) { |
||
| 64 | $col->add([ |
||
| 65 | new Applet(), |
||
| 66 | 'appletId' => $applet['id'], |
||
| 67 | 'jointClass' => $applet['class'], |
||
| 68 | 'options' => $applet['options'], |
||
| 69 | 'locked' => $this->isLocked() |
||
| 70 | ]); |
||
| 71 | } |
||
| 72 | } |
||
| 73 | |||
| 74 | if (! $this->isLocked()) { |
||
| 75 | $columns->js(true)->find('.sortable')->sortable([ |
||
| 76 | 'cursor' => 'move', |
||
| 77 | 'handle' => '.panel-sortable-handle', |
||
| 78 | 'connectWith' => '.sortable', |
||
| 79 | 'items' => '.applet', |
||
| 80 | ]); |
||
| 81 | |||
| 82 | $columns->js(true)->find('.column.sortable')->on('sortupdate', new jsFunction([ |
||
| 83 | $columns->add('jsCallback')->set([$this, 'saveColumn'], [ |
||
| 84 | new jsExpression(' |
||
| 85 | { |
||
| 86 | column: $(this).attr("column-id"), |
||
| 87 | applets: $(this).sortable( "toArray", { attribute: "applet-id" }) |
||
| 88 | }') |
||
| 89 | ]) |
||
| 90 | ])); |
||
| 91 | |||
| 92 | $columns->js(true)->find('.applet-close')->click(new jsFunction(['e'], [new jsExpression('if (confirm("' . __('Delete this applet?') . '")) {$(e.target).closest(".applet").fadeOut(400, function(){var col = $(this).closest(".column.sortable");this.remove();col.trigger("sortupdate");})}')])); |
||
| 93 | } |
||
| 94 | |||
| 95 | $this->columns = $columns; |
||
| 96 | |||
| 97 | $this->requireCSS(); |
||
| 98 | } |
||
| 99 | |||
| 100 | public function editDashboard() |
||
| 101 | { |
||
| 102 | $dashboard = $this->dashboard(); |
||
| 103 | |||
| 104 | $this->location([$dashboard['name'], __('Find Applets')]); |
||
| 105 | |||
| 106 | $this->showDashboard(); |
||
| 107 | |||
| 108 | ActionBar::addItemButton('back'); |
||
| 109 | |||
| 110 | $adminColumn = $this->columns->addColumn(); |
||
| 111 | |||
| 112 | $search = $adminColumn->add(new Input([ |
||
| 113 | 'placeholder' => __('Search applets'), |
||
| 114 | 'icon' => 'search' |
||
| 115 | ]))->setStyle(['width' => '100%']); |
||
| 116 | |||
| 117 | $search->js(true)->on('keyup', new jsFunction(['e'], [ |
||
| 118 | new jsExpression(' |
||
| 119 | var str = $(e.target).val().toLowerCase(); |
||
| 120 | |||
| 121 | $("#dashboard_applets_new").children(".applet").each(function(i, nodeObj) { |
||
| 122 | var node = $(nodeObj); |
||
| 123 | |||
| 124 | node.toggle(node.attr("searchkey").indexOf(str) != -1); |
||
| 125 | }); |
||
| 126 | ') |
||
| 127 | ])); |
||
| 128 | |||
| 129 | $col = $adminColumn->add([ |
||
| 130 | 'View', |
||
| 131 | 'id' => 'dashboard_applets_new', |
||
| 132 | 'ui' => 'admin sortable', |
||
| 133 | 'attr' => [ |
||
| 134 | 'dashboard-id' => $dashboard->id, |
||
| 135 | 'column-id' => 'admin' |
||
| 136 | ] |
||
| 137 | ]); |
||
| 138 | |||
| 139 | foreach ( AppletJoint::collect() as $applet ) { |
||
| 140 | $col->add([ |
||
| 141 | new Applet(), |
||
| 142 | 'appletId' => 'new_' . str_ireplace('\\', '-', get_class($applet)), |
||
| 143 | 'jointClass' => $applet, |
||
| 144 | 'admin' => 1, |
||
| 145 | ]); |
||
| 146 | } |
||
| 147 | } |
||
| 148 | |||
| 149 | public function addMenu() |
||
| 196 | ]); |
||
| 197 | } |
||
| 198 | |||
| 199 | public function addDashboard($view) |
||
| 235 | ]; |
||
| 236 | }); |
||
| 237 | } |
||
| 238 | |||
| 239 | public function renameDashboard($view) |
||
| 253 | ]; |
||
| 254 | }); |
||
| 255 | } |
||
| 256 | |||
| 257 | public function deleteDashboard($jsCallback, $dashboardId) |
||
| 267 | } |
||
| 268 | |||
| 269 | public function reorderDashboards($view) |
||
| 270 | { |
||
| 271 | $grid = $view->add(['Grid', 'paginator' => false, 'menu' => false]); |
||
| 272 | |||
| 273 | $grid->setModel($this->userDashboards()->setOrder('position')); |
||
| 274 | |||
| 275 | $grid->addDragHandler()->onReorder(function ($order) use ($grid) { |
||
| 276 | foreach ($this->userDashboards() as $dashboard) { |
||
| 277 | $dashboard->save(['position' => array_search($dashboard->id, $order)]); |
||
| 278 | } |
||
| 279 | |||
| 280 | return [ |
||
| 281 | new jsReload($grid), |
||
| 282 | $this->notifySuccess(__('Dashboards reordered!')) |
||
| 283 | ]; |
||
| 284 | }); |
||
| 285 | |||
| 286 | $view->add(['View', 'ui' => 'buttons'])->add(['Button', __('Done'), 'primary'])->on('click', new jsExpression('location.reload()')); |
||
| 287 | } |
||
| 288 | |||
| 289 | public function saveColumn($jsCallback, $columnHash) |
||
| 290 | { |
||
| 291 | $applets = $columnHash['applets']?? []; |
||
| 292 | |||
| 293 | if ($new = preg_grep('/^new_/', $applets)) { |
||
| 294 | $new = reset($new); |
||
| 295 | |||
| 296 | $row = array_search($new, $applets); |
||
| 297 | |||
| 298 | $applets[$row] = $this->dashboard()->ref('applets')->insert([ |
||
| 299 | 'class' => str_ireplace('-', '\\', preg_replace('/^new_/', '', $new)), |
||
| 300 | 'column' => $columnHash['column'], |
||
| 301 | 'row' => $row |
||
| 302 | ]); |
||
| 303 | } |
||
| 304 | |||
| 305 | foreach ($this->dashboard()->ref('applets')->withID($applets) as $applet) { |
||
| 306 | $applet->save([ |
||
| 307 | 'column' => $columnHash['column'], |
||
| 308 | 'row' => array_search($applet->id, $applets) |
||
| 309 | ]); |
||
| 310 | } |
||
| 311 | |||
| 312 | $removed = $this->dashboard()->ref('applets')->addCondition('column', $columnHash['column']); |
||
| 313 | |||
| 314 | if ($applets) { |
||
| 315 | $removed->addCondition('id', 'not', $applets); |
||
| 316 | } |
||
| 317 | |||
| 318 | $this->dashboard()->ref('applets')->addCondition('column', 0)->action('delete')->execute(); |
||
| 319 | |||
| 320 | $removed->action('update')->set('column', 0)->execute(); |
||
| 321 | } |
||
| 322 | |||
| 323 | public function showSettings($appletId) |
||
| 324 | { |
||
| 325 | $applet = $this->dashboard()->ref('applets')->load($appletId); |
||
| 326 | |||
| 327 | $joint = new $applet['class'](); |
||
| 328 | |||
| 329 | $this->location([__('Edit Applet Settings'), $joint->caption()]); |
||
| 330 | |||
| 331 | $form = $this->add(new Form()); |
||
| 332 | $form->addElements($joint->elements()); |
||
| 333 | $form->confirmLeave(); |
||
| 334 | |||
| 335 | $form->model->set($applet['options']); |
||
| 336 | |||
| 337 | $form->validate(function(Form $form) use ($applet) { |
||
| 338 | $applet->save(['options' => $form->model->get()]); |
||
| 339 | |||
| 340 | return $form->notifySuccess(__('Settings saved!')); |
||
| 341 | }); |
||
| 342 | |||
| 343 | ActionBar::addItemButton('back'); |
||
| 344 | |||
| 345 | ActionBar::addItemButton('save')->on('click', $form->submit()); |
||
| 346 | } |
||
| 347 | |||
| 348 | public function lock() |
||
| 349 | { |
||
| 350 | $this->locked = true; |
||
| 351 | |||
| 352 | return $this; |
||
| 353 | } |
||
| 354 | |||
| 355 | public function isLocked() |
||
| 356 | { |
||
| 357 | return $this->locked || ! Auth::user()->can('edit dashboard'); |
||
| 358 | } |
||
| 359 | |||
| 360 | protected function isSingleDashboard() |
||
| 361 | { |
||
| 362 | return $this->userDashboards()->action('count')->getOne() <= 1; |
||
| 363 | } |
||
| 364 | |||
| 365 | /** |
||
| 366 | * @return Dashboard |
||
| 367 | * |
||
| 368 | * @throws \Symfony\Component\HttpKernel\Exception\HttpException |
||
| 369 | * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException |
||
| 370 | */ |
||
| 371 | protected function dashboard() |
||
| 372 | { |
||
| 373 | if (! is_object($this->dashboard)) { |
||
| 374 | $this->dashboard = $this->dashboard? Dashboard::create()->tryLoad($this->dashboard): $this->defaultUserDashboard(); |
||
| 375 | } |
||
| 376 | |||
| 377 | return $this->dashboard?: abort(404); |
||
| 378 | } |
||
| 379 | |||
| 380 | protected function defaultUserDashboard() |
||
| 381 | { |
||
| 382 | $userDashboard = $this->userDashboards()->setOrder('position')->tryLoadAny(); |
||
| 383 | |||
| 384 | if (! $userDashboard->loaded()) { |
||
| 385 | $this->lock(); |
||
| 386 | |||
| 387 | $userDashboard = $this->defaultSystemDashboard(); |
||
| 388 | } |
||
| 389 | |||
| 390 | return $userDashboard; |
||
| 391 | } |
||
| 392 | |||
| 393 | protected function defaultSystemDashboard() |
||
| 396 | } |
||
| 397 | |||
| 398 | protected function userDashboards($userId = null) |
||
| 399 | { |
||
| 400 | return Dashboard::create()->addCondition('user_id', $userId ?? $this->userId()); |
||
| 401 | } |
||
| 402 | |||
| 403 | /** |
||
| 404 | * @return number |
||
| 405 | */ |
||
| 406 | protected function userId() |
||
| 409 | } |
||
| 410 | } |
||
| 411 |
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:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths