Passed
Push — develop ( 08a7fd...d357af )
by Nikolay
04:35
created

ConsoleMenu::start()

Size

Total Lines 64
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 51
c 1
b 0
f 0
dl 0
loc 64
nc 12
nop 0

How to fix   Long Method   

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\Core\System;
21
22
use Closure;
23
use Exception;
24
use LucidFrame\Console\ConsoleTable;
25
use MikoPBX\Common\Models\PbxSettings;
26
use MikoPBX\Common\Models\PbxSettingsConstants;
27
use MikoPBX\Common\Models\Storage as StorageModel;
28
use MikoPBX\Common\Providers\TranslationProvider;
29
use MikoPBX\Core\Config\RegisterDIServices;
30
use MikoPBX\Core\System\{Configs\IptablesConf, Configs\NginxConf};
31
use MikoPBX\Service\Main;
32
use Phalcon\Di;
33
use PhpSchool\CliMenu\Action\GoBackAction;
34
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
35
use PhpSchool\CliMenu\CliMenu;
36
use PhpSchool\CliMenu\Input\InputIO;
37
use PhpSchool\CliMenu\Input\Text;
38
use PhpSchool\CliMenu\MenuStyle;
39
use PhpSchool\CliMenu\Style\SelectableStyle;
40
41
class ConsoleMenu
42
{
43
44
    private bool $isLiveCd;
45
    private bool $isDocker;
46
47
    public function __construct()
48
    {
49
        $this->isLiveCd = file_exists('/offload/livecd');
50
        $this->isDocker = Util::isDocker();
51
    }
52
53
    /**
54
     * Building a network connection setup menu
55
     * @param CliMenuBuilder $menuBuilder
56
     * @return void
57
     */
58
    public function setupLan(CliMenuBuilder $menuBuilder): void
59
    {
60
        $menuBuilder->setTitle(Util::translate('Choose action'))
61
            ->addItem(
62
                '[1] ' . Util::translate('Configuring using DHCP'),
63
                function (CliMenu $menu) {
64
                    // Action for DHCP configuration
65
                    echo Util::translate('The LAN interface will now be configured via DHCP...');
66
                    $network = new Network();
67
                    $data = [];
68
                    $data['dhcp'] = 1;
69
                    $network->updateNetSettings($data);
70
                    $network->lanConfigure();
71
                    $nginxConf = new NginxConf();
72
                    $nginxConf->reStart();
73
                    sleep(1);
74
                    if ($parent = $menu->getParent()) {
75
                        $menu->closeThis();
76
                        $parent->open();
77
                    }
78
                }
79
            )
80
            ->addItem(
81
                '[2] ' . Util::translate('Manual setting'),
82
                function (CliMenu $menu) {
83
                    // Action for manual LAN setting
84
                    $network = new Network();
85
86
                    // Set style for input menu
87
                    $style = (new MenuStyle())
88
                        ->setBg('white')
89
                        ->setFg('black');
90
91
                    // Validate IP address input
92
                    $input_ip = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
93
                        public function validate(string $input): bool
94
                        {
95
                            return Verify::isIpAddress($input);
96
                        }
97
                    };
98
99
                    // Prompt for new LAN IP address
100
                    $elDialog = $input_ip
101
                        ->setPromptText(Util::translate('Enter the new LAN IP address: '))
102
                        ->setValidationFailedText(Util::translate('WARNING'))
103
                        ->ask();
104
                    $lanIp = $elDialog->fetch();
105
106
                    // Prompt for subnet mask
107
                    $helloText = Util::translate('Subnet masks are to be entered as bit counts (as in CIDR notation).');
108
                    $input_bits = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
109
                        public function validate(string $input): bool
110
                        {
111
                            echo $input;
112
                            return (is_numeric($input) && ($input >= 1) && ($input <= 32));
113
                        }
114
                    };
115
                    $elDialog = $input_bits
116
                        ->setPromptText($helloText)
117
                        ->setValidationFailedText('e.g. 32 = 255.255.255.255, 24 = 255.255.255.0')
118
                        ->ask();
119
                    $lanBits = $elDialog->fetch();
120
121
                    // Prompt for LAN gateway IP address
122
                    $elDialog = $input_ip
123
                        ->setPromptText(Util::translate('Enter the LAN gateway IP address: '))
124
                        ->setValidationFailedText(Util::translate('WARNING'))
125
                        ->ask();
126
                    $gwIp = $elDialog->fetch();
127
128
                    // Prompt for LAN DNS IP address
129
                    $elDialog = $input_ip
130
                        ->setPromptText(Util::translate('Enter the LAN DNS IP address: '))
131
                        ->setValidationFailedText(Util::translate('WARNING'))
132
                        ->ask();
133
                    $dnsip = $elDialog->fetch();
134
135
                    // Update network settings and configure LAN
136
                    $data = [];
137
                    $data['ipaddr'] = $lanIp;
138
                    $data['subnet'] = $lanBits;
139
                    $data['gateway'] = $gwIp;
140
                    $data['primarydns'] = $dnsip;
141
                    $data['dhcp'] = '0';
142
143
                    echo Util::translate('The LAN interface will now be configured ...');
144
                    $network->updateNetSettings($data);
145
                    $network->resolvConfGenerate();
146
                    $network->lanConfigure();
147
                    $nginxConf = new NginxConf();
148
                    $nginxConf->reStart();
149
150
                    sleep(1);
151
                    if ($parent = $menu->getParent()) {
152
                        $menu->closeThis();
153
                        $parent->open();
154
                    }
155
                }
156
            )
