Passed
Push — develop ( a4a90f...fc5c50 )
by Nikolay
05:38
created

Elements::getMenu()   B

Complexity

Conditions 10
Paths 9

Size

Total Lines 51
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 37
c 0
b 0
f 0
dl 0
loc 51
rs 7.6666
cc 10
nc 9
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * MikoPBX - free phone system for small business
4
 * Copyright © 2017-2023 Alexey Portnov and Nikolay Beketov
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with this program.
17
 * If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
namespace MikoPBX\AdminCabinet\Library;
21
22
use MikoPBX\AdminCabinet\Controllers\AsteriskManagersController;
23
use MikoPBX\AdminCabinet\Controllers\CallDetailRecordsController;
24
use MikoPBX\AdminCabinet\Controllers\CallQueuesController;
25
use MikoPBX\AdminCabinet\Controllers\ConferenceRoomsController;
26
use MikoPBX\AdminCabinet\Controllers\ConsoleController;
27
use MikoPBX\AdminCabinet\Controllers\CustomFilesController;
28
use MikoPBX\AdminCabinet\Controllers\DialplanApplicationsController;
29
use MikoPBX\AdminCabinet\Controllers\ExtensionsController;
30
use MikoPBX\AdminCabinet\Controllers\Fail2BanController;
31
use MikoPBX\AdminCabinet\Controllers\FirewallController;
32
use MikoPBX\AdminCabinet\Controllers\GeneralSettingsController;
33
use MikoPBX\AdminCabinet\Controllers\IncomingRoutesController;
34
use MikoPBX\AdminCabinet\Controllers\IvrMenuController;
35
use MikoPBX\AdminCabinet\Controllers\MailSettingsController;
36
use MikoPBX\AdminCabinet\Controllers\NetworkController;
37
use MikoPBX\AdminCabinet\Controllers\OutboundRoutesController;
38
use MikoPBX\AdminCabinet\Controllers\OutOffWorkTimeController;
39
use MikoPBX\AdminCabinet\Controllers\PbxExtensionModulesController;
40
use MikoPBX\AdminCabinet\Controllers\ProvidersController;
41
use MikoPBX\AdminCabinet\Controllers\RestartController;
42
use MikoPBX\AdminCabinet\Controllers\SoundFilesController;
43
use MikoPBX\AdminCabinet\Controllers\SystemDiagnosticController;
44
use MikoPBX\AdminCabinet\Controllers\TimeSettingsController;
45
use MikoPBX\AdminCabinet\Controllers\UpdateController;
46
use MikoPBX\AdminCabinet\Providers\SecurityPluginProvider;
47
use MikoPBX\Common\Models\PbxExtensionModules;
48
use MikoPBX\Common\Models\PbxSettings;
49
use MikoPBX\Common\Providers\PBXConfModulesProvider;
50
use MikoPBX\Modules\Config\WebUIConfigInterface;
51
use Phalcon\Di\Injectable;
52
use Phalcon\Text;
53
54
/**
55
 * Elements
56
 * Helps to build UI elements for the application
57
 *
58
 * @property \MikoPBX\Common\Providers\TranslationProvider translation
59
 *
60
 */
