Completed
Push — master ( 390e01...ea6653 )
by Andrii
15:42
created

ServerController::getStates()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 7
Bugs 1 Features 0
Metric Value
c 7
b 1
f 0
dl 0
loc 5
rs 9.4285
ccs 0
cts 0
cp 0
cc 1
eloc 3
nc 1
nop 0
crap 2
1
<?php
2
3
/*
4
 * Server module for HiPanel
5
 *
6
 * @link      https://github.com/hiqdev/hipanel-module-server
7
 * @package   hipanel-module-server
8
 * @license   BSD-3-Clause
9
 * @copyright Copyright (c) 2015-2016, HiQDev (http://hiqdev.com/)
10
 */
11
12
namespace hipanel\modules\server\controllers;
13
14
use hipanel\actions\Action;
15
use hipanel\actions\IndexAction;
16
use hipanel\actions\OrientationAction;
17
use hipanel\actions\PrepareBulkAction;
18
use hipanel\actions\ProxyAction;
19
use hipanel\actions\RedirectAction;
20
use hipanel\actions\RenderAction;
21
use hipanel\actions\RenderJsonAction;
22
use hipanel\actions\RequestStateAction;
23
use hipanel\actions\SearchAction;
24
use hipanel\actions\SmartDeleteAction;
25
use hipanel\actions\SmartUpdateAction;
26
use hipanel\actions\ValidateFormAction;
27
use hipanel\actions\ViewAction;
28
use hipanel\base\CrudController;
29
use hipanel\models\Ref;
30
use hipanel\modules\finance\models\Tariff;
31
use hipanel\modules\server\cart\ServerRenewProduct;
32
use hipanel\modules\server\helpers\ServerHelper;
33
use hipanel\modules\server\models\Osimage;
34
use hipanel\modules\server\models\Server;
35
use hipanel\modules\server\models\ServerUseSearch;
36
use hiqdev\yii2\cart\actions\AddToCartAction;
37
use Yii;
38
use yii\base\Event;
39
use yii\helpers\ArrayHelper;
40
use yii\web\NotFoundHttpException;
41
42
class ServerController extends CrudController
43 1
{
44
    public function actions()
45
    {
46
        return [
47 1
            'index' => [
48 1
                'class' => IndexAction::class,
49
                'findOptions' => ['with_requests' => true, 'with_discounts' => true],
50
                'on beforePerform' => function (Event $event) {
51
                    /** @var \hipanel\actions\SearchAction $action */
52
                    $action = $event->sender;
53
                    $dataProvider = $action->getDataProvider();
54
                    $dataProvider->query->joinWith('ips');
55
56
                    $dataProvider->query
57
                        ->andWhere(['with_requests' => 1])
58
                        ->andWhere(['with_discounts' => 1])
59
                        ->andWhere(['with_ips' => 1])
60 1
                        ->select(['*']);
61
                },
62
                'data' => function ($action) {
0 ignored issues
show
Unused Code introduced by
The parameter $action is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
63
                    return [
64
                        'types'  => Ref::getList('type,device,server'),
65 1
                        'states' => Ref::getList('state,device'),
66
                    ];
67 1
                },
68 1
                'filterStorageMap' => [
69 1
                    'name_like' => 'server.server.name',
70 1
                    'ips' => 'hosting.ip.ip_in',
71 1
                    'state' => 'server.server.state',
72 1
                    'client_id' => 'client.client.id',
73 1
                    'seller_id' => 'client.client.seller_id',
74
                ],
75 1
            ],
76 1
            'search' => [
77
                'class' => SearchAction::class,
78 1
            ],
79
            'view' => [
80
                'class' => ViewAction::class,
81
                'on beforePerform' => function (Event $event) {
82
                    /** @var \hipanel\actions\SearchAction $action */
83
                    $action = $event->sender;
84
                    $dataProvider = $action->getDataProvider();
85
                    $dataProvider->query->joinWith('uses');
86
                    $dataProvider->query->joinWith('ips');
87
88
                    // TODO: ipModule is not wise yet. Redo
89
                    $dataProvider->query
90
                        ->andWhere(['with_requests' => 1])
91
                        ->andWhere(['show_deleted' => 1])
92
                        ->andWhere(['with_discounts' => 1])
93
                        ->andWhere(['with_uses' => 1])
94 1
                        ->andWhere(['with_ips' => 1])
95
                        ->select(['*']);
96
                },
97
                'data' => function ($action) {
98
                    /**
99
                     * @var
100
                     * @var $model Server
101
                     */
102
                    $controller = $action->controller;
103
                    $model = $action->getModel();
104
                    $model->vnc = $controller->getVNCInfo($model);
105
106
                    $panels = $controller->getPanelTypes();
107
108
                    $tariff = Yii::$app->cache->getAuthTimeCached(3600, [$model->tariff_id], function ($tariff_id) {
109
                        return Tariff::find()->where([
110
                            'id' => $tariff_id,
111
                            'show_final' => true,
112
                            'show_deleted' => true,
113
                            'with_resources' => true,
114
                        ])->joinWith('resources')->one();
115
                    });
116
117
                    $ispSupported = false;
118
                    if ($tariff !== null) {
119
                        foreach ($tariff->getResources() as $resource) {
120
                            if ($resource->type === 'isp' && $resource->quantity > 0) {
121
                                $ispSupported = true;
122
                            }
123
                        }
124
                    }
125
126
                    $osimages = $controller->getOsimages($model);
127
                    $groupedOsimages = ServerHelper::groupOsimages($osimages, $ispSupported);
128
129
                    if ($model->isLiveCDSupported()) {
130
                        $osimageslivecd = $controller->getOsimagesLiveCd();
131
                    }
132
133
                    $blockReasons = $controller->getBlockReasons();
134
135
                    return compact([
136
                        'model',
137
                        'osimages',
138
                        'osimageslivecd',
139
                        'groupedOsimages',
140
                        'panels',
141 1
                        'blockReasons',
142 1
                    ]);
143
                },
144 1
            ],
145 1
            'requests-state' => [
146 1
                'class' => RequestStateAction::className(),
147
                'model' => Server::className(),
148 1
            ],
149 1
            'set-note' => [
150 1
                'class' => SmartUpdateAction::class,
151 1
                'success' => Yii::t('hipanel/server', 'Note changed'),
152
                'error' => Yii::t('hipanel/server', 'Failed to change note'),
153 1
            ],
154 1
            'set-label' => [
155 1
                'class' => SmartUpdateAction::class,
156 1
                'success' => Yii::t('hipanel/server', 'Internal note changed'),
157
                'error' => Yii::t('hipanel/server', 'Failed to change internal note'),
158 1
            ],
159 1
            'set-lock' => [
160 1
                'class' => RenderAction::class,
161
                'success' => Yii::t('hipanel/server', 'Record was changed'),
162 1
                'error' => Yii::t('hipanel/server', 'Error occurred'),
163
                'POST pjax' => [
164 1
                    'save' => true,
165 1
                    'success' => [
166 1
                        'class' => ProxyAction::class,
167 1
                        'action' => 'index',
168
                    ],
169 1
                ],
170
                'POST' => [
171 1
                    'save' => true,
172
                    'success' => [
173
                        'class' => RenderJsonAction::class,
174
                        'return' => function ($action) {
175 1
                            /** @var \hipanel\actions\Action $action */
176 1
                            return $action->collection->models;
177 1
                        },
178 1
                    ],
179
                ],
180 1
            ],
181 1
            'sale' => [
182
                'class' => SmartUpdateAction::class,
183
                'view' => '_saleModal',
184
                'POST' => [
185
                    'save' => true,
186
                    'success' => [
187 1
                        'class' => RenderJsonAction::class,
188 1
                        'return' => function ($action) {
189
                            return ['success' => !$action->collection->hasErrors()];
190 1
                        },
191 1
                    ],
192 1
                ],
193 1
            ],
194
            'enable-vnc' => [
195 1
                'class' => ViewAction::class,
196 1
                'view' => '_vnc',
197 1
                'data' => function ($action) {
198 1
                    $model = $action->getModel();
199
                    $model->checkOperable();
200 1
                    $model->vnc = $action->controller->getVNCInfo($model, true);
201 1
                    return [];
202 1
                },
203 1
            ],
204
            'reboot' => [
205 1
                'class' => SmartUpdateAction::class,
206 1
                'success' => Yii::t('hipanel/server', 'Reboot task has been successfully added to queue'),
207 1
                'error' => Yii::t('hipanel/server', 'Error during the rebooting'),
208 1
            ],
209
            'reset' => [
210 1
                'class' => SmartUpdateAction::class,
211 1
                'success' => Yii::t('hipanel/server', 'Reset task has been successfully added to queue'),
212 1
                'error' => Yii::t('hipanel/server', 'Error during the resetting'),
213 1
            ],
214
            'shutdown' => [
215 1
                'class' => SmartUpdateAction::class,
216 1
                'success' => Yii::t('hipanel/server', 'Shutdown task has been successfully added to queue'),
217 1
                'error' => Yii::t('hipanel/server', 'Error during the shutting down'),
218 1
            ],
219
            'power-off' => [
220 1
                'class' => SmartUpdateAction::class,
221 1
                'success' => Yii::t('hipanel/server', 'Power off task has been successfully added to queue'),
222 1
                'error' => Yii::t('hipanel/server', 'Error during the turning power off'),
223 1
            ],
224
            'power-on' => [
225 1
                'class' => SmartUpdateAction::class,
226 1
                'success' => Yii::t('hipanel/server', 'Power on task has been successfully added to queue'),
227 1
                'error' => Yii::t('hipanel/server', 'Error during the turning power on'),
228 1
            ],
229
            'reset-password' => [
230 1
                'class' => SmartUpdateAction::class,
231 1
                'success' => Yii::t('hipanel/server', 'Root password reset task has been successfully added to queue'),
232 1
                'error' => Yii::t('hipanel/server', 'Error during the resetting root password'),
233 1
            ],
234
            'enable-block' => [
235 1
                'class' => SmartUpdateAction::class,
236 1
                'success' => Yii::t('hipanel/server', 'Server was blocked successfully'),
237 1
                'error' => Yii::t('hipanel/server', 'Error during the server blocking'),
238 1
            ],
239
            'disable-block' => [
240 1
                'class' => SmartUpdateAction::class,
241
                'success' => Yii::t('hipanel/server', 'Server was unblocked successfully'),
242
                'error' => Yii::t('hipanel/server', 'Error during the server unblocking'),
243
            ],
244
            'refuse' => [
245
                'class' => SmartUpdateAction::class,
246
                'success' => Yii::t('hipanel/server', 'You have refused the service'),
247
                'error' => Yii::t('hipanel/server', 'Error during the refusing the service'),
248 1
            ],
249 1
            'enable-autorenewal' => [
250 1
                'class' => SmartUpdateAction::class,
251 1
                'success' => Yii::t('hipanel/server', 'Server renewal enabled successfully'),
252
                'error' => Yii::t('hipanel/server', 'Error during the renewing the service'),
253 1
            ],
254
            'reinstall' => [
255
                'class' => SmartUpdateAction::class,
256
                'on beforeSave' => function (Event $event) {
257
                    /** @var Action $action */
258
                    $action = $event->sender;
259
                    foreach ($action->collection->models as $model) {
260 1
                        $model->osimage = Yii::$app->request->post('osimage');
261 1
                        $model->panel = Yii::$app->request->post('panel');
262 1
                    }
263 1
                },
264
                'success' => Yii::t('hipanel/server', 'Server reinstalling task has been successfully added to queue'),
265 1
                'error' => Yii::t('hipanel/server', 'Error during the server reinstalling'),
266 1
            ],
267
            'boot-live' => [
268 1
                'class' => SmartUpdateAction::class,
269 1
                'on beforeSave' => function (Event $event) {
270 1
                    /** @var Action $action */
271
                    $action = $event->sender;
272 1
                    foreach ($action->collection->models as $model) {
273 1
                        $model->osimage = Yii::$app->request->post('osimage');
274 1
                    }
275
                },
276 1
                'success' => Yii::t('hipanel/server', 'Live CD booting task has been successfully added to queue'),
277 1
                'error' => Yii::t('hipanel/server', 'Error during the booting live CD'),
278 1
            ],
279 1
            'validate-form' => [
280
                'class' => ValidateFormAction::class,
281 1
            ],
282 1
            'buy' => [
283 1
                'class' => RedirectAction::class,
284 1
                'url' => Yii::$app->params['orgUrl'],
285
            ],
286 1
            'add-to-cart-renewal' => [
287 1
                'class' => AddToCartAction::class,
288 1
                'productClass' => ServerRenewProduct::class,
289 1
            ],
290
            'delete' => [
291 1
                'class' => SmartDeleteAction::class,
292
                'success' => Yii::t('hipanel/server', 'Server was deleted successfully'),
293 1
                'error' => Yii::t('hipanel/server', 'Failed to delete server'),
294 1
            ],
295 1
            'bulk-delete-modal' => [
296
                'class' => PrepareBulkAction::class,
297
                'scenario' => 'delete',
298
                'view' => '_bulkDelete',
299
            ],
300
            'bulk-enable-block' => [
301
                'class' => SmartUpdateAction::class,
302
                'scenario' => 'enable-block',
303
                'success' => Yii::t('hipanel/server', 'Servers were blocked successfully'),
304
                'error' => Yii::t('hipanel/server', 'Error during the servers blocking'),
305
                'POST html' => [
306
                    'save'    => true,
307
                    'success' => [
308
                        'class' => RedirectAction::class,
309 1
                    ],
310 1
                ],
311
                'on beforeSave' => function (Event $event) {
312 1
                    /** @var \hipanel\actions\Action $action */
313 1
                    $action = $event->sender;
314 1
                    $type = Yii::$app->request->post('type');
315
                    $comment = Yii::$app->request->post('comment');
316
                    if (!empty($type)) {
317
                        foreach ($action->collection->models as $model) {
318
                            $model->setAttributes([
319 1
                                'type' => $type,
320 1
                                'comment' => $comment,
321
                            ]);
322 1
                        }
323 1
                    }
324 1
                },
325 1
            ],
326
            'bulk-enable-block-modal' => [
327 1
                'class' => PrepareBulkAction::class,
328
                'scenario' => 'enable-block',
329 1
                'view' => '_bulkEnableBlock',
330 1
                'data' => function ($action, $data) {
331 1
                    return array_merge($data, [
332
                        'blockReasons' => $this->getBlockReasons(),
333
                    ]);
334
                },
335
            ],
336
            'bulk-disable-block' => [
337
                'class' => SmartUpdateAction::class,
338
                'scenario' => 'disable-block',
339
                'success' => Yii::t('hipanel/server', 'Servers were unblocked successfully'),
340
                'error' => Yii::t('hipanel/server', 'Error during the servers unblocking'),
341 1
                'POST html' => [
342 1
                    'save'    => true,
343
                    'success' => [
344 1
                        'class' => RedirectAction::class,
345 1
                    ],
346 1
                ],
347 1
                'on beforeSave' => function (Event $event) {
348
                    /** @var \hipanel\actions\Action $action */
349 1
                    $action = $event->sender;
350
                    $comment = Yii::$app->request->post('comment');
351
                    if (!empty($type)) {
0 ignored issues
show
Bug introduced by
The variable $type seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
352
                        foreach ($action->collection->models as $model) {
353
                            $model->setAttribute('comment', $comment);
354
                        }
355
                    }
356
                },
357
            ],
358
            'bulk-disable-block-modal' => [
359
                'class' => PrepareBulkAction::class,
360
                'scenario' => 'disable-block',
361
                'view' => '_bulkDisableBlock',
362
            ],
363
            'set-orientation' => [
364
                'class' => OrientationAction::class,
365
                'allowedRoutes' => [
366
                    '@server/index'
367
                ]
368
            ]
369
370
        ];
371
    }
372
373
    /**
374
     * Gets info of VNC on the server.
375
     *
376
     * @param Server $model
377
     * @param bool $enable
378
     *
379
     * @return array
380
     */
381
    public function getVNCInfo($model, $enable = false)
382
    {
383
        $vnc['endTime'] = strtotime('+8 hours', strtotime($model->statuses['serverEnableVNC']));
0 ignored issues
show
Documentation introduced by
The property statuses does not exist on object<hipanel\modules\server\models\Server>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Coding Style Comprehensibility introduced by
$vnc was never initialized. Although not strictly required by PHP, it is generally a good practice to add $vnc = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
384
        if (($vnc['endTime'] > time() || $enable) && $model->isOperable()) {
385
            $vnc['enabled'] = true;
386
            $vnc = ArrayHelper::merge($vnc, Server::perform('EnableVNC', ['id' => $model->id]));
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<hipanel\modules\server\models\Server>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
387
        }
388
389
        return $vnc;
390
    }
391
392
    public function actionDrawChart()
393
    {
394
        $post = Yii::$app->request->post();
395
        if (!in_array($post['type'], ['traffic', 'bandwidth'], true)) {
396
            throw new NotFoundHttpException();
397
        }
398
399
        $searchModel = new ServerUseSearch();
400
        $dataProvider = $searchModel->search([]);
401
        $dataProvider->pagination = false;
402
        $dataProvider->query->options = ['scenario' => 'get-uses'];
0 ignored issues
show
Bug introduced by
Accessing options on the interface yii\db\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
403
        $dataProvider->query->andWhere($post);
404
        $models = $dataProvider->getModels();
405
406
        list($labels, $data) = ServerHelper::groupUsesForChart($models);
0 ignored issues
show
Documentation introduced by
$models is of type array|null, but the function expects a array<integer,object<hip...rver\models\ServerUse>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
407
408
        return $this->renderAjax('_' . $post['type'] . '_consumption', [
409
            'labels' => $labels,
410
            'data' => $data,
411
        ]);
412
    }
413
414
    /**
415
     * Gets OS images.
416
     *
417
     * @param Server $model
418
     * @throws NotFoundHttpException
419
     * @return array
420
     */
421
    protected function getOsimages(Server $model = null)
422
    {
423
        if ($model !== null) {
424
            $type = $model->type;
0 ignored issues
show
Documentation introduced by
The property type does not exist on object<hipanel\modules\server\models\Server>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
425
        } else {
426
            $type = null;
427
        }
428
429
        $models = ServerHelper::getOsimages($type);
430
431
        if ($models === null) {
432
            throw new NotFoundHttpException('The requested page does not exist.');
433
        }
434
435
        return $models;
436
    }
437
438
    protected function getOsimagesLiveCd()
439
    {
440
        $models = Yii::$app->cache->getTimeCached(3600, [true], function ($livecd) {
441
            return Osimage::findAll(['livecd' => $livecd]);
442
        });
443
444
        if ($models !== null) {
445
            return $models;
446
        }
447
448
        throw new NotFoundHttpException('The requested page does not exist.');
449
    }
450
451
    protected function getPanelTypes()
452
    {
453
        return ServerHelper::getPanels();
454
    }
455
}
456