157
            ->setWidth(75)
158
            ->setBackgroundColour('black', 'black')
159
            ->enableAutoShortcuts()
160
            ->disableDefaultItems()
161
            ->addItem('[3] ' . Util::translate('Cancel'), new GoBackAction());
162
    }
163
164
    /**
165
     * Menu Language Settings
166
     * @param CliMenuBuilder $menuBuilder
167
     * @return void
168
     */
169
    public function setupLanguage(CliMenuBuilder $menuBuilder): void
170
    {
171
        $languages = [
172
            'en' => Util::translate('ex_English'),
173
            'ru' => Util::translate('ex_Russian'),
174
            'de' => Util::translate('ex_Deutsch'),
175
            'es' => Util::translate('ex_Spanish'),
176
            'fr' => Util::translate('ex_French'),
177
            'pt' => Util::translate('ex_Portuguese'),
178
            'uk' => Util::translate('ex_Ukrainian'),
179
            'it' => Util::translate('ex_Italian'),
180
            'da' => Util::translate('ex_Danish'),
181
            'nl' => Util::translate('ex_Dutch'),
182
            'pl' => Util::translate('ex_Polish'),
183
            'sv' => Util::translate('ex_Swedish'),
184
            'az' => Util::translate('ex_Azərbaycan'),
185
            'ro' => Util::translate('ex_Romanian'),
186
            // not able to show in console without additional shell fonts, maybe later we add it
187
            // 'th' => Util::translate('ex_Thai'),
188
            // 'el'      => Util::translate('ex_Greek'),
189
            // 'ka'      => Util::translate('ex_Georgian'),
190
            // 'cs'      => Util::translate('ex_Czech'),
191
            // 'tr'      => Util::translate('ex_Turkish'),
192
            // 'ja'      => Util::translate('ex_Japanese'),
193
            // 'vi'      => Util::translate('ex_Vietnamese'),
194
            // 'zh_Hans' => Util::translate('ex_Chinese'),
195
        ];
196
197
        $menuBuilder->setTitle('Choose shell language')
198
            ->setWidth(75)
199
            ->setBackgroundColour('black', 'black')
200
            ->enableAutoShortcuts()
201
            ->disableDefaultItems();
202
203
        // Apply language selection
204
        $index = 1;
205
        foreach ($languages as $language => $name) {
206
            $menuBuilder->addItem(
207
                "[$index] $name",
208
                function () use ($language) {
209
                    $mikoPBXConfig = new MikoPBXConfig();
210
                    $mikoPBXConfig->setGeneralSettings(PbxSettingsConstants::SSH_LANGUAGE, $language);
211
                    $di = Di::getDefault();
212
                    if ($di) {
213
                        $di->remove(TranslationProvider::SERVICE_NAME);
214
                    }
215
                    $this->start();
216
                }
217
            );
218
            $index++;
219
        }
220
        $menuBuilder->addItem("[$index] Cancel", new GoBackAction());
221
    }
