Passed
Push — develop ( 4a8e6d...3766e9 )
by Nikolay
06:00 queued 10s
created

WorkerModelsEvents   F

Complexity

Total Complexity 78

Size/Duplication

Total Lines 505
Duplicated Lines 0 %

Importance

Changes 9
Bugs 0 Features 0
Metric Value
wmc 78
eloc 239
c 9
b 0
f 0
dl 0
loc 505
rs 2.16

26 Methods

Rating   Name   Duplication   Size   Complexity  
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 start() 0 40 2
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 5 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 processModelChanges() 0 9 2
A reloadSip() 0 3 1
A reloadPbxConfModules() 0 3 1
A reloadNats() 0 4 1
A reloadManager() 0 3 1
F fillModifiedTables() 0 162 45
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
    ModelsBase,
30
    NetworkFilters,
31
    OutgoingRoutingTable,
32
    OutWorkTimes,
33
    PbxExtensionModules,
34
    PbxSettings,
35
    Sip,
36
    SoundFiles};
37
use MikoPBX\Core\Asterisk\Configs\QueueConf;
38
use MikoPBX\Core\System\{BeanstalkClient,
39
    Configs\CronConf,
40
    Configs\IptablesConf,
41
    Configs\NatsConf,
42
    Configs\NginxConf,
43
    Configs\NTPConf,
44
    Configs\PHPConf,
45
    Configs\SSHConf,
46
    PBX,
47
    System,
48
    Util};
