Passed
Push — develop ( 53bcb9...fab6e0 )
by Nikolay
05:05 queued 10s
created

WorkerModelsEvents::reloadPbxConfModules()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
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, 9 2020
7
 */
8
9
namespace MikoPBX\Core\Workers;
10
require_once 'Globals.php';
11
12
use MikoPBX\Common\Models\{AsteriskManagerUsers,
13
    CallQueueMembers,
14
    CallQueues,
15
    Codecs,
16
    ConferenceRooms,
17
    CustomFiles,
18
    DialplanApplications,
19
    ExtensionForwardingRights,
20
    Extensions,
21
    ExternalPhones,
22
    Fail2BanRules,
23
    FirewallRules,
24
    Iax,
25
    IncomingRoutingTable,
26
    IvrMenu,
27
    IvrMenuActions,
28
    LanInterfaces,
29
    NetworkFilters,
30
    OutgoingRoutingTable,
31
    OutWorkTimes,
32
    PbxExtensionModules,
33
    PbxSettings,
34
    Sip,
35
    SoundFiles};
36
use MikoPBX\Core\Asterisk\Configs\QueueConf;
37
use MikoPBX\Core\System\{BeanstalkClient,
38
    Configs\CronConf,
39
    Configs\IptablesConf,
40
    Configs\NatsConf,
41
    Configs\NginxConf,
42
    Configs\SSHConf,
43
    PBX,
44
    System,
45
    Util};
