Passed
Push — main ( 09cef8...5784d3 )
by Will
03:02
created

devices::getVendor()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 13
c 0
b 0
f 0
dl 0
loc 15
ccs 15
cts 15
cp 1
rs 9.8333
cc 1
nc 1
nop 1
crap 1
1
<?php
2
declare(strict_types = 1);
3
namespace hexydec\agentzero;
4
5
/**
6
 * @phpstan-import-type MatchConfig from config
7
 */
8
class devices {
9
10
	/**
11
	 * Generates a configuration array for matching devices
12
	 * 
13
	 * @return MatchConfig An array with keys representing the string to match, and a value of an array containing parsing and output settings
0 ignored issues
show
Bug introduced by
The type hexydec\agentzero\MatchConfig was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
	 */
15 21
	public static function get() : array {
16 1
		$fn = [
17 1
			'ios' => function (string $value, int $i, array $tokens) : array {
18 15
				$version = null;
19 15
				$model = null;
20 15
				foreach ($tokens AS $item) {
21 15
					if (\str_starts_with($item, 'Mobile/')) {
22 15
						$model = \mb_substr($item, 7);
23 15
					} elseif (\str_starts_with($item, 'CPU iPhone OS ')) {
24 14
						$version = \str_replace('_', '.', \mb_substr($item, 14, \mb_strpos($item, ' ', 14) - 14));
25 15
					} elseif (\str_starts_with($item, 'CPU OS ')) {
26 2
						$version = \str_replace('_', '.', \mb_substr($item, 7, \mb_strpos($item, ' ', 7) - 7));
27
					}
28
				}
29 15
				return [
30 15
					'type' => 'human',
31 15
					'category' => $value === 'iPad' ? 'tablet' : 'mobile',
32 15
					'architecture' => 'arm',
33 15
					'bits' => $value === 'iPod' ? 32 : 64,
34 15
					'kernel' => 'Linux',
35 15
					'platform' => 'iOS',
36 15
					'platformversion' => $version,
37 15
					'vendor' => 'Apple',
38 15
					'device' => $value,
39 15
					'model' => $model
40 15
				];
41 1
			},
42 1
			'xbox' => fn (string $value) : array => [
43 3
				'device' => $value,
44 3
				'type' => 'human',
45 3
				'category' => 'console',
46 3
				'vendor' => 'Microsoft',
47 3
			],
48 1
			'playstation' => function (string $value) : array {
49 1
				$parts = \explode(' ', $value);
50 1
				if (\str_contains($parts[1], '/')) {
51 1
					list($parts[1], $parts[2]) = \explode('/', $parts[1]);
52
				}
53 1
				$platform = [
54 1
					4 => 'Orbis OS',
55 1
					5 => 'FreeBSD'
56 1
				];
57 1
				return [
58 1
					'device' => $parts[0].' '.$parts[1],
59 1
					'kernel' => 'Linux',
60 1
					'platform' => $platform[\intval($parts[1])] ?? null,
61 1
					'platformversion' => $parts[2] ?? null,
62 1
					'type' => 'human',
63 1
					'category' => 'console',
64 1
					'vendor' => 'Sony',
65 1
					'processor' => 'AMD',
66 1
					'architecture' => 'x86',
67 1
					'bits' => 64
68 1
				];
69 1
			},
70 1
			'firetablet' => fn (string $value) : array => [
71 2
				'type' => 'human',
72 2
				'category' => 'tablet',
73 2
				'vendor' => 'Amazon',
74 2
				'device' => 'Fire Tablet',
75 2
				'model' => $value
76 2
			]
77 1
		];
78 1
		return [
79 1
			'iPhone' => [
80 1
				'match' => 'exact',
81 1
				'categories' => $fn['ios']
82 1
			],
83 1
			'iPad' => [
84 1
				'match' => 'exact',
85 1
				'categories' => $fn['ios']
86 1
			],
87 1
			'iPod' => [
88 1
				'match' => 'exact',
89 1
				'categories' => $fn['ios']
90 1
			],
91 1
			'iPod touch' => [
92 1
				'match' => 'exact',
93 1
				'categories' => $fn['ios']
94 1
			],
95 1
			'Macintosh' => [
96 1
				'match' => 'exact',
97 1
				'categories' => [
98 1
					'vendor' => 'Apple',
99 1
					'device' => 'Macintosh'
100 1
				]
101 1
			],
102 1
			'Quest' => [
103 1
				'match' => 'start',
104 1
				'categories' => fn (string $value) : array => [
105 3
					'vendor' => 'Oculus',
106 3
					'device' => $value,
107 3
					'type' => 'human',
108 3
					'category' => 'vr'
109 3
				]
110 1
			],
111 1
			'Pacific' => [
112 1
				'match' => 'start',
113 1
				'categories' => [
114 1
					'vendor' => 'Oculus',
115 1
					'device' => 'Go',
116 1
					'type' => 'human',
117 1
					'category' => 'vr'
118 1
				]
119 1
			],
120 1
			'Nintendo Wii U' => [
121 1
				'match' => 'exact',
122 1
				'categories' => [
123 1
					'device' => 'Wii U',
124 1
					'type' => 'human',
125 1
					'category' => 'console',
126 1
					'architecture' => 'PowerPC',
127 1
					'vendor' => 'Nintendo'
128 1
				]
129 1
			],
130 1
			'Nintendo WiiU' => [
131 1
				'match' => 'exact',
132 1
				'categories' => [
133 1
					'device' => 'Wii U',
134 1
					'type' => 'human',
135 1
					'category' => 'console',
136 1
					'architecture' => 'PowerPC',
137 1
					'vendor' => 'Nintendo'
138 1
				]
139 1
			],
140 1
			'Nintendo Wii' => [
141 1
				'match' => 'exact',
142 1
				'categories' => [
143 1
					'device' => 'Wii',
144 1
					'type' => 'human',
145 1
					'category' => 'console',
146 1
					'vendor' => 'Nintendo'
147 1
				]
148 1
			],
149 1
			'Nintendo 3DS' => [
150 1
				'match' => 'exact',
151 1
				'categories' => [
152 1
					'device' => '3DS',
153 1
					'type' => 'human',
154 1
					'category' => 'console',
155 1
					'vendor' => 'Nintendo'
156 1
				]
157 1
			],
158 1
			'Nintendo Switch' => [
159 1
				'match' => 'exact',
160 1
				'categories' => [
161 1
					'device' => 'Switch',
162 1
					'type' => 'human',
163 1
					'category' => 'console',
164 1
					'vendor' => 'Nintendo'
165 1
				]
166 1
			],
167 1
			'Xbox Series S' => [
168 1
				'match' => 'exact',
169 1
				'categories' => $fn['xbox']
170 1
			],
171 1
			'Xbox Series X' => [
172 1
				'match' => 'exact',
173 1
				'categories' => $fn['xbox']
174 1
			],
175 1
			'Xbox One' => [
176 1
				'match' => 'exact',
177 1
				'categories' => $fn['xbox']
178 1
			],
179 1
			'Xbox 360' => [
180 1
				'match' => 'exact',
181 1
				'categories' => $fn['xbox']
182 1
			],
183 1
			'Xbox' => [
184 1
				'match' => 'exact',
185 1
				'categories' => $fn['xbox']
186 1
			],
187 1
			'Playstation 4' => [
188 1
				'match' => 'start',
189 1
				'categories' => $fn['playstation']
190 1
			],
191 1
			'Playstation 5' => [
192 1
				'match' => 'start',
193 1
				'categories' => $fn['playstation']
194 1
			],
195 1
			'SHIELD Android TV' => [
196 1
				'match' => 'start',
197 1
				'categories' => [
198 1
					'type' => 'human',
199 1
					'category' => 'console',
200 1
					'vendor' => 'NVIDIA',
201 1
					'device' => 'Shield'
202 1
				]
203 1
			],
204 1
			'CrKey/' => [
205 1
				'match' => 'start',
206 1
				'categories' => fn (string $value) : array => [
207 2
					'type' => 'human',
208 2
					'category' => 'tv',
209 2
					'vendor' => 'Google',
210 2
					'device' => 'Chromecast',
211 2
					'model' => \explode(',', \mb_substr($value, 6), 2)[0]
212 2
				]
213 1
			],
214 1
			'ChromeBook' => [
215 1
				'match' => 'any',
216 1
				'categories' => [
217 1
					'type' => 'human',
218 1
					'category' => 'desktop'
219 1
				]
220 1
			],
221 1
			'GoogleTV' => [
222 1
				'match' => 'exact',
223 1
				'categories' => [
224 1
					'type' => 'human',
225 1
					'category' => 'tv',
226 1
					'device' => 'GoogleTV'
227 1
				]
228 1
			],
229 1
			'CriKey/' => [
230 1
				'match' => 'start',
231 1
				'categories' => fn (string $value) : array => [
232
					'type' => 'human',
233
					'category' => 'tv',
234
					'device' => 'Chromecast',
235
					'vendor' => 'Google',
236
					'platformversion' => \mb_substr($value, 7)
237
				]
238 1
			],
239 1
			'Apple/' => [
240 1
				'match' => 'start',
241 1
				'categories' => fn (string $value) : array => [
242 1
					'type' => 'human',
243 1
					'device' => \mb_substr($value, 6)
244 1
				]
245 1
			],
246 1
			'KFT' => [
247 1
				'match' => 'start',
248 1
				'categories' => $fn['firetablet']
249 1
			],
250 1
			'KFO' => [
251 1
				'match' => 'start',
252 1
				'categories' => $fn['firetablet']
253 1
			],
254 1
			'KFM' => [
255 1
				'match' => 'start',
256 1
				'categories' => $fn['firetablet']
257 1
			],
258 1
			'AFT' => [
259 1
				'match' => 'start',
260 1
				'categories' => fn (string $value) : array => [
261 1
					'type' => 'human',
262 1
					'category' => 'tv',
263 1
					'vendor' => 'Amazon',
264 1
					'device' => 'Fire TV',
265 1
					'model' => $value
266 1
				]
267 1
			],
268 1
			'Roku/' => [
269 1
				'match' => 'start',
270 1
				'categories' => fn (string $value, int $i, array $tokens) : array => [
271 1
					'type' => 'human',
272 1
					'category' => 'tv',
273 1
					'kernel' => 'Linux',
274 1
					'platform' => 'Roku OS',
275 1
					'platformversion' => \mb_substr($value, 5),
276 1
					'vendor' => 'Roku',
277 1
					'device' => 'Roku',
278 1
					'build' => $tokens[++$i] ?? null
279 1
				]
280 1
			],
281 1
			'AmigaOneX1000' => [
282 1
				'match' => 'exact',
283 1
				'categories' => [
284 1
					'type' => 'human',
285 1
					'category' => 'desktop',
286 1
					'device' => 'AmigaOneX1000'
287 1
				]
288 1
			],
289 1
			'googleweblight' => [
290 1
				'match' => 'exact',
291 1
				'categories' => [
292 1
					'proxy' => 'googleweblight'
293 1
				]
294 1
			],
295 1
			'SAMSUNG-' => [
296 1
				'match' => 'start',
297 1
				'categories' => function (string $value) : array {
298 2
					$parts = \explode('/', $value, 2);
299 2
					return [
300 2
						'device' => \mb_substr($parts[0], 8),
301 2
						'build' => $parts[1] ?? null,
302 2
						'type' => 'human',
303 2
						'category' => 'mobile',
304 2
						'vendor' => 'Samsung'
305 2
					];
306 1
				}
307 1
			],
308 1
			'Samsung' => [
309 1
				'match' => 'start',
310 12
				'categories' => fn (string $value) : ?array => \str_starts_with($value, 'SamsungBrowser') ? null : [
311 12
					'vendor' => 'Samsung'
312 12
				]
313 1
			],
314 1
			'Acer' => [
315 1
				'match' => 'start',
316 1
				'categories' => [
317 1
					'vendor' => 'Acer'
318 1
				]
319 1
			],
320 1
			'SonyEricsson' => [
321 1
				'match' => 'start',
322 1
				'categories' => function (string $value) : array {
323 1
					$parts = \explode('/', $value, 2);
324 1
					return [
325 1
						'type' => 'human',
326 1
						'category' => 'mobile',
327 1
						'vendor' => 'Sony Ericsson',
328 1
						'device' => \mb_substr($parts[0], 12),
329 1
						'build' => $parts[1] ?? null
330 1
					];
331 1
				}
332 1
			],
333 1
			'LGE' => [
334 1
				'match' => 'exact',
335 1
				'categories' => function (string $value, int $i, array $tokens) : array {
336 1
					$device = $tokens[++$i] ?? null;
337 1
					$platformversion = $tokens[++$i] ?? null;
338 1
					$build = $tokens[++$i] ?? null;
339 1
					return [
340 1
						'type' => 'human',
341 1
						'category' => 'tv',
342 1
						'device' => $device,
343 1
						'build' => $build,
344 1
						'platformversion' => $platformversion,
345 1
						'vendor' => 'LG'
346 1
					];
347 1
				}
348 1
			],
349 1
			'NOKIA' => [
350 1
				'match' => 'start',
351 1
				'categories' => function (string $value) : array {
352 2
					$parts = \explode('/', $value, 2);
353 2
					$device = \trim(\mb_substr($parts[0], 5, \str_ends_with($parts[0], ' Build') ? -6 : null));
354 2
					return [
355 2
						'type' => 'human',
356 2
						'category' => 'mobile',
357 2
						'vendor' => 'Nokia',
358 2
						'device' => $device !== '' ? $device : null,
359 2
						'build' => $parts[1] ?? null,
360 2
					];
361 1
				}
362 1
			],
363 1
			'Lumia' => [
364 1
				'match' => 'start',
365 1
				'categories' => fn (string $value) : array => [
366 2
					'type' => 'human',
367 2
					'category' => 'mobile',
368 2
					'vendor' => 'Nokia',
369 2
					'device' => $value
370 2
				]
371 1
			],
372 1
			'BRAVIA' => [
373 1
				'match' => 'start',
374 1
				'categories' => [
375 1
					'type' => 'human',
376 1
					'category' => 'tv',
377 1
					'vendor' => 'Sony'
378 1
				]
379 1
			],
380 1
			'TECNO' => [
381 1
				'match' => 'start',
382 1
				'categories' => fn (string $value) : array => [
383 1
					'type' => 'human',
384 1
					'category' => 'mobile',
385 1
					'vendor' => 'Tecno',
386 1
					'device' => \explode(' ', $value, 2)[1] ?? null
387 1
				]
388 1
			],
389 1
			'ThinkPad' => [
390 1
				'match' => 'start',
391 1
				'categories' => function (string $value, int $i, array $tokens) : array {
392 1
					if (\mb_strpos($tokens[++$i] ?? '', 'Build/') === 0) {
393 1
						$device = \explode('_', \mb_substr($tokens[$i], 6));
394
					}
395 1
					return [
396 1
						'type' => 'human',
397 1
						'vendor' => 'Lenovo',
398 1
						'device' => $device[0] ?? null,
399 1
						'model' => $device[1] ?? null,
400 1
						'build' => $device[2] ?? null
401 1
					];
402 1
				}
403 1
			],
404 1
			'Model/' => [
405 1
				'match' => 'start',
406 1
				'categories' => fn (string $value) : array => [
407
					'model' => \mb_substr($value, 6)
408
				]
409 1
			],
410 1
			'Build/' => [
411 1
				'match' => 'any',
412 1
				'categories' => function (string $value) : array {
413 21
					return self::getDevice($value);
414 1
				}
415 1
			],
416 1
		];
417
	}
418
419
	/**
420
	 * Extracts device information from a token
421
	 * 
422
	 * @param string $value A token expected to contain device information
423
	 * @return array<string,string|null> An array containing the extracted devices information
424
	 */
425 31
	public static function getDevice(string $value) : array {
426 31
		foreach (['Mobile', 'Tablet', 'Safari', 'AppleWebKit', 'Linux', 'rv:'] AS $item) {
427 31
			if (\mb_stripos($value, $item) === 0) {
428 5
				return [];
429
			}
430
		}
431 29
		$device = \explode('Build/', \str_ireplace('build/', 'Build/', $value), 2);
0 ignored issues
show
Bug introduced by
It seems like str_ireplace('build/', 'Build/', $value) can also be of type array; however, parameter $string of explode() 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

431
		$device = \explode('Build/', /** @scrutinizer ignore-type */ \str_ireplace('build/', 'Build/', $value), 2);
Loading history...
432 29
		$device[0] = \trim($device[0]);
433 29
		$vendors = [
434 29
			'Samsung' => 'Samsung',
435 29
			'OnePlus' => 'OnePlus',
436 29
			'CPH' =>'OnePlus',
437 29
			'KB' => 'OnePlus',
438 29
			'Pixel' => 'Google',
439 29
			'SM-' => 'Samsung',
440 29
			'LM-' => 'LG',
441 29
			'LG' => 'LG',
442 29
			'RMX' => 'RealMe',
443 29
			'HTC' => 'HTC',
444 29
			'Nexus' => 'Google',
445 29
			'MI ' => 'Xiaomi',
446 29
			'HM ' => 'Xiaomi',
447 29
			'Huawei' => 'Huawei',
448 29
			'Honor' => 'Honor',
449 29
			'Motorola' => 'Motorola',
450 29
			'moto' => 'Motorola',
451 29
			'Intel' => 'Intel',
452 29
			'SonyEricsson' => 'Sony Ericsson',
453 29
			'Tecno' => 'Tecno',
454 29
			'Vivo' => 'Vivo',
455 29
			'Huawei' => 'Huawei',
456 29
			'Oppo' => 'Oppo',
457 29
			'Asus' => 'Asus',
458 29
			'Alcatel' => 'Alcatel',
459 29
			'Oppo' => 'Oppo'
460 29
		];
461 29
		$vendor = null;
462 29
		foreach ($vendors AS $key => $item) {
463 29
			if (($pos = \mb_stripos($value, $key)) !== false) {
464 19
				$vendor = $item;
465 19
				if ($pos === 0 && ($key === $item || $key === 'SonyEricsson')) {
466 9
					$device[0] = \trim(\mb_substr($device[0], \mb_strlen($key)), ' -_');
467
				}
468 19
				break;
469
			}
470
		}
471 29
		return [
472 29
			'vendor' => $vendor === null ? null : self::getVendor($vendor),
473 29
			'device' => $device[0] === '' ? null : $device[0],
474 29
			'build' => $device[1] ?? null
475 29
		];
476
	}
477
478 19
	public static function getVendor(string $value) : string {
479 19
		$map = [
480 19
			'oneplus' => 'OnePlus',
481 19
			'lg' => 'LG',
482 19
			'lge' => 'LG',
483 19
			'realme' => 'RealMe',
484 19
			'htc' => 'HTC',
485 19
			'sonyericsson' => 'Sony Ericsson',
486 19
			'tcl' => 'TCL',
487 19
			'zte' => 'ZTE',
488 19
			'hmd' => 'HMD',
489 19
			'lt' => 'LT'
490 19
		];
491 19
		$value = \mb_strtolower($value);
492 19
		return $map[$value] ?? \mb_convert_case($value, MB_CASE_TITLE);
493
	}
494
}