Passed
Push — develop ( bbba6b...68db6a )
by Nikolay
05:49 queued 11s
created

PbxExtensionUtils   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 132
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 16
eloc 61
dl 0
loc 132
rs 10
c 1
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
B installModule() 0 36 6
A getModuleDir() 0 11 2
A isEnabled() 0 4 2
B uninstallModule() 0 40 6
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, 6 2020
7
 *
8
 */
9
10
namespace MikoPBX\Modules;
11
12
13
use MikoPBX\Common\Models\PbxExtensionModules;
14
use MikoPBX\Core\System\MikoPBXConfig;
15
use MikoPBX\Core\System\Util;
16
use MikoPBX\Core\Workers\Cron\WorkerSafeScriptsCore;
17
use MikoPBX\Modules\Setup\PbxExtensionSetupFailure;
18
use Phalcon\Di;
19
use Phalcon\Di\Exception;
20
21
class PbxExtensionUtils
22
{
23
    /**
24
     * Check module state by UniqueID
25
     * @param string $moduleUniqueID
26
     *
27
     * @return bool
28
     */
29
    public static function isEnabled(string $moduleUniqueID):bool
30
    {
31
        $result        = PbxExtensionModules::findFirstByUniqid($moduleUniqueID);
32
        return ($result!==false && $result->disabled !== '1');
33
    }
34
35
    /**
36
     * Return module dir by UniqueID
37
     * @param string $moduleUniqueID
38
     *
39
     * @return string
40
     * @throws \Phalcon\Di\Exception
41
     */
42
    public static function getModuleDir(string $moduleUniqueID):string
43
    {
44
        $di      = Di::getDefault();
45
46
        if ($di === null){
47
            throw new Exception('\Phalcon\DI not installed');
48
        }
49
        $config  = $di->getShared('config');
50
        $modulesDir    = $config->path('core.modulesDir');
51
52
        return"{$modulesDir}/{$moduleUniqueID}";
53
54
    }
55
56
    /**
57
     * Install module from file
58
     *
59
     * @param string $filePath
60
     *
61
     * @param string $moduleUniqueID
62
     *
63
     * @return array
64
     * @throws \Phalcon\Di\Exception
65
     */
66
    public static function installModule(string $filePath, string $moduleUniqueID):array
67
    {
68
        $result = [];
69
        $error            = false;
70
        $currentModuleDir = self::getModuleDir($moduleUniqueID);
71
        $needBackup       = is_dir($currentModuleDir);
72
73
        if ($needBackup){
74
            self::uninstallModule($moduleUniqueID, true);
75
        }
76
77
        $semZaPath = Util::which('7za');
78
        Util::mwExec("{$semZaPath} e -spf -aoa -o{$currentModuleDir} {$filePath}");
79
        Util::addRegularWWWRights($currentModuleDir);
80
81
        $pbxExtensionSetupClass       = "\\Modules\\{$moduleUniqueID}\\Setup\\PbxExtensionSetup";
82
        if (class_exists($pbxExtensionSetupClass)
83
            && method_exists($pbxExtensionSetupClass, 'installModule'))
84
        {
85
            $setup = new $pbxExtensionSetupClass($moduleUniqueID);
86
            if ( ! $setup->installModule()) {
87
                $error          = true;
88
                $result['data'] = 'Install error:' . implode('<br>', $setup->getMessages());
89
            }
90
        } else {
91
            $result['data'] = "Install error: the class {$pbxExtensionSetupClass} not exists";
92
        }
93
94
        if ($error) {
95
            $result['result'] = 'ERROR';
96
        } else {
97
            $result['result'] = 'Success';
98
            $result['needRestartWorkers'] = true;
99
        }
100
101
        return $result;
102
    }
103
104
    /**
105
     * Uninstall module
106
     * @param string $moduleUniqueID
107
     *
108
     * @param bool   $keepSettings
109
     *
110
     * @return array
111
     * @throws \Phalcon\Di\Exception
112
     */
113
    public static function uninstallModule(string $moduleUniqueID, bool $keepSettings):array
114
    {
115
        $result = [];
116
        $currentModuleDir = self::getModuleDir($moduleUniqueID);
117
        // Kill all module processes
118
        if (is_dir("{$currentModuleDir}/bin")) {
119
            $busyboxPath = Util::which('busybox');
120
            $killPath    = Util::which('kill');
121
            $lsofPath    = Util::which('lsof');
122
            $grepPath    = Util::which('grep');
123
            $awkPath     = Util::which('awk');
124
            $uniqPath    = Util::which('uniq');
125
            Util::mwExec(
126
                "{$busyboxPath} {$killPath} -9 $({$lsofPath} {$currentModuleDir}/bin/* |  {$busyboxPath} {$grepPath} -v COMMAND | {$busyboxPath} {$awkPath}  '{ print $2}' | {$busyboxPath} {$uniqPath})"
127
            );
128
        }
129
        // Uninstall module with keep settings and backup db
130
        $moduleClass = "\\Modules\\{$moduleUniqueID}\\Setup\\PbxExtensionSetup";
131
        if (class_exists($moduleClass)
132
            && method_exists($moduleClass, 'uninstallModule')) {
133
            $setup = new $moduleClass($moduleUniqueID);
134
        } else {
135
            // Заглушка которая позволяет удалить модуль из базы данных, которого нет на диске
136
            $moduleClass = PbxExtensionSetupFailure::class;
137
            $setup       = new $moduleClass($moduleUniqueID);
138
        }
139
        if ($setup->uninstallModule($keepSettings)) {
140
            $result['result'] = 'Success';
141
            $result['needRestartWorkers'] = true;
142
        } else {
143
            $result['result'] = 'ERROR';
144
            $result['data']   = implode('<br>', $setup->getMessages());
145
        }
146
147
        if (is_dir($currentModuleDir)) {
148
            // Broken or very old module. Force uninstall.
149
            $rmPath = Util::which('rm');
150
            Util::mwExec("{$rmPath} -rf {$currentModuleDir}");
151
        }
152
        return $result;
153
    }
154
}