Passed
Push — develop ( f7e1ab...9043c9 )
by Nikolay
06:16
created

SystemManagementProcessor   C

Complexity

Total Complexity 54

Size/Duplication

Total Lines 338
Duplicated Lines 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
wmc 54
eloc 238
c 6
b 0
f 0
dl 0
loc 338
rs 6.4799

3 Methods

Rating   Name   Duplication   Size   Complexity  
F callBack() 0 149 33
F restoreDefaultSettings() 0 135 18
A upgradeFromImg() 0 29 3

How to fix   Complexity   

Complex Class

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

1
<?php
2
/*
3
 * Copyright © MIKO LLC - All Rights Reserved
4
 * Unauthorized copying of this file, via any medium is strictly prohibited
5
 * Proprietary and confidential
6
 * Written by Alexey Portnov, 9 2020
7
 */
8
9
namespace MikoPBX\PBXCoreREST\Lib;
10
11
12
use MikoPBX\Common\Models\AsteriskManagerUsers;
13
use MikoPBX\Common\Models\CallDetailRecords;
14
use MikoPBX\Common\Models\Extensions;
15
use MikoPBX\Common\Models\IncomingRoutingTable;
16
use MikoPBX\Common\Models\OutgoingRoutingTable;
17
use MikoPBX\Common\Models\OutWorkTimes;
18
use MikoPBX\Common\Models\PbxExtensionModules;
19
use MikoPBX\Common\Models\Providers;
20
use MikoPBX\Common\Models\SoundFiles;
21
use MikoPBX\Common\Providers\MessagesProvider;
22
use MikoPBX\Common\Providers\PBXConfModulesProvider;
23
use MikoPBX\Common\Providers\TranslationProvider;
24
use MikoPBX\Core\Asterisk\Configs\VoiceMailConf;
25
use MikoPBX\Core\System\Notifications;
26
use MikoPBX\Core\System\System;
27
use MikoPBX\Core\System\Util;
28
use MikoPBX\Modules\PbxExtensionState;
29
use MikoPBX\Modules\PbxExtensionUtils;
30
use MikoPBX\PBXCoreREST\Workers\WorkerMergeUploadedFile;
31
use Phalcon\Di;
32
use Phalcon\Di\Injectable;
33
34
class SystemManagementProcessor extends Injectable
35
{
36
    /**
37
     * Processes System requests
38
     *
39
     * @param array $request
40
     *
41
     * @return \MikoPBX\PBXCoreREST\Lib\PBXApiResult
42
     *
43
     * @throws \Exception
44
     */
45
    public static function callBack(array $request): PBXApiResult
46
    {
47
        $action         = $request['action'];
48
        $data           = $request['data'];
49
        $res            = new PBXApiResult();
50
        $res->processor = __METHOD__;
51
        switch ($action) {
52
            case 'reboot':
53
                System::rebootSync();
54
                $res->success = true;
55
                break;
56
            case 'shutdown':
57
                System::shutdown();
58
                $res->success = true;
59
                break;
60
            case 'mergeUploadedFile':
61
                $phpPath              = Util::which('php');
62
                $workerDownloaderPath = Util::getFilePathByClassName(WorkerMergeUploadedFile::class);
63
                Util::mwExecBg("{$phpPath} -f {$workerDownloaderPath} '{$data['settings_file']}'");
64
                $res->success = true;
65
                break;
66
            case 'getDate':
67
                $res->success           = true;
68
                $res->data['timestamp'] = time();
69
                break;
70
            case 'setDate':
71
                $res->success = System::setDate($data['timestamp'], $data['userTimeZone']);
72
                break;
73
            case 'updateCoreLanguage':
74
                $di = Di::getDefault();
75
                $di->remove('messages');
76
                $di->remove('translation');
77
                $di->register(new MessagesProvider());
78
                $di->register(new TranslationProvider());
79
                break;
80
            case 'updateMailSettings':
81
                // TODO:
82
                $res->success = true;
83
                break;
84
            case 'sendMail':
85
                if (isset($data['email']) && isset($data['subject']) && isset($data['body'])) {
86
                    if (isset($data['encode']) && $data['encode'] === 'base64') {
87
                        $data['subject'] = base64_decode($data['subject']);
88
                        $data['body']    = base64_decode($data['body']);
89
                    }
90
                    $result = Notifications::sendMail($data['email'], $data['subject'], $data['body']);
91
                    if ($result === true) {
92
                        $res->success = true;
93
                    } else {
94
                        $res->success    = false;
95
                        $res->messages[] = $result;
96
                    }
97
                } else {
98
                    $res->success    = false;
99
                    $res->messages[] = 'Not all query parameters are set';
100
                }
101
                break;
102
            case 'fileReadContent':
103
                $res = FilesManagementProcessor::fileReadContent($data['filename'], $data['needOriginal']);
104
                break;
105
            case 'reloadMsmtp':
106
                $notifications = new Notifications();
107
                $notifications->configure();
108
                $voiceMailConfig = new VoiceMailConf();
109
                $voiceMailConfig->generateConfig();
110
                $asteriskPath = Util::which('asterisk');
111
                Util::mwExec("{$asteriskPath} -rx 'voicemail reload'");
112
                $res->success = true;
113
                break;
114
            case 'unBanIp':
115
                $res = FirewallManagementProcessor::fail2banUnbanAll($data['ip']);
116
                break;
117
            case 'getBanIp':
118
                $res = FirewallManagementProcessor::getBanIp();
119
                break;
120
            case 'downloadNewFirmware':
121
                $res = FilesManagementProcessor::downloadNewFirmware($request['data']);
122
                break;
123
            case 'firmwareDownloadStatus':
124
                $res = FilesManagementProcessor::firmwareDownloadStatus();
125
                break;
126
            case 'upgrade':
127
                $res = SystemManagementProcessor::upgradeFromImg($data['temp_filename']);
128
                break;
129
            case 'removeAudioFile':
130
                $res = FilesManagementProcessor::removeAudioFile($data['filename']);
131
                break;
132
            case 'convertAudioFile':
133
                $mvPath = Util::which('mv');
134
                Util::mwExec("{$mvPath} {$data['temp_filename']} {$data['filename']}");
135
                $res = FilesManagementProcessor::convertAudioFile($data['filename']);
136
                break;
137
            case 'downloadNewModule':
138
                $module = $request['data']['uniqid'];
139
                $url    = $request['data']['url'];
140
                $md5    = $request['data']['md5'];
141
                $res    = FilesManagementProcessor::moduleStartDownload($module, $url, $md5);
142
                break;
143
            case 'moduleDownloadStatus':
144
                $module = $request['data']['uniqid'];
145
                $res    = FilesManagementProcessor::moduleDownloadStatus($module);
146
                break;
147
            case 'installNewModule':
148
                $filePath = $request['data']['filePath'];
149
                $res      = FilesManagementProcessor::installModuleFromFile($filePath);
150
                break;
151
            case 'enableModule':
152
                $moduleUniqueID       = $request['data']['uniqid'];
153
                $moduleStateProcessor = new PbxExtensionState($moduleUniqueID);
154
                if ($moduleStateProcessor->enableModule() === false) {
155
                    $res->success  = false;
156
                    $res->messages = $moduleStateProcessor->getMessages();
157
                } else {
158
                    PBXConfModulesProvider::recreateModulesProvider();
159
                    $res->data                       = $moduleStateProcessor->getMessages();
160
                    $res->data['needRestartWorkers'] = true; //TODO:: Проверить надо ли это
161
                    $res->success                    = true;
162
                }
163
                break;
164
            case 'disableModule':
165
                $moduleUniqueID       = $request['data']['uniqid'];
166
                $moduleStateProcessor = new PbxExtensionState($moduleUniqueID);
167
                if ($moduleStateProcessor->disableModule() === false) {
168
                    $res->success  = false;
169
                    $res->messages = $moduleStateProcessor->getMessages();
170
                } else {
171
                    PBXConfModulesProvider::recreateModulesProvider();
172
                    $res->data                       = $moduleStateProcessor->getMessages();
173
                    $res->data['needRestartWorkers'] = true; //TODO:: Проверить надо ли это
174
                    $res->success                    = true;
175
                }
176
                break;
177
            case 'uninstallModule':
178
                $moduleUniqueID = $request['data']['uniqid'];
179
                $keepSettings   = $request['data']['keepSettings'] === 'true';
180
                $res            = FilesManagementProcessor::uninstallModule($moduleUniqueID, $keepSettings);
181
                break;
182
            case 'restoreDefault':
183
                $res = self::restoreDefaultSettings();
184
                break;
185
            default:
186
                $res             = new PBXApiResult();
187
                $res->processor  = __METHOD__;
188
                $res->messages[] = "Unknown action - {$action} in systemCallBack";
189
        }
190
191
        $res->function = $action;
192
193
        return $res;
194
    }
195
196
    /**
197
     * Upgrade MikoPBX from uploaded IMG file
198
     *
199
     * @param string $tempFilename path to uploaded image
200
     *
201
     * @return PBXApiResult
202
     */
203
    public static function upgradeFromImg(string $tempFilename): PBXApiResult
204
    {
205
        $res                  = new PBXApiResult();
206
        $res->processor       = __METHOD__;
207
        $res->success         = true;
208
        $res->data['message'] = 'In progress...';
209
210
211
        if ( ! file_exists($tempFilename)) {
212
            $res->success    = false;
213
            $res->messages[] = "Update file '{$tempFilename}' not found.";
214
215
            return $res;
216
        }
217
218
        if ( ! file_exists('/var/etc/cfdevice')) {
219
            $res->success    = false;
220
            $res->messages[] = "The system is not installed";
221
222
            return $res;
223
        }
224
        $dev = trim(file_get_contents('/var/etc/cfdevice'));
225
226
        $link = '/tmp/firmware_update.img';
227
        Util::createUpdateSymlink($tempFilename, $link);
228
        $mikopbx_firmwarePath = Util::which('mikopbx_firmware');
229
        Util::mwExecBg("{$mikopbx_firmwarePath} recover_upgrade {$link} /dev/{$dev}");
230
231
        return $res;
232
    }
233
234
    /**
235
     * Deletes all settings and uploaded files
236
     */
237
    private static function restoreDefaultSettings(): PBXApiResult
238
    {
239
        $res                             = new PBXApiResult();
240
        $res->processor                  = __METHOD__;
241
        $di = DI::getDefault();
242
        if ($di===null){
243
            $res->messages[]='Error on DI initialize';
244
            return $res;
245
        }
246
247
        $res->success                    = true;
248
        $res->data['needRestartWorkers'] = true;
249
        $rm                              = Util::which('rm');
250
251
        // Delete all providers
252
        $records = Providers::find();
253
        if ( ! $records->delete()) {
254
            $res->messages[] = $records->getMessages();
255
            $res->success    = false;
256
        }
257
258
        // Delete routes
259
        $records = OutgoingRoutingTable::find();
260
        if ( ! $records->delete()) {
261
            $res->messages[] = $records->getMessages();
262
            $res->success    = false;
263
        }
264
265
        $records = IncomingRoutingTable::find();
266
        if ( ! $records->delete()) {
267
            $res->messages[] = $records->getMessages();
268
            $res->success    = false;
269
        }
270
271
        // Delete out of work settings
272
        $records = OutWorkTimes::find();
273
        if ( ! $records->delete()) {
274
            $res->messages[] = $records->getMessages();
275
            $res->success    = false;
276
        }
277
278
        // AMI Users
279
        $records = AsteriskManagerUsers::find();
280
        if ( ! $records->delete()) {
281
            $res->messages[] = $records->getMessages();
282
            $res->success    = false;
283
        }
284
285
        // Pre delete some extensions type
286
        // IVR Menu
287
        $records = Extensions::find('type="'.Extensions::TYPE_IVR_MENU.'"');
288
        $records->delete();
289
290
        // CONFERENCE
291
        $records = Extensions::find('type="'.Extensions::TYPE_CONFERENCE.'"');
292
        $records->delete();
293
294
        // QUEUE
295
        $records = Extensions::find('type="'.Extensions::TYPE_QUEUE.'"');
296
        $records->delete();
297
298
299
        // Other extensions
300
        $parameters     = [
301
            'conditions' => 'not number IN ({ids:array})',
302
            'bind'       => [
303
                'ids' => [
304
                    '000063', //Reads back the extension
305
                    '000064', //0000MILLI
306
                    '10003246'//Echo test
307
                ],
308
            ],
309
        ];
310
        $stopDeleting   = false;
311
        $countRecords   = Extensions::count($parameters);
312
        $deleteAttempts = 0;
313
        while ($stopDeleting === false) {
314
            $record = Extensions::findFirst($parameters);
315
            if ($record === null) {
316
                $stopDeleting = true;
317
                continue;
318
            }
319
            if ( ! $record->delete()) {
320
                $deleteAttempts += 1;
321
            }
322
            if ($deleteAttempts > $countRecords * 10) {
323
                $stopDeleting    = true; // Prevent loop
324
                $res->messages[] = $record->getMessages();
325
            }
326
        }
327
328
        // SoundFiles
329
        $parameters = [
330
            'conditions' => 'category = :custom:',
331
            'bind'       => [
332
                'custom' => SoundFiles::CATEGORY_CUSTOM,
333
            ],
334
        ];
335
        $records    = SoundFiles::find($parameters);
336
337
        foreach ($records as $record) {
338
            if (stripos($record->path, '/storage/usbdisk1/mikopbx') !== false) {
339
                Util::mwExec("{$rm} -rf {$record->path}");
340
                if ( ! $record->delete()) {
341
                    $res->messages[] = $record->getMessages();
342
                    $res->success    = false;
343
                }
344
            }
345
        }
346
347
        // PbxExtensions
348
        $records = PbxExtensionModules::find();
349
        foreach ($records as $record) {
350
            $moduleDir = PbxExtensionUtils::getModuleDir($record->uniqid);
351
            Util::mwExec("{$rm} -rf {$moduleDir}");
352
            if ( ! $record->delete()) {
353
                $res->messages[] = $record->getMessages();
354
                $res->success    = false;
355
            }
356
        }
357
358
        // Delete CallRecords
359
        $records = CallDetailRecords::find();
360
        if ( ! $records->delete()) {
361
            $res->messages[] = $records->getMessages();
362
            $res->success    = false;
363
        }
364
365
        // Delete CallRecords sound files
366
        $callRecordsPath  = $di->getShared('config')->path('asterisk.monitordir');
367
        if (stripos($callRecordsPath, '/storage/usbdisk1/mikopbx') !== false) {
368
             Util::mwExec("{$rm} -rf {$callRecordsPath}/*");
369
        }
370
371
        return $res;
372
    }
373
374
}