ConsoleMenu::getBannerText()
last analyzed

Size

Total Lines 119
Code Lines 70

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 70
dl 0
loc 119
c 1
b 0
f 0
nc 3104
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
/*
4
 * MikoPBX - free phone system for small business
5
 * Copyright © 2017-2025 Alexey Portnov and Nikolay Beketov
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License along with this program.
18
 * If not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
namespace MikoPBX\Core\System;
22
23
use Closure;
24
use Exception;
25
use LucidFrame\Console\ConsoleTable;
26
use MikoPBX\Common\Models\PbxSettings;
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\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
    private bool $isLiveCd;
44
    private bool $isDocker;
45
46
    public function __construct()
47
    {
48
        $this->isLiveCd = file_exists('/offload/livecd');
49
        $this->isDocker = Util::isDocker();
50
    }
51
52
    /**
53
     * Building a network connection setup menu
54
     * @param CliMenuBuilder $menuBuilder
55
     * @return void
56
     */
57
    public function setupLan(CliMenuBuilder $menuBuilder): void
58
    {
59
        $menuBuilder->setTitle(Util::translate('Choose action'))
60
            ->addItem(
61
                '[1] ' . Util::translate('Configuring using DHCP'),
62
                function (CliMenu $menu) {
63
                    // Action for DHCP configuration
64
                    echo Util::translate('The LAN interface will now be configured via DHCP...');
65
                    $network = new Network();
66
                    $data = [];
67
                    $data['dhcp'] = 1;
68
                    $network->updateNetSettings($data);
69
                    $network->lanConfigure();
70
                    $nginxConf = new NginxConf();
71
                    $nginxConf->reStart();
72
                    sleep(1);
73
                    if ($parent = $menu->getParent()) {
74
                        $menu->closeThis();
75
                        $parent->open();
76
                    }
77
                }
78
            )
79
            ->addItem(
80
                '[2] ' . Util::translate('Manual setting'),
81
                function (CliMenu $menu) {
82
                    // Action for manual LAN setting
83
                    $network = new Network();
84
85
                    // Set style for input menu
86
                    $style = (new MenuStyle())
87
                        ->setBg('white')
88
                        ->setFg('black');
89
90
                    // Validate IP address input
91
                    $input_ip = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
92
                        public function validate(string $input): bool
93
                        {
94
                            return Verify::isIpAddress($input);
95
                        }
96
                    };
97
98
                    // Prompt for new LAN IP address
99
                    $elDialog = $input_ip
100
                        ->setPromptText(Util::translate('Enter the new LAN IP address: '))
101
                        ->setValidationFailedText(Util::translate('WARNING'))
102
                        ->ask();
103
                    $lanIp = $elDialog->fetch();
104
105
                    // Prompt for subnet mask
106
                    $helloText = Util::translate('Subnet masks are to be entered as bit counts (as in CIDR notation).');
107
                    $input_bits = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
108
                        public function validate(string $input): bool
109
                        {
110
                            echo $input;
111
                            return (is_numeric($input) && ($input >= 1) && ($input <= 32));
112
                        }
113
                    };
114
                    $elDialog = $input_bits
115
                        ->setPromptText($helloText)
116
                        ->setValidationFailedText('e.g. 32 = 255.255.255.255, 24 = 255.255.255.0')
117
                        ->ask();
118
                    $lanBits = $elDialog->fetch();
119
120
                    // Prompt for LAN gateway IP address
121
                    $elDialog = $input_ip
122
                        ->setPromptText(Util::translate('Enter the LAN gateway IP address: '))
123
                        ->setValidationFailedText(Util::translate('WARNING'))
124
                        ->ask();
125
                    $gwIp = $elDialog->fetch();
126
127
                    // Prompt for LAN DNS IP address
128
                    $elDialog = $input_ip
129
                        ->setPromptText(Util::translate('Enter the LAN DNS IP address: '))
130
                        ->setValidationFailedText(Util::translate('WARNING'))
131
                        ->ask();
132
                    $dnsip = $elDialog->fetch();
133
134
                    // Update network settings and configure LAN
135
                    $data = [];
136
                    $data['ipaddr'] = $lanIp;
137
                    $data['subnet'] = $lanBits;
138
                    $data['gateway'] = $gwIp;
139
                    $data['primarydns'] = $dnsip;
140
                    $data['dhcp'] = '0';
141
142
                    echo Util::translate('The LAN interface will now be configured ...');
143
                    $network->updateNetSettings($data);
144
                    $network->resolvConfGenerate();
145
                    $network->lanConfigure();
146
                    $nginxConf = new NginxConf();
147
                    $nginxConf->reStart();
148
149
                    sleep(1);
150
                    if ($parent = $menu->getParent()) {
151
                        $menu->closeThis();
152
                        $parent->open();
153
                    }
154
                }