49
use MikoPBX\PBXCoreREST\Workers\WorkerApiCommands;
50
use Throwable;
51
52
ini_set('error_reporting', E_ALL);
53
ini_set('display_startup_errors', 1);
54
55
class WorkerModelsEvents extends WorkerBase
56
{
57
    private const R_MANAGERS = 'reloadManager';
58
59
    private const R_QUEUES = 'reloadQueues';
60
61
    private const R_DIALPLAN = 'reloadDialplan';
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 int $timeout = 2;
105
    private array $arrObject;
106
    private array $PRIORITY_R;
107
    protected int $maxProc=1;
108
109
110
    /**
111
     * Entry point
112
     *
113
     * @param $argv
114
     */
115
    public function start($argv): void
116
    {
117
118
        $this->arrObject = $this->di->getShared('pbxConfModules');
119
120
        $this->PRIORITY_R = [
121
            self::R_CONF_MODULES,
122
            self::R_REST_API_WORKER,
123
            self::R_NETWORK,
124
            self::R_FIREWALL,
125
            self::R_SSH,
126
            self::R_LICENSE,
127
            self::R_NATS,
128
            self::R_TIMEZONE,
129
            self::R_NTP,
130
            self::R_PHP_FPM,
131
            self::R_NGINX,
132
            self::R_CRON,
133
            self::R_FEATURES,
134
            self::R_SIP,
135
            self::R_IAX,
136
            self::R_DIALPLAN,
137
            self::R_QUEUES,
138
            self::R_MANAGERS,
139
            self::R_CUSTOM_F,
140
            self::R_VOICEMAIL,
141
            self::R_MOH,
142
            self::R_CALL_EVENTS_WORKER,
143
        ];
144
145
        $this->modified_tables = [];
146
147
        $client = new BeanstalkClient();
148
        $client->subscribe(self::class, [$this, 'processModelChanges']);
149
        $client->subscribe($this->makePingTubeName(self::class), [$this, 'pingCallBack']);
150
        $client->setTimeoutHandler([$this, 'timeoutHandler']);
151
152
153
        while (true) {
154
            $client->wait();
155
        }
156
    }
157
158
    /**
159
     * Parses for received Beanstalk message
160
     *
161
     * @param BeanstalkClient $message
162
     */
163
    public function processModelChanges(BeanstalkClient $message): void
164
    {
165
        $receivedMessage = json_decode($message->getBody(), true);
166
        $this->fillModifiedTables($receivedMessage);
167
        $this->startReload();
168
169
        // Send information about models changes to additional modules
170
        foreach ($this->arrObject as $appClass) {
171
            $appClass->modelsEventChangeData($receivedMessage);
172
        }
173
    }
174
175
    /**
176
     * Collects changes to determine which modules must be reloaded or reconfigured
177
     *
178
     * @param $data
179
     */
180
    private function fillModifiedTables($data): void
181
    {
182
        $count_changes = count($this->modified_tables);
183
        $called_class = $data['model'] ?? '';
184
185
        // Clear all caches on any changed models
186
        PbxSettings::clearCache($called_class);
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
                $pbxSettings = PbxSettings::findFirstByKey($data['recordId']);
274
                if ($pbxSettings===null){
275
                    return;
276
                }
277
                if ($pbxSettings->itHasFeaturesSettingsChanges()) {
278
                    $this->modified_tables[self::R_FEATURES] = true;
279
                    $this->modified_tables[self::R_DIALPLAN] = true;
280
                }
281
                if ($pbxSettings->itHasAMIParametersChanges()) {
282
                    $this->modified_tables[self::R_MANAGERS] = true;
283
                }
284
                if ($pbxSettings->itHasIaxParametersChanges()) {
285
                    $this->modified_tables[self::R_IAX] = true;
286
                }
287
                if ($pbxSettings->itHasSipParametersChanges()) {
288
                    $this->modified_tables[self::R_SIP] = true;
289
                }
290
                if ($pbxSettings->itHasSSHParametersChanges()) {
291
                    $this->modified_tables[self::R_SSH] = true;
292
                }
293
                if ($pbxSettings->itHasFirewallParametersChanges()) {
294
                    $this->modified_tables[self::R_FIREWALL] = true;
295
                }
296
                if ($pbxSettings->itHasWebParametersChanges()) {
297
                    $this->modified_tables[self::R_NGINX] = true;
298
                }
299
                if ($pbxSettings->itHasCronParametersChanges()) {
300
                    $this->modified_tables[self::R_CRON] = true;
301
                }
302
                if ($pbxSettings->itHasDialplanParametersChanges()) {
303
                    $this->modified_tables[self::R_DIALPLAN] = true;
304
                }
305
                if ($pbxSettings->itHasVoiceMailParametersChanges()) {
306
                    $this->modified_tables[self::R_VOICEMAIL] = true;
307
                }
308
                if ($pbxSettings->itHasVisualLanguageSettings()) {
309
                    $this->modified_tables[self::R_REST_API_WORKER] = true;
310
                }
311
                if ($pbxSettings->itHasLicenseSettings()) {
312
                    $this->modified_tables[self::R_LICENSE] = true;
313
                    $this->modified_tables[self::R_NATS]    = true;
314
                }
315
                if ($pbxSettings->itHasTimeZoneSettings()) {
316
                    $this->modified_tables[self::R_TIMEZONE]    = true;
317
                    $this->modified_tables[self::R_NGINX]    = true;
318
                    $this->modified_tables[self::R_PHP_FPM]    = true;
319
                    $this->modified_tables[self::R_REST_API_WORKER] = true;
320
                }
321
                if ($pbxSettings->itHasNTPSettings()) {
322
                    $this->modified_tables[self::R_NTP]    = true;
323
                }
324
                if ($pbxSettings->itHasCallRecordSettings()) {
325
                    $this->modified_tables[ self::R_CALL_EVENTS_WORKER]  = true;
326
                }
327
                break;
328
            case Sip::class:
329
                $this->modified_tables[self::R_SIP]      = true;
330
                $this->modified_tables[self::R_DIALPLAN] = true;
331
                break;
332
            case PbxExtensionModules::class:
333
                $this->modified_tables[self::R_CONF_MODULES] = true;
334
                $this->modified_tables[self::R_CRON] = true;
335
                break;
336
            default:
337
        }
338
339
        if ($count_changes === 0 && count($this->modified_tables) > 0) {
340
            // Начинаем отсчет времени при получении первой задачи.
341
            $this->last_change = time();
342
        }
343
344
    }
345
346
    /**
347
     * Apply changes
348
     *
349
     * @return void
350
     */
351
    private function startReload(): void
352
    {
353
        if (count($this->modified_tables) === 0) {
354
            return;
355
        }
356
        $delta = time() - $this->last_change;
357
        if ($delta < $this->timeout) {
358
            return;
359
        }
360
361
        foreach ($this->PRIORITY_R as $method_name) {
362
            $action = $this->modified_tables[$method_name] ?? null;
363
            if ($action === null) {
364
                continue;
365
            }
366
            if (method_exists($this, $method_name)) {
367
                $this->$method_name();
368
            }
369
        }
370
371
        foreach ($this->arrObject as $appClass) {
372
            $appClass->modelsEventNeedReload($this->modified_tables);
373
        }
374
        $this->modified_tables = [];
375
    }
376
377
378
    /**
379
     * Restarts gnats queue server daemon
380
     */
381
    public function reloadNats():void
382
    {
383
        $natsConf = new NatsConf();
384
        $natsConf->reStart();
385
    }
386
387
    
