Passed
Push — develop ( c56079...6ebb8b )
by Портнов
04:29
created

AdvicesProcessor   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 339
Duplicated Lines 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
wmc 43
eloc 177
c 6
b 0
f 0
dl 0
loc 339
rs 8.96

9 Methods

Rating   Name   Duplication   Size   Complexity  
A callBack() 0 13 2
B getAdvicesAction() 0 59 10
A checkStorage() 0 23 6
A checkFirewalls() 0 17 3
A isConnected() 0 10 2
B checkPasswords() 0 71 9
A checkCorruptedFiles() 0 9 2
A checkUpdates() 0 31 4
A checkRegistration() 0 31 5

How to fix   Complexity   

Complex Class

Complex classes like AdvicesProcessor 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 AdvicesProcessor, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*
3
 * MikoPBX - free phone system for small business
4
 * Copyright (C) 2017-2020 Alexey Portnov and Nikolay Beketov
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with this program.
17
 * If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
namespace MikoPBX\PBXCoreREST\Lib;
21
22
use MikoPBX\Common\Providers\ManagedCacheProvider;
23
use MikoPBX\Core\System\Storage;
24
use MikoPBX\Core\System\Util;
25
use MikoPBX\Common\Models\{NetworkFilters, PbxSettings, Sip};
26
use GuzzleHttp;
27
use Phalcon\Di\Injectable;
28
use SimpleXMLElement;
29
use MikoPBX\Service\Main;
30
31
/**
32
 * Class AdvicesProcessor
33
 *
34
 * @package MikoPBX\PBXCoreREST\Lib
35
 *
36
 * @property \MikoPBX\Common\Providers\LicenseProvider license
37
 * @property \MikoPBX\Common\Providers\TranslationProvider translation
38
 * @property \Phalcon\Config                               config
39
 */