222
223
    /**
224
     * Launching the console menu
225
     * @return void
226
     */
227
    public function start(): void
228
    {
229
        RegisterDIServices::init();
230
231
        // Set Cyrillic font for display
232
        Util::setCyrillicFont();
233
        $separator = '-';
234
        $titleWidth = 75;
235
        $title = str_repeat($separator, 2) . '  ' . Util::translate("PBX console setup") . '  ';
236
        $titleSeparator = mb_substr($title . str_repeat($separator, $titleWidth - mb_strlen($title)), 0, $titleWidth);
237
238
        $menu = new CliMenuBuilder();
239
        $menu->setTitle($this->getBannerText())
240
            ->setTitleSeparator($titleSeparator)
241
            ->enableAutoShortcuts()
242
            ->setPadding(0)
243
            ->setMarginAuto()
244
            ->setForegroundColour('white', 'white')
245
            ->setBackgroundColour('black', 'black')
246
            ->modifySelectableStyle(
247
                function (SelectableStyle $style) {
248
                    $style->setSelectedMarker(' ')
249
                        ->setUnselectedMarker(' ');
250
                }
251
            )
252
            ->setWidth($titleWidth)
253
            ->addItem(' ', static function (CliMenu $menu) {
0 ignored issues
show
Unused Code introduced by
The parameter $menu is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

253
            ->addItem(' ', static function (/** @scrutinizer ignore-unused */ CliMenu $menu) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
254
            })
255
            ->addSubMenu('[1] Change language', Closure::fromCallable([$this, 'setupLanguage']));
256
257
        if ($this->isDocker) {
258
            $menu->addSubMenu('[3] ' . Util::translate('Reboot system'), Closure::fromCallable([$this, 'setupReboot']))
259
                ->addItem('[4] ' . Util::translate('Ping host'), Closure::fromCallable([$this, 'pingAction']))
260
                ->addItem('[5] ' . Util::translate('Firewall') . $this->firewallWarning(), Closure::fromCallable([$this, 'setupFirewall']))
261
                ->addItem('[7] ' . Util::translate('Reset admin password'), Closure::fromCallable([$this, 'resetPassword']));
262
        } elseif ($this->isLiveCd) {
263
            $menu->addSubMenu('[2] ' . Util::translate('Set up LAN IP address'), Closure::fromCallable([$this, 'setupLan']))
264
                ->addSubMenu('[3] ' . Util::translate('Reboot system'), Closure::fromCallable([$this, 'setupReboot']))
265
                ->addItem('[4] ' . Util::translate('Ping host'), Closure::fromCallable([$this, 'pingAction']));
266
            // Add items for live CD options
267
            if (file_exists('/conf.recover/conf')) {
268
                $menu->addItem('[8] ' . Util::translate('Install or recover'), Closure::fromCallable([$this, 'installRecoveryAction']));
269
            } else {
270
                $menu->addItem('[8] ' . Util::translate('Install on Hard Drive'), Closure::fromCallable([$this, 'installAction']));
271
            }
272
        } else {
273
            $menu->addSubMenu('[2] ' . Util::translate('Set up LAN IP address'), Closure::fromCallable([$this, 'setupLan']))
274
                ->addSubMenu('[3] ' . Util::translate('Reboot system'), Closure::fromCallable([$this, 'setupReboot']))
275
                ->addItem('[4] ' . Util::translate('Ping host'), Closure::fromCallable([$this, 'pingAction']))
276
                ->addItem('[5] ' . Util::translate('Firewall') . $this->firewallWarning(), Closure::fromCallable([$this, 'setupFirewall']))
277
                ->addSubMenu('[6] ' . Util::translate('Storage') . $this->storageWarning(), Closure::fromCallable([$this, 'setupStorage']))
278
                ->addItem('[7] ' . Util::translate('Reset admin password'), Closure::fromCallable([$this, 'resetPassword']));
279
        }
280
        $menu->addItem('[9] ' . Util::translate('Console'), Closure::fromCallable([$this, 'consoleAction']))
281
            ->disableDefaultItems();
282
283
        $menuBuilder = $menu->build();
284
        if ($menuBuilder->getTerminal()->isInteractive()) {
285
            echo(str_repeat(PHP_EOL, $menu->getTerminal()->getHeight()));
286
            try {
287
                $menuBuilder->open();
288
            } catch (\Throwable $e) {
289
                Util::sysLogMsg('ConsoleMenu', $e->getMessage());
290
                sleep(1);
291
            }
292
        }
293
    }
294
295
    /**
296
     * Function to get the banner text
297
     */
298
    private function getBannerText(): string
299
    {
300
        $network = new Network();
301
302
        $liveCdText = '';
303
        if ($this->isLiveCd) {
304
            $liveCdText = Util::translate('PBX is running in Live or Recovery mode');
305
        }
306
307
        // Determine version and build time
308
        if (file_exists('/offload/version')) {
309
            $version_file = '/offload/version';
310
        } else {
311
            $version_file = '/etc/version';
312
        }
313
314
        $version = trim(file_get_contents($version_file));
315
        $buildtime = trim(file_get_contents('/etc/version.buildtime'));
316
317
        // Copyright information
318
        $copyright_info = 'MikoPBX is Copyright © 2017-2024. All rights reserved.' . PHP_EOL .
319
            "   \033[01;31m" . $liveCdText . "\033[39m";
320
321
322
        // Get enabled LAN interfaces
323
        $networks = $network->getEnabledLanInterfaces();
324
        $id_text = 0;
325
326
        $countSpaceIP = 1;
327
        $ipTable = [];
328
        $externAddress = '';
329
        foreach ($networks as $if_data) {
330
            $if_data['interface_orign'] = $if_data['interface'];
331
            $if_data['interface'] = ($if_data['vlanid'] > 0) ? "vlan{$if_data['vlanid']}" : $if_data['interface'];
332
            $interface = $network->getInterface($if_data['interface']);
333
334
            // Determine the IP line
335
            if ($if_data['dhcp'] === '1') {
336
                $ip_line = 'IP via DHCP';
337
            } elseif ($if_data['vlanid'] > 0) {
338
                $ip_line = "VLAN via {$if_data['interface_orign']}";
339
                $countSpaceIP = Max($countSpaceIP - 11, strlen($ip_line));
340
            } else {
341
                $ip_line = 'Static IP  ';
342
            }
343
344
            // Determine the IP info
345
            $ip_info = 'unassigned';
346
            if (!empty($interface['ipaddr'])) {
347
                $ip_info = "\033[01;33m{$interface['ipaddr']}\033[39m";
348
            }
349
350
            if (!empty($interface['mac']) && $id_text < 4) {
351
                $ipTable[] = ["{$if_data['interface']}:", $ip_line, $ip_info];
352
                $id_text++;
353
            }
354
355
            if ($if_data['internet'] === '1') {
356
                if (!empty($if_data['exthostname'])) {
357
                    $externAddress = $if_data['exthostname'];
358
                } elseif (!empty($if_data['extipaddr'])) {
359
                    $externAddress = $if_data['extipaddr'];
360
                }
361
            }
362
363
        }
364
365
        // Check for system integrity
366
        $broken = static function () {
367
            if (Util::isT2SdeLinux()) {
368
                $files = Main::checkForCorruptedFiles();
369
                if (count($files) !== 0) {
370
                    return "   \033[01;31m" . Util::translate('The integrity of the system is broken') . "\033[39m";
371
                }
372
            } elseif (php_uname('m') === 'x86_64' && Util::isDocker()) {
373
                $files = Main::checkForCorruptedFiles();
374
                $result = '    Is Docker';
375
                if (count($files) !== 0) {
376
                    $result .= ": \033[01;31m" . Util::translate('The integrity of the system is broken') . "\033[39m";
377
                }
378
                return $result;
379
            } elseif (Util::isDocker()) {
380
                // ARM and other platform...
381
                return '    Is Docker';
382
            } else {
383
                return '    Is Debian';
384
            }
385
            return '';
386
        };
387
388
        // Generate the banner text
389
        $result = "*** " . Util::translate('this_is') . "\033[01;32mMikoPBX v.$version\033[39m" . PHP_EOL .
390
            "   built on $buildtime for Generic (x64)" . PHP_EOL .
391
            "   " . $copyright_info . PHP_EOL;
392
393
394
        // Create and populate the IP table
395
        $table = new ConsoleTable();
396
        foreach ($ipTable as $row) {
397
            $table->addRow($row);
398
        }
399
400
        // Add external address if available
401
        if (!empty($externAddress)) {
402
            $table->addRow(['external:', '', $externAddress]);
403
            $id_text++;
404
        }
405
406
        // Add empty rows if needed
407
        while ($id_text < 4) {
408
            $table->addRow([' ', ' ']);
409
            $id_text++;
410
        }
411
412
        // Append the IP table to the result
413
        $result .= $table->hideBorder()->getTable() . PHP_EOL;
414
415
        // Append system integrity information
416
        $result .= $broken();
417
        return $result;
418
    }
419
420
    /**
421
     * Returns the firewall status text
422
     * @return string
423
     */
424
    public function firewallWarning(): string
425
    {
426
        // Check if firewall is disabled
427
        if (PbxSettings::getValueByKey(PbxSettingsConstants::PBX_FIREWALL_ENABLED) === '0') {
428
            return "\033[01;34m (" . Util::translate('Firewall disabled') . ") \033[39m";
429
        }
430
        return '';
431
    }
432
433
    /**
434
     * Returns the text of the storage status
435
     * @return string
436
     */
437
    public function storageWarning(): string
438
    {
439
        // Check if storage disk is unmounted and not in livecd mode
440
        if (!$this->isLiveCd && !Storage::isStorageDiskMounted()) {
441
            return "    \033[01;31m (" . Util::translate('Storage unmounted') . ") \033[39m";
442
        }
443
        return '';
444
    }
445
446
    /**
447
     * Reboot and Shutdown Settings
448
     * @param CliMenuBuilder $b
449
     * @return void
450
     */
451
    public function setupReboot(CliMenuBuilder $b): void
452
    {
453
        $b->setTitle(Util::translate('Choose action'))
454
            ->enableAutoShortcuts()
455
            ->addItem(
456
                '[1] ' . Util::translate('Reboot'),
457
                function (CliMenu $menu) {
458
                    try {
459
                        $menu->close();
460
                    } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
461
                    }
462
                    file_put_contents('/tmp/rebooting', '1');
463
                    exit(0);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
464
                }
465
            )
466
            ->addItem(
467
                '[2] ' . Util::translate('Power off'),
468
                function (CliMenu $menu) {
469
                    try {
470
                        $menu->close();
471
                    } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
472
                    }
473
                    file_put_contents('/tmp/shutdown', '1');
474
                    exit(0);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
475
                }
476
            )