155
            )
156
            ->setWidth(75)
157
            ->setBackgroundColour('black', 'black')
158
            ->enableAutoShortcuts()
159
            ->disableDefaultItems()
160
            ->addItem('[3] ' . Util::translate('Cancel'), new GoBackAction());
161
    }
162
163
    /**
164
     * Menu Language Settings
165
     * @param CliMenuBuilder $menuBuilder
166
     * @return void
167
     */
168
    public function setupLanguage(CliMenuBuilder $menuBuilder): void
169
    {
170
        $languages = [
171
            'en' => Util::translate('ex_English'),
172
            'ru' => Util::translate('ex_Russian'),
173
            'de' => Util::translate('ex_Deutsch'),
174
            'es' => Util::translate('ex_Spanish'),
175
            'fr' => Util::translate('ex_French'),
176
            'pt' => Util::translate('ex_Portuguese'),
177
            'uk' => Util::translate('ex_Ukrainian'),
178
            'it' => Util::translate('ex_Italian'),
179
            'da' => Util::translate('ex_Danish'),
180
            'nl' => Util::translate('ex_Dutch'),
181
            'pl' => Util::translate('ex_Polish'),
182
            'sv' => Util::translate('ex_Swedish'),
183
            'az' => Util::translate('ex_Azerbaijan'),
184
            'ro' => Util::translate('ex_Romanian'),
185
            // not able to show in console without additional shell fonts, maybe later we add it
186
            // 'th' => Util::translate('ex_Thai'),
187
            // 'el'      => Util::translate('ex_Greek'),
188
            // 'ka'      => Util::translate('ex_Georgian'),
189
            // 'cs'      => Util::translate('ex_Czech'),
190
            // 'tr'      => Util::translate('ex_Turkish'),
191
            // 'ja'      => Util::translate('ex_Japanese'),
192
            // 'vi'      => Util::translate('ex_Vietnamese'),
193
            // 'zh_Hans' => Util::translate('ex_Chinese'),
194
        ];
195
196
        $menuBuilder->setTitle('Choose shell language')
197
            ->setWidth(75)
198
            ->setBackgroundColour('black', 'black')
199
            ->enableAutoShortcuts()
200
            ->disableDefaultItems();
201
202
        // Apply language selection
203
        $index = 1;
204
        foreach ($languages as $language => $name) {
205
            $menuBuilder->addItem(
206
                "[$index] $name",
207
                function () use ($language) {
208
                    PbxSettings::setValueByKey(PbxSettings::SSH_LANGUAGE, $language);
209
                    $di = Di::getDefault();
210
                    $di?->remove(TranslationProvider::SERVICE_NAME);
211
                    $this->start();
212
                }
213
            );
214
            $index++;
215
        }
216
        $menuBuilder->addItem("[$index] Cancel", new GoBackAction());
217
    }
218
219
    /**
220
     * Launching the console menu
221
     * @return void
222
     */
223
    public function start(): void
