platforms::get()   F
last analyzed

Complexity

Conditions 46
Paths 1

Size

Total Lines 402
Code Lines 318

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 377
CRAP Score 46

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 46
eloc 318
c 3
b 0
f 0
nc 1
nop 0
dl 0
loc 402
ccs 377
cts 378
cp 0.9974
crap 46
rs 3.3333

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
declare(strict_types = 1);
3
namespace hexydec\agentzero;
4
5
class platforms {
6
7
	/**
8
	 * Generates a configuration array for matching platforms
9
	 * 
10
	 * @return array<string,props> An array with keys representing the string to match, and values a props object defining how to generate the match and which properties to set
11
	 */
12 61
	public static function get() : array {
13 1
		$fn = [
14 1
			'platformlinux' => function (string $value) : array {
15 16
				if (!\str_starts_with($value, 'Red Hat/') && ($platform = \mb_strstr($value, ' ', true)) !== false) {
16 5
					$value = $platform;
17
				}
18 16
				$parts = \explode('/', $value, 2);
19 16
				if (!isset($parts[1])) {
20 14
					$parts = \explode('-', $value, 2);
21
				}
22 16
				if (!isset($parts[1])) {
23 12
					$parts = \explode(' ', $value, 2);
24
				}
25 16
				return [
26 16
					'type' => 'human',
27 16
					'category' => 'desktop',
28 16
					'kernel' => 'Linux',
29 16
					'platform' => self::getPlatform($parts[0]),
30 16
					'platformversion' => $parts[1] ?? null
31 16
				];
32 1
			},
33 1
			'platformwindows' => function (string $value) : array {
34 49
				$mapping = [
35 49
					'5.0' => '2000',
36 49
					'5.1' => 'XP',
37 49
					'5.2' => 'XP',
38 49
					'6.0' => 'Vista',
39 49
					'6.1' => '7',
40 49
					'6.2' => '8',
41 49
					'6.3' => '8.1',
42 49
					'10.0' => '10'
43 49
				];
44 49
				$version = null;
45 49
				foreach (['Windows NT ', 'Windows '] AS $item) {
46 49
					if (($pos = \mb_stripos($value, $item)) !== false) {
47 49
						$version = \explode(' ', \mb_substr($value, $pos + \mb_strlen($item)))[0];
48 49
						break;
49
					}
50
				}
51 49
				return [
52 49
					'type' => 'human',
53 49
					'category' => 'desktop',
54 49
					'kernel' => 'Windows NT',
55 49
					'platform' => 'Windows',
56 49
					'platformversion' => $mapping[$version] ?? $version
57 49
				];
58 1
			},
59 1
			'android' => function (string $value, int $i, array $tokens) : array {
60 42
				$os = \explode(' ', $value, 3);
61
62
				// skip language
63 42
				if (!empty($tokens[++$i]) && (\strlen($tokens[$i]) === 2 || (\strlen($tokens[$i]) === 5 && \mb_strpos($tokens[$i], '_') === 2))) {
64 2
					$i++;
65
				}
66
67
				// only where the token length is greater than 2, or it doesn't contain a /, or if it does it is Build/
68 42
				$device = empty($tokens[$i]) || \strlen($tokens[$i]) <= 2 || (\str_contains($tokens[$i], '/') && \mb_stripos($tokens[$i], 'Build/') === false) ? [] : devices::getDevice($tokens[$i]);
69 42
				return \array_merge($device, [
70 42
					'type' => 'human',
71 42
					'platform' => 'Android',
72 42
					'platformversion' => isset($os[1]) ? \explode('/', $os[1])[0] : null
73 42
				]);
74 1
			}
75 1
		];
76
77 50
		return [
78
79
			// platforms
80 50
			'PalmSource' => new props('start', fn (string $value) : array => [
81 3
				'type' => 'human',
82 3
				'category' => 'mobile',
83 3
				'platform' => 'PalmOS',
84 3
				'platformversion' => \mb_substr($value, 11) ?: null,
85 3
				'kernel' => 'AMX 68000',
86 3
				'architecture' => 'Arm',
87 3
				'bits' => 32,
88 3
			]),
89 50
			'PalmOS' => new props('start', fn (string $value) : array => [
90 2
				'type' => 'human',
91 2
				'category' => 'mobile',
92 2
				'platform' => 'PalmOS',
93 2
				'platformversion' => \mb_substr($value, 7) ?: null,
94 2
				'kernel' => 'AMX 68000',
95 2
				'architecture' => 'Arm',
96 2
				'bits' => 32,
97 2
			]),
98 50
			'Windows NT ' => new props('any', $fn['platformwindows']),
99 50
			'Windows Phone' => new props('start', function (string $value) : array {
100 3
				$version = \mb_substr($value, 14);
101 3
				return [
102 3
					'type' => 'human',
103 3
					'category' => 'mobile',
104 3
					'platform' => 'Windows Phone',
105 3
					'platformversion' => $version,
106 3
					'kernel' => \intval($version) >= 8 ? 'Windows NT' : 'Windows CE'
107 3
				];
108 50
			}),
109 50
			'Win98' => new props('start', function (string $value, int $i, array $tokens) : array {
110 2
				foreach ($tokens AS $item) {
111 2
					if (\str_starts_with($item, 'PalmSource')) {
112
						return [];
113
					}
114
				}
115 2
				return [
116 2
					'type' => 'human',
117 2
					'category' => 'desktop',
118 2
					'architecture' => 'x86',
119 2
					'bits' => 32,
120 2
					'kernel' => 'MS-DOS',
121 2
					'platform' => 'Windows',
122 2
					'platformversion' => '98'
123 2
				];
124 50
			}),
125 50
			'Win32' => new props('exact', [
126 50
				'type' => 'human',
127 50
				'category' => 'desktop',
128 50
				'architecture' => 'x86',
129 50
				'bits' => 32,
130 50
				'platform' => 'Windows'
131 50
			]),
132 50
			'Win64' => new props('exact', [
133 50
				'type' => 'human',
134 50
				'category' => 'desktop',
135 50
				'bits' => 64,
136 50
				'platform' => 'Windows'
137 50
			]),
138 50
			'WinNT' => new props('start', fn (string $value) : array => [
139 2
				'type' => 'human',
140 2
				'category' => 'desktop',
141 2
				'architecture' => 'x86',
142 2
				'bits' => 32,
143 2
				'kernel' => 'Windows NT',
144 2
				'platform' => 'Windows',
145 2
				'platformversion' => \mb_substr($value, 5)
146 2
			]),
147 50
			'Windows' => new props('any', function (string $value, int $i, array $tokens) use ($fn) : array {
148 50
				foreach ($tokens AS $item) {
149 50
					if (\str_starts_with($item, 'PalmSource')) {
150 2
						return [];
151
					}
152
				}
153 49
				return $fn['platformwindows']($value);
154 50
			}),
155 50
			'MacOS/' => new props('start', fn (string $value) : array => [
156 2
				'type' => 'human',
157 2
				'category' => 'desktop',
158 2
				'vendor' => 'Apple',
159 2
				'platform' => 'MacOS',
160 2
				'platformversion' => \mb_substr($value, 6),
161 2
				'bits' => 64
162 2
			]),
163 50
			'Mac OS X' => new props('any', function (string $value) : array {
164 31
				$version = \str_replace('_', '.', \mb_substr($value, \mb_stripos($value, 'Mac OS X') + 9));
165 31
				$register = $version && \intval(\explode('.', $version)[1] ?? 0) >= 6 ? 64 : null;
166 31
				return [
167 31
					'type' => 'human',
168 31
					'category' => 'desktop',
169 31
					'kernel' => 'Linux',
170 31
					'platform' => 'Mac OS X',
171 31
					'platformversion' => $version === '' ? null : $version,
172 31
					'bits' => $register
173 31
				];
174 50
			}),
175 50
			'AppleTV' => new props('exact', [
176 50
				'type' => 'human',
177 50
				'category' => 'tv',
178 50
				'device' => 'AppleTV',
179 50
				'platform' => 'tvOS',
180 50
				'bits' => 64
181 50
			]),
182 50
			'iOS/' => new props('start', fn (string $value) : array => [
183 2
				'type' => 'human',
184 2
				'category' => 'mobile',
185 2
				'platform' => 'iOS',
186 2
				'platformversion' => \mb_substr($value, 4)
187 2
			]),
188 50
			'iOS ' => new props('start', fn (string $value) : array => [
189 3
				'type' => 'human',
190 3
				'category' => 'mobile',
191 3
				'platform' => 'iOS',
192 3
				'platformversion' => \str_replace('_', '.', \mb_substr($value, 4))
193 3
			]),
194 50
			'iOS' => new props('exact', fn (string $value, int $i, array $tokens) : array => [
195 1
				'type' => 'human',
196 1
				'category' => 'mobile',
197 1
				'platform' => 'iOS',
198 1
				'platformversion' => $tokens[$i+1] ?? null
199 1
			]),
200 50
			'iPadOS' => new props('exact', fn (string $value, int $i, array $tokens) : array => [
201 1
				'type' => 'human',
202 1
				'category' => 'tablet',
203 1
				'vendor' => 'Apple',
204 1
				'device' => 'iPad',
205 1
				'platform' => 'iOS',
206 1
				'platformversion' => $tokens[$i+1] ?? null
207 1
			]),
208 50
			'CrOS' => new props('start', function (string $value) : array {
209 4
				$parts = \explode(' ', $value);
210 4
				return [
211 4
					'type' => 'human',
212 4
					'category' => 'desktop',
213 4
					'platform' => 'Chrome OS',
214 4
					'platformversion' => $parts[2] ?? null
215 4
				];
216 50
			}),
217 50
			'Kindle/' => new props('start', fn (string $value) : array => [
218 2
				'type' => 'human',
219 2
				'category' => 'ebook',
220 2
				'platform' => 'Kindle',
221 2
				'platformversion' => \mb_substr($value, 7)
222 2
			]),
223 50
			'Tizen' => new props('start', function (string $value) : array {
224 1
				$parts = \explode(' ', $value, 2);
225 1
				return [
226 1
					'type' => 'human',
227 1
					'category' => 'desktop',
228 1
					'kernel' => 'Linux',
229 1
					'platform' => 'Tizen',
230 1
					'platformversion' => $parts[1] ?? null
231 1
				];
232 50
			}),
233 50
			'KAIOS/' => new props('start', function (string $value, int $i, array $tokens) : array {
234
235
				// find device
236 1
				foreach ($tokens AS $i => $item) {
237 1
					if ($item === 'Mobile' && !\str_starts_with($tokens[$i++] ?? 'rv:', 'rv:')) {
238 1
						if (\str_contains($tokens[$i], '/')) {
239 1
							$parts = \explode('/', $tokens[$i]);
240
						} else {
241 1
							$parts = \explode(' ', \str_replace('_', ' ', $tokens[$i]), 2);
242
						}
243 1
						break;
244
					}
245
				}
246 1
				return [
247 1
					'type' => 'human',
248 1
					'category' => 'mobile',
249 1
					'kernel' => 'Linux',
250 1
					'architecture' => 'Arm',
251 1
					'platform' => 'KaiOS',
252 1
					'platformversion' => \mb_substr($value, 6),
253 1
					'vendor' => !empty($parts[0]) ? devices::getVendor($parts[0]) : null,
254 1
					'device' => $parts[1] ?? null,
255 1
					'build' => $parts[2] ?? null
256 1
				];
257 50
	}		),
258 50
			'Ubuntu' => new props('start', $fn['platformlinux']),
259 50
			'Kubuntu' => new props('start', $fn['platformlinux']),
260 50
			'Mint' => new props('start', $fn['platformlinux']),
261 50
			'SUSE' => new props('start', $fn['platformlinux']),
262 50
			'Red Hat/' => new props('start', $fn['platformlinux']),
263 50
			'Debian' => new props('start', $fn['platformlinux']),
264 50
			'Darwin' => new props('start', $fn['platformlinux']),
265 50
			'Fedora' => new props('start', $fn['platformlinux']),
266 50
			'CentOS' => new props('start', $fn['platformlinux']),
267 50
			'Rocky' => new props('start', $fn['platformlinux']),
268 50
			'Alma' => new props('start', $fn['platformlinux']),
269 50
			'Gentoo' => new props('start', $fn['platformlinux']),
270 50
			'Slackware' => new props('start', $fn['platformlinux']),
271 50
			'OpenSUSE' => new props('start', $fn['platformlinux']),
272 50
			'FreeBSD' => new props('start', $fn['platformlinux']),
273 50
			'OpenBSD' => new props('start', $fn['platformlinux']),
274 50
			'ArchLinux' => new props('exact', fn () : array => [
275 1
				'type' => 'human',
276 1
				'category' => 'desktop',
277 1
				'kernel' => 'Linux',
278 1
				'platform' => 'Arch',
279 1
			]),
280 50
			'Arch' => new props('exact', fn () : array => [
281 1
				'type' => 'human',
282 1
				'category' => 'desktop',
283 1
				'kernel' => 'Linux',
284 1
				'platform' => 'Arch',
285 1
			]),
286 50
			'Web0S' => new props('exact', $fn['platformlinux']),
287 50
			'webOSTV' => new props('exact', [
288 50
				'type' => 'human',
289 50
				'category' => 'tv',
290 50
				'kernel' => 'Linux',
291 50
				'platform' => 'WebOS'
292 50
			]),
293 50
			'WEBOS' => new props('start', fn (string $value) : array => [
294 2
				'type' => 'human',
295 2
				'category' => 'tv',
296 2
				'kernel' => 'Linux',
297 2
				'platform' => 'WebOS',
298 2
				'platformversion' => \mb_substr($value, 5)
299 2
			]),
300 50
			'Roku ' => new props('start', function (string $value, int $i, array $tokens) : array {
301 1
				$app = \str_contains($tokens[$i - 1] ?? '', '/') ? \explode('/', $tokens[$i - 1], 2) : null;
302 1
				return \array_merge(
303 1
					[
304 1
						'type' => 'human',
305 1
						'category' => 'tv',
306 1
						'kernel' => 'Linux',
307 1
						'platform' => 'Roku OS',
308 1
						'platformversion' => \mb_substr($value, 5),
309 1
						'app' => $app[0] ?? null,
310 1
						'appname' => $app[0] ?? null,
311 1
						'appversion' => $app[1] ?? null,
312 1
					],
313 1
					isset($tokens[$i + 2]) ? devices::getDevice($tokens[$i + 2]) : []
314 1
				);
315 50
			}),
316 50
			'SunOS' => new props('start', [
317 50
				'type' => 'human',
318 50
				'category' => 'desktop',
319 50
				'kernel' => 'unix',
320 50
				'platform' => 'Solaris',
321 50
			]),
322 50
			'AmigaOS' => new props('any', function (string $value) : array {
323 3
				if (($pos = \mb_stripos($value, 'AmigaOS')) !== false) {
324 3
					$value = \mb_substr($value, $pos);
325
				}
326 3
				$parts = \explode(' ', $value, 2);
327 3
				return [
328 3
					'type' => 'human',
329 3
					'category' => 'desktop',
330 3
					'kernel' => 'Exec',
331 3
					'platform' => 'AmigaOS',
332 3
					'platformversion' => isset($parts[1]) && \strspn($parts[1], '0123456789.-_') === \strlen($parts[1]) ? $parts[1] : null
333 3
				];
334 50
			}),
335 50
			'Fuchsia' => new props('exact', function (string $value, int $i, array $tokens) : array {
336 1
				$os = \explode(' ', $tokens[++$i], 2);
337 1
				return [
338 1
					'type' => 'human',
339 1
					'category' => 'mobile',
340 1
					'kernel' => 'Zircon',
341 1
					'platform' => 'Fuchsia',
342 1
					'platformversion' => isset($os[1]) && \strspn($os[1], '0123456789.-_', \strlen($os[0])) === \strlen($os[1]) ? $os[1] : null
343 1
				];
344 50
			}),
345 50
			'Maemo' => new props('exact', function (string $value, int $i, array $tokens) : array {
346 1
				$os = \explode(' ', $tokens[++$i], 2);
347 1
				return [
348 1
					'type' => 'human',
349 1
					'category' => 'mobile',
350 1
					'kernel' => 'Linux',
351 1
					'platform' => 'Maemo',
352 1
					'platformversion' => isset($os[1]) && \strspn($os[1], '0123456789.-_', \strlen($os[0])) === \strlen($os[1]) ? $os[1] : null
353 1
				];
354 50
			}),
355 50
			'J2ME/MIDP' => new props('exact', fn (string $value) : array => [
356 3
				'type' => 'human',
357 3
				'category' => 'mobile',
358 3
				'kernel' => 'Java VM',
359 3
				'platform' => $value
360 3
			]),
361 50
			'Haiku' => new props('any', function (string $value) : array {
362 3
				$parts = \explode('/', $value, 2);
363 3
				return [
364 3
					'type' => 'human',
365 3
					'category' => 'desktop',
366 3
					'kernel' => 'Haiku',
367 3
					'platform' => 'Haiku',
368 3
					'platformversion' => $parts[1] ?? null
369 3
				];
370 50
			}),
371 50
			'BeOS' => new props('start', function (string $value) : array {
372 1
				$parts = \explode('/', $value, 2);
373 1
				return [
374 1
					'type' => 'human',
375 1
					'category' => 'desktop',
376 1
					'kernel' => 'BeOS',
377 1
					'platform' => 'BeOS',
378 1
					'platformversion' => $parts[1] ?? null
379 1
				];
380 50
			}),
381 50
			'Android' => new props('exact', $fn['android']),
382 50
			'Android/' => new props('start', fn (string $value) : array => [
383 2
				'type' => 'human',
384 2
				'platform' => 'Android',
385 2
				'platformversion' => \explode('/', $value, 3)[1] ?: null
386 2
			]),
387 50
			'Android ' => new props('start', $fn['android']),
388 50
			'Android-' => new props('start', $fn['android']),
389 50
			'Linux' => new props('any', function (string $value, int $i, array $tokens) : array {
390 61
				return [
391 61
					'kernel' => 'Linux',
392 61
					'platform' => 'Linux',
393 61
					'platformversion' => \str_contains($tokens[$i + 1] ?? '', '.') && \strspn($tokens[$i + 1], '0123456789.') >= 3 ? \explode(' ', $tokens[$i + 1])[0] : null
394 61
				];
395 50
			}),
396 50
			'X11' => new props('exact', function (string $value, int $i, array $tokens) : array {
397 32
				$os = \explode(' ', $tokens[++$i] ?? '', 2);
398 32
				return [
399 32
					'category' => 'desktop',
400 32
					'kernel' => 'Linux',
401 32
					'platform' => $os[0] ?: 'X11',
402 32
					'platformversion' => isset($os[1]) && \strspn($os[1], '0123456789.-_', \strlen($os[0])) === \strlen($os[1]) ? $os[1] : null
403 32
				];
404 50
			}),
405 50
			'OS/2' => new props('exact', [
406 50
				'category' => 'desktop',
407 50
				'platform' => 'OS/2'
408 50
			]),
409 50
			'Version/' => new props('start', fn (string $value) : array => [
410 46
				'platformversion' => \mb_substr($value, 8)
411 46
			]),
412 50
			'platformVersion/' => new props('start', fn (string $value) : array => [
413 2
				'platformversion' => \mb_substr($value, 16)
414 2
			]),
415 50
		];
416
	}
417
418 24
	public static function getPlatform(string $value) : string {
419 24
		$map = [
420 24
			'webos' => 'WebOS',
421 24
			'web0s' => 'WebOS',
422 24
			'j2me/midp' => 'J2ME/MIDP',
423 24
			'centos' => 'CentOS',
424 24
			'suse' => 'SUSE',
425 24
			'freebsd' => 'FreeBSD',
426 24
			'openbsd' => 'OpenBSD',
427 24
			'netbsd' => 'NetBSD',
428 24
			'opensuse' => 'OpenSUSE',
429 24
			'iphone' => 'iOS'
430 24
		];
431 24
		$value = \mb_strtolower($value);
432 24
		return $map[$value] ?? \mb_convert_case($value, MB_CASE_TITLE);
433
	}
434
}