477
            ->setWidth(75)
478
            ->setForegroundColour('white', 'white')
479
            ->setBackgroundColour('black', 'black')
480
            ->disableDefaultItems()
481
            ->addItem('[3] ' . Util::translate('Cancel'), new GoBackAction());
482
    }
483
484
    /**
485
     * Ping Command Handler
486
     * @param CliMenu $menu
487
     * @return void
488
     */
489
    public function pingAction(CliMenu $menu): void
490
    {
491
        $style = new MenuStyle();
492
        $style->setBg('white')
493
            ->setFg('black');
494
        $input_ip = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
495
        };
496
        $elLanIp = $input_ip
497
            ->setPromptText(Util::translate('Enter a host name or IP address: (Press ESC to exit)'))
498
            ->setValidationFailedText(Util::translate('WARNING'))
499
            ->ask();
500
        $pingHost = $elLanIp->fetch();
501
        $pingPath = Util::which('ping');
502
        $timeoutPath = Util::which('timeout');
503
        passthru("$timeoutPath 4 $pingPath -c3 " . escapeshellarg($pingHost));
504
        sleep(2);
505
        $this->start();
506
    }
507
508
    /**
509
     * Configuring firewall
510
     * @param CliMenu $menu
511
     * @return void
512
     */
513
    public function setupFirewall(CliMenu $menu): void
