1 | <?php |
||
2 | declare(strict_types = 1); |
||
3 | namespace hexydec\agentzero; |
||
4 | |||
5 | class hints { |
||
6 | |||
7 | /** |
||
8 | * Parses client hints to set agentzero properties |
||
9 | * |
||
10 | * @param string &$ua A reference to the User-Agent string, which may be used with brand names and versions |
||
11 | * @param array $hints An array of client hints |
||
12 | * @return stdClass A stdClass object containing parsed values for agentzero |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
13 | */ |
||
14 | 100 | public static function parse(string &$ua, array $hints) : \stdClass { |
|
15 | 100 | $map = [ |
|
16 | 100 | 'sec-ch-ua-mobile' => fn (\stdClass $obj, string $value) : string => $obj->category = $value === '?1' ? 'mobile' : 'desktop', |
|
17 | 100 | 'sec-ch-ua-platform' => fn (\stdClass $obj, string $value) : ?string => $obj->platform = \trim($value, '"') ?: null, |
|
18 | 100 | 'sec-ch-ua-platform-version' => function (\stdClass $obj, string $value) : void { |
|
19 | 1 | $value = \trim($value, '"'); |
|
20 | 1 | if (($obj->platform ?? null) === 'Windows') { |
|
21 | 1 | $map = [ |
|
22 | 1 | '8', |
|
23 | 1 | '10.1507', |
|
24 | 1 | '10.1511', |
|
25 | 1 | '10.1607', |
|
26 | 1 | '10.1703', |
|
27 | 1 | '10.1709', |
|
28 | 1 | '10.1803', |
|
29 | 1 | '10.1809', |
|
30 | 1 | '10.1903', |
|
31 | 1 | '10.1909', |
|
32 | 1 | '10.2004', |
|
33 | 1 | '10.20H2', |
|
34 | 1 | '10.21H1', |
|
35 | 1 | '10.21H2' |
|
36 | 1 | ]; |
|
37 | 1 | $major = \intval($value); |
|
38 | 1 | if (isset($map[$major])) { |
|
39 | 1 | $value = $map[$major] ?? '11'; |
|
40 | } |
||
41 | } |
||
42 | 1 | $obj->platformversion = $value ?: null; |
|
43 | 100 | }, |
|
44 | 100 | 'sec-ch-ua-model' => fn (\stdClass $obj, string $value) : ?string => $obj->model = \trim($value, '"') ?: null, |
|
45 | 100 | 'sec-ch-ua-full-version-list' => function (\stdClass $obj, string $value, string &$ua) : void { |
|
46 | 1 | $brands = []; |
|
47 | |||
48 | // process brands string |
||
49 | 1 | foreach (\explode(',', $value) AS $item) { |
|
50 | 1 | $parts = \explode('";v="', \trim($item, ' "')); |
|
51 | |||
52 | // remove GREASE brands |
||
53 | 1 | if (\strcspn($parts[0], '()-./:;=?_') === \strlen($parts[0])) { |
|
54 | 1 | $brands[$parts[0]] = $parts[1]; |
|
55 | } |
||
56 | } |
||
57 | |||
58 | // remove Chromium if Google Chrome present |
||
59 | 1 | if (isset($brands['Chromium'], $brands['Google Chrome'])) { |
|
60 | 1 | unset($brands['Chromium']); |
|
61 | } |
||
62 | |||
63 | // sort the values in importance order |
||
64 | 1 | $sort = ['Chromium', 'Google Chrome']; |
|
65 | 1 | $count = \count($sort); |
|
66 | 1 | \uksort($brands, function (string $a, string $b) use ($sort, $count) : int { |
|
67 | $aval = $bval = $count; |
||
68 | foreach ($sort AS $key => $item) { |
||
69 | if ($a === $item) { |
||
70 | $aval = $key; |
||
71 | } |
||
72 | if ($b === $item) { |
||
73 | $bval = $key; |
||
74 | } |
||
75 | } |
||
76 | return $aval - $bval; |
||
77 | 1 | }); |
|
78 | |||
79 | // add to UA string |
||
80 | 1 | foreach ($brands AS $key => $item) { |
|
81 | 1 | $ua = $key.'/'.$item.' '.$ua; |
|
82 | } |
||
83 | 100 | }, |
|
84 | 100 | 'device-memory' => fn (\stdClass $obj, string $value) : int => $obj->ram = \intval(\floatval($value) * 1024), |
|
85 | 100 | 'width' => fn (\stdClass $obj, string $value) : int => $obj->width = \intval($value), |
|
86 | 100 | 'ect' => fn (\stdClass $obj, string $value) : string => $obj->nettype = $value |
|
87 | 100 | ]; |
|
88 | 100 | $obj = new \stdClass(); |
|
89 | 100 | foreach ($hints AS $key => $item) { |
|
90 | 1 | $key = \strtolower($key); |
|
91 | 1 | if (isset($map[$key])) { |
|
92 | 1 | $map[$key]($obj, $item, $ua); |
|
93 | } |
||
94 | } |
||
95 | 100 | return $obj; |
|
0 ignored issues
–
show
|
|||
96 | } |
||
97 | } |