224
    {
225
        RegisterDIServices::init();
226
227
        // Set Cyrillic font for display
228
        Util::setCyrillicFont();
229
        $separator = '-';
230
        $titleWidth = 75;
231
        $title = str_repeat($separator, 2) . '  ' . Util::translate("PBX console setup") . '  ';
232
        $titleSeparator = mb_substr($title . str_repeat($separator, $titleWidth - mb_strlen($title)), 0, $titleWidth);
233
234
        $menu = new CliMenuBuilder();
235
        $menu->setTitle($this->getBannerText())
236
            ->setTitleSeparator($titleSeparator)
237
            ->enableAutoShortcuts()
238
            ->setPadding(0)
239
            ->setMarginAuto()
240
            ->setForegroundColour('white', 'white')
241
            ->setBackgroundColour('black', 'black')
242
            ->modifySelectableStyle(
243
                function (SelectableStyle $style) {
244
                    $style->setSelectedMarker(' ')
245
                        ->setUnselectedMarker(' ');
246
                }
247
            )
248
            ->setWidth($titleWidth)
249
            ->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

249
            ->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...
250
            })
251
            ->addSubMenu('[1] Change language', Closure::fromCallable([$this, 'setupLanguage']));
252
253
        if ($this->isDocker) {
254
            $menu->addSubMenu('[3] ' . Util::translate('Reboot system'), Closure::fromCallable([$this, 'setupReboot']))
255
                ->addItem('[4] ' . Util::translate('Ping host'), Closure::fromCallable([$this, 'pingAction']))
256
                ->addItem('[5] ' . Util::translate('Firewall') . $this->firewallWarning(), Closure::fromCallable([$this, 'setupFirewall']))
257
                ->addItem('[7] ' . Util::translate('Reset admin password'), Closure::fromCallable([$this, 'resetPassword']));
258
        } elseif ($this->isLiveCd) {
259
            $menu->addSubMenu('[2] ' . Util::translate('Set up LAN IP address'), Closure::fromCallable([$this, 'setupLan']))
260
                ->addSubMenu('[3] ' . Util::translate('Reboot system'), Closure::fromCallable([$this, 'setupReboot']))
261
                ->addItem('[4] ' . Util::translate('Ping host'), Closure::fromCallable([$this, 'pingAction']));
262
            // Add items for live CD options
263
            if (file_exists('/conf.recover/conf')) {
264
                $menu->addItem('[8] ' . Util::translate('Install or recover'), Closure::fromCallable([$this, 'installRecoveryAction']));
265
            } else {
266
                $menu->addItem('[8] ' . Util::translate('Install on Hard Drive'), Closure::fromCallable([$this, 'installAction']));
267
            }
268
        } else {
269
            $menu->addSubMenu('[2] ' . Util::translate('Set up LAN IP address'), Closure::fromCallable([$this, 'setupLan']))
270
                ->addSubMenu('[3] ' . Util::translate('Reboot system'), Closure::fromCallable([$this, 'setupReboot']))
271
                ->addItem('[4] ' . Util::translate('Ping host'), Closure::fromCallable([$this, 'pingAction']))
272
                ->addItem('[5] ' . Util::translate('Firewall') . $this->firewallWarning(), Closure::fromCallable([$this, 'setupFirewall']))
273
                ->addSubMenu('[6] ' . Util::translate('Storage') . $this->storageWarning(), Closure::fromCallable([$this, 'setupStorage']))
274
                ->addItem('[7] ' . Util::translate('Reset admin password'), Closure::fromCallable([$this, 'resetPassword']));
275
        }
276
        $menu->addItem('[9] ' . Util::translate('Console'), Closure::fromCallable([$this, 'consoleAction']))
277
            ->disableDefaultItems();
278
279
        $menuBuilder = $menu->build();
280
        if ($menuBuilder->getTerminal()->isInteractive()) {
281
            echo(str_repeat(PHP_EOL, $menu->getTerminal()->getHeight()));
282
            try {
283
                $menuBuilder->open();
284
            } catch (\Throwable $e) {
285
                SystemMessages::sysLogMsg('ConsoleMenu', $e->getMessage());
286
                sleep(1);
287
            }
288
        }
289
    }
290
291
    /**
292
     * Function to get the banner text
293
     */
294
    private function getBannerText(): string