46
use MikoPBX\PBXCoreREST\Workers\WorkerApiCommands;
47
48
ini_set('error_reporting', E_ALL);
49
ini_set('display_startup_errors', 1);
50
51
class WorkerModelsEvents extends WorkerBase
52
{
53
    private const R_MANAGERS = 'reloadManager';
54
55
    private const R_QUEUES = 'reloadQueues';
56
57
    private const R_DIALPLAN = 'reloadDialplan';
58
59
    private const R_PBX_SETTINGS = 'clearCachePbxSettings';
60
61
    private const R_CUSTOM_F = 'updateCustomFiles';
62
63
    private const R_FIREWALL = 'reloadFirewall';
64
65
    private const R_NETWORK = 'networkReload';
66
67
    private const R_IAX = 'reloadIax';
68
69
    private const R_SIP = 'reloadSip';
70
71
    private const R_FEATURES = 'reloadFeatures';
72
73
    private const R_CRON = 'reloadCron';
74
75
    private const R_NGINX = 'reloadNginx';
76
77
    private const R_SSH = 'reloadSSH';
78
79
    private const R_LICENSE = 'reloadLicense';
80
81
    private const R_NATS = 'reloadNats';
82
83
    private const R_VOICEMAIL = 'reloadVoicemail';
84
85
    private const R_REST_API_WORKER = 'reloadRestAPIWorker';
86
87
    private const R_MOH_RELOAD = 'reloadMoh';
88
89
    private const R_CONF_MODULES = 'reloadPbxConfModules';
90
91
    private int $last_change;
92
    private array $modified_tables;
93
94
    private PbxSettings $pbxSettings;
95
    private int $timeout = 3;
96
    private array $arrObject;
97
    private array $PRIORITY_R;
98
    protected int $maxProc=1;
99
100
101
    /**
102
     * Entry point
103
     *
104
     * @param $argv
105
     */
106
    public function start($argv): void
107
    {
108
109
        $this->arrObject = $this->di->getShared('pbxConfModules');
110
111
        $this->PRIORITY_R = [
112
            self::R_CONF_MODULES,
113
            self::R_REST_API_WORKER,
114
            self::R_PBX_SETTINGS,
115
            self::R_NETWORK,
116
            self::R_FIREWALL,
117
            self::R_SSH,
118
            self::R_LICENSE,
119
            self::R_NATS,
120
            self::R_NGINX,
121
            self::R_CRON,
122
            self::R_FEATURES,
123
            self::R_SIP,
124
            self::R_IAX,
125
            self::R_DIALPLAN,
126
            self::R_QUEUES,
127
            self::R_MANAGERS,
128
            self::R_CUSTOM_F,
129
            self::R_VOICEMAIL,
130
            self::R_MOH_RELOAD
131
        ];
132
133
        $this->modified_tables = [];
134
        $this->pbxSettings     = new PbxSettings();
135
136
        $client = new BeanstalkClient();
137
        $client->subscribe(self::class, [$this, 'processModelChanges']);
138
        $client->subscribe($this->makePingTubeName(self::class), [$this, 'pingCallBack']);
139
        $client->setTimeoutHandler([$this, 'timeoutHandler']);
140
141
142
        while (true) {
143
            $client->wait();
144
        }
145
    }
146
147
    /**
148
     * Parser for received Beanstalk message
149
     *
150
     * @param BeanstalkClient $message
151
     */
152
    public function processModelChanges($message): void
153
    {
154
        $receivedMessage = json_decode($message->getBody(), true);
155
        $this->fillModifiedTables($receivedMessage);
156
        $this->startReload();
157
158
        // Send information about models changes to additional modules
159
        foreach ($this->arrObject as $appClass) {
160
            $appClass->modelsEventChangeData($receivedMessage);
161
        }
162
    }
163
164
    /**
165
     * Collect changes to determine which modules must be reloaded or reconfigured
166
     *
167
     * @param $data
168
     */
169
    private function fillModifiedTables($data): void
170
    {
171
        $count_changes = count($this->modified_tables);
172
173
        $called_class = $data['model'] ?? '';
174
        switch ($called_class) {
175
            case AsteriskManagerUsers::class:
176
                $this->modified_tables[self::R_MANAGERS] = true;
177
                break;
178
            case CallQueueMembers::class:
179
                $this->modified_tables[self::R_QUEUES] = true;
180
                break;
181
            case CallQueues::class:
182
                $this->modified_tables[self::R_QUEUES]   = true;
183
                $this->modified_tables[self::R_DIALPLAN] = true;
184
                break;
185
            case ConferenceRooms::class:
186
                $this->modified_tables[self::R_DIALPLAN] = true;
187
                break;
188
            case CustomFiles::class:
189
                $this->modified_tables[self::R_CUSTOM_F] = true;
190
                break;
191
            case DialplanApplications::class:
192
                $this->modified_tables[self::R_DIALPLAN] = true;
193
                break;
194
            case ExtensionForwardingRights::class:
195
                $this->modified_tables[self::R_SIP]      = true;
196
                $this->modified_tables[self::R_DIALPLAN] = true;
197
                break;
198
            case Extensions::class:
199
                $this->modified_tables[self::R_DIALPLAN] = true;
200
                break;
201
            case ExternalPhones::class:
202
                $this->modified_tables[self::R_DIALPLAN] = true;
203
                break;
204
            case Fail2BanRules::class:
205
                $this->modified_tables[self::R_FIREWALL] = true;
206
                break;
207
            case FirewallRules::class:
208
                $this->modified_tables[self::R_FIREWALL] = true;
209
                break;
210
            case Iax::class:
211
                $this->modified_tables[self::R_IAX]      = true;
212
                $this->modified_tables[self::R_DIALPLAN] = true;
213
                break;
214
            case Codecs::class:
215
                $this->modified_tables[self::R_IAX] = true;
216
                $this->modified_tables[self::R_SIP]     = true;
217
                break;
218
            case IncomingRoutingTable::class:
219
                $this->modified_tables[self::R_DIALPLAN] = true;
220
                break;
221
            case IvrMenu::class:
222
                $this->modified_tables[self::R_DIALPLAN] = true;
223
                break;
224
            case SoundFiles::class:
225
                $this->modified_tables[self::R_MOH_RELOAD] = true;
226
                break;
227
            case IvrMenuActions::class:
228
                $this->modified_tables[self::R_DIALPLAN] = true;
229
                break;
230
            case LanInterfaces::class:
231
                $this->modified_tables[self::R_NETWORK] = true;
232
                $this->modified_tables[self::R_IAX]     = true;
233
                $this->modified_tables[self::R_SIP]     = true;
234
                break;
235
            case NetworkFilters::class:
236
                $this->modified_tables[self::R_FIREWALL] = true;
237
                $this->modified_tables[self::R_SIP]      = true;
238
                $this->modified_tables[self::R_MANAGERS] = true;
239
                break;
240
            case OutgoingRoutingTable::class:
241
                $this->modified_tables[self::R_DIALPLAN] = true;
242
                break;
243
            case OutWorkTimes::class:
244
                $this->modified_tables[self::R_DIALPLAN] = true;
245
                break;
246
            case PbxSettings::class:
247
                $this->modified_tables[self::R_PBX_SETTINGS] = true;
248
                $this->pbxSettings->key = $data['recordId'] ?? '';
249
                if ($this->pbxSettings->itHasFeaturesSettingsChanges()) {
250
                    $this->modified_tables[self::R_FEATURES] = true;
251
                }
252
                if ($this->pbxSettings->itHasAMIParametersChanges()) {
253
                    $this->modified_tables[self::R_MANAGERS] = true;
254
                }
255
                if ($this->pbxSettings->itHasIaxParametersChanges()) {
256
                    $this->modified_tables[self::R_IAX] = true;
257
                }
258
                if ($this->pbxSettings->itHasSipParametersChanges()) {
259
                    $this->modified_tables[self::R_SIP] = true;
260
                }
261
                if ($this->pbxSettings->itHasSSHParametersChanges()) {
262
                    $this->modified_tables[self::R_SSH] = true;
263
                }
264
                if ($this->pbxSettings->itHasFirewallParametersChanges()) {
265
                    $this->modified_tables[self::R_FIREWALL] = true;
266
                }
267
                if ($this->pbxSettings->itHasWebParametersChanges()) {
268
                    $this->modified_tables[self::R_NGINX] = true;
269
                }
270
                if ($this->pbxSettings->itHasCronParametersChanges()) {
271
                    $this->modified_tables[self::R_CRON] = true;
272
                }
273
                if ($this->pbxSettings->itHasDialplanParametersChanges()) {
274
                    $this->modified_tables[self::R_DIALPLAN] = true;
275
                }
276
                if ($this->pbxSettings->itHasVoiceMailParametersChanges()) {
277
                    $this->modified_tables[self::R_VOICEMAIL] = true;
278
                }
279
                if ($this->pbxSettings->itHasVisualLanguageSettings()) {
280
                    $this->modified_tables[self::R_REST_API_WORKER] = true;
281
                }
282
                if ('PBXInternalExtensionLength' === $this->pbxSettings->key) {
283
                    $this->modified_tables[self::R_DIALPLAN] = true;
284
                    $this->modified_tables[self::R_SIP]      = true;
285
                }
286
                if ('PBXLicense' === $this->pbxSettings->key) {
287
                    $this->modified_tables[self::R_LICENSE] = true;
288
                    $this->modified_tables[self::R_NATS]    = true;
289
                }
290
                break;
291
            case Sip::class:
292
                $this->modified_tables[self::R_SIP]      = true;
293
                $this->modified_tables[self::R_DIALPLAN] = true;
294
                break;
295
            case SoundFiles::class:
296
                $this->modified_tables[self::R_DIALPLAN] = true;
297
                break;
298
            case PbxExtensionModules::class:
299
                $this->modified_tables[self::R_CONF_MODULES] = true;
300
                $this->modified_tables[self::R_CRON] = true;
301
                break;
302
            default:
303
        }
304
305
        if ($count_changes === 0 && count($this->modified_tables) > 0) {
306
            // Начинаем отсчет времени при получении первой задачи.
307
            $this->last_change = time();
308
        }
309
    }
310
311
    /**
312
     * Apply changes
313
     *
314
     * @return void
315
     */
316
    private function startReload(): void
317
    {
318
        if (count($this->modified_tables) === 0) {
319
            return;
320
        }
321
        $delta = time() - $this->last_change;
322
        if ($delta < $this->timeout) {
323
            return;
324
        }
325
326
        foreach ($this->PRIORITY_R as $method_name) {
327
            $action = $this->modified_tables[$method_name] ?? null;
328
            if ($action === null) {
329
                continue;
330
            }
331
            if (method_exists($this, $method_name)) {
332
                $this->$method_name();
333
            }
334
        }
335
336
        foreach ($this->arrObject as $appClass) {
337
            $appClass->modelsEventNeedReload($this->modified_tables);
338
        }
339
        $this->modified_tables = [];
340
    }
341
342
343
    /**
344
     * Restarts gnats queue server daemon
345
     */
346
    public function reloadNats():void
347
    {
348
        $natsConf = new NatsConf();
349
        $natsConf->reStart();
350
    }
351
352
    /**
353
     * Clear cache pbx settings
354
     */
355
    public function clearCachePbxSettings():void
356
    {
357
        $this->pbxSettings->clearCache(PbxSettings::class);
358
    }
359
360
    /**
361
     * Reloads Asterisk dialplan
362
     */
363
    public function reloadDialplan(): void
364
    {
365
        PBX::dialplanReload();
366
    }
367
368
    /**
369
     * Reloads Asterisk manager interface module
370
     */
371
    public function reloadManager(): void
372
    {
373
        PBX::managerReload();
374
    }
375
376
    /**
377
     * Generates queue.conf and restart asterisk queue module
378
     */
379
    public function reloadQueues(): void
380
    {
381
        QueueConf::queueReload();
382
    }
383
384
    /**
385
     * Updates custom changes in config files
386
     */
387
    public function updateCustomFiles(): void
388
    {
389
        System::updateCustomFiles();
390
    }
391
392
    /**
393
     * Apply iptable settings and restart firewall
394
     */
395
    public function reloadFirewall(): void
396
    {
397
        IptablesConf::reloadFirewall();
398
    }
399
400
    /**
401
     *  Refresh networks configs and restarts network daemon
402
     */
403
    public function networkReload(): void
404
    {
405
        System::networkReload();
406
    }
407
408
    /**
409
     * Refresh IAX configs and reload iax2 module
410
     */
411
    public function reloadIax(): void
412
    {
413
        PBX::iaxReload();
414
    }
415
416
    /**
417
     * Reload MOH file list in Asterisk.
418
     */
419
    public function reloadMoh(): void
420
    {
421
        PBX::mohReload();
422
    }
423
424
    /**
425
     * Refresh SIP configs and reload PJSIP module
426
     */
427
    public function reloadSip(): void
428
    {
429
        PBX::sipReload();
430
    }
431
432
    /**
433
     *  Refresh features configs and reload features module
434
     */
435
    public function reloadFeatures(): void
436
    {
437
        PBX::featuresReload();
438
    }
439
440
    /**
441
     * Restarts CROND daemon
442
     */
443
    public function reloadCron(): void
444
    {
445
        $cron = new CronConf();
446
        $cron->reStart();
447
    }
448
449
    /**
450
     * Restarts Nginx daemon
451
     */
452
    public function reloadNginx(): void
453
    {
454
        $nginxConf  = new NginxConf();
455
        $nginxConf->reStart();
456
    }
457
458
    /**
459
     * Configure SSH settings
460
     */
461
    public function reloadSSH(): void
462
    {
463
        $sshConf = new SSHConf();
464
        $sshConf->configure();
465
    }
466
467
    /**
468
     *  Reloads Asterisk voicemail module
469
     */
470
    public function reloadVoicemail(): void
471
    {
472
        PBX::voicemailReload();
473
    }
474
475
    /**
476
     *  Reloads WorkerApiCommands worker
477
     */
478
    public function reloadRestAPIWorker(): void
479
    {
480
        Util::restartPHPWorker(WorkerApiCommands::class);
481
    }
482
483
    /**
484
     *  Reloads modules property
485
     */
486
    public function reloadPbxConfModules():void
487
    {
488
        $this->arrObject = $this->di->getShared('pbxConfModules');
489
    }
490
491
    /**
492
     * Timeout handles
493
     */
494
    public function timeoutHandler()
495
    {
496
        $this->last_change = time() - $this->timeout;
497
        $this->startReload();
498
    }
499
500
}
501
502
/**
503
 * Start point
504
 */
505
$workerClassname = WorkerModelsEvents::class;
506
if (isset($argv) && count($argv) > 1 && $argv[1] === 'start') {
507
    cli_set_process_title($workerClassname);
508
    try {
509
        $worker = new $workerClassname();
510
        $worker->start($argv);
511
    } catch (\Error $e) {
512
        global $errorLogger;
513
        $errorLogger->captureException($e);
514
        sleep(1);
515
    }
516
}