Passed
Pull Request — master (#16)
by Nikolay
13:10 queued 02:12
created

WorkerModelsEvents   F

Complexity

Total Complexity 78

Size/Duplication

Total Lines 509
Duplicated Lines 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
wmc 78
eloc 240
c 6
b 0
f 0
dl 0
loc 509
rs 2.16

27 Methods

Rating   Name   Duplication   Size   Complexity  
A start() 0 42 2
A processModelChanges() 0 9 2
A updateTomeZone() 0 3 1
A reloadIax() 0 3 1
A reloadFirewall() 0 3 1
A reloadFeatures() 0 3 1
A reloadWorkerCallEvents() 0 3 1
A clearCachePbxSettings() 0 3 1
A reloadMoh() 0 3 1
A reloadQueues() 0 3 1
A updateCustomFiles() 0 3 1
A reloadCron() 0 4 1
B startReload() 0 24 7
A reloadNtp() 0 3 1
A reloadNginx() 0 4 1
A reloadVoicemail() 0 3 1
A reloadSSH() 0 4 1
A reloadRestAPIWorker() 0 3 1
A networkReload() 0 3 1
A timeoutHandler() 0 4 1
A reloadPHPFPM() 0 3 1
A reloadSip() 0 3 1
A reloadPbxConfModules() 0 3 1
A reloadNats() 0 4 1
A reloadManager() 0 3 1
F fillModifiedTables() 0 156 44
A reloadDialplan() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like WorkerModelsEvents 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 WorkerModelsEvents, and based on these observations, apply Extract Interface, too.

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