295
    {
296
        $network = new Network();
297
298
        $liveCdText = '';
299
        if ($this->isLiveCd) {
300
            $liveCdText = Util::translate('PBX is running in Live or Recovery mode');
301
        }
302
303
        // Determine version and build time
304
        if (file_exists('/offload/version')) {
305
            $version_file = '/offload/version';
306
        } else {
307
            $version_file = '/etc/version';
308
        }
309
310
        $version = trim(file_get_contents($version_file));
311
        $buildtime = trim(file_get_contents('/etc/version.buildtime'));
312
313
        // Copyright information
314
        $copyright_info = 'MikoPBX is Copyright © 2017-2025. All rights reserved.' . PHP_EOL .
315
            "   \033[01;31m" . $liveCdText . "\033[39m";
316
317
318
        // Get enabled LAN interfaces
319
        $networks = $network->getEnabledLanInterfaces();
320
        $id_text = 0;
321
322
        $countSpaceIP = 1;
323
        $ipTable = [];
324
        $externAddress = '';
325
        foreach ($networks as $if_data) {
326
            $if_data['interface_orign'] = $if_data['interface'];
327
            $if_data['interface'] = ($if_data['vlanid'] > 0) ? "vlan{$if_data['vlanid']}" : $if_data['interface'];
328
            $interface = $network->getInterface($if_data['interface']);
329
330
            // Determine the IP line
331
            if ($if_data['dhcp'] === '1') {
332
                $ip_line = 'IP via DHCP';
333
            } elseif ($if_data['vlanid'] > 0) {
334
                $ip_line = "VLAN via {$if_data['interface_orign']}";
335
                $countSpaceIP = Max($countSpaceIP - 11, strlen($ip_line));
336
            } else {
337
                $ip_line = 'Static IP  ';
338
            }
339
340
            // Determine the IP info
341
            $ip_info = 'unassigned';
342
            if (!empty($interface['ipaddr'])) {
343
                $ip_info = "\033[01;33m{$interface['ipaddr']}\033[39m";
344
            }
345
346
            if (!empty($interface['mac']) && $id_text < 4) {
347
                $ipTable[] = ["{$if_data['interface']}:", $ip_line, $ip_info];
348
                $id_text++;
349
            }
350
351
            if ($if_data['internet'] === '1') {
352
                if (!empty($if_data['exthostname'])) {
353
                    $externAddress = $if_data['exthostname'];
354
                } elseif (!empty($if_data['extipaddr'])) {
355
                    $externAddress = $if_data['extipaddr'];
356
                }
357
            }
358
        }
359
360
        // Check for system integrity
361
        $broken = static function () {
362
            if (Util::isT2SdeLinux()) {
363
                $files = Main::checkForCorruptedFiles();
364
                if (count($files) !== 0) {
365
                    return "   \033[01;31m" . Util::translate('The integrity of the system is broken') . "\033[39m";
366
                }
367
            } elseif (php_uname('m') === 'x86_64' && Util::isDocker()) {
368
                $files = Main::checkForCorruptedFiles();
369
                $result = '    Is Docker';
370
                if (count($files) !== 0) {
371
                    $result .= ": \033[01;31m" . Util::translate('The integrity of the system is broken') . "\033[39m";
372
                }
373
                return $result;
374
            } elseif (Util::isDocker()) {
375
                // ARM and other platform...
376
                return '    Is Docker';
377
            } else {
378
                return '    Is Debian';
379
            }
380
            return '';
381
        };
382
383
        // Generate the banner text
384
        $result = "*** " . Util::translate('this_is') . "\033[01;32mMikoPBX v.$version\033[39m" . PHP_EOL .
385
            "   built on $buildtime for Generic (x64)" . PHP_EOL .
386
            "   " . $copyright_info . PHP_EOL;
387
388
389
        // Create and populate the IP table
390
        $table = new ConsoleTable();
391
        foreach ($ipTable as $row) {
392
            $table->addRow($row);
393
        }
394
395
        // Add external address if available
396
        if (!empty($externAddress)) {
397
            $table->addRow(['external:', '', $externAddress]);
398
            $id_text++;
399
        }
400
401
        // Add empty rows if needed
402
        while ($id_text < 4) {
403
            $table->addRow([' ', ' ']);
404
            $id_text++;
405
        }
406
407
        // Append the IP table to the result
408
        $result .= $table->hideBorder()->getTable() . PHP_EOL;
409
410
        // Append system integrity information
411
        $result .= $broken();
412
        return $result;
413
    }
