Passed
Push — develop ( c283a9...d800b2 )
by Nikolay
06:33
created

UpdateConfigsUpToVer20202754::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 0
1
<?php
2
/*
3
 * Copyright (C) MIKO LLC - All Rights Reserved
4
 * Unauthorized copying of this file, via any medium is strictly prohibited
5
 * Proprietary and confidential
6
 * Written by Nikolay Beketov, 10 2020
7
 *
8
 */
9
10
namespace MikoPBX\Core\System\Upgrade\Releases;
11
12
use MikoPBX\Common\Models\Codecs;
13
use MikoPBX\Common\Models\Extensions;
14
use MikoPBX\Common\Models\SoundFiles;
15
use MikoPBX\Core\System\MikoPBXConfig;
16
use MikoPBX\Core\System\Upgrade\UpgradeSystemConfigInterface;
17
use MikoPBX\Core\System\Util;
18
use Phalcon\Config as ConfigAlias;
19
use Phalcon\Di\Injectable;
20
21
class UpdateConfigsUpToVer20202754 extends Injectable implements UpgradeSystemConfigInterface
22
{
23
    public const PBX_VERSION = '2020.2.754';
24
25
    private ConfigAlias $config;
26
27
    private MikoPBXConfig $mikoPBXConfig;
28
29
    private bool $isLiveCD;
30
31
    /**
32
     * Class constructor.
33
     */
34
    public function __construct()
35
    {
36
        $this->config        = $this->getDI()->getShared('config');
37
        $this->mikoPBXConfig = new MikoPBXConfig();
38
        $this->isLiveCD      = file_exists('/offload/livecd');
39
    }
40
41
    /**
42
     * Updates system configuration according to new rules
43
     */
44
    public function processUpdate(): void
45
    {
46
        if ($this->isLiveCD) {
47
            return;
48
        }
49
50
        $this->deleteOrphanCodecs();
51
        $this->addCustomCategoryToSoundFiles();
52
        $this->cleanAstDB();
53
        $this->copyMohFilesToStorage();
54
        $this->removeOldCacheFolders();
55
        $this->removeOldSessionsFiles();
56
        $this->updateExtensionsTable();
57
        $this->moveReadOnlySoundsToStorage();
58
    }
59
60
    /**
61
     * Deletes all not actual codecs
62
     */
63
    private function deleteOrphanCodecs()
64
    {
65
        $availCodecs = [
66
            // Видео кодеки.
67
            'h263p' => 'H.263+',
68
            'h263'  => 'H.263',
69
            'h264'  => 'H.264',
70
            // Аудио кодеки
71
            'adpcm' => 'ADPCM',
72
            'alaw'  => 'G.711 A-law',
73
            'ulaw'  => 'G.711 µ-law',
74
            'g719'  => 'G.719',
75
            'g722'  => 'G.722',
76
            'g726'  => 'G.726',
77
            'gsm'   => 'GSM',
78
            'ilbc'  => 'ILBC',
79
            'lpc10' => 'LPC-10',
80
            'speex' => 'Speex',
81
            'slin'  => 'Signed Linear PCM',
82
            'opus'  => 'Opus',
83
        ];
84
        $codecs      = Codecs::find();
85
        // Удалим лишние кодеки
86
        /** @var Codecs $codec */
87
        foreach ($codecs as $codec) {
88
            if (array_key_exists($codec->name, $availCodecs)) {
89
                $this->checkDisabledCodec($codec);
90
                continue;
91
            }
92
            if ( ! $codec->delete()) {
93
                Util::sysLogMsg(
94
                    __CLASS__,
95
                    'Can not delete codec ' . $codec->name . ' from MikoPBX\Common\Models\Codecs'
96
                );
97
            }
98
        }
99
        $this->addNewCodecs($availCodecs);
100
        $this->disableCodecs();
101
    }
102
103
    /**
104
     * Checks whether it correct field "disabled" for codec record.
105
     *
106
     * @param Codecs $codec
107
     */
108
    private function checkDisabledCodec(Codecs $codec): void
109
    {
110
        if ( ! in_array($codec->disabled, ['0', '1'], true)) {
111
            $codec->disabled = '0';
112
            $codec->save();
113
        }
114
    }
115
116
    /**
117
     * Adds new codecs from $availCodecs array if it doesn't exist
118
     *
119
     * @param array $availCodecs
120
     */
121
    private function addNewCodecs(array $availCodecs): void
122
    {
123
        foreach ($availCodecs as $availCodec => $desc) {
124
            $codecData = Codecs::findFirst('name="' . $availCodec . '"');
125
            if ($codecData === null) {
126
                $codecData = new Codecs();
127
            } elseif ($codecData->description === $desc) {
128
                unset($codecData);
129
                continue;
130
            }
131
            $codecData->name = $availCodec;
132
            if (strpos($availCodec, 'h26') === 0) {
133
                $type = 'video';
134
            } else {
135
                $type = 'audio';
136
            }
137
            $codecData->type        = $type;
138
            $codecData->description = $desc;
139
            if ( ! $codecData->save()) {
140
                Util::sysLogMsg(
141
                    __CLASS__,
142
                    'Can not update codec info ' . $codecData->name . ' from \MikoPBX\Common\Models\Codecs'
143
                );
144
            }
145
        }
146
    }
147
148
    /**
149
     * Disables unusable codecs
150
     */
151
    private function disableCodecs(): void
152
    {
153
        $availCodecs = [
154
            'h264' => 'H.264',
155
            'alaw' => 'G.711 A-law',
156
            'ulaw' => 'G.711 µ-law',
157
            'opus' => 'Opus',
158
            'ilbc' => 'ILBC',
159
        ];
160
161
        $codecs = Codecs::find();
162
        // Удалим лишние кодеки
163
        /** @var Codecs $codec */
164
        foreach ($codecs as $codec) {
165
            if (array_key_exists($codec->name, $availCodecs)) {
166
                continue;
167
            }
168
            $codec->disabled = '1';
169
            $codec->save();
170
        }
171
    }
172
173
    /**
174
     * Updates category attribute on SoundFiles table
175
     * Add custom category to all sound files
176
     */
177
    private function addCustomCategoryToSoundFiles(): void
178
    {
179
        $soundFiles = SoundFiles::find();
180
        foreach ($soundFiles as $sound_file) {
181
            $sound_file->category = SoundFiles::CATEGORY_CUSTOM;
182
            $sound_file->update();
183
        }
184
    }
185
186
    /**
187
     * Clean UserBuddyStatus on AstDB
188
     */
189
    private function cleanAstDB(): void
190
    {
191
        $astDbPath = $this->config->path('astDatabase.dbfile');
192
        if (file_exists($astDbPath)) {
193
            $table = 'astdb';
194
            $sql   = 'DELETE FROM ' . $table . ' WHERE key LIKE "/DND/SIP%" OR key LIKE "/CF/SIP%" OR key LIKE "/UserBuddyStatus/SIP%"';
195
            $db    = new \SQLite3($astDbPath);
196
            try {
197
                $db->exec($sql);
198
            } catch (\Error $e) {
199
                Util::sysLogMsg(__CLASS__, 'Can clean astdb from UserBuddyStatus...' . $e->getMessage());
200
                sleep(2);
201
            }
202
            $db->close();
203
            unset($db);
204
        }
205
    }
206
207
    /**
208
     * Copies MOH sound files to storage and creates record on SoundFiles table
209
     */
210
    private function copyMohFilesToStorage(): void
211
    {
212
        $oldMohDir = $this->config->path('asterisk.astvarlibdir') . '/sounds/moh';
213
        if ( ! file_exists($oldMohDir)) {
214
            return;
215
        }
216
        $currentMohDir = $this->config->path('asterisk.mohdir');
217
        if ( ! Util::mwMkdir($currentMohDir)) {
218
            return;
219
        }
220
221
        $files = scandir($oldMohDir);
222
        foreach ($files as $file) {
223
            if (in_array($file, ['.', '..'])) {
224
                continue;
225
            }
226
            if (copy($oldMohDir . '/' . $file, $currentMohDir . '/' . $file)) {
227
                $sound_file           = new SoundFiles();
228
                $sound_file->path     = $currentMohDir . '/' . $file;
229
                $sound_file->category = SoundFiles::CATEGORY_MOH;
230
                $sound_file->name     = $file;
231
                $sound_file->save();
232
            }
233
        }
234
    }
235
236
    /**
237
     * Removes old cache folders
238
     */
239
    private function removeOldCacheFolders(): void
240
    {
241
        $mediaMountPoint = $this->config->path('core.mediaMountPoint');
242
        $oldCacheDirs    = [
243
            "$mediaMountPoint/mikopbx/cache_js_dir",
244
            "$mediaMountPoint/mikopbx/cache_img_dir",
245
            "$mediaMountPoint/mikopbx/cache_css_dir",
246
        ];
247
        foreach ($oldCacheDirs as $old_cache_dir) {
248
            if (is_dir($old_cache_dir)) {
249
                $rmPath = Util::which('rm');
250
                Util::mwExec("{$rmPath} -rf $old_cache_dir");
251
            }
252
        }
253
    }
254
    /**
255
     * Removes old sessions files
256
     */
257
    private function removeOldSessionsFiles(): void
258
    {
259
        $mediaMountPoint = $this->config->path('core.mediaMountPoint');
260
        $oldCacheDirs    = [
261
            "$mediaMountPoint/mikopbx/log/nats/license.key",
262
            "$mediaMountPoint/mikopbx/log/nats/*.cache",
263
            "$mediaMountPoint/mikopbx/log/pdnsd/cache",
264
            "$mediaMountPoint/mikopbx/log/Module*",
265
            "$mediaMountPoint/mikopbx/php_session",
266
            "$mediaMountPoint/mikopbx/tmp/*",
267
            "$mediaMountPoint/mikopbx/log/ProvisioningServerPnP",
268
        ];
269
        foreach ($oldCacheDirs as $old_cache_dir) {
270
            if (is_dir($old_cache_dir)) {
271
                $rmPath = Util::which('rm');
272
                Util::mwExec("{$rmPath} -rf $old_cache_dir");
273
            }
274
        }
275
    }
276
277
278
    /**
279
     * Updates show_in_phonebook attribute on Extensions table
280
     */
281
    private function updateExtensionsTable(): void
282
    {
283
        $showInPhonebookTypes = [
284
            Extensions::TYPE_DIALPLAN_APPLICATION,
285
            Extensions::TYPE_SIP,
286
            Extensions::TYPE_EXTERNAL,
287
            Extensions::TYPE_QUEUE,
288
            Extensions::TYPE_IVR_MENU,
289
            Extensions::TYPE_CONFERENCE,
290
291
        ];
292
        $extensions           = Extensions::find();
293
        foreach ($extensions as $extension) {
294
            if (in_array($extension->type, $showInPhonebookTypes)) {
295
                $extension->show_in_phonebook = '1';
296
                $extension->update();
297
            }
298
        }
299
    }
300
301
    /**
302
     * Moves predefined sound files to storage disk
303
     * Changes SoundFiles records
304
     */
305
    private function moveReadOnlySoundsToStorage(): void
306
    {
307
        $currentMediaDir = $this->config->path('asterisk.customSoundDir') . '/';
308
        if ( ! is_dir($currentMediaDir)) {
309
            Util::mwMkdir($currentMediaDir);
310
        }
311
        $soundFiles = SoundFiles::find();
312
        foreach ($soundFiles as $soundFile) {
313
            if (stripos($soundFile->path, '/offload/asterisk/sounds/other/') === 0) {
314
                $newPath = $currentMediaDir . pathinfo($soundFile->path)['basename'];
315
                if (copy($soundFile->path, $newPath)) {
316
                    $soundFile->path = $newPath;
317
                    $soundFile->update();
318
                }
319
            }
320
        }
321
    }
322
323
324
}