Passed
Push — develop ( 3b062d...2b12c9 )
by Nikolay
23:37 queued 09:37
created

UpdateSystemConfig   D

Complexity

Total Complexity 58

Size/Duplication

Total Lines 394
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 0
Metric Value
wmc 58
eloc 222
dl 0
loc 394
rs 4.5599
c 7
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A fillInitialSettings() 0 17 3
A updateConfigsUpToVer64() 0 30 4
A deleteLostModules() 0 7 3
B updateConfigsUpToVer2020162() 0 58 9
B updateConfigs() 0 52 7
F updateConfigsUpToVer20202573() 0 128 21
A __construct() 0 4 1
A updateConfigEveryRelease() 0 4 1
B updateConfigsUpToVer62110() 0 32 9

How to fix   Complexity   

Complex Class

Complex classes like UpdateSystemConfig 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 UpdateSystemConfig, 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, 7 2020
7
 */
8
9
namespace MikoPBX\Core\System\Upgrade;
10
11
use MikoPBX\Common\Models\AsteriskManagerUsers;
12
use MikoPBX\Common\Models\Codecs;
13
use MikoPBX\Common\Models\DialplanApplications;
14
use MikoPBX\Common\Models\Extensions;
15
use MikoPBX\Common\Models\Extensions as ExtensionsModel;
16
use MikoPBX\Common\Models\FirewallRules;
17
use MikoPBX\Common\Models\IvrMenu;
18
use MikoPBX\Common\Models\NetworkFilters;
19
use MikoPBX\Common\Models\PbxExtensionModules;
20
use MikoPBX\Common\Models\Sip;
21
use MikoPBX\Common\Models\SoundFiles;
22
use MikoPBX\Core\System\Configs\IptablesConf;
23
use MikoPBX\Core\System\MikoPBXConfig;
24
use MikoPBX\Core\System\PBX;
25
use MikoPBX\Core\System\Storage;
26
use MikoPBX\Core\System\Util;
27
use Phalcon\Di;
28
29
class UpdateSystemConfig extends Di\Injectable
30
{
31
    /**
32
     * @var \Phalcon\Config
33
     */
34
    private $config;
35
36
    /**
37
     * @var MikoPBXConfig
38
     */
39
    private $mikoPBXConfig;
40
41
    /**
42
     * System constructor.
43
     */
44
    public function __construct()
45
    {
46
        $this->config = $this->di->getShared('config');
47
        $this->mikoPBXConfig = new MikoPBXConfig();
48
    }
49
50
    /**
51
     * Update settings after every new release
52
     */
53
    public function updateConfigs(): bool
54
    {
55
        $this->deleteLostModules();
56
57
        $previous_version = str_ireplace('-dev', '', $this->mikoPBXConfig->getGeneralSettings('PBXVersion'));
58
        $current_version  = str_ireplace('-dev', '', trim(file_get_contents('/etc/version')));
59
        if ($previous_version !== $current_version) {
60
61
            if (version_compare($previous_version, '1.0.0', '<=')) {
62
                $this->fillInitialSettings();
63
                $previous_version = '1.0.1';
64
                Util::echoWithSyslog(' - UpdateConfigs: Upgrade applications up tp '.$previous_version.' ');
65
                Util::echoGreenDone();
66
            }
67
68
            if (version_compare($previous_version, '6.2.110', '<')) {
69
                $this->updateConfigsUpToVer62110();
70
                $previous_version = '6.2.110';
71
                Util::echoWithSyslog(' - UpdateConfigs: Upgrade applications up tp '.$previous_version.' ');
72
                Util::echoGreenDone();
73
            }
74
75
            if (version_compare($previous_version, '6.4', '<')) {
76
                $this->updateConfigsUpToVer64();
77
                $previous_version = '6.4';
78
                Util::echoWithSyslog(' - UpdateConfigs: Upgrade applications up tp '.$previous_version.' ');
79
                Util::echoGreenDone();
80
            }
81
82
            if (version_compare($previous_version, '2020.1.62', '<')) {
83
                $this->updateConfigsUpToVer2020162();
84
                $previous_version = '2020.1.62';
85
                Util::echoWithSyslog(' - UpdateConfigs: Upgrade applications up tp '.$previous_version.' ');
86
                Util::echoGreenDone();
87
            }
88
89
            if (version_compare($previous_version, '2020.2.314', '<')) {
90
                $this->updateConfigsUpToVer20202573();
91
                $previous_version = '2020.2.573';
92
                Util::echoWithSyslog(' - UpdateConfigs: Upgrade applications up tp '.$previous_version.' ');
93
                Util::echoGreenDone();
94
            }
95
96
            //... add new updates procedures above this comment line... //
97
98
            $this->updateConfigEveryRelease();
99
100
            $this->mikoPBXConfig->setGeneralSettings('PBXVersion', trim(file_get_contents('/etc/version')));
101
102
        }
103
104
        return true;
105
    }
106
107
    /**
108
     * Delete modules, not installed on the system
109
     */
110
    private function deleteLostModules(): void
111
    {
112
        /** @var \MikoPBX\Common\Models\PbxExtensionModules $modules */
113
        $modules = PbxExtensionModules::find();
114
        foreach ($modules as $module) {
115
            if ( ! is_dir("{$this->config->path('core.modulesDir')}/{$module->uniqid}")) {
116
                $module->delete();
117
            }
118
        }
119
    }
120
121
    /**
122
     * Every new release routines
123
     */
124
    private function updateConfigEveryRelease():void
125
    {
126
        Storage::clearSessionsFiles();
127
        IptablesConf::updateFirewallRules();
128
    }
129
130
    /**
131
     * First bootup
132
     */
133
    private function fillInitialSettings(): void
134
    {
135
        // Обновление конфигов. Это первый запуск системы.
136
        /** @var \MikoPBX\Common\Models\Sip $peers */
137
        /** @var \MikoPBX\Common\Models\Sip $peer */
138
        $peers = Sip::find('type="peer"');
139
        foreach ($peers as $peer) {
140
            $peer->secret = md5('' . time() . 'sip' . $peer->id);
141
            $peer->save();
142
        }
143
144
        /** @var \MikoPBX\Common\Models\AsteriskManagerUsers $managers */
145
        /** @var \MikoPBX\Common\Models\AsteriskManagerUsers $manager */
146
        $managers = AsteriskManagerUsers::find();
147
        foreach ($managers as $manager) {
148
            $manager->secret = md5('' . time() . 'manager' . $manager->id);
149
            $manager->save();
150
        }
151
    }
152
153
154
    /**
155
     * Upgrade from * to 6.2.110
156
     */
157
    private function updateConfigsUpToVer62110(): void
158
    {
159
        /** @var \MikoPBX\Common\Models\Codecs $codec_g722 */
160
        $codec_g722 = Codecs::findFirst('name="g722"');
161
        if ($codec_g722 === null) {
162
            $codec_g722              = new Codecs();
163
            $codec_g722->name        = 'g722';
164
            $codec_g722->type        = 'audio';
165
            $codec_g722->description = 'G.722';
166
            $codec_g722->save();
167
        }
168
169
        /** @var \MikoPBX\Common\Models\IvrMenu $ivrs */
170
        /** @var \MikoPBX\Common\Models\IvrMenu $ivr */
171
        $ivrs = IvrMenu::find();
172
        foreach ($ivrs as $ivr) {
173
            if (empty($ivr->number_of_repeat)) {
174
                $ivr->number_of_repeat = 5;
175
                $ivr->save();
176
            }
177
            if (empty($ivr->timeout)) {
178
                $ivr->timeout = 7;
179
                $ivr->save();
180
            }
181
        }
182
183
        // Чистим мусор.
184
        /** @var \MikoPBX\Common\Models\PbxExtensionModules $modules */
185
        $modules = PbxExtensionModules::find();
186
        foreach ($modules as $module) {
187
            if ($module->version === '1.0' && empty($module->support_email) && 'МИКО' === $module->developer) {
188
                $module->delete();
189
            }
190
        }
191
    }
192
193
    /**
194
     * Upgrade from 6.2.110 to 6.4
195
     */
196
    private function updateConfigsUpToVer64(): void
197
    {
198
        /** @var \MikoPBX\Common\Models\DialplanApplications $res */
199
        $app_number = '10000100';
200
        $app_logic  = base64_encode('1,Goto(voice_mail_peer,voicemail,1)');
201
        $d_app      = DialplanApplications::findFirst('extension="' . $app_number . '"');
202
        if ($d_app === null) {
203
            $d_app                   = new DialplanApplications();
204
            $d_app->applicationlogic = $app_logic;
205
            $d_app->extension        = $app_number;
206
            $d_app->description      = 'Voice Mail';
207
            $d_app->name             = 'VOICEMAIL';
208
            $d_app->type             = 'plaintext';
209
            $d_app->uniqid           = 'DIALPLAN-APPLICATION-' . md5(time());
210
211
            if ($d_app->save()) {
212
                $extension = ExtensionsModel::findFirst("number = '{$app_number}'");
213
                if ($extension === null) {
214
                    $extension                    = new ExtensionsModel();
215
                    $extension->number            = $app_number;
216
                    $extension->type              = 'DIALPLAN APPLICATION';
217
                    $extension->callerid          = $d_app->name;
218
                    $extension->show_in_phonebook = '1';
0 ignored issues
show
Documentation Bug introduced by
It seems like '1' of type string is incompatible with the declared type integer|null of property $show_in_phonebook.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
219
                    $extension->save();
220
                }
221
            }
222
        } else {
223
            $d_app->applicationlogic = $app_logic;
224
            $d_app->type             = 'plaintext';
225
            $d_app->save();
226
        }
227
    }
228
229
    private function updateConfigsUpToVer2020162(): void
230
    {
231
        $sqlite3Path = Util::which('sqlite3');
232
233
        /** @var \MikoPBX\Common\Models\FirewallRules $rule */
234
        $result = FirewallRules::find();
235
        foreach ($result as $rule) {
236
            /** @var \MikoPBX\Common\Models\NetworkFilters $network_filter */
237
            $network_filter = NetworkFilters::findFirst($rule->networkfilterid);
238
            if ($network_filter === null) {
239
                // Это "битая" роль, необходимо ее удалить. Нет ссылки на подсеть.
240
                $rule->delete();
241
            }
242
        }
243
244
        // Корректировка AstDB
245
        $astdb_file = $this->config->path('astDatabase.dbfile');
246
        if (file_exists($astdb_file)) {
247
            // С переходом на PJSIP удалим статусы SIP.
248
            Util::mwExec("{$sqlite3Path}  {$astdb_file} 'DELETE FROM astdb WHERE key LIKE \"/UserBuddyStatus/SIP%\"'");
249
        }
250
251
        PBX::checkCodec('ilbc', 'iLBC', 'audio');
252
        PBX::checkCodec('opus', 'Opus Codec', 'audio');
253
254
        $PrivateKey = $this->mikoPBXConfig->getGeneralSettings('WEBHTTPSPrivateKey');
255
        $PublicKey  = $this->mikoPBXConfig->getGeneralSettings('WEBHTTPSPublicKey');
256
        if (empty($PrivateKey) || empty($PublicKey)) {
257
            $certs = Util::generateSslCert();
258
            $this->mikoPBXConfig->setGeneralSettings('WEBHTTPSPrivateKey', $certs['PrivateKey']);
259
            $this->mikoPBXConfig->setGeneralSettings('WEBHTTPSPublicKey', $certs['PublicKey']);
260
        }
261
262
263
        $app_number = '10003246';
264
        $d_app      = DialplanApplications::findFirst('extension="' . $app_number . '"');
265
        if ($d_app === null) {
266
            $app_text                = '1,Answer()' . "\n" .
267
                'n,AGI(cdr_connector.php,${ISTRANSFER}dial_answer)' . "\n" .
268
                'n,Echo()' . "\n" .
269
                'n,Hangup()' . "\n";
270
            $d_app                   = new DialplanApplications();
271
            $d_app->applicationlogic = base64_encode($app_text);
272
            $d_app->extension        = $app_number;
273
            $d_app->description      = 'Echos audio and video back to the caller as soon as it is received. Used to test connection delay.';
274
            $d_app->name             = 'Echo test';
275
            $d_app->type             = 'plaintext';
276
            $d_app->uniqid           = 'DIALPLAN-APPLICATION-' . md5(time());
277
278
            if ($d_app->save()) {
279
                $extension = ExtensionsModel::findFirst("number = '{$app_number}'");
280
                if ($extension === null) {
281
                    $extension                    = new ExtensionsModel();
282
                    $extension->number            = $app_number;
283
                    $extension->type              = 'DIALPLAN APPLICATION';
284
                    $extension->callerid          = $d_app->name;
285
                    $extension->show_in_phonebook = '1';
0 ignored issues
show
Documentation Bug introduced by
It seems like '1' of type string is incompatible with the declared type integer|null of property $show_in_phonebook.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
286
                    $extension->save();
287
                }
288
            }
289
        }
290
    }
291
292
    /**
293
     * Update to 2020.2.314
294
     */
295
    private function updateConfigsUpToVer20202573(): void
296
    {
297
298
        $availCodecs = [
299
            // Видео кодеки.
300
            'h263p' => 'H.263+',
301
            'h263'  => 'H.263',
302
            'h264'  => 'H.264',
303
304
            // Аудио кодеки
305
            'adpcm' => 'ADPCM',
306
            'alaw'  => 'G.711 A-law',
307
            'ulaw'  => 'G.711 µ-law',
308
            'g719'  => 'G.719',
309
            'g722'  => 'G.722',
310
            'g726'  => 'G.726',
311
            'gsm'   => 'GSM',
312
            'ilbc'  => 'ILBC',
313
            'lpc10' => 'LPC-10',
314
            'speex' => 'Speex',
315
            'slin'  => 'Signed Linear PCM',
316
            'opus'  => 'Opus',
317
        ];
318
        $codecs = Codecs::find();
319
        // Удалим лишние кодеки
320
        /** @var \MikoPBX\Common\Models\Codecs $codec */
321
        foreach ($codecs as $codec){
322
            if(array_key_exists($codec->name, $availCodecs)){
323
                continue;
324
            }
325
            if(!$codec->delete()){
326
                Util::sysLogMsg(__CLASS__, 'Can not delete codec '.$codec->name. ' from MikoPBX\Common\Models\Codecs');
327
            }
328
        }
329
330
        foreach ($availCodecs as $availCodec => $desc){
331
            $codecData = Codecs::findFirst('name="'.$availCodec.'"');
332
            if ($codecData === null) {
333
                $codecData              = new Codecs();
334
            }elseif($codecData->description === $desc){
335
                unset($codecData);
336
                continue;
337
            }
338
            $codecData->name        = $availCodec;
339
            if(substr($availCodec,0,3) === 'h26'){
340
                $type = 'video';
341
            }else{
342
                $type = 'audio';
343
            }
344
            $codecData->type        = $type;
345
            $codecData->description = $desc;
346
            if(!$codecData->save()){
347
                Util::sysLogMsg(__CLASS__, 'Can not update codec info '.$codecData->name. ' from \MikoPBX\Common\Models\Codecs');
348
            }
349
        }
350
        unset($codecs);
351
352
        // Add custom category to all sound files
353
        $soundFiles = SoundFiles::find();
354
        foreach ($soundFiles as $sound_file) {
355
            $sound_file->category = SoundFiles::CATEGORY_CUSTOM;
356
            $sound_file->update();
357
        }
358
359
        // Clean AstDB
360
        $astDbPath = $this->config->path('astDatabase.dbfile');
361
        if(file_exists($astDbPath)){
362
            $table = 'astdb';
363
            $sql = 'DELETE FROM '.$table.' WHERE key LIKE "/DND/SIP%" OR key LIKE "/CF/SIP%" OR key LIKE "/UserBuddyStatus/SIP%"';
364
            $db = new \SQLite3($astDbPath);
365
            try {
366
                $db->exec($sql);
367
            } catch (\Exception $e) {
368
                Util::sysLogMsg(__CLASS__, 'Can clean astdb from UserBuddyStatus...');
369
                sleep(2);
370
            }
371
            $db->close();
372
            unset($db);
373
        }
374
375
        // Add moh files to db and copy them to storage
376
        $oldMohDir     = $this->config->path('asterisk.astvarlibdir') . '/sounds/moh';
377
        $currentMohDir = $this->config->path('asterisk.mohdir');
378
        if ( ! Util::mwMkdir($currentMohDir)) {
379
            return;
380
        }
381
        if(!file_exists($oldMohDir)){
382
            if(!file_exists('/offload/livecd')){
383
                Util::sysLogMsg("UpdateConfigsUpToVer20202314", 'Directory sounds/moh not found', LOG_ERR);
384
            }
385
            return;
386
        }
387
        $files = scandir($oldMohDir);
388
        foreach ($files as $file) {
389
            if (in_array($file, ['.', '..'])) {
390
                continue;
391
            }
392
            if (copy($oldMohDir . '/' . $file, $currentMohDir . '/' . $file)) {
393
                $sound_file           = new SoundFiles();
394
                $sound_file->path     = $currentMohDir . '/' . $file;
395
                $sound_file->category = SoundFiles::CATEGORY_MOH;
396
                $sound_file->name     = $file;
397
                $sound_file->save();
398
            }
399
        }
400
401
        // Remove old cache folders
402
        $mediaMountPoint = $this->config->path('core.mediaMountPoint');
403
        $oldCacheDirs    = [
404
            "$mediaMountPoint/mikopbx/cache_js_dir",
405
            "$mediaMountPoint/mikopbx/cache_img_dir",
406
            "$mediaMountPoint/mikopbx/cache_css_dir",
407
        ];
408
        foreach ($oldCacheDirs as $old_cache_dir) {
409
            if (is_dir($old_cache_dir)) {
410
                $rmPath = Util::which('rm');
411
                Util::mwExec("{$rmPath} -rf $old_cache_dir");
412
            }
413
        }
414
415
        // Update Extensions table
416
        $parameters = [
417
            'conditions' => 'not show_in_phonebook="1" AND is_general_user_number="1"',
418
        ];
419
        $wrongRecords = Extensions::find($parameters);
420
        foreach ($wrongRecords as $extension){
421
            $extension->show_in_phonebook='1';
422
            $extension->update();
423
        }
424
    }
425
426
}