Completed
Push — master ( 874b51...78033e )
by Dmitry
12:13
created

ServerController::actionIsOperable()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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