Passed
Push — develop ( 2448c8...de9fda )
by Nikolay
06:00 queued 10s
created

WorkerApiCommands::modulesCallBack()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 12
c 5
b 0
f 0
dl 0
loc 21
rs 9.8666
cc 3
nc 3
nop 1
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, 8 2020
7
 */
8
9
namespace MikoPBX\PBXCoreREST\Workers;
10
11
use MikoPBX\Core\System\{BeanstalkClient, System, Util};
12
use MikoPBX\Core\Workers\WorkerBase;
13
use MikoPBX\PBXCoreREST\Lib\AdvicesProcessor;
14
use MikoPBX\PBXCoreREST\Lib\CdrDBProcessor;
15
use MikoPBX\PBXCoreREST\Lib\IAXStackProcessor;
16
use MikoPBX\PBXCoreREST\Lib\LogsManagementProcessor;
17
use MikoPBX\PBXCoreREST\Lib\PBXApiResult;
18
use MikoPBX\PBXCoreREST\Lib\SIPStackProcessor;
19
use MikoPBX\PBXCoreREST\Lib\StorageManagementProcessor;
20
use MikoPBX\PBXCoreREST\Lib\SysinfoManagementProcessor;
21
use MikoPBX\PBXCoreREST\Lib\SystemManagementProcessor;
22
use MikoPBX\PBXCoreREST\Lib\FilesManagementProcessor;
23
24
require_once 'Globals.php';
25
26
class WorkerApiCommands extends WorkerBase
27
{
28
    /**
29
     * Modules can expose additional REST methods and processors,
30
     * look at src/Modules/Config/RestAPIConfigInterface.php
31
     */
32
    private array $additionalProcessors;
33
34
    private bool $needRestart = false;
35
36
    /**
37
     * @param $argv
38
     */
39
    public function start($argv): void
40
    {
41
        $client = new BeanstalkClient();
42
        $client->subscribe($this->makePingTubeName(self::class), [$this, 'pingCallBack']);
43
        $client->subscribe(__CLASS__, [$this, 'prepareAnswer']);
44
45
        $this->registerModulesProcessors();
46
47
        while ($this->needRestart===false) {
48
            try {
49
                $client->wait();
50
            } catch (\Exception $e) {
51
                global $errorLogger;
52
                $errorLogger->captureException($e);
53
                sleep(1);
54
            }
55
        }
56
    }
57
58
    /**
59
     * Every module config class can process requests under root rights,
60
     * if it described in Config class
61
     */
62
    private function registerModulesProcessors():void
63
    {
64
        $additionalModules          = $this->di->getShared('pbxConfModules');
65
        $this->additionalProcessors = [];
66
        foreach ($additionalModules as $moduleConfigObject) {
67
            if ($moduleConfigObject->moduleUniqueId !== 'InternalConfigModule'
68
                && method_exists($moduleConfigObject, 'moduleRestAPICallback')
69
            ) {
70
                $this->additionalProcessors[] = [
71
                    $moduleConfigObject->moduleUniqueId,
72
                    $moduleConfigObject,
73
                    'moduleRestAPICallback',
74
                ];
75
            }
76
        }
77
    }
78
79
    /**
80
     * Process API request from frontend
81
     *
82
     * @param BeanstalkClient $message
83
     */
84
    public function prepareAnswer($message): void
85
    {
86
        try {
87
            $request   = json_decode($message->getBody(), true, 512, JSON_THROW_ON_ERROR);
88
            $processor = $request['processor'];
89
90
            switch ($processor) {
91
                case 'advices':
92
                    $res = AdvicesProcessor::advicesCallBack($request);
93
                    break;
94
                case 'cdr':
95
                    $res = CdrDBProcessor::cdrCallBack($request);
96
                    break;
97
                case 'sip':
98
                    $res = SIPStackProcessor::sipCallBack($request);
99
                    break;
100
                case 'iax':
101
                    $res = IAXStackProcessor::iaxCallBack($request);
102
                    break;
103
                case 'system':
104
                    $res = SystemManagementProcessor::systemCallBack($request);
105
                    break;
106
                case 'syslog':
107
                    $res = LogsManagementProcessor::syslogCallBack($request);
108
                    break;
109
                case 'sysinfo':
110
                    $res = SysinfoManagementProcessor::sysinfoCallBack($request);
111
                    break;
112
                case 'storage':
113
                    $res = StorageManagementProcessor::storageCallBack($request);
114
                    break;
115
                case 'upload':
116
                    $res = FilesManagementProcessor::uploadCallBack($request);
117
                    break;
118
                case 'modules':
119
                    $res = $this->modulesCallBack($request);
120
                    break;
121
                default:
122
                    $res             = new PBXApiResult();
123
                    $res->processor = __METHOD__;
124
                    $res->success    = false;
125
                    $res->messages[] = "Unknown processor - {$processor} in prepareAnswer";
126
            }
127
        } catch (\Exception $exception) {
128
            $res             = new PBXApiResult();
129
            $res->processor = __METHOD__;
130
            $res->messages[] = 'Exception on WorkerApiCommands - ' . $exception->getMessage();
131
        }
132
133
        $message->reply(json_encode($res->getResult()));
134
135
        // Check if new code added from modules
136
        if (is_array($res->data)
137
            && array_key_exists('needRestartWorkers', $res->data)
138
            && $res->data['needRestartWorkers']
139
        ) {
140
            System::restartAllWorkers();
141
            $this->needRestart=true;
142
        }
143
144
        // Check if modules change state
145
        if (is_array($res->data)
146
            && array_key_exists('needReloadModules', $res->data)
147
            && $res->data['needReloadModules']
148
        ) {
149
            $this->registerModulesProcessors();
150
        }
151
152
    }
153
154
155
    /**
156
     * Processes modules API requests
157
     *
158
     * @param array $request
159
     *
160
     * @return \MikoPBX\PBXCoreREST\Lib\PBXApiResult
161
     */
162
    private function modulesCallBack(array $request): PBXApiResult
163
    {
164
        clearstatcache();
165
166
        $action = $request['action'];
167
        $module = $request['module'];
168
169
        $res             = new PBXApiResult();
170
        $res->processor = __METHOD__;
171
        $res->messages[] = "Unknown action - {$action} in modulesCallBack";
172
        $res->function   = $action;
173
174
        // Try process request over additional modules
175
        foreach ($this->additionalProcessors as [$moduleUniqueId, $moduleConfigObject, $callBack]) {
176
            if (stripos($module, $moduleUniqueId) === 0) {
177
                $res = $moduleConfigObject->$callBack($request);
178
                break;
179
            }
180
        }
181
182
        return $res;
183
    }
184
185
}
186
187
// Start worker process
188
$workerClassname = WorkerApiCommands::class;
189
if (isset($argv) && count($argv) > 1 && $argv[1] === 'start') {
190
    cli_set_process_title($workerClassname);
191
    while (true) {
192
        try {
193
            $worker = new $workerClassname();
194
            $worker->start($argv);
195
        } catch (\Exception $e) {
196
            global $errorLogger;
197
            $errorLogger->captureException($e);
198
            Util::sysLogMsg("{$workerClassname}_EXCEPTION", $e->getMessage());
199
        }
200
    }
201
}
202