Passed
Push — develop ( 0816d1...716ffe )
by Портнов
05:11
created

SystemMessages::getInfoMessage()   D

Complexity

Conditions 17
Paths 216

Size

Total Lines 93
Code Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 59
c 0
b 0
f 0
dl 0
loc 93
rs 4.1833
cc 17
nc 216
nop 1

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-2024 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 MikoPBX\Common\Models\LanInterfaces;
23
use MikoPBX\Common\Models\PbxSettings;
24
use MikoPBX\Common\Models\PbxSettingsConstants;
25
use MikoPBX\Common\Providers\LoggerProvider;
26
use Phalcon\Di;
27
28
/**
29
 * SystemMessages class
30
 *
31
 * @package MikoPBX\Core\System
32
 *
33
 */
34
class SystemMessages extends Di\Injectable
35
{
36
    public const RESULT_DONE = 'Done';
37
    public const RESULT_FAILED = 'Failed';
38
    public const RESULT_SKIPPED = 'Skipped';
39
40
    private static array $defaultTexts = [
41
        self::RESULT_DONE => " \033[32;1mDONE\033[0m \n", // Green for DONE
42
        self::RESULT_FAILED => " \033[31;1mFAIL\033[0m \n",  // Red for FAILED
43
        self::RESULT_SKIPPED => " \033[33;1mSKIP\033[0m \n", // Yellow for SKIPPED
44
    ];
45
46
    /**
47
     * Echoes a result message with progress dots.
48
     *
49
     * @param string $message The result message to echo.
50
     * @param string $result The result status (DONE by default).
51
     *
52
     * @return void
53
     */
54
    public static function teletypeEchoResult(string $message, string $result = self::RESULT_DONE): void
55
    {
56
        $len = max(0, 80 - strlen($message) - 9);
57
        $spaces = str_repeat('.', $len);
58
        $formattedResult = self::getFormattedResult($result);
59
        self::echoToTeletype($spaces.$formattedResult);
60
    }
61
62
    /**
63
     * Echoes a message and logs it to the ttyS0-ttyS5.
64
     *
65
     * @param string $message The message to echo in a serial console.
66
     *
67
     * @return void
68
     */
69
    public static function echoToTeletype(string $message): void
70
    {
71
        // Log to serial tty
72
        for ($i = 0; $i <= 5; $i++) {
73
            $device = "/dev/ttyS$i";
74
            $busyboxPath = Util::which('busybox');
75
            // Get the result of the command execution
76
            $result = shell_exec("$busyboxPath setserial -g \"$device\" | $busyboxPath grep -v unknown 2> /dev/null");
77
            // If the result is not empty
78
            if (!empty($result)) {
79
                // Perform the same
80
                file_put_contents($device, $message, FILE_APPEND);
81
            }
82
        }
83
    }
84
85
    /**
86
     * Prepares formatted result string.
87
     *
88
     * @param string $result The result status.
89
     *
90
     * @return string Formatted result status.
91
     */
92
    private static function getFormattedResult(string $result = self::RESULT_DONE): string
93
    {
94
        if ($result === '1') {
95
            $result = self::RESULT_DONE;
96
        } elseif ($result === '0') {
97
            $result = self::RESULT_FAILED;
98
        }
99
        if (array_key_exists($result, self::$defaultTexts)) {
100
            $resultMessage = self::$defaultTexts[$result];
101
        } else {
102
            $resultMessage = "\033[90m$result\033[0m \n"; // Grey for unknown results
103
        }
104
        return $resultMessage;
105
    }
106
107
    /**
108
     * Echoes a result message with progress dots.
109
     *
110
     * @param string $message The result message to echo.
111
     * @param string $result The result status (DONE by default).
112
     *
113
     * @return void
114
     */
115
    public static function echoResult(string $message, string $result = self::RESULT_DONE): void
116
    {
117
        $cols = self::getCountCols();
118
        if (!is_numeric($cols)) {
119
            // Failed to retrieve the screen width.
120
            return;
121
        }
122
        $len = $cols - strlen($message) - 8;
123
        if ($len < 2) {
124
            // Incorrect screen width.
125
            return;
126
        }
127
128
        $spaces = str_repeat('.', $len);
129
        $formattedResult = self::getFormattedResult($result);
130
        echo $spaces. $formattedResult;
131
    }
132
133
    /**
134
     * Gets the count of columns in the terminal window.
135
     *
136
     * @return string The count of columns.
137
     */
138
    public static function getCountCols(): string
139
    {
140
        $len = 1 * trim(shell_exec('tput cols'));
141
142
        // If the count of columns is zero, set it to a default value of 80
143
        if ($len === 0) {
144
            $len = 80;
145
        } else {
146
            // Limit the count of columns to a maximum of 80
147
            $len = min($len, 80);
148
        }
149
        return $len;
150
    }
151
152
    /**
153
     * Echoes a message and logs it to the system log.
154
     *
155
     * @param string $message The message to echo and log.
156
     *
157
     * @return void
158
     */
159
    public static function echoWithSyslog(string $message): void
160
    {
161
        echo $message;
162
        // Log the message to the system log with LOG_INFO level
163
        self::sysLogMsg(static::class, $message, LOG_INFO);
164
    }
165
166
    /**
167
     * Adds messages to Syslog.
168
     *
169
     * @param string $ident The category, class, or method identification.
170
     * @param string $message The log message.
171
     * @param int $level The log level (default: LOG_WARNING).
172
     *
173
     * @return void
174
     */
175
    public static function sysLogMsg(string $ident, string $message, int $level = LOG_WARNING): void
176
    {
177
        /** @var \Phalcon\Logger $logger */
178
        $logger = Di::getDefault()->getShared(LoggerProvider::SERVICE_NAME);
179
        $logger->log($level, "{$message} on {$ident}");
180
    }
181
182
183
    /**
184
     * Echoes the starting message for a stage.
185
     *
186
     * @param string $message The message to echo.
187
     */
188
    public static function echoStartMsg(string $message): void
189
    {
190
        SystemMessages::echoToTeletype($message);
191
        SystemMessages::echoWithSyslog($message);
192
    }
193
194
    /**
195
     * Echoes the result message for a stage.
196
     *
197
     * @param string $result The result of the stage.
198
     */
199
    public static function echoResultMsg(string $message, string $result = SystemMessages::RESULT_DONE): void
200
    {
201
        SystemMessages::teletypeEchoResult($message, $result);
202
        SystemMessages::echoResult($message, $result);
203
    }
204
205
    /**
206
     * Retrieves the information message containing available web interface addresses.
207
     * @param bool $showCredentials Optional, if true the message will have the login information
208
     * @return string The information message.
209
     */
210
    public static function getInfoMessage(bool $showCredentials=false): string
211
    {
212
        // Assuming a total width of 53 characters for each line
213
        $lineWidth = 53;
214
215
        $info = PHP_EOL . "┌────────────────────────────────────────────────┐";
216
        $info .= PHP_EOL . "│                                                │";
217
        $headerSpace = $lineWidth - 3 - 5; // 3 for "│    🌟 MikoPBX - All services are fully loaded 🌟 " and 5 for " │" at the end
218
        $headerLine = sprintf("│  %-{$headerSpace}s │", "🌟 MikoPBX - All services are fully loaded 🌟");
219
        $info .= PHP_EOL . $headerLine;
220
        $info .= PHP_EOL . "│                                                │";
221
        $info .= PHP_EOL . "├────────────────────────────────────────────────┤";
222
223
        $addresses = [
224
            'local' => [],
225
            'external' => []
226
        ];
227
        /** @var LanInterfaces $interface */
228
        $interfaces = LanInterfaces::find("disabled='0'");
229
        foreach ($interfaces as $interface) {
230
            if (!empty($interface->ipaddr)) {
231
                $addresses['local'][] = $interface->ipaddr;
232
            }
233
            if (!empty($interface->exthostname) && !in_array($interface->exthostname, $addresses['local'], true)) {
234
                $addresses['external'][] = explode(':', $interface->exthostname)[0] ?? '';
235
            }
236
            if (!empty($interface->extipaddr) && !in_array($interface->extipaddr, $addresses['local'], true)) {
237
                $addresses['external'][] = explode(':', $interface->extipaddr)[0] ?? '';
238
            }
239
        }
240
        unset($interfaces);
241
242
243
        // Local network
244
        $port = PbxSettings::getValueByKey(PbxSettingsConstants::WEB_HTTPS_PORT);
245
        $info .= PHP_EOL . "│                                                │";
246
        $headerSpace = $lineWidth - 13 - 1; // 13 for "│    🌐 Web Interface Access 🌐 " and 1 for " │"
247
        $headerLine = sprintf("│            %-{$headerSpace}s │", "🌐 Web Interface Access 🌐");
248
        $info .= PHP_EOL . $headerLine;
249
        $info .= PHP_EOL . "│                                                │";
250
        $info .= PHP_EOL . "│    Local Network Address:                      │";
251
252
        $addressSpace = $lineWidth - 7 - 5; // 7 for "│    ➜ " and 5 for " │" at the end
253
        foreach ($addresses['local'] as $address) {
254
            if (empty($address)) {
255
                continue;
256
            }
257
            $formattedAddress = $port === '443' ? "https://$address" : "https://$address:$port";
258
            // Use sprintf to format the string with padding to ensure constant length
259
            $info .= PHP_EOL . sprintf("│    ➜ %-{$addressSpace}s │", $formattedAddress);
260
261
        }
262
        $info .= PHP_EOL . "│                                                │";
263
264
        // External web address info
265
        if (!empty($addresses['external'])) {
266
            $info .= PHP_EOL . "│    External Network Address:                   │";
267
            foreach ($addresses['external'] as $address) {
268
                if (empty($address)) {
269
                    continue;
270
                }
271
                $formattedAddress = $port === '443' ? "https://$address" : "https://$address:$port";
272
                // Use sprintf to format the string with padding to ensure constant length
273
                $info .= PHP_EOL . sprintf("│    ➜ %-{$addressSpace}s │", $formattedAddress);
274
275
            }
276
            $info .= PHP_EOL . "│                                                │";
277
        }
278
279
        if ($showCredentials) {
280
            // Default web user info
281
            $cloudInstanceId = PbxSettings::getValueByKey(PbxSettingsConstants::CLOUD_INSTANCE_ID);
282
            $webAdminPassword = PbxSettings::getValueByKey(PbxSettingsConstants::WEB_ADMIN_PASSWORD);
283
            $defaultPassword = PbxSettings::getDefaultArrayValues()[PbxSettingsConstants::WEB_ADMIN_PASSWORD];
284
            if ($cloudInstanceId === $webAdminPassword || $webAdminPassword === $defaultPassword) {
285
                $adminUser = PbxSettings::getValueByKey(PbxSettingsConstants::WEB_ADMIN_LOGIN);
286
287
                $credentialSpace = $lineWidth - 5 - 3; // 5 for "│    🔑 Default Credentials: " and 3 for " │"
288
                $credentialLine = sprintf("│    %-{$credentialSpace}s │", "🔑 Default web credentials:");
289
                $info .= PHP_EOL . $credentialLine;
290
                // Login
291
                $loginSpace = $lineWidth - 12 - 5; // 12 for "│    Login: " and 5 for " │" at the end
292
                $loginLine = sprintf("│    Login: %-{$loginSpace}s │", $adminUser); // Format the login line
293
                $info .= PHP_EOL . $loginLine;
294
295
                // Password
296
                $passwordSpace = $lineWidth - 15 - 5; // 15 for "│    Password: " and 5 for " │" at the end
297
                $passwordLine = sprintf("│    Password: %-{$passwordSpace}s │", $cloudInstanceId); // Format the password line
298
                $info .= PHP_EOL . $passwordLine;
299
            }
300
        }
301
        $info .= PHP_EOL . "└────────────────────────────────────────────────┘" . PHP_EOL . PHP_EOL;
302
        return $info;
303
    }
304
}