514
    {
515
        // Code for firewall optionn
516
        $mikoPBXConfig = new MikoPBXConfig();
517
        $firewall_enable = $mikoPBXConfig->getGeneralSettings(PbxSettingsConstants::PBX_FIREWALL_ENABLED);
518
519
        if ($firewall_enable === '1') {
520
            $action = 'disable';
521
        } else {
522
            $action = 'enable';
523
        }
524
525
        $helloText = Util::translate("Do you want $action firewall now? (y/n): ");
526
        $style = (new MenuStyle())
527
            ->setBg('white')
528
            ->setFg('black');
529
530
        $inputDialog = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
531
            public function validate(string $input): bool
532
            {
533
                return ($input === 'y' || $input === 'n');
534
            }
535
        };
536
        $elDialog = $inputDialog
537
            ->setPromptText($helloText)
538
            ->setValidationFailedText(Util::translate('WARNING') . ': y/n')
539
            ->ask();
540
        $result = $elDialog->fetch();
541
542
        if ($result === 'y') {
543
            $enable = '0';
544
            if ('enable' === $action) {
545
                $enable = '1';
546
            }
547
            $mikoPBXConfig->setGeneralSettings(PbxSettingsConstants::PBX_FIREWALL_ENABLED, $enable);
548
            $mikoPBXConfig->setGeneralSettings(PbxSettingsConstants::PBX_FAIL2BAN_ENABLED, $enable);
549
            IptablesConf::reloadFirewall();
550
            echo "Firewall is {$action}d...";
551
        }