388
    /**
389
     * Reloads Asterisk dialplan
390
     */
391
    public function reloadDialplan(): void
392
    {
393
        PBX::dialplanReload();
394
    }
395
396
    /**
397
     * Reloads Asterisk manager interface module
398
     */
399
    public function reloadManager(): void
400
    {
401
        PBX::managerReload();
402
    }
403
404
    /**
405
     * Generates queue.conf and restart asterisk queue module
406
     */
407
    public function reloadQueues(): void
408
    {
409
        QueueConf::queueReload();
410
    }
411
412
    /**
413
     * Updates custom changes in config files
414
     */
415
    public function updateCustomFiles(): void
416
    {
417
        System::updateCustomFiles();
418
    }
419
420
    /**
421
     * Apply iptable settings and restart firewall
422
     */
423
    public function reloadFirewall(): void
424
    {
425
        IptablesConf::reloadFirewall();
426
    }
427
428
    /**
429
     *  Refresh networks configs and restarts network daemon
430
     */
431
    public function networkReload(): void
432
    {
433
        System::networkReload();
434
    }
435
436
    /**
437
     * Refresh IAX configs and reload iax2 module
438
     */
439
    public function reloadIax(): void
440
    {
441
        PBX::iaxReload();
442
    }
443
444
    /**
445
     * Reload MOH file list in Asterisk.
446
     */
447
    public function reloadMoh(): void
448
    {
449
        PBX::mohReload();
450
    }
451
452
    /**
453
     * Refresh SIP configs and reload PJSIP module
454
     */
455
    public function reloadSip(): void
456
    {
457
        PBX::sipReload();
458
    }
459
460
    /**
461
     *  Refresh features configs and reload features module
462
     */
463
    public function reloadFeatures(): void
464
    {
465
        PBX::featuresReload();
466
    }
467
468
    /**
469
     * Restarts CROND daemon
470
     */
471
    public function reloadCron(): void
472
    {
473
        $cron = new CronConf();
474
        $cron->reStart();
475
    }
476
477
    /**
478
     * Restarts NTP daemon
479
     */
480
    public function reloadNtp(): void
481
    {
482
        NTPConf::configure();
483
    }
484
485
    /**
486
     * Restarts Nginx daemon
487
     */
488
    public function reloadNginx(): void
489
    {
490
        $nginxConf  = new NginxConf();
491
        $nginxConf->generateConf();
492
        $nginxConf->reStart();
493
    }
494
495
    /**
496
     * Restarts PHP-FPM daemon
497
     */
498
    public function reloadPHPFPM(): void
499
    {
500
        PHPConf::reStart();
501
    }
502
503
    /**
504
     * Configure SSH settings
505
     */
506
    public function reloadSSH(): void
507
    {
508
        $sshConf = new SSHConf();
509
        $sshConf->configure();
510
    }
511
512
    /**
513
     * Reconfigure TomeZone settings
514
     */
515
    public function updateTomeZone(): void
516
    {
517
        System::timezoneConfigure();
518
    }
519
520
    /**
521
     *  Reloads Asterisk voicemail module
522
     */
523
    public function reloadVoicemail(): void
524
    {
525
        PBX::voicemailReload();
526
    }
527
528
    /**
529
     *  Reloads WorkerApiCommands worker
530
     */
531
    public function reloadRestAPIWorker(): void
532
    {
533
        Util::processPHPWorker(WorkerApiCommands::class);
534
    }
535
536
537
    /**
538
     *  Reloads WorkerCallEvents worker
539
     */
540
    public function reloadWorkerCallEvents(): void
541
    {
542
        Util::processPHPWorker(WorkerCallEvents::class);
543
    }
544
545
    /**
546
     *  Reloads modules property
547
     */
548
    public function reloadPbxConfModules():void
549
    {
550
        $this->arrObject = $this->di->getShared('pbxConfModules');
551
    }
552
553
    /**
554
     * Timeout handles
555
     */
556
    public function timeoutHandler()
557
    {
558
        $this->last_change = time() - $this->timeout;
559
        $this->startReload();
560
    }
561
562
}
563
564
/**
565
 * Start point
566
 */
567
$workerClassname = WorkerModelsEvents::class;
568
if (isset($argv) && count($argv) > 1 && $argv[1] === 'start') {
569
    cli_set_process_title($workerClassname);
570
    try {
571
        $worker = new $workerClassname();
572
        $worker->start($argv);
573
    } catch (Throwable $e) {
574
        global $errorLogger;
575
        $errorLogger->captureException($e);
576
        sleep(1);
577
    }
578
}