414
415
    /**
416
     * Returns the firewall status text
417
     * @return string
418
     */
419
    public function firewallWarning(): string
420
    {
421
        // Check if the firewall is disabled
422
        if (PbxSettings::getValueByKey(PbxSettings::PBX_FIREWALL_ENABLED) === '0') {
423
            return "\033[01;34m (" . Util::translate('Firewall disabled') . ") \033[39m";
424
        }
425
        return '';
426
    }
427
428
    /**
429
     * Returns the text of the storage status
430
     * @return string
431
     */
432
    public function storageWarning(): string
433
    {
434
        // Check if storage disk is unmounted and not in livecd mode
435
        if (!$this->isLiveCd && !Storage::isStorageDiskMounted()) {
436
            return "    \033[01;31m (" . Util::translate('Storage unmounted') . ") \033[39m";
437
        }
438
        return '';
439
    }
440
441
    /**
442
     * Reboot and Shutdown Settings
443
     * @param CliMenuBuilder $b
444
     * @return void
445
     */
446
    public function setupReboot(CliMenuBuilder $b): void
447
    {
448
        $b->setTitle(Util::translate('Choose action'))
449
            ->enableAutoShortcuts()
450
            ->addItem(
451
                '[1] ' . Util::translate('Reboot'),
452
                function (CliMenu $menu) {
453
                    try {
454
                        $menu->close();
455
                    } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
456
                    }
457
                    System::reboot();
458
                    sleep(2);
459
                    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...
460
                }
461
            )
462
            ->addItem(
463
                '[2] ' . Util::translate('Power off'),
464
                function (CliMenu $menu) {
465
                    try {
466
                        $menu->close();
467
                    } catch (Exception $e){
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
468
                    }
469
                    file_put_contents('/tmp/shutdown', '1');
470
                    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...
471
                }
472
            )
473
            ->setWidth(75)
474
            ->setForegroundColour('white', 'white')
475
            ->setBackgroundColour('black', 'black')
476
            ->disableDefaultItems()
477
            ->addItem('[3] ' . Util::translate('Cancel'), new GoBackAction());
478
    }
479
480
    /**
481
     * Ping Command Handler
482
     * @param CliMenu $menu
483
     * @return void
484
     */
485
    public function pingAction(CliMenu $menu): void
486
    {
487
        $style = new MenuStyle();
488
        $style->setBg('white')
489
            ->setFg('black');
490
        $input_ip = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
491
        };
492
        $elLanIp = $input_ip
493
            ->setPromptText(Util::translate('Enter a host name or IP address: (Press ESC to exit)'))
494
            ->setValidationFailedText(Util::translate('WARNING'))
495
            ->ask();
496
        $pingHost = $elLanIp->fetch();
497
        $pingPath = Util::which('ping');
498
        $timeoutPath = Util::which('timeout');
499
        passthru("$timeoutPath 4 $pingPath -c3 " . escapeshellarg($pingHost));
500
        sleep(2);
501
        $this->start();
502
    }
503
504
    /**
505
     * Configuring firewall
506
     * @param CliMenu $menu
507
     * @return void
508
     */
509
    public function setupFirewall(CliMenu $menu): void
510
    {
511
        // Code for firewall optionn
512
        $firewall_enable = PbxSettings::getValueByKey(PbxSettings::PBX_FIREWALL_ENABLED);
513
514
        if ($firewall_enable === '1') {
515
            $action = 'disable';
516
        } else {
517
            $action = 'enable';
518
        }
519
520
        $helloText = Util::translate("Do you want $action firewall now? (y/n): ");
521
        $style = (new MenuStyle())
522
            ->setBg('white')
523
            ->setFg('black');
524
525
        $inputDialog = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
526
            public function validate(string $input): bool
527
            {
528
                return ($input === 'y' || $input === 'n');
529
            }
530
        };