552
        $this->start();
553
    }
554
555
    /**
556
     * Setting up a disk for data storage
557
     * @param CliMenuBuilder $b
558
     * @return void
559
     */
560
    public function setupStorage(CliMenuBuilder $b): void
561
    {
562
        $b->setTitle(Util::translate('Choose action'))
563
            ->addItem(
564
                '[1] ' . Util::translate('Connect storage'),
565
                function (CliMenu $menu) {
566
                    // Code for connecting storage
567
                    $menu->close();
568
                    Storage::selectAndConfigureStorageDisk('0');
569
                    sleep(1);
570
                    exit(0);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
571
                }
572
            )
573
            ->addItem(
574
                '[2] ' . Util::translate('Check storage'),
575
                function (CliMenu $menu) {
576
                    // Code for checking storage
577
                    /** @var StorageModel $data */
578
                    $data = StorageModel::findFirst();
579
                    if (!$data) {
0 ignored issues
show
introduced by
$data is of type MikoPBX\Common\Models\Storage, thus it always evaluated to true.
Loading history...
580
                        echo "\n " . Util::translate('Valid disks not found...') . " \n";
581
                        return;
582
                    }
583
                    $style = (new MenuStyle())
584
                        ->setBg('white')
585
                        ->setFg('black');
586
                    $input_ip = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
587
                        public function validate(string $input): bool
588
                        {
589
                            return ($input === 'y' || $input === 'n');
590
                        }
591
                    };
592
                    $elDialog = $input_ip
593
                        ->setPromptText(Util::translate('All processes will be completed. Continue? (y/n):'))
594
                        ->setValidationFailedText(Util::translate('WARNING') . ': y/n')
595
                        ->ask();
596
                    $result = $elDialog->fetch();
597
                    $menu->close();
598
                    if ($result !== 'y') {
599
                        sleep(2);
600
                        exit(0);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
601
                    }
602
                    $dev_name = file_exists("{$data->device}4") ? "{$data->device}4" : "{$data->device}1";
603
604
                    passthru('/sbin/freestorage');
605
                    passthru('e2fsck -f -p ' . escapeshellarg($dev_name), $return_var);
606
                    echo "check return $return_var";
607
                    sleep(2);
608
                    system('/sbin/pbx_reboot');
609
                }
610
            )
