Passed
Push — develop ( b9c919...bd4ef2 )
by Портнов
05:38
created

WorkerModelsEvents::reloadIax()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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