OsInfo::isOs()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 1
dl 0
loc 15
ccs 8
cts 8
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * For the full copyright and license information, please view
5
 * the LICENSE file that was distributed with this source code.
6
 */
7
8
declare(strict_types=1);
9
10
namespace loophp\phposinfo;
11
12
use Exception;
13
use loophp\phposinfo\Enum\Family;
14
use loophp\phposinfo\Enum\FamilyName;
15
use loophp\phposinfo\Enum\Os;
16
use loophp\phposinfo\Enum\OsName;
17
18
use function define;
19
use function defined;
20
use function is_string;
21
22
use const PHP_OS;
23
use const PHP_OS_FAMILY;
24
25
final class OsInfo implements OsInfoInterface
26
{
27 1
    public static function arch(): string
28
    {
29 1
        return php_uname('m');
30
    }
31
32 3
    public static function family(): string
33
    {
34 3
        return sprintf('%s', FamilyName::value(Family::key(self::detectFamily())));
35
    }
36
37 1
    public static function hostname(): string
38
    {
39 1
        return php_uname('n');
40
    }
41
42 1
    public static function isApple(): bool
43
    {
44 1
        return self::isFamily(Family::DARWIN);
45
    }
46
47 1
    public static function isBSD(): bool
48
    {
49 1
        return self::isFamily(Family::BSD);
50
    }
51
52 1
    public static function isFamily($family): bool
53
    {
54 1
        $detectedFamily = self::detectFamily();
55
56 1
        if (true === is_string($family)) {
57 1
            $family = self::normalizeConst($family);
58
59 1
            if (false === Family::has($family)) {
60 1
                return false;
61
            }
62
63 1
            $family = Family::value($family);
64
        }
65
66 1
        return $detectedFamily === $family;
67
    }
68
69 1
    public static function isOs($os): bool
70
    {
71 1
        $detectedOs = self::detectOs();
72
73 1
        if (true === is_string($os)) {
74 1
            $os = self::normalizeConst($os);
75
76 1
            if (false === Os::has($os)) {
77 1
                return false;
78
            }
79
80 1
            $os = Os::value($os);
81
        }
82
83 1
        return $detectedOs === $os;
84
    }
85
86 1
    public static function isUnix(): bool
87
    {
88 1
        return self::isFamily(Family::LINUX);
89
    }
90
91 1
    public static function isWindows(): bool
92
    {
93 1
        return self::isFamily(Family::WINDOWS);
94
    }
95
96 2
    public static function os(): string
97
    {
98 2
        return sprintf('%s', OsName::value(Os::key(self::detectOs())));
99
    }
100
101 1
    public static function register(): void
102
    {
103 1
        $family = self::family();
104 1
        $os = self::os();
105
106 1
        if (false === defined('PHP_OS_FAMILY')) {
107
            define('PHP_OS_FAMILY', $family);
108
        }
109
110 1
        if (false === defined('PHP_OS')) {
111
            define('PHP_OS', $os);
112
        }
113
114 1
        if (false === defined('PHPOSINFO_OS_FAMILY')) {
115 1
            define('PHPOSINFO_OS_FAMILY', $family);
116
        }
117
118 1
        if (false === defined('PHPOSINFO_OS')) {
119 1
            define('PHPOSINFO_OS', $os);
120
        }
121 1
    }
122
123 1
    public static function release(): string
124
    {
125 1
        return php_uname('r');
126
    }
127
128 1
    public static function uuid(): ?string
129
    {
130 1
        $uuidGenerator = 'shell_exec';
131 1
        $uuidCommand = null;
132
133 1
        switch (self::family()) {
134 1
            case FamilyName::LINUX:
135
                $uuidCommand = '( cat /var/lib/dbus/machine-id /etc/machine-id 2> /dev/null || hostname ) | head -n 1 || :';
136 1
137
                break;
138
139 1
            case FamilyName::DARWIN:
140
                $uuidCommand = 'ioreg -rd1 -c IOPlatformExpertDevice | grep IOPlatformUUID';
141
                $uuidGenerator = static function (string $command) use ($uuidGenerator): ?string {
142
                    $output = $uuidGenerator($command);
143
                    $uuid = null;
144
145
                    if (null !== $output) {
146
                        $parts = explode('=', str_replace('"', '', $output));
147
                        $uuid = strtolower(trim($parts[1]));
148
                    }
149
150
                    return $uuid;
151
                };
152
153
                break;
154
155
            case FamilyName::WINDOWS:
156
                $uuidCommand = '%windir%\\System32\\reg query "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography" /v MachineGuid';
157
158
                break;
159
160
            case FamilyName::BSD:
161
                $uuidCommand = 'kenv -q smbios.system.uuid';
162
163
                break;
164
165
            default:
166
                $uuidGenerator = static fn (?string $command): ?string => $command;
167
        }
168
169
        return null !== $uuidCommand ? $uuidGenerator($uuidCommand) : null;
170
    }
171
172 1
    public static function version(): string
173
    {
174
        return php_uname('v');
175 1
    }
176
177 1
    /**
178
     * @throws Exception
179
     */
180
    private static function detectFamily(?int $os = null): int
181
    {
182
        $os ??= self::detectOs();
183 3
184
        // Get the last 4 bits.
185 3
        $family = $os - (($os >> 16) << 16);
186
187
        if (true === Family::isValid($family)) {
188 3
            return $family;
189
        }
190 3
191 3
        if (true === defined(PHP_OS_FAMILY)) {
192
            $phpOsFamily = self::normalizeConst(PHP_OS_FAMILY);
193
194
            if (true === Family::has($phpOsFamily)) {
195
                return (int) Family::value($phpOsFamily);
196
            }
197
        }
198
199
        throw self::errorMessage();
200
    }
201
202
    /**
203
     * @throws Exception
204
     */
205
    private static function detectOs(): int
206
    {
207
        foreach ([php_uname('s'), PHP_OS] as $os) {
208 3
            $os = self::normalizeConst($os);
209
210 3
            if (true === Os::has($os)) {
211 3
                return (int) Os::value($os);
212
            }
213 3
        }
214 3
215
        throw self::errorMessage();
216
    }
217
218
    /**
219
     * @throws Exception
220
     */
221
    private static function errorMessage(): Exception
222
    {
223
        $uname = php_uname();
224
        $os = php_uname('s');
225
226
        $message = <<<EOF
227
            Unable to find a proper information for this operating system.
228
229
            Please open an issue on https://github.com/loophp/phposinfo and attach the
230
            following information so I can update the library:
231
232
            ---8<---
233
            php_uname(): {$uname}
234
            php_uname('s'): {$os}
235
            --->8---
236
237
            Thanks.
238
239
            EOF;
240
241
        throw new Exception($message);
242
    }
243
244
    private static function normalizeConst(string $name): string
245
    {
246
        return strtoupper(
247 3
            str_replace('-.', '', (string) preg_replace('/[^a-zA-Z0-9]/', '', $name))
248
        );
249 3
    }
250
}
251