Passed
Push — develop ( dc1165...764b3a )
by Nikolay
07:08 queued 11s
created

UpdateConfigsUpToVer20202730::processUpdate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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