Passed
Push — develop ( 905a46...2a15f6 )
by Портнов
05:00
created

SystemManagementProcessor   F

Complexity

Total Complexity 84

Size/Duplication

Total Lines 625
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 0
Metric Value
wmc 84
eloc 384
dl 0
loc 625
rs 2
c 7
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
D callBack() 0 81 19
A cleaningMainTables() 0 34 5
B statusOfModuleInstallation() 0 35 6
A preCleaning() 0 21 5
B sendMail() 0 23 7
B restoreDefaultSettings() 0 75 8
A installModule() 0 46 5
A cleanSoundFiles() 0 16 4
A disableModule() 0 15 2
A uninstallModule() 0 44 5
A enableModule() 0 15 2
A cleaningOtherExtensions() 0 29 5
B convertAudioFile() 0 53 8
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
 * 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\Models\AsteriskManagerUsers;
23
use MikoPBX\Common\Models\CallQueueMembers;
24
use MikoPBX\Common\Models\CallQueues;
25
use MikoPBX\Common\Models\CustomFiles;
26
use MikoPBX\Common\Models\ExtensionForwardingRights;
27
use MikoPBX\Common\Models\Extensions;
28
use MikoPBX\Common\Models\FirewallRules;
29
use MikoPBX\Common\Models\Iax;
30
use MikoPBX\Common\Models\IncomingRoutingTable;
31
use MikoPBX\Common\Models\IvrMenu;
32
use MikoPBX\Common\Models\IvrMenuActions;
33
use MikoPBX\Common\Models\NetworkFilters;
34
use MikoPBX\Common\Models\OutgoingRoutingTable;
35
use MikoPBX\Common\Models\OutWorkTimes;
36
use MikoPBX\Common\Models\PbxExtensionModules;
37
use MikoPBX\Common\Models\PbxSettings;
38
use MikoPBX\Common\Models\Sip;
39
use MikoPBX\Common\Models\SoundFiles;
40
use MikoPBX\Common\Models\Users;
41
use MikoPBX\Common\Providers\PBXConfModulesProvider;
42
use MikoPBX\Core\Asterisk\CdrDb;
43
use MikoPBX\Core\System\Notifications;
44
use MikoPBX\Core\System\Processes;
45
use MikoPBX\Core\System\System;
46
use MikoPBX\Core\System\Upgrade\UpdateDatabase;
47
use MikoPBX\Core\System\Util;
48
use MikoPBX\Modules\PbxExtensionState;
49
use MikoPBX\Modules\PbxExtensionUtils;
50
use MikoPBX\Modules\Setup\PbxExtensionSetupFailure;
51
use MikoPBX\PBXCoreREST\Workers\WorkerModuleInstaller;
52
use Phalcon\Di;
53
use Phalcon\Di\Injectable;
54
55
class SystemManagementProcessor extends Injectable
56
{
57
    /**
58
     * Processes System requests
59
     *
60
     * @param array $request
61
     *
62
     * @return \MikoPBX\PBXCoreREST\Lib\PBXApiResult
63
     *
64
     * @throws \Exception
65
     */
66
    public static function callBack(array $request): PBXApiResult
67
    {
68
        $action         = $request['action'];
69
        $data           = $request['data'];
70
        $res            = new PBXApiResult();
71
        $res->processor = __METHOD__;
72
        switch ($action) {
73
            case 'reboot':
74
                System::rebootSync();
75
                $res->success = true;
76
                break;
77
            case 'shutdown':
78
                System::shutdown();
79
                $res->success = true;
80
                break;
81
            case 'getDate':
82
                $res->success           = true;
83
                $res->data['timestamp'] = time();
84
                break;
85
            case 'setDate':
86
                $res->success = System::setDate($data['timestamp'], $data['userTimeZone']);
87
                break;
88
            case 'updateMailSettings':
89
                $notifier     = new Notifications();
90
                $res->success = $notifier->sendTestMail();
91
                break;
92
            case 'sendMail':
93
                $res = self::sendMail($data);
94
                break;
95
            case 'unBanIp':
96
                $res = FirewallManagementProcessor::fail2banUnbanAll($data['ip']);
97
                break;
98
            case 'getBanIp':
99
                $res = FirewallManagementProcessor::getBanIp();
100
                break;
101
            case 'upgrade':
102
                $res = self::upgradeFromImg($data['temp_filename']);
103
                break;
104
            case 'installNewModule':
105
                $filePath = $request['data']['filePath'];
106
                $res      = self::installModule($filePath);
107
                break;
108
            case 'statusOfModuleInstallation':
109
                $filePath = $request['data']['filePath'];
110
                $res      = self::statusOfModuleInstallation($filePath);
111
                break;
112
            case 'enableModule':
113
                $moduleUniqueID = $request['data']['uniqid'];
114
                $res            = self::enableModule($moduleUniqueID);
115
                break;
116
            case 'disableModule':
117
                $moduleUniqueID = $request['data']['uniqid'];
118
                $res            = self::disableModule($moduleUniqueID);
119
                break;
120
            case 'uninstallModule':
121
                $moduleUniqueID = $request['data']['uniqid'];
122
                $keepSettings   = $request['data']['keepSettings'] === 'true';
123
                $res            = self::uninstallModule($moduleUniqueID, $keepSettings);
124
                break;
125
            case 'restoreDefault':
126
                $ch = 0;
127
                do{
128
                    $ch++;
129
                    $res = self::restoreDefaultSettings();
130
                    sleep(1);
131
                }while($ch <= 10 && !$res->success);
132
                break;
133
            case 'convertAudioFile':
134
                $mvPath = Util::which('mv');
135
                Processes::mwExec("{$mvPath} {$request['data']['temp_filename']} {$request['data']['filename']}");
136
                $res = self::convertAudioFile($request['data']['filename']);
137
                break;
138
            default:
139
                $res             = new PBXApiResult();
140
                $res->processor  = __METHOD__;
141
                $res->messages[] = "Unknown action - {$action} in systemCallBack";
142
        }
143
144
        $res->function = $action;
145
146
        return $res;
147
    }
148
149
    /**
150
     * Sends test email to admin address
151
     *
152
     * @param                                       $data
153
     *
154
     * @return \MikoPBX\PBXCoreREST\Lib\PBXApiResult $res
155
     */
156
    private static function sendMail($data): PBXApiResult
157
    {
158
        $res            = new PBXApiResult();
159
        $res->processor = __METHOD__;
160
        if (isset($data['email']) && isset($data['subject']) && isset($data['body'])) {
161
            if (isset($data['encode']) && $data['encode'] === 'base64') {
162
                $data['subject'] = base64_decode($data['subject']);
163
                $data['body']    = base64_decode($data['body']);
164
            }
165
            $notifier = new Notifications();
166
            $result   = $notifier->sendMail($data['email'], $data['subject'], $data['body']);
167
            if ($result === true) {
168
                $res->success = true;
169
            } else {
170
                $res->success    = false;
171
                $res->messages[] = 'Notifications::sendMail method returned false';
172
            }
173
        } else {
174
            $res->success    = false;
175
            $res->messages[] = 'Not all query parameters were set';
176
        }
177
178
        return $res;
179
    }
180
181
    /**
182
     * Upgrade MikoPBX from uploaded IMG file
183
     *
184
     * @param string $tempFilename path to uploaded image
185
     *
186
     * @return PBXApiResult
187
     */
188
    public static function upgradeFromImg(string $tempFilename): PBXApiResult
189
    {
190
        $res                  = new PBXApiResult();
191
        $res->processor       = __METHOD__;
192
        $res->success         = true;
193
        $res->data['message'] = 'In progress...';
194
195
196
        if ( ! file_exists($tempFilename)) {
197
            $res->success    = false;
198
            $res->messages[] = "Update file '{$tempFilename}' not found.";
199
200
            return $res;
201
        }
202
203
        if ( ! file_exists('/var/etc/cfdevice')) {
204
            $res->success    = false;
205
            $res->messages[] = "The system is not installed";
206
207
            return $res;
208
        }
209
        $dev = trim(file_get_contents('/var/etc/cfdevice'));
210
211
        $link = '/tmp/firmware_update.img';
212
        Util::createUpdateSymlink($tempFilename, $link);
213
        $mikoPBXFirmwarePath = Util::which('mikopbx_firmware');
214
        Processes::mwExecBg("{$mikoPBXFirmwarePath} recover_upgrade {$link} /dev/{$dev}");
215
216
        return $res;
217
    }
218
219
    /**
220
     * Install new additional extension module
221
     *
222
     * @param $filePath
223
     *
224
     * @return \MikoPBX\PBXCoreREST\Lib\PBXApiResult
225
     *
226
     */
227
    public static function installModule($filePath): PBXApiResult
228
    {
229
        $res            = new PBXApiResult();
230
        $res->processor = __METHOD__;
231
        $resModuleMetadata = FilesManagementProcessor::getMetadataFromModuleFile($filePath);
232
        if ( ! $resModuleMetadata->success) {
233
            return $resModuleMetadata;
234
        }
235
236
        $moduleUniqueID = $resModuleMetadata->data['uniqid'];
237
        // If it enabled send disable action first
238
        if (PbxExtensionUtils::isEnabled($moduleUniqueID)){
239
            $res = self::disableModule($moduleUniqueID);
240
            if (!$res->success){
241
                return $res;
242
            }
243
        }
244
245
        $currentModuleDir = PbxExtensionUtils::getModuleDir($moduleUniqueID);
246
        $needBackup       = is_dir($currentModuleDir);
247
248
        if ($needBackup) {
249
            self::uninstallModule($moduleUniqueID, true);
250
        }
251
252
        // We will start the background process to install module
253
        $temp_dir            = dirname($filePath);
254
        file_put_contents( $temp_dir . '/installation_progress', '0');
255
        file_put_contents( $temp_dir . '/installation_error', '');
256
        $install_settings = [
257
            'filePath' => $filePath,
258
            'currentModuleDir' => $currentModuleDir,
259
            'uniqid' => $moduleUniqueID,
260
        ];
261
        $settings_file  = "{$temp_dir}/install_settings.json";
262
        file_put_contents(
263
            $settings_file,
264
            json_encode($install_settings, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)
265
        );
266
        $phpPath               = Util::which('php');
267
        $workerFilesMergerPath = Util::getFilePathByClassName(WorkerModuleInstaller::class);
268
        Processes::mwExecBg("{$phpPath} -f {$workerFilesMergerPath} start '{$settings_file}'");
269
        $res->data['filePath']= $filePath;
270
        $res->success = true;
271
272
        return $res;
273
    }
274
275
276
    /**
277
     * Uninstall module
278
     *
279
     * @param string $moduleUniqueID
280
     *
281
     * @param bool   $keepSettings
282
     *
283
     * @return PBXApiResult
284
     */
285
    public static function uninstallModule(string $moduleUniqueID, bool $keepSettings): PBXApiResult
286
    {
287
        $res              = new PBXApiResult();
288
        $res->processor   = __METHOD__;
289
        $currentModuleDir = PbxExtensionUtils::getModuleDir($moduleUniqueID);
290
        // Kill all module processes
291
        if (is_dir("{$currentModuleDir}/bin")) {
292
            $busyboxPath = Util::which('busybox');
293
            $killPath    = Util::which('kill');
294
            $lsofPath    = Util::which('lsof');
295
            $grepPath    = Util::which('grep');
296
            $awkPath     = Util::which('awk');
297
            $uniqPath    = Util::which('uniq');
298
            Processes::mwExec(
299
                "{$busyboxPath} {$killPath} -9 $({$lsofPath} {$currentModuleDir}/bin/* |  {$busyboxPath} {$grepPath} -v COMMAND | {$busyboxPath} {$awkPath}  '{ print $2}' | {$busyboxPath} {$uniqPath})"
300
            );
301
        }
302
        // Uninstall module with keep settings and backup db
303
        $moduleClass = "\\Modules\\{$moduleUniqueID}\\Setup\\PbxExtensionSetup";
304
305
        try {
306
            if (class_exists($moduleClass)
307
                && method_exists($moduleClass, 'uninstallModule')) {
308
                $setup = new $moduleClass($moduleUniqueID);
309
            } else {
310
                // Заглушка которая позволяет удалить модуль из базы данных, которого нет на диске
311
                $moduleClass = PbxExtensionSetupFailure::class;
312
                $setup       = new $moduleClass($moduleUniqueID);
313
            }
314
            $setup->uninstallModule($keepSettings);
315
        } finally {
316
            if (is_dir($currentModuleDir)) {
317
                // Broken or very old module. Force uninstall.
318
                $rmPath = Util::which('rm');
319
                Processes::mwExec("{$rmPath} -rf {$currentModuleDir}");
320
321
                $moduleClass = PbxExtensionSetupFailure::class;
322
                $setup       = new $moduleClass($moduleUniqueID);
323
                $setup->unregisterModule();
324
            }
325
        }
326
        $res->success = true;
327
328
        return $res;
329
    }
330
331
    /**
332
     * Enables extension module
333
     *
334
     * @param string $moduleUniqueID
335
     *
336
     * @return \MikoPBX\PBXCoreREST\Lib\PBXApiResult $res
337
     */
338
    private static function enableModule(string $moduleUniqueID): PBXApiResult
339
    {
340
        $res                  = new PBXApiResult();
341
        $res->processor       = __METHOD__;
342
        $moduleStateProcessor = new PbxExtensionState($moduleUniqueID);
343
        if ($moduleStateProcessor->enableModule() === false) {
344
            $res->success  = false;
345
            $res->messages = $moduleStateProcessor->getMessages();
346
        } else {
347
            PBXConfModulesProvider::recreateModulesProvider();
348
            $res->data    = $moduleStateProcessor->getMessages();
349
            $res->success = true;
350
        }
351
352
        return $res;
353
    }
354
355
    /**
356
     * Disables extension module
357
     *
358
     * @param string $moduleUniqueID
359
     *
360
     * @return \MikoPBX\PBXCoreREST\Lib\PBXApiResult $res
361
     */
362
    private static function disableModule(string $moduleUniqueID): PBXApiResult
363
    {
364
        $res                  = new PBXApiResult();
365
        $res->processor       = __METHOD__;
366
        $moduleStateProcessor = new PbxExtensionState($moduleUniqueID);
367
        if ($moduleStateProcessor->disableModule() === false) {
368
            $res->success  = false;
369
            $res->messages = $moduleStateProcessor->getMessages();
370
        } else {
371
            PBXConfModulesProvider::recreateModulesProvider();
372
            $res->data    = $moduleStateProcessor->getMessages();
373
            $res->success = true;
374
        }
375
376
        return $res;
377
    }
378
379
    public static function preCleaning(&$res):void
380
    {
381
        $preCleaning = [
382
            CallQueues::class => [
383
                'redirect_to_extension_if_empty',
384
                'redirect_to_extension_if_unanswered',
385
                'redirect_to_extension_if_repeat_exceeded'
386
            ],
387
            IvrMenu::class => [
388
                'timeout_extension'
389
            ]
390
        ];
391
        foreach ($preCleaning as $class => $columns) {
392
            $records = call_user_func([$class, 'find']);
393
            foreach ($records as $record){
394
                foreach ($columns as $column){
395
                    $record->$column = '';
396
                }
397
                if ( ! $record->save()) {
398
                    $res->messages[] = $record->getMessages();
399
                    $res->success    = false;
400
                }
401
            }
402
        }
403
    }
404
405
    public static function cleaningMainTables(&$res):void
406
    {
407
        // Pre delete some types
408
        $clearThisModels = [
409
            [ExtensionForwardingRights::class => ''],
410
            [OutWorkTimes::class => ''],
411
            [IvrMenuActions::class => ''],
412
            [CallQueueMembers::class => ''],
413
            [OutgoingRoutingTable::class => ''],
414
            [IncomingRoutingTable::class => 'id>1'],
415
            [Sip::class => ''], // All SIP providers
416
            [Iax::class => ''], // All IAX providers
417
            [AsteriskManagerUsers::class => ''],
418
            [Extensions::class => 'type="' . Extensions::TYPE_IVR_MENU . '"'],  // IVR Menu
419
            [Extensions::class => 'type="' . Extensions::TYPE_CONFERENCE . '"'],  // CONFERENCE
420
            [Extensions::class => 'type="' . Extensions::TYPE_QUEUE . '"'],  // QUEUE
421
            [Users::class => 'id>"1"'], // All except root with their extensions
422
            [CustomFiles::class => ''],
423
            [NetworkFilters::class=>'permit!="0.0.0.0/0" AND deny!="0.0.0.0/0"'] //Delete all other rules
424
        ];
425
        foreach ($clearThisModels as $modelParams) {
426
            foreach ($modelParams as $key => $value) {
427
                $records = call_user_func([$key, 'find'], $value);
428
                if (!$records->delete()) {
429
                    $res->messages[] = $records->getMessages();
430
                    $res->success    = false;
431
                }
432
            }
433
        }
434
        // Allow all connections for 0.0.0.0/0
435
        $firewallRules = FirewallRules::find();
436
        foreach ($firewallRules as $firewallRule){
437
            $firewallRule->action = 'allow';
438
            $firewallRule->save();
439
        }
440
    }
441
442
    public static function cleaningOtherExtensions(&$res):void
443
    {
444
        // Other extensions
445
        $parameters     = [
446
            'conditions' => 'not number IN ({ids:array})',
447
            'bind'       => [
448
                'ids' => [
449
                    '000063', // Reads back the extension
450
                    '000064', // 0000MILLI
451
                    '10003246',// Echo test
452
                    '10000100' // Voicemail
453
                ],
454
            ],
455
        ];
456
        $stopDeleting   = false;
457
        $countRecords   = Extensions::count($parameters);
458
        $deleteAttempts = 0;
459
        while ($stopDeleting === false) {
460
            $record = Extensions::findFirst($parameters);
461
            if ($record === null) {
462
                $stopDeleting = true;
463
                continue;
464
            }
465
            if ( ! $record->delete()) {
466
                $deleteAttempts += 1;
467
            }
468
            if ($deleteAttempts > $countRecords * 10) {
469
                $stopDeleting    = true; // Prevent loop
470
                $res->messages[] = $record->getMessages();
471
            }
472
        }
473
    }
474
475
    public static function cleanSoundFiles(&$res):void
476
    {
477
        $rm     = Util::which('rm');
478
        $parameters = [
479
            'conditions' => 'category = :custom:',
480
            'bind'       => [
481
                'custom' => SoundFiles::CATEGORY_CUSTOM,
482
            ],
483
        ];
484
        $records    = SoundFiles::find($parameters);
485
        foreach ($records as $record) {
486
            if (stripos($record->path, '/storage/usbdisk1/mikopbx') !== false) {
487
                Processes::mwExec("{$rm} -rf {$record->path}");
488
                if ( ! $record->delete()) {
489
                    $res->messages[] = $record->getMessages();
490
                    $res->success    = false;
491
                }
492
            }
493
        }
494
    }
495
496
    /**
497
     * Deletes all settings and uploaded files
498
     */
499
    public static function restoreDefaultSettings(): PBXApiResult
500
    {
501
        $res            = new PBXApiResult();
502
        $res->processor = __METHOD__;
503
        $di             = DI::getDefault();
504
        if ($di === null) {
505
            $res->messages[] = 'Error on DI initialize';
506
            return $res;
507
        }
508
        $rm     = Util::which('rm');
509
        $res->success = true;
510
511
        // Change incoming rule to default action
512
        IncomingRoutingTable::resetDefaultRoute();
513
        self::preCleaning($res);
514
515
        self::cleaningMainTables($res);
516
        self::cleaningOtherExtensions($res);
517
        self::cleanSoundFiles($res);
518
519
        // PbxExtensions
520
        $records = PbxExtensionModules::find();
521
        foreach ($records as $record) {
522
            $moduleDir = PbxExtensionUtils::getModuleDir($record->uniqid);
523
            Processes::mwExec("{$rm} -rf {$moduleDir}");
524
            if ( ! $record->delete()) {
525
                $res->messages[] = $record->getMessages();
526
                $res->success    = false;
527
            }
528
        }
529
530
        // Fill PBXSettingsByDefault
531
        $defaultValues = PbxSettings::getDefaultArrayValues();
532
        $fixedKeys = [
533
            'Name',
534
            'Description',
535
            'SSHPassword',
536
            'SSHRsaKey',
537
            'SSHDssKey',
538
            'SSHAuthorizedKeys',
539
            'SSHecdsaKey',
540
            'SSHLanguage',
541
            'WEBHTTPSPublicKey',
542
            'WEBHTTPSPrivateKey',
543
            'RedirectToHttps',
544
            'PBXLanguage',
545
            'PBXVersion',
546
            'WebAdminLogin',
547
            'WebAdminPassword',
548
            'WebAdminLanguage',
549
        ];
550
        foreach ($defaultValues as $key=>$defaultValue){
551
            if (in_array($key, $fixedKeys, true)){
552
                continue;
553
            }
554
            $record = PbxSettings::findFirstByKey($key);
555
            if ($record===null){
556
                $record = new PbxSettings();
557
                $record->key = $key;
558
            }
559
            $record->value = $defaultValue;
560
        }
561
562
        // Delete CallRecords from database
563
        $cdr = CdrDb::getPathToDB();
564
        Processes::mwExec("{$rm} -rf {$cdr}*");
565
        $dbUpdater = new UpdateDatabase();
566
        $dbUpdater->updateDatabaseStructure();
567
568
        // Delete CallRecords sound files
569
        $callRecordsPath = $di->getShared('config')->path('asterisk.monitordir');
570
        if (stripos($callRecordsPath, '/storage/usbdisk1/mikopbx') !== false) {
571
            Processes::mwExec("{$rm} -rf {$callRecordsPath}/*");
572
        }
573
        return $res;
574
    }
575
576
    /**
577
     * Converts file to wav file with 8000 bitrate
578
     *
579
     * @param $filename
580
     *
581
     * @return \MikoPBX\PBXCoreREST\Lib\PBXApiResult
582
     */
583
    public static function convertAudioFile($filename): PBXApiResult
584
    {
585
        $res            = new PBXApiResult();
586
        $res->processor = __METHOD__;
587
        if ( ! file_exists($filename)) {
588
            $res->success    = false;
589
            $res->messages[] = "File '{$filename}' not found.";
590
591
            return $res;
592
        }
593
        $out          = [];
594
        $tmp_filename = '/tmp/' . time() . "_" . basename($filename);
595
        if (false === copy($filename, $tmp_filename)) {
596
            $res->success    = false;
597
            $res->messages[] = "Unable to create temporary file '{$tmp_filename}'.";
598
599
            return $res;
600
        }
601
602
        // Change extension to wav
603
        $n_filename     = Util::trimExtensionForFile($filename) . ".wav";
604
        $n_filename_mp3 = Util::trimExtensionForFile($filename) . ".mp3";
605
        // Convert file
606
        $tmp_filename = escapeshellcmd($tmp_filename);
607
        $n_filename   = escapeshellcmd($n_filename);
608
        $soxPath      = Util::which('sox');
609
        Processes::mwExec("{$soxPath} -v 0.99 -G '{$tmp_filename}' -c 1 -r 8000 -b 16 '{$n_filename}'", $out);
610
        $result_str = implode('', $out);
611
612
        $lamePath = Util::which('lame');
613
        Processes::mwExec("{$lamePath} -b 32 --silent '{$n_filename}' '{$n_filename_mp3}'", $out);
614
        $result_mp3 = implode('', $out);
615
616
        // Чистим мусор.
617
        unlink($tmp_filename);
618
        if ($result_str !== '' && $result_mp3 !== '') {
619
            // Ошибка выполнения конвертации.
620
            $res->success    = false;
621
            $res->messages[] = $result_str;
622
623
            return $res;
624
        }
625
626
        if (file_exists($filename)
627
            && $filename !== $n_filename
628
            && $filename !== $n_filename_mp3) {
629
            unlink($filename);
630
        }
631
632
        $res->success = true;
633
        $res->data[]  = $n_filename_mp3;
634
635
        return $res;
636
    }
637
638
    /**
639
     * Returns Status of module installation process
640
     *
641
     * @param string $filePath
642
     *
643
     * @return \MikoPBX\PBXCoreREST\Lib\PBXApiResult
644
     */
645
    public static function statusOfModuleInstallation(string $filePath): PBXApiResult
646
    {
647
        $res            = new PBXApiResult();
648
        $res->processor = __METHOD__;
649
        $di             = Di::getDefault();
650
        if ($di === null) {
651
            $res->messages[] = 'Dependency injector does not initialized';
652
653
            return $res;
654
        }
655
        $temp_dir            = dirname($filePath);
656
        $progress_file = $temp_dir . '/installation_progress';
657
        $error_file = $temp_dir . '/installation_error';
658
        if (!file_exists($error_file)|| !file_exists($progress_file)){
659
            $res->success                   = false;
660
            $res->data['i_status']          = 'PROGRESS_FILE_NOT_FOUND';
661
            $res->data['i_status_progress'] = '0';
662
        }
663
        elseif (file_get_contents($error_file)!=='') {
664
            $res->success                   = false;
665
            $res->data['i_status']          = 'INSTALLATION_ERROR';
666
            $res->data['i_status_progress'] = '0';
667
            $res->messages[]                = file_get_contents($error_file);
668
        } elseif ('100' === file_get_contents($progress_file)) {
669
            $res->success                   = true;
670
            $res->data['i_status_progress'] = '100';
671
            $res->data['i_status']          = 'INSTALLATION_COMPLETE';
672
        } else {
673
            $res->success                   = true;
674
            $res->data['i_status']          = 'INSTALLATION_IN_PROGRESS';
675
            $res->data['i_status_progress'] = file_get_contents($progress_file);
676
        }
677
678
679
        return $res;
680
    }
681
}