611
            ->addItem(
612
                '[3] ' . Util::translate('Resize storage'),
613
                function (CliMenu $menu) {
614
                    // Code for resizing storage
615
                    /** @var StorageModel $data */
616
                    $data = StorageModel::findFirst();
617
                    if ($data === null) {
618
                        echo "\n " . Util::translate('Valid disks not found...') . " \n";
619
                        return;
620
                    }
621
                    $style = (new MenuStyle())
622
                        ->setBg('white')
623
                        ->setFg('black');
624
625
                    $input_ip = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
626
                        public function validate(string $input): bool
627
                        {
628
                            return ($input === 'y' || $input === 'n');
629
                        }
630
                    };
631
                    $elDialog = $input_ip
632
                        ->setPromptText(Util::translate('All processes will be completed. Continue? (y/n):'))
633
                        ->setValidationFailedText(Util::translate('WARNING') . ': y/n')
634
                        ->ask();
635
                    $result = $elDialog->fetch();
636
                    $menu->close();
637
                    if ($result !== 'y') {
638
                        sleep(2);
639
                        exit(0);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
640
                    }
641
642
                    passthru('/sbin/freestorage');
643
                    passthru('/etc/rc/resize_storage_part ' . escapeshellarg($data->device), $return_var);
0 ignored issues
show
Bug introduced by
It seems like $data->device can also be of type null; however, parameter $arg of escapeshellarg() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

643
                    passthru('/etc/rc/resize_storage_part ' . escapeshellarg(/** @scrutinizer ignore-type */ $data->device), $return_var);
Loading history...
644
                    echo "resize storage return $return_var";
645
                    sleep(2);
646
                    if ($return_var === 0) {
647
                        $pbx_rebootPath = Util::which('pbx_reboot');
648
                        Processes::mwExecBg($pbx_rebootPath);
649
                    }
650
                }
651
            )
652
            ->setWidth(75)
653
            ->enableAutoShortcuts()
654
            ->setForegroundColour('white', 'white')
655
            ->setBackgroundColour('black', 'black')
656
            ->disableDefaultItems()
657
            ->addItem('[4] ' . Util::translate('Cancel'), new GoBackAction());
658
    }
659
660
    /**
661
     * Reset web password
662
     * @param CliMenu $menu
663
     * @return void
664
     */
665
    public function resetPassword(CliMenu $menu): void
666
    {
667
        // Code for resetting admin password
668
        $style = (new MenuStyle())
669
            ->setBg('white')
670
            ->setFg('black');
671
672
        $input_ip = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
673
            public function validate(string $input): bool
674
            {
675
                return ($input === 'y' || $input === 'n');
676
            }
677
        };
678
        $elResetPassword = $input_ip
679
            ->setPromptText('Do you want reset password? (y/n):')
680
            ->setValidationFailedText(Util::translate('WARNING') . ': y/n')
681
            ->ask();
682
        $result = $elResetPassword->fetch();
683
        if ($result !== 'y') {
684
            return;
685
        }
686
        try {
687
            $menu->close();
688
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
689
        }
690
        $mikoPBXConfig = new MikoPBXConfig();
691
        $res_login = $mikoPBXConfig->resetGeneralSettings('WebAdminLogin');
692
        $res_password = $mikoPBXConfig->resetGeneralSettings('WebAdminPassword');
693
694
        if ($res_login === true && $res_password === true) {
695
            echo Util::translate('Password successfully reset. New login: admin. New password: admin.');
696
        } else {
697
            echo Util::translate('Error resetting password.');
698
        }
699
        sleep(2);
700
        $this->start();
701
    }
702
703
    /**
704
     * System Installation or Recovery action
705
     * @param CliMenu $menu
706
     * @return void
707
     */
708
    public function installRecoveryAction(CliMenu $menu): void
709
    {
710
        echo "\e[?25h";
711
        try {
712
            $menu->close();
713
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
714
        }
715
        file_put_contents('/tmp/ejectcd', '');
716
        $installer = new PBXRecovery();
717
        $installer->run();
718
        exit(0);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
719
    }
720
721
    /**
722
     * System Installation
723
     * @param CliMenu $menu
724
     * @return void
725
     */
726
    public function installAction(CliMenu $menu): void
727
    {
728
        echo "\e[?25h";
729
        try {
730
            $menu->close();
731
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
732
        }
733
        file_put_contents('/tmp/ejectcd', '');
734
        $installer = new PBXInstaller();
735
        $installer->run();
736
        exit(0);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
737
    }
738
739
    /**
740
     * Console Opening Action
741
     * @param CliMenu $menu
742
     * @return void
743
     */
744
    public function consoleAction(CliMenu $menu): void
745
    {
746
        // Enable cursor
747
        echo "\e[?25h";
748
        try {
749
            $menu->close();
750
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
751
        }
752
        file_put_contents('/tmp/start_sh', '');
753
        exit(0);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
754
    }
755
}