40
class AdvicesProcessor extends Injectable
41
{
42
43
    /**
44
     * Processes Advices request
45
     *
46
     * @param array $request
47
     *
48
     * @return PBXApiResult
49
     */
50
    public static function callBack(array $request): PBXApiResult
51
    {
52
        $action = $request['action'];
53
        if('getList' === $action){
54
            $proc = new self();
55
            $res  = $proc->getAdvicesAction();
56
        }else{
57
            $res             = new PBXApiResult();
58
            $res->processor  = __METHOD__;
59
            $res->messages[] = "Unknown action - {$action} in advicesCallBack";
60
        }
61
        $res->function = $action;
62
        return $res;
63
    }
64
65
66
    /**
67
     * Makes list of notifications about system, firewall, passwords, wrong settings
68
     *
69
     * @return PBXApiResult
70
     */
71
    private function getAdvicesAction(): PBXApiResult
72
    {
73
        $res            = new PBXApiResult();
74
        $res->processor = __METHOD__;
75
76
        $arrMessages     = [];
77
        $arrAdvicesTypes = [
78
            ['type' => 'isConnected', 'cacheTime' => 15],
79
            ['type' => 'checkCorruptedFiles', 'cacheTime' => 15],
80
            ['type' => 'checkPasswords', 'cacheTime' => 3],
81
            ['type' => 'checkFirewalls', 'cacheTime' => 15],
82
            ['type' => 'checkStorage', 'cacheTime' => 120],
83
            ['type' => 'checkUpdates', 'cacheTime' => 3600],
84
            ['type' => 'checkRegistration', 'cacheTime' => 86400],
85
        ];
86
        $managedCache = $this->getDI()->getShared(ManagedCacheProvider::SERVICE_NAME);
87
        $language = PbxSettings::getValueByKey('WebAdminLanguage');
88
89
        foreach ($arrAdvicesTypes as $adviceType) {
90
            $currentAdvice = $adviceType['type'];
91
            $cacheTime     = $adviceType['cacheTime'];
92
            $cacheKey      = 'AdvicesProcessor:getAdvicesAction:'.$currentAdvice;
93
            if ($managedCache->has($cacheKey)) {
94
                $oldResult = json_decode($managedCache->get($cacheKey), true, 512, JSON_THROW_ON_ERROR);
95
                if ($language === $oldResult['LastLanguage']) {
96
                    $arrMessages[] = $oldResult['LastMessage'];
97
                    continue;
98
                }
99
            }
100
            $newResult = $this->$currentAdvice();
101
            if ( ! empty($newResult)) {
102
                $arrMessages[] = $newResult;
103
            }
104
            $managedCache->set(
105
                $cacheKey,
106
                json_encode([
107
                                'LastLanguage' => $language,
108
                                'LastMessage' => $newResult,
109
                            ], JSON_THROW_ON_ERROR),
110
                $cacheTime
111
            );
112
        }
113
        $res->success = true;
114
        $result       = [];
115
        foreach ($arrMessages as $message) {
116
            foreach ($message as $key => $value) {
117
                if(is_array($value)){
118
                    if(!isset($result[$key])){
119
                        $result[$key] = [];
120
                    }
121
                    $result[$key] = array_merge($result[$key], $value);
122
                }elseif ( ! empty($value)) {
123
                    $result[$key][] = $value;
124
                }
125
            }
126
        }
127
        $res->data['advices'] = $result;
128
129
        return $res;
130
    }
131
132
    /**
133
     * Check passwords quality
134
     *
135
     * @return array
136
     * @noinspection PhpUnusedPrivateMethodInspection
137
     */
138
    private function checkPasswords(): array
139
    {
140
        $messages           = [
141
            'warning' => [],
142
            'needUpdate' => []
143
        ];
144
        $arrOfDefaultValues = PbxSettings::getDefaultArrayValues();
145
        $fields = [
146
            'WebAdminPassword'  => [
147
                'url'  => 'general-settings/modify/#/passwords',
148
                'type' => 'gs_WebPasswordFieldName',
149
                'value'=> PbxSettings::getValueByKey('WebAdminPassword')
150
            ],
151
            'SSHPassword'       => [
152
                'url'  => 'general-settings/modify/#/ssh',
153
                'type' => 'gs_SshPasswordFieldName',
154
                'value'=> PbxSettings::getValueByKey('SSHPassword')
155
            ],
156
        ];
157
        if ($arrOfDefaultValues['WebAdminPassword'] === PbxSettings::getValueByKey('WebAdminPassword')) {
158
            $messages['warning'][] = $this->translation->_(
159
                'adv_YouUseDefaultWebPassword',
160
                ['url' => $this->url->get('general-settings/modify/#/passwords')]
161
            );
162
            unset($fields['WebAdminPassword']);
163
            $messages['needUpdate'][] = 'WebAdminPassword';
164
        }
165
        if ($arrOfDefaultValues['SSHPassword'] === PbxSettings::getValueByKey('SSHPassword')) {
166
            $messages['warning'][] = $this->translation->_(
167
                'adv_YouUseDefaultSSHPassword',
168
                ['url' => $this->url->get('general-settings/modify/#/ssh')]
169
            );
170
            unset($fields['SSHPassword']);
171
            $messages['needUpdate'][] = 'SSHPassword';
172
        }elseif(PbxSettings::getValueByKey('SSHPasswordHash') !== md5_file('/etc/passwd')){
173
            $messages['warning'][] = $this->translation->_(
174
                'gs_SSHPPasswordCorrupt',
175
                ['url' => $this->url->get('general-settings/modify/#/ssh')]
176
            );
177
        }
178
179
        $peersData = Sip::find([
180
               "type = 'peer' AND ( disabled <> '1')",
181
               'columns' => 'id,extension,secret']
182
        );
183
        foreach ($peersData as $peer){
184
            $fields[$peer['extension']] = [
185
                'url'  => '/admin-cabinet/extensions/modify/'.$peer['id'],
186
                'type' => 'gs_UserPasswordFieldName',
187
                'value'=> $peer['secret']
188
            ];
189
        }
190
191
        $cloudInstanceId = PbxSettings::getValueByKey('CloudInstanceId');
192
        foreach ($fields as $key => $value){
193
            if($cloudInstanceId !== $value['value'] && !Util::isSimplePassword($value['value'])){
194
                continue;
195
            }
196
197
            if(in_array($key, ['WebAdminPassword', 'SSHPassword'], true)){
198
                $messages['needUpdate'][] = $key;
199
            }
200
            $messages['warning'][] = $this->translation->_(
201
                'adv_isSimplePassword',
202
                [
203
                    'type' => $this->translation->_($value['type']),
204
                    'url' => $this->url->get($value['url'])
205
                ]
206
            );
207
        }
208
        return $messages;
209
    }
210
211
    /**
212
     * Check passwords quality
213
     *
214
     * @return array
215
     * @noinspection PhpUnusedPrivateMethodInspection
216
     */
217
    private function checkCorruptedFiles(): array
218
    {
219
        $messages           = [];
220
        $files = Main::checkForCorruptedFiles();
221
        if (count($files) !== 0) {
222
            $messages['warning'] = $this->translation->_('The integrity of the system is broken', ['url' => '']).'. '.$this->translation->_('systemBrokenComment', ['url' => '']);
223
        }
224
225
        return $messages;
226
    }
227
228
    /**
229
     * Check firewall status
230
     *
231
     * @return array
232
     * @noinspection PhpUnusedPrivateMethodInspection
233
     */
234
    private function checkFirewalls(): array
235
    {
236
        $messages = [];
237
        if (PbxSettings::getValueByKey('PBXFirewallEnabled') === '0') {
238
            $messages['warning'] = $this->translation->_(
239
                'adv_FirewallDisabled',
240
                ['url' => $this->url->get('firewall/index/')]
241
            );
242
        }
243
        if (NetworkFilters::count() === 0) {
244
            $messages['warning'] = $this->translation->_(
245
                'adv_NetworksNotConfigured',
246
                ['url' => $this->url->get('firewall/index/')]
247
            );
248
        }
249
250
        return $messages;
251
    }
252
253
    /**
254
     * Check storage is mount and how many space available
255
     *
256
     * @return array
257
     *
258
     * @noinspection PhpUnusedPrivateMethodInspection
259
     */
260
    private function checkStorage(): array
261
    {
262
        $messages           = [];
263
        $st                 = new Storage();
264
        $storageDiskMounted = false;
265
        $disks              = $st->getAllHdd();
266
        foreach ($disks as $disk) {
267
            if (array_key_exists('mounted', $disk)
268
                && strpos($disk['mounted'], '/storage/usbdisk') !== false) {
269
                $storageDiskMounted = true;
270
                if ($disk['free_space'] < 500) {
271
                    $messages['warning']
272
                        = $this->translation->_(
273
                        'adv_StorageDiskRunningOutOfFreeSpace',
274
                        ['free' => $disk['free_space']]
275
                    );
276
                }
277
            }
278
        }
279
        if ($storageDiskMounted === false) {
280
            $messages['error'] = $this->translation->_('adv_StorageDiskUnMounted');
281
        }
282
        return $messages;
283
    }
284
285
    /**
286
     * Check new version PBX
287
     *
288
     * @return array
289
     * @throws \GuzzleHttp\Exception\GuzzleException
290
     * @noinspection PhpUnusedPrivateMethodInspection
291
     */
292
    private function checkUpdates(): array
293
    {
294
        $messages   = [];
295
        $PBXVersion = PbxSettings::getValueByKey('PBXVersion');
296
297
        $client = new GuzzleHttp\Client();
298
        $res    = $client->request(
299
            'POST',
300
            'https://releases.mikopbx.com/releases/v1/mikopbx/ifNewReleaseAvailable',
301
            [
302
                'form_params' => [
303
                    'PBXVER' => $PBXVersion,
304
                ],
305
            ]
306
        );
307
        if ($res->getStatusCode() !== 200) {
308
            return [];
309
        }
310
311
        $answer = json_decode($res->getBody(), false);
312
        if ($answer !== null && $answer->newVersionAvailable === true) {
313
            $messages['info'] = $this->translation->_(
314
                'adv_AvailableNewVersionPBX',
315
                [
316
                    'url' => $this->url->get('update/index/'),
317
                    'ver' => $answer->version,
318
                ]
319
            );
320
        }
321
322
        return $messages;
323
    }
324
325
    /**
326
     * Check mikopbx license status
327
     *
328
     * @noinspection PhpUnusedPrivateMethodInspection
329
     */
330
    private function checkRegistration(): array
331
    {
332
        $messages = [];
333
        $licKey   = PbxSettings::getValueByKey('PBXLicense');
334
        $language   = PbxSettings::getValueByKey('WebAdminLanguage');
335
336
        if ( ! empty($licKey)) {
337
            $checkBaseFeature = $this->license->featureAvailable(33);
338
            if ($checkBaseFeature['success'] === false) {
339
                if ($language === 'ru') {
340
                    $url = 'https://wiki.mikopbx.com/licensing#faq_chavo';
341
                } else {
342
                    $url = "https://wiki.mikopbx.com/{$language}:licensing#faq_chavo";
343
                }
344
                $textError = (string)($checkBaseFeature['error']??'');
345
                $messages['warning'] = $this->translation->_(
346
                    'adv_ThisCopyHasLicensingTroubles',
347
                    [
348
                        'url'   => $url,
349
                        'error' => $this->license->translateLicenseErrorMessage($textError),
350
                    ]
351
                );
352
            }
353
354
            $licenseInfo = $this->license->getLicenseInfo($licKey);
355
            if ($licenseInfo instanceof SimpleXMLElement) {
356
                file_put_contents('/tmp/licenseInfo', json_encode($licenseInfo->attributes()));
357
            }
358
        }
359
360
        return $messages;
361
    }
362
363
    /**
364
     * Checks whether internet connection is available or not
365
     *
366
     * @return array
367
     * @noinspection PhpUnusedPrivateMethodInspection
368
     */
369
    private function isConnected(): array
370
    {
371
        $messages = [];
372
        $connected = @fsockopen("www.google.com", 443);
373
        if ($connected !== false) {
374
            fclose($connected);
375
        } else {
376
            $messages['warning'] = $this->translation->_('adv_ProblemWithInternetConnection');
377
        }
378
        return $messages;
379
    }
380
}