531
        $elDialog = $inputDialog
532
            ->setPromptText($helloText)
533
            ->setValidationFailedText(Util::translate('WARNING') . ': y/n')
534
            ->ask();
535
        $result = $elDialog->fetch();
536
537
        if ($result === 'y') {
538
            $enable = '0';
539
            if ('enable' === $action) {
540
                $enable = '1';
541
            }
542
            PbxSettings::setValueByKey(PbxSettings::PBX_FIREWALL_ENABLED, $enable);
543
            PbxSettings::setValueByKey(PbxSettings::PBX_FAIL2BAN_ENABLED, $enable);
544
            IptablesConf::reloadFirewall();
545
            echo "Firewall is {$action}d...";
546
        }
547
        $this->start();
548
    }
549
550
    /**
551
     * Setting up a disk for data storage
552
     * @param CliMenuBuilder $b
553
     * @return void
554
     */
555
    public function setupStorage(CliMenuBuilder $b): void
556
    {
557
        $b->setTitle(Util::translate('Choose action'))
558
            ->addItem(
559
                '[1] ' . Util::translate('Connect storage'),
560
                function (CliMenu $menu) {
561
                    // Code for connecting storage
562
                    $menu->close();
563
                    Storage::selectAndConfigureStorageDisk();
564
                    sleep(1);
565
                    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...
566
                }
567
            )
568
            ->addItem(
569
                '[2] ' . Util::translate('Check storage'),
570
                function (CliMenu $menu) {
571
                    // Code for checking storage
572
                    /** @var StorageModel $data */
573
                    $data = StorageModel::findFirst();
574
                    if (!$data) {
0 ignored issues
show
introduced by
$data is of type MikoPBX\Common\Models\Storage, thus it always evaluated to true.
Loading history...
575
                        echo "\n " . Util::translate('Valid disks not found...') . " \n";
576
                        return;
577
                    }
578
                    $style = (new MenuStyle())
579
                        ->setBg('white')
580
                        ->setFg('black');
581
                    $input_ip = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
582
                        public function validate(string $input): bool
583
                        {
584
                            return ($input === 'y' || $input === 'n');
585
                        }
586
                    };
587
                    $elDialog = $input_ip
588
                        ->setPromptText(Util::translate('All processes will be completed. Continue? (y/n):'))
589
                        ->setValidationFailedText(Util::translate('WARNING') . ': y/n')
590
                        ->ask();
591
                    $result = $elDialog->fetch();
592
                    $menu->close();
593
                    if ($result !== 'y') {
594
                        sleep(2);
595
                        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...
596
                    }
597
                    $dev_name = file_exists("{$data->device}4") ? "{$data->device}4" : "{$data->device}1";
598
599
                    passthru('/sbin/freestorage');
600
                    passthru('e2fsck -f -p ' . escapeshellarg($dev_name), $return_var);
601
                    echo "check return $return_var";
602
                    sleep(2);
603
                    system('/sbin/pbx_reboot');
604
                }
605
            )
