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:
1 | <?php |
||
45 | class ServerController extends CrudController |
||
46 | { |
||
47 | public function behaviors() |
||
48 | { |
||
49 | return array_merge(parent::behaviors(), [ |
||
50 | 'server-actions-verb' => [ |
||
51 | 'class' => VerbFilter::class, |
||
52 | 'actions' => [ |
||
53 | 'reboot' => ['post'], |
||
54 | 'reset' => ['post'], |
||
55 | 'shutdown' => ['post'], |
||
56 | 'power-off' => ['post'], |
||
57 | 'power-on' => ['post'], |
||
58 | 'reset-password' => ['post'], |
||
59 | 'enable-block' => ['post'], |
||
60 | 'disable-block' => ['post'], |
||
61 | 'refuse' => ['post'], |
||
62 | ] |
||
63 | ] |
||
64 | ]); |
||
65 | } |
||
66 | |||
67 | 1 | public function actions() |
|
68 | { |
||
69 | return [ |
||
70 | 'index' => [ |
||
71 | 1 | 'class' => IndexAction::class, |
|
72 | 1 | 'findOptions' => ['with_requests' => true, 'with_discounts' => true], |
|
73 | View Code Duplication | 'on beforePerform' => function (Event $event) { |
|
|
|||
74 | /** @var \hipanel\actions\SearchAction $action */ |
||
75 | $action = $event->sender; |
||
76 | $dataProvider = $action->getDataProvider(); |
||
77 | $dataProvider->query->joinWith('ips'); |
||
78 | |||
79 | $dataProvider->query |
||
80 | ->andWhere(['with_ips' => 1]) |
||
81 | ->andWhere(['with_tariffs' => 1]) |
||
82 | ->andWhere(['with_switches' => 1]) |
||
83 | ->andWhere(['with_requests' => 1]) |
||
84 | ->andWhere(['with_discounts' => 1]) |
||
85 | ->select(['*']); |
||
86 | 1 | }, |
|
87 | 'filterStorageMap' => [ |
||
88 | 1 | 'name_like' => 'server.server.name', |
|
89 | 1 | 'ips' => 'hosting.ip.ip_in', |
|
90 | 1 | 'state' => 'server.server.state', |
|
91 | 1 | 'client_id' => 'client.client.id', |
|
92 | 1 | 'seller_id' => 'client.client.seller_id', |
|
93 | 1 | ], |
|
94 | 1 | ], |
|
95 | 'search' => [ |
||
96 | 1 | 'class' => ComboSearchAction::class, |
|
97 | 1 | ], |
|
98 | 'view' => [ |
||
99 | 1 | 'class' => ViewAction::class, |
|
100 | View Code Duplication | 'on beforePerform' => function (Event $event) { |
|
101 | /** @var \hipanel\actions\SearchAction $action */ |
||
102 | $action = $event->sender; |
||
103 | $dataProvider = $action->getDataProvider(); |
||
104 | $dataProvider->query->joinWith('uses'); |
||
105 | $dataProvider->query->joinWith('ips'); |
||
106 | |||
107 | // TODO: ipModule is not wise yet. Redo |
||
108 | $dataProvider->query |
||
109 | ->andWhere(['with_requests' => 1]) |
||
110 | ->andWhere(['show_deleted' => 1]) |
||
111 | ->andWhere(['with_discounts' => 1]) |
||
112 | ->andWhere(['with_uses' => 1]) |
||
113 | ->andWhere(['with_ips' => 1]) |
||
114 | ->select(['*']); |
||
115 | 1 | }, |
|
116 | 'data' => function ($action) { |
||
117 | /** |
||
118 | * @var Action $action |
||
119 | * @var self $controller |
||
120 | * @var Server $model |
||
121 | */ |
||
122 | $controller = $action->controller; |
||
123 | $model = $action->getModel(); |
||
124 | $model->vnc = $controller->getVNCInfo($model); |
||
125 | |||
126 | $panels = $controller->getPanelTypes(); |
||
127 | |||
128 | $cacheKeys = [__METHOD__, 'view', 'tariff', $model->tariff_id, Yii::$app->user->getId()]; |
||
129 | $tariff = Yii::$app->cache->getOrSet($cacheKeys, function () use ($model) { |
||
130 | return Tariff::find()->where([ |
||
131 | 'id' => $model->tariff_id, |
||
132 | 'show_final' => true, |
||
133 | 'show_deleted' => true, |
||
134 | 'with_resources' => true, |
||
135 | ])->joinWith('resources')->one(); |
||
136 | }); |
||
137 | |||
138 | $ispSupported = false; |
||
139 | if ($tariff !== null) { |
||
140 | foreach ($tariff->getResources() as $resource) { |
||
141 | if ($resource->type === 'isp' && $resource->quantity > 0) { |
||
142 | $ispSupported = true; |
||
143 | } |
||
144 | } |
||
145 | } |
||
146 | |||
147 | $osimages = $controller->getOsimages($model); |
||
148 | $groupedOsimages = ServerHelper::groupOsimages($osimages, $ispSupported); |
||
149 | |||
150 | if ($model->isLiveCDSupported()) { |
||
151 | $osimageslivecd = $controller->getOsimagesLiveCd(); |
||
152 | } |
||
153 | |||
154 | $blockReasons = $controller->getBlockReasons(); |
||
155 | |||
156 | return compact([ |
||
157 | 'model', |
||
158 | 'osimages', |
||
159 | 'osimageslivecd', |
||
160 | 'groupedOsimages', |
||
161 | 'panels', |
||
162 | 'blockReasons', |
||
163 | ]); |
||
164 | 1 | }, |
|
165 | 1 | ], |
|
166 | 'requests-state' => [ |
||
167 | 1 | 'class' => RequestStateAction::class, |
|
168 | 1 | 'model' => Server::class, |
|
169 | 1 | ], |
|
170 | 'set-note' => [ |
||
171 | 1 | 'class' => SmartUpdateAction::class, |
|
172 | 1 | 'success' => Yii::t('hipanel:server', 'Note changed'), |
|
173 | 1 | 'error' => Yii::t('hipanel:server', 'Failed to change note'), |
|
174 | 1 | ], |
|
175 | 'set-label' => [ |
||
176 | 1 | 'class' => SmartUpdateAction::class, |
|
177 | 1 | 'success' => Yii::t('hipanel:server', 'Internal note changed'), |
|
178 | 1 | 'error' => Yii::t('hipanel:server', 'Failed to change internal note'), |
|
179 | 1 | ], |
|
180 | 'set-lock' => [ |
||
181 | 1 | 'class' => RenderAction::class, |
|
182 | 1 | 'success' => Yii::t('hipanel:server', 'Record was changed'), |
|
183 | 1 | 'error' => Yii::t('hipanel:server', 'Error occurred'), |
|
184 | 'POST pjax' => [ |
||
185 | 1 | 'save' => true, |
|
186 | 'success' => [ |
||
187 | 1 | 'class' => ProxyAction::class, |
|
188 | 1 | 'action' => 'index', |
|
189 | 1 | ], |
|
190 | 1 | ], |
|
191 | 'POST' => [ |
||
192 | 1 | 'save' => true, |
|
193 | 'success' => [ |
||
194 | 1 | 'class' => RenderJsonAction::class, |
|
195 | 'return' => function ($action) { |
||
196 | /** @var \hipanel\actions\Action $action */ |
||
197 | return $action->collection->models; |
||
198 | 1 | }, |
|
199 | 1 | ], |
|
200 | 1 | ], |
|
201 | 1 | ], |
|
202 | 'sale' => [ |
||
203 | 1 | 'class' => SmartUpdateAction::class, |
|
204 | 1 | 'view' => '_saleModal', |
|
205 | 'POST' => [ |
||
206 | 1 | 'save' => true, |
|
207 | 'success' => [ |
||
208 | 1 | 'class' => RenderJsonAction::class, |
|
209 | 'return' => function ($action) { |
||
210 | return ['success' => !$action->collection->hasErrors()]; |
||
211 | 1 | }, |
|
212 | 1 | ], |
|
213 | 1 | ], |
|
214 | 1 | ], |
|
215 | 'enable-vnc' => [ |
||
216 | 1 | 'class' => ViewAction::class, |
|
217 | 1 | 'view' => '_vnc', |
|
218 | 'data' => function ($action) { |
||
219 | $model = $action->getModel(); |
||
220 | if ($model->canEnableVNC()) { |
||
221 | $model->vnc = $this->getVNCInfo($model, true); |
||
222 | } |
||
223 | |||
224 | return []; |
||
225 | 1 | }, |
|
226 | 1 | ], |
|
227 | 'reboot' => [ |
||
228 | 1 | 'class' => SmartPerformAction::class, |
|
229 | 1 | 'success' => Yii::t('hipanel:server', 'Reboot task has been successfully added to queue'), |
|
230 | 1 | 'error' => Yii::t('hipanel:server', 'Error during the rebooting'), |
|
231 | 1 | ], |
|
232 | 'reset' => [ |
||
233 | 1 | 'class' => SmartPerformAction::class, |
|
234 | 1 | 'success' => Yii::t('hipanel:server', 'Reset task has been successfully added to queue'), |
|
235 | 1 | 'error' => Yii::t('hipanel:server', 'Error during the resetting'), |
|
236 | 1 | ], |
|
237 | 'shutdown' => [ |
||
238 | 1 | 'class' => SmartPerformAction::class, |
|
239 | 1 | 'success' => Yii::t('hipanel:server', 'Shutdown task has been successfully added to queue'), |
|
240 | 1 | 'error' => Yii::t('hipanel:server', 'Error during the shutting down'), |
|
241 | 1 | ], |
|
242 | 'power-off' => [ |
||
243 | 1 | 'class' => SmartPerformAction::class, |
|
244 | 1 | 'success' => Yii::t('hipanel:server', 'Power off task has been successfully added to queue'), |
|
245 | 1 | 'error' => Yii::t('hipanel:server', 'Error during the turning power off'), |
|
246 | 1 | ], |
|
247 | 'power-on' => [ |
||
248 | 1 | 'class' => SmartPerformAction::class, |
|
249 | 1 | 'success' => Yii::t('hipanel:server', 'Power on task has been successfully added to queue'), |
|
250 | 1 | 'error' => Yii::t('hipanel:server', 'Error during the turning power on'), |
|
251 | 1 | ], |
|
252 | 'reset-password' => [ |
||
253 | 1 | 'class' => SmartPerformAction::class, |
|
254 | 1 | 'success' => Yii::t('hipanel:server', 'Root password reset task has been successfully added to queue'), |
|
255 | 1 | 'error' => Yii::t('hipanel:server', 'Error during the resetting root password'), |
|
256 | 1 | ], |
|
257 | 'enable-block' => [ |
||
258 | 1 | 'class' => SmartPerformAction::class, |
|
259 | 1 | 'success' => Yii::t('hipanel:server', 'Server was blocked successfully'), |
|
260 | 1 | 'error' => Yii::t('hipanel:server', 'Error during the server blocking'), |
|
261 | 1 | ], |
|
262 | 'disable-block' => [ |
||
263 | 1 | 'class' => SmartPerformAction::class, |
|
264 | 1 | 'success' => Yii::t('hipanel:server', 'Server was unblocked successfully'), |
|
265 | 1 | 'error' => Yii::t('hipanel:server', 'Error during the server unblocking'), |
|
266 | 1 | ], |
|
267 | 'refuse' => [ |
||
268 | 1 | 'class' => SmartPerformAction::class, |
|
269 | 1 | 'success' => Yii::t('hipanel:server', 'You have refused the service'), |
|
270 | 1 | 'error' => Yii::t('hipanel:server', 'Error during the refusing the service'), |
|
271 | 1 | ], |
|
272 | 'enable-autorenewal' => [ |
||
273 | 1 | 'class' => SmartUpdateAction::class, |
|
274 | 1 | 'success' => Yii::t('hipanel:server', 'Server renewal enabled successfully'), |
|
275 | 1 | 'error' => Yii::t('hipanel:server', 'Error during the renewing the service'), |
|
276 | 1 | ], |
|
277 | 'reinstall' => [ |
||
278 | 1 | 'class' => SmartUpdateAction::class, |
|
279 | 'on beforeSave' => function (Event $event) { |
||
280 | /** @var Action $action */ |
||
281 | $action = $event->sender; |
||
282 | foreach ($action->collection->models as $model) { |
||
283 | $model->osimage = Yii::$app->request->post('osimage'); |
||
284 | $model->panel = Yii::$app->request->post('panel'); |
||
285 | } |
||
286 | 1 | }, |
|
287 | 1 | 'success' => Yii::t('hipanel:server', 'Server reinstalling task has been successfully added to queue'), |
|
288 | 1 | 'error' => Yii::t('hipanel:server', 'Error during the server reinstalling'), |
|
289 | 1 | ], |
|
290 | 'boot-live' => [ |
||
291 | 1 | 'class' => SmartUpdateAction::class, |
|
292 | 'on beforeSave' => function (Event $event) { |
||
293 | /** @var Action $action */ |
||
294 | $action = $event->sender; |
||
295 | foreach ($action->collection->models as $model) { |
||
296 | $model->osimage = Yii::$app->request->post('osimage'); |
||
297 | } |
||
298 | 1 | }, |
|
299 | 1 | 'success' => Yii::t('hipanel:server', 'Live CD booting task has been successfully added to queue'), |
|
300 | 1 | 'error' => Yii::t('hipanel:server', 'Error during the booting live CD'), |
|
301 | 1 | ], |
|
302 | 'validate-form' => [ |
||
303 | 1 | 'class' => ValidateFormAction::class, |
|
304 | 1 | ], |
|
305 | 'buy' => [ |
||
306 | 1 | 'class' => RedirectAction::class, |
|
307 | 1 | 'url' => Yii::$app->params['orgUrl'], |
|
308 | 1 | ], |
|
309 | 'add-to-cart-renewal' => [ |
||
310 | 1 | 'class' => AddToCartAction::class, |
|
311 | 1 | 'productClass' => ServerRenewProduct::class, |
|
312 | 1 | ], |
|
313 | 'delete' => [ |
||
314 | 1 | 'class' => SmartDeleteAction::class, |
|
315 | 1 | 'success' => Yii::t('hipanel:server', 'Server was deleted successfully'), |
|
316 | 1 | 'error' => Yii::t('hipanel:server', 'Failed to delete server'), |
|
317 | 1 | ], |
|
318 | 'bulk-delete-modal' => [ |
||
319 | 1 | 'class' => PrepareBulkAction::class, |
|
320 | 1 | 'scenario' => 'delete', |
|
321 | 1 | 'view' => '_bulkDelete', |
|
322 | 1 | ], |
|
323 | 'bulk-enable-block' => [ |
||
324 | 1 | 'class' => SmartUpdateAction::class, |
|
325 | 1 | 'scenario' => 'enable-block', |
|
326 | 1 | 'success' => Yii::t('hipanel:server', 'Servers were blocked successfully'), |
|
327 | 1 | 'error' => Yii::t('hipanel:server', 'Error during the servers blocking'), |
|
328 | 'POST html' => [ |
||
329 | 1 | 'save' => true, |
|
330 | 'success' => [ |
||
331 | 1 | 'class' => RedirectAction::class, |
|
332 | 1 | ], |
|
333 | 1 | ], |
|
334 | 'on beforeSave' => function (Event $event) { |
||
335 | /** @var \hipanel\actions\Action $action */ |
||
336 | $action = $event->sender; |
||
337 | $type = Yii::$app->request->post('type'); |
||
338 | $comment = Yii::$app->request->post('comment'); |
||
339 | if (!empty($type)) { |
||
340 | foreach ($action->collection->models as $model) { |
||
341 | $model->setAttributes([ |
||
342 | 'type' => $type, |
||
343 | 'comment' => $comment, |
||
344 | ]); |
||
345 | } |
||
346 | } |
||
347 | 1 | }, |
|
348 | 1 | ], |
|
349 | 'bulk-enable-block-modal' => [ |
||
350 | 1 | 'class' => PrepareBulkAction::class, |
|
351 | 1 | 'scenario' => 'enable-block', |
|
352 | 1 | 'view' => '_bulkEnableBlock', |
|
353 | 'data' => function ($action, $data) { |
||
354 | return array_merge($data, [ |
||
355 | 'blockReasons' => $this->getBlockReasons(), |
||
356 | ]); |
||
357 | 1 | }, |
|
358 | 1 | ], |
|
359 | 'bulk-disable-block' => [ |
||
360 | 1 | 'class' => SmartUpdateAction::class, |
|
361 | 1 | 'scenario' => 'disable-block', |
|
362 | 1 | 'success' => Yii::t('hipanel:server', 'Servers were unblocked successfully'), |
|
363 | 1 | 'error' => Yii::t('hipanel:server', 'Error during the servers unblocking'), |
|
364 | 'POST html' => [ |
||
365 | 1 | 'save' => true, |
|
366 | 'success' => [ |
||
367 | 1 | 'class' => RedirectAction::class, |
|
368 | 1 | ], |
|
369 | 1 | ], |
|
370 | 'on beforeSave' => function (Event $event) { |
||
371 | /** @var \hipanel\actions\Action $action */ |
||
372 | $action = $event->sender; |
||
373 | $comment = Yii::$app->request->post('comment'); |
||
374 | if (!empty($type)) { |
||
375 | foreach ($action->collection->models as $model) { |
||
376 | $model->setAttribute('comment', $comment); |
||
377 | } |
||
378 | } |
||
379 | 1 | }, |
|
380 | 1 | ], |
|
381 | 'bulk-disable-block-modal' => [ |
||
382 | 1 | 'class' => PrepareBulkAction::class, |
|
383 | 1 | 'scenario' => 'disable-block', |
|
384 | 1 | 'view' => '_bulkDisableBlock', |
|
385 | 1 | ], |
|
386 | 'set-orientation' => [ |
||
387 | 1 | 'class' => OrientationAction::class, |
|
388 | 'allowedRoutes' => [ |
||
389 | '@server/index' |
||
390 | 1 | ] |
|
391 | 1 | ] |
|
392 | |||
393 | 1 | ]; |
|
394 | } |
||
395 | |||
396 | /** |
||
397 | * Gets info of VNC on the server. |
||
398 | * |
||
399 | * @param Server $model |
||
400 | * @param bool $enable |
||
401 | * @return array |
||
402 | * @throws ResponseErrorException |
||
403 | */ |
||
404 | public function getVNCInfo($model, $enable = false) |
||
405 | { |
||
406 | $vnc = ['endTime' => strtotime('+8 hours', strtotime($model->statuses['serverEnableVNC']))]; |
||
407 | if ($model->canEnableVnc() && $vnc['endTime'] > time() || $enable) { |
||
408 | try { |
||
409 | $vnc = ArrayHelper::merge($vnc, Server::perform('enable-VNC', ['id' => $model->id])); |
||
410 | $vnc['enabled'] = true; |
||
411 | } catch (ResponseErrorException $e) { |
||
412 | if ($e->getMessage() !== 'vds_has_tasks') { // expected error, that could be skipped |
||
413 | throw $e; |
||
414 | } |
||
415 | $vnc['enabled'] = false; |
||
416 | } |
||
417 | } |
||
418 | |||
419 | return $vnc; |
||
420 | } |
||
421 | |||
422 | public function actionDrawChart() |
||
423 | { |
||
424 | $post = Yii::$app->request->post(); |
||
425 | if (!in_array($post['type'], ['traffic', 'bandwidth'], true)) { |
||
426 | throw new NotFoundHttpException(); |
||
427 | } |
||
428 | |||
429 | $searchModel = new ServerUseSearch(); |
||
430 | $dataProvider = $searchModel->search([]); |
||
431 | $dataProvider->pagination = false; |
||
432 | $dataProvider->query->action('get-uses'); |
||
433 | $dataProvider->query->andWhere($post); |
||
434 | $models = $dataProvider->getModels(); |
||
435 | |||
436 | list($labels, $data) = ServerHelper::groupUsesForChart($models); |
||
437 | |||
438 | return $this->renderAjax('_' . $post['type'] . '_consumption', [ |
||
439 | 'labels' => $labels, |
||
440 | 'data' => $data, |
||
441 | ]); |
||
442 | } |
||
443 | |||
444 | /** |
||
445 | * Gets OS images. |
||
446 | * |
||
447 | * @param Server $model |
||
448 | * @throws NotFoundHttpException |
||
449 | * @return array |
||
450 | */ |
||
451 | protected function getOsimages(Server $model = null) |
||
452 | { |
||
453 | if ($model !== null) { |
||
454 | $type = $model->type; |
||
455 | } else { |
||
456 | $type = null; |
||
457 | } |
||
458 | |||
459 | $models = ServerHelper::getOsimages($type); |
||
460 | |||
461 | if ($models === null) { |
||
462 | throw new NotFoundHttpException('The requested page does not exist.'); |
||
463 | } |
||
464 | |||
465 | return $models; |
||
466 | } |
||
467 | |||
468 | protected function getOsimagesLiveCd() |
||
469 | { |
||
470 | $models = Yii::$app->cache->getOrSet([__METHOD__], function () { |
||
471 | return Osimage::findAll(['livecd' => true]); |
||
472 | }, 3600); |
||
473 | |||
474 | if ($models !== null) { |
||
475 | return $models; |
||
476 | } |
||
477 | |||
478 | throw new NotFoundHttpException('The requested page does not exist.'); |
||
479 | } |
||
480 | |||
481 | protected function getPanelTypes() |
||
485 | |||
486 | public function actionIsOperable($id) |
||
487 | { |
||
488 | Yii::$app->response->format = Response::FORMAT_JSON; |
||
489 | |||
490 | $result = ['id' => $id, 'result' => false]; |
||
491 | |||
498 | } |
||
499 |
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.