61
class Elements extends Injectable
62
{
63
64
    private array $_headerMenu
65
        = [
66
            'setup' => [
67
                'caption' => 'mm_Setup',
68
                'iconclass' => '',
69
                'submenu' => [
70
                    ExtensionsController::class => [
71
                        'caption' => 'mm_Extensions',
72
                        'iconclass' => 'user outline',
73
                        'action' => 'index',
74
                        'param' => '',
75
                        'style' => '',
76
                    ],
77
                    CallQueuesController::class => [
78
                        'caption' => 'mm_CallQueues',
79
                        'iconclass' => 'users',
80
                        'action' => 'index',
81
                        'param' => '',
82
                        'style' => '',
83
                    ],
84
                    IvrMenuController::class => [
85
                        'caption' => 'mm_IvrMenu',
86
                        'iconclass' => 'sitemap',
87
                        'action' => 'index',
88
                        'param' => '',
89
                        'style' => '',
90
                    ],
91
                    ConferenceRoomsController::class => [
92
                        'caption' => 'mm_ConferenceRooms',
93
                        'iconclass' => 'phone volume',
94
                        'action' => 'index',
95
                        'param' => '',
96
                        'style' => '',
97
                    ],
98
                    SoundFilesController::class => [
99
                        'caption' => 'mm_SoundFiles',
100
                        'iconclass' => 'sound',
101
                        'action' => 'index',
102
                        'param' => '',
103
                        'style' => '',
104
                    ],
105
                    CallDetailRecordsController::class => [
106
                        'caption' => 'mm_CallDetailRecords',
107
                        'iconclass' => 'list ul',
108
                        'action' => 'index',
109
                        'param' => '',
110
                        'style' => '',
111
                    ],
112
                ],
113
            ],
114
            'routing' => [
115
                'caption' => 'mm_Routing',
116
                'iconclass' => '',
117
                'submenu' => [
118
                    ProvidersController::class => [
119
                        'caption' => 'mm_Providers',
120
                        'iconclass' => 'server',
121
                        'action' => 'index',
122
                        'param' => '',
123
                        'style' => '',
124
                    ],
125
                    IncomingRoutesController::class => [
126
                        'caption' => 'mm_IncomingRoutes',
127
                        'iconclass' => 'map signs',
128
                        'action' => 'index',
129
                        'param' => '',
130
                        'style' => '',
131
                    ],
132
                    OutboundRoutesController::class => [
133
                        'caption' => 'mm_OutboundRoutes',
134
                        'iconclass' => 'random',
135
                        'action' => 'index',
136
                        'param' => '',
137
                        'style' => '',
138
                    ],
139
                    OutOffWorkTimeController::class => [
140
                        'caption' => 'mm_OutOffWorkTime',
141
                        'iconclass' => 'calendar times outline',
142
                        'action' => 'index',
143
                        'param' => '',
144
                        'style' => '',
145
                    ],
146
                ],
147
            ],
148
149
            'modules' => [
150
                'caption' => 'mm_PbxExtensionModules',
151
                'iconclass' => '',
152
                'submenu' => [
153
                    DialplanApplicationsController::class => [
154
                        'caption' => 'mm_DialplanApplications',
155
                        'iconclass' => 'php',
156
                        'action' => 'index',
157
                        'param' => '',
158
                        'style' => '',
159
                    ],
160
                    PbxExtensionModulesController::class => [
161
                        'caption' => 'mm_ModuleManager',
162
                        'iconclass' => 'puzzle piece',
163
                        'action' => 'index',
164
                        'param' => '',
165
                        'style' => '',
166
                    ],
167
                ],
168
            ],
169
170
            'maintenance' => [
171
                'caption' => 'mm_Maintenance',
172
                'iconclass' => '',
173
                'submenu' => [
174
                    UpdateController::class => [
175
                        'caption' => 'mm_Update',
176
                        'iconclass' => 'sync',
177
                        'action' => 'index',
178
                        'param' => '',
179
                        'style' => '',
180
                    ],
181
                    SystemDiagnosticController::class => [
182
                        'caption' => 'mm_SystemDiagnostic',
183
                        'iconclass' => 'stethoscope',
184
                        'action' => 'index',
185
                        'param' => '',
186
                        'style' => '',
187
                    ],
188
                    ConsoleController::class => [
189
                        'caption' => 'mm_SSHConsole',
190
                        'iconclass' => 'terminal',
191
                        'action' => 'index',
192
                        'param' => '',
193
                        'style' => '',
194
                    ],
195
                    RestartController::class => [
196
                        'caption' => 'mm_Restart',
197
                        'iconclass' => 'power off',
198
                        'action' => 'manage',
199
                        'param' => '',
200
                        'style' => '',
201
                    ],
202
                ],
203
            ],
204
            'networkSettings' => [
205
                'caption' => 'mm_NetworkSettings',
206
                'iconclass' => '',
207
                'submenu' => [
208
                    NetworkController::class => [
209
                        'caption' => 'mm_Network',
210
                        'iconclass' => 'globe',
211
                        'action' => 'modify',
212
                        'param' => '',
213
                        'style' => '',
214
                    ],
215
                    FirewallController::class => [
216
                        'caption' => 'mm_Firewall',
217
                        'iconclass' => 'shield alternate',
218
                        'action' => 'index',
219
                        'param' => '',
220
                        'style' => '',
221
                    ],
222
                    Fail2BanController::class => [
223
                        'caption' => 'mm_Fail2Ban',
224
                        'iconclass' => 'user secret',
225
                        'action' => 'index',
226
                        'param' => '',
227
                        'style' => '',
228
                    ],
229
                ],
230
            ],
231
            'server' => [
232
                'caption' => 'mm_System',
233
                'iconclass' => '',
234
                'submenu' => [
235
                    GeneralSettingsController::class => [
236
                        'caption' => 'mm_GeneralSettings',
237
                        'iconclass' => 'cogs',
238
                        'action' => 'modify',
239
                        'param' => '',
240
                        'style' => '',
241
                    ],
242
                    TimeSettingsController::class => [
243
                        'caption' => 'mm_TimeSettings',
244
                        'iconclass' => 'time',
245
                        'action' => 'modify',
246
                        'param' => '',
247
                        'style' => '',
248
                    ],
249
                    MailSettingsController::class => [
250
                        'caption' => 'mm_MailSettings',
251
                        'iconclass' => 'envelope outline',
252
                        'action' => 'modify',
253
                        'param' => '',
254
                        'style' => '',
255
                    ],
256
                    AsteriskManagersController::class => [
257
                        'caption' => 'mm_AsteriskManagers',
258
                        'iconclass' => 'asterisk',
259
                        'action' => 'index',
260
                        'param' => '',
261
                        'style' => '',
262
                    ],
263
                    CustomFilesController::class => [
264
                        'caption' => 'mm_CustomFiles',
265
                        'iconclass' => 'linux',
266
                        'action' => 'index',
267
                        'param' => '',
268
                        'style' => '',
269
                    ],
270
                ],
271
            ],
272
273
        ];
274
275
    /**
276
     * Generates the HTML code for the header menu by iterating through the items and checking if they are allowed
277
     * to be displayed by the current user based on their role.
278
     *
279
     * @return void
280
     */
281
    public function getMenu(): void
282
    {
283
        $resultHtml = '';
284
        $this->addMenuItemSSHMenu();
285
        $this->addMenuItemsFromExternalModules();
286
287
        foreach ($this->_headerMenu as $group => $groupparams) {
288
            $addToHTML = false;
289
            $groupHtml = '';
290
            if (array_key_exists('submenu', $groupparams)) {
291
                $groupHtml .= '<div class="item">';
292
                $groupHtml .= '<div class="header">';
293
                if (array_key_exists('iconclass', $groupparams) && !empty($groupparams['iconclass'])) {
294
                    $groupHtml .= "<i class='{$groupparams['iconclass']} icon'></i>";
295
                }
296
                $groupHtml .= $this->translation->_($groupparams['caption']) . '</div>';
297
                $groupHtml .= "<div class='menu' data-group='{$group}'>";
298
                foreach ($groupparams['submenu'] as $controller => $option) {
299
                    $isAllowed = $this->di->get(SecurityPluginProvider::SERVICE_NAME, [$controller, $option['action']]);
300
                    if ($isAllowed) {
301
                        $link = $this->getLinkToControllerAction($controller,  $option['action'], $option['param']);
302
                        $caption = $this->translation->_($option['caption']);
303
                        $groupHtml .= "<a class='item {$option['style']}' href='{$link}'";
304
                        if (isset($option['data-value'])) {
305
                            $groupHtml .= " data-value='{$option['data-value']}'";
306
                        }
307
                        $groupHtml .= ">
308
                    		<i class='{$option['iconclass']} icon'></i>{$caption}
309
                    	 </a>";
310
311
                        $addToHTML = true;
312
                    }
313
                }
314
                $groupHtml .= '</div>';
315
                $groupHtml .= '</div>';
316
            } else {
317
                $isAllowedGroup = $this->di->get(SecurityPluginProvider::SERVICE_NAME, [$group, $groupparams['action'] ?? 'index']);
318
                if ($isAllowedGroup) {
319
                    $link = $this->getLinkToControllerAction($group,  $groupparams['action'], $groupparams['param']);
320
                    $caption = $this->translation->_($groupparams['caption']);
321
                    $groupHtml .= "<a class='item {$groupparams['style']}' href='{$link}'>
322
                    	    <i class='{$groupparams['iconclass']} icon'></i>{$caption}
323
                        </a>";
324
                    $addToHTML = true;
325
                }
326
            }
327
            if ($addToHTML) {
328
                $resultHtml .= $groupHtml;
329
            }
330
        }
331
        echo $resultHtml;
332
    }
333
334
    /**
335
     * Returns icon html by controller full class name
336
     *
337
     * @param $controllerClass
338
     *
339
     * @return string
340
     */
341
    public function getIconByController($controllerClass): string
342
    {
343
        $result = '';
344
        foreach ($this->_headerMenu as $index => $group) {
345
            if ($index === $controllerClass
346
                && array_key_exists('iconclass', $group[$controllerClass])
347
                && !empty($group[$controllerClass]['iconclass'])
348
            ) {
349
                $result = "<i class='{$group[$controllerClass]['iconclass']} icon'></i>";
350
                break;
351
            }
352
            if (array_key_exists('submenu', $group)) {
353
                foreach ($group['submenu'] as $index2 => $submenu) {
354
                    if ($index2 === $controllerClass
355
                        && !empty($submenu['iconclass'])) {
356
                        $result = "<i class='{$submenu['iconclass']} icon'></i>";
357
                        break;
358
                    }
359
                }
360
            }
361
        }
362
363
        return $result;
364
    }
365
366
    /**
367
     * Returns an array with the allowed menu groups based on the current user's permissions.
368
     *
369
     * @return array An array of the allowed menu groups where the key is the group name and the value is its caption.
370
     */
371
    public function getMenuGroups(): array
372
    {
373
        $result = [];
374
        foreach ($this->_headerMenu as $group => $groupparams) {
375
            if (array_key_exists('submenu', $groupparams)) {
376
                $result[$group] = $this->translation->_($groupparams['caption']);
377
            }
378
        }
379
380
        return $result;
381
    }
382
383
384
    /**
385
     * Prepares array of available WEB UI languages
386
     * @return array
387
     */
388
    public function getAvailableWebAdminLanguages(): array
389
    {
390
        return [
391
            'en' => $this->translation->_('ex_English'),
392
            'ru' => $this->translation->_('ex_Russian'),
393
            'de' => $this->translation->_('ex_Deutsch'),
394
            'es' => $this->translation->_('ex_Spanish'),
395
            'el' => $this->translation->_('ex_Greek'),
396
            'fr' => $this->translation->_('ex_French'),
397
            'pt' => $this->translation->_('ex_Portuguese'),
398
            'pt_BR' => $this->translation->_('ex_PortugueseBrazil'),
399
            'uk' => $this->translation->_('ex_Ukrainian'),
400
            'ka' => $this->translation->_('ex_Georgian'),
401
            'it' => $this->translation->_('ex_Italian'),
402
            'da' => $this->translation->_('ex_Danish'),
403
            'pl' => $this->translation->_('ex_Polish'),
404
            'sv' => $this->translation->_('ex_Swedish'),
405
            'cs' => $this->translation->_('ex_Czech'),
406
            'tr' => $this->translation->_('ex_Turkish'),
407
            'ja' => $this->translation->_('ex_Japanese'),
408
            'vi' => $this->translation->_('ex_Vietnamese'),
409
            'az' => $this->translation->_('ex_Azərbaycan'),
410
            'zh_Hans' => $this->translation->_('ex_Chinese'),
411
        ];
412
    }
413
414
    /**
415
     * Adds menu items from enabled external modules to the header menu.
416
     *
417
     * @return void
418
     */
419
    private function addMenuItemsFromExternalModules(): void
420
    {
421
        $modules = PbxExtensionModules::getEnabledModulesArray();
422
        foreach ($modules as $module) {
423
            $moduleUniqId = $module['uniqid'];
424
            $moduleMainController = "Modules\\{$moduleUniqId}\\App\\Controllers\\{$moduleUniqId}Controller";
425
            if (!class_exists($moduleMainController) || !method_exists($moduleMainController, 'indexAction')) {
426
                continue;
427
            }
428
            $menuSettingsKey = "AdditionalMenuItem{$moduleUniqId}";
429
            $menuSettings = PbxSettings::findFirstByKey($menuSettingsKey);
430
            if ($menuSettings !== null) {
431
                $menuItem = json_decode($menuSettings->value, true);
432
                if ($menuItem['showAtSidebar']) {
433
                    $this->_headerMenu[$menuItem['group']]['submenu'][$moduleMainController] = [
434
                        'caption' => $menuItem['caption'],
435
                        'iconclass' => $menuItem['iconClass'],
436
                        'action' => 'index',
437
                        'param' => '',
438
                        'style' => '',
439
                    ];
440
                }
441
            }
442
        }
443
444
        PBXConfModulesProvider::hookModulesMethod(WebUIConfigInterface::ON_BEFORE_HEADER_MENU_SHOW, [&$this->_headerMenu]);
445
    }
446
447
    /**
448
     * Modifies SSH console menu item
449
     *
450
     * @return void
451
     */
452
    private function addMenuItemSSHMenu(): void
453
    {
454
        if (PbxSettings::getValueByKey('SSHDisablePasswordLogins') !== '1') {
455
            $sshPort = PbxSettings::getValueByKey('SSHPort');
456
            $this->_headerMenu['maintenance']['submenu'][ConsoleController::class]['data-value'] = "root@{$_SERVER['SERVER_ADDR']}:$sshPort";
457
        } else {
458
            unset ($this->_headerMenu['maintenance']['submenu'][ConsoleController::class]);
459
        }
460
    }
461
462
    /**
463
     * Get the link to a controller action.
464
     *
465
     * @param string $controller The controller namespace.
466
     * @param string $action The action name.
467
     * @param string $param The parameter value.
468
     *
469
     * @return string The generated link.
470
     */
471
    private function getLinkToControllerAction(string $controller, string $action, string $param): string
472
    {
473
        $controllerParts = explode('\\', $controller);
474
        $controllerName = end($controllerParts);
475
        // Remove the "Controller" suffix if present
476
        $controllerName = str_replace("Controller", "", $controllerName);
477
478
        // Convert the controller name to a dash-separated format
479
        $controllerName = Text::uncamelize($controllerName, '-');
480
481
        if ($controllerParts[0]==='Module'){
482
            // Convert the module name to a dash-separated format
483
            $moduleName = Text::uncamelize($controllerParts[1], '-');
484
            $url = $this->url->get("$moduleName/$controllerName/$action/$param");
485
        } else {
486
            $url = $this->url->get("$controllerName/$action/$param");
487
        }
488
489
        return $url;
490
    }
491
492
}
493