606
            ->addItem(
607
                '[3] ' . Util::translate('Resize storage'),
608
                function (CliMenu $menu) {
609
                    // Code for resizing storage
610
                    /** @var StorageModel $data */
611
                    $data = StorageModel::findFirst();
612
                    if ($data === null) {
613
                        echo "\n " . Util::translate('Valid disks not found...') . " \n";
614
                        return;
615
                    }
616
                    $style = (new MenuStyle())
617
                        ->setBg('white')
618
                        ->setFg('black');
619
620
                    $input_ip = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
621
                        public function validate(string $input): bool
622
                        {
623
                            return ($input === 'y' || $input === 'n');
624
                        }
625
                    };
626
                    $elDialog = $input_ip
627
                        ->setPromptText(Util::translate('All processes will be completed. Continue? (y/n):'))
628
                        ->setValidationFailedText(Util::translate('WARNING') . ': y/n')
629
                        ->ask();
630
                    $result = $elDialog->fetch();
631
                    $menu->close();
632
                    if ($result !== 'y') {
633
                        sleep(2);
634
                        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...
635
                    }
636
                    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

636
                    passthru('/etc/rc/resize_storage_part ' . escapeshellarg(/** @scrutinizer ignore-type */ $data->device), $return_var);
Loading history...
637
                    echo "resize storage return $return_var";
638
                    sleep(2);
639
                    if ($return_var === 0) {
640
                        file_put_contents('/tmp/ejectcd', '');
641
                        $pbx_rebootPath = Util::which('pbx_reboot');
642
                        Processes::mwExecBg($pbx_rebootPath);
643
                    }
644
                }
645
            )
646
            ->setWidth(75)
647
            ->enableAutoShortcuts()
648
            ->setForegroundColour('white', 'white')
649
            ->setBackgroundColour('black', 'black')
650
            ->disableDefaultItems()
651
            ->addItem('[4] ' . Util::translate('Cancel'), new GoBackAction());
652
    }
653
654
    /**
655
     * Reset web password
656
     * @param CliMenu $menu
657
     * @return void
658
     */
659
    public function resetPassword(CliMenu $menu): void
660
    {
661
        // Code for resetting admin password
662
        $style = (new MenuStyle())
663
            ->setBg('white')
664
            ->setFg('black');
665
666
        $input_ip = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
667
            public function validate(string $input): bool
668
            {
669
                return ($input === 'y' || $input === 'n');
670
            }
671
        };
672
        $elResetPassword = $input_ip
673
            ->setPromptText('Do you want reset password? (y/n):')
674
            ->setValidationFailedText(Util::translate('WARNING') . ': y/n')
675
            ->ask();
676
        $result = $elResetPassword->fetch();
677
        if ($result !== 'y') {
678
            return;
679
        }
680
        try {
681
            $menu->close();
682
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
683
        }
684
        
685
        PbxSettings::resetValueToDefault(PbxSettings::WEB_ADMIN_LOGIN);
686
        PbxSettings::resetValueToDefault(PbxSettings::WEB_ADMIN_PASSWORD);
687
688
        $newLogin = PbxSettings::getValueByKey(PbxSettings::WEB_ADMIN_LOGIN);
689
        $newPassword = PbxSettings::getValueByKey(PbxSettings::WEB_ADMIN_PASSWORD);
690
        echo Util::translate("Password successfully reset. New login: $newLogin. New password: $newPassword.");
691
        sleep(2);
692
        $this->start();
693
    }
694
695
    /**
696
     * System Installation or Recovery action
697
     * @param CliMenu $menu
698
     * @return void
699
     */
700
    public function installRecoveryAction(CliMenu $menu): void
701
    {
702
        echo "\e[?25h";
703
        try {
704
            $menu->close();
705
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
706
        }
707
        file_put_contents('/tmp/ejectcd', '');
708
        $recovery = new PBXRecovery();
709
        $recovery->run();
710
        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...
711
    }
712
713
    /**
714
     * System Installation
715
     * @param CliMenu $menu
716
     * @return void
717
     */
718
    public function installAction(CliMenu $menu): void
719
    {
720
        echo "\e[?25h";
721
        try {
722
            $menu->close();
723
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
724
        }
725
        file_put_contents('/tmp/ejectcd', '');
726
        $installer = new PBXInstaller();
727
        $installer->run();
728
        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...
729
    }
730
731
    /**
732
     * Console Opening Action
733
     * @param CliMenu $menu
734
     * @return void
735
     */
736
    public function consoleAction(CliMenu $menu): void
737
    {
738
        // Enable cursor
739
        echo "\e[?25h";
740
        try {
741
            $menu->close();
742
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
743
        }
744
        file_put_contents('/tmp/start_sh', '');
745
        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...
746
    }
747
}
748