PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.15.5
Independent Analytics – WordPress Analytics Plugin v2.15.5
2.15.5 2.15.4 2.15.3 2.15.2 2.15.1 2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / vendor / matomo / device-detector / ClientHints.php
independent-analytics / vendor / matomo / device-detector Last commit date
Cache 2 years ago Parser 1 month ago Yaml 3 months ago regexes 1 month ago ClientHints.php 1 month ago DeviceDetector.php 1 month ago autoload.php 7 months ago
ClientHints.php
342 lines
1 <?php
2
3 /**
4 * Device Detector - The Universal Device Detection library for parsing User Agents
5 *
6 * @link https://matomo.org
7 *
8 * @license http://www.gnu.org/licenses/lgpl.html LGPL v3 or later
9 */
10 declare (strict_types=1);
11 namespace IAWPSCOPED\DeviceDetector;
12
13 /** @internal */
14 class ClientHints
15 {
16 /**
17 * Represents `Sec-CH-UA-Arch` header field: The underlying architecture's instruction set
18 *
19 * @var string
20 */
21 protected $architecture = '';
22 /**
23 * Represents `Sec-CH-UA-Bitness` header field: The underlying architecture's bitness
24 *
25 * @var string
26 */
27 protected $bitness = '';
28 /**
29 * Represents `Sec-CH-UA-Mobile` header field: whether the user agent should receive a specifically "mobile" UX
30 *
31 * @var bool
32 */
33 protected $mobile = \false;
34 /**
35 * Represents `Sec-CH-UA-Model` header field: the user agent's underlying device model
36 *
37 * @var string
38 */
39 protected $model = '';
40 /**
41 * Represents `Sec-CH-UA-Platform` header field: the platform's brand
42 *
43 * @var string
44 */
45 protected $platform = '';
46 /**
47 * Represents `Sec-CH-UA-Platform-Version` header field: the platform's major version
48 *
49 * @var string
50 */
51 protected $platformVersion = '';
52 /**
53 * Represents `Sec-CH-UA-Full-Version` header field: the platform's major version
54 *
55 * @var string
56 */
57 protected $uaFullVersion = '';
58 /**
59 * Represents `Sec-CH-UA-Full-Version-List` header field: the full version for each brand in its brand list
60 *
61 * @var array
62 */
63 protected $fullVersionList = [];
64 /**
65 * Represents `x-requested-with` header field: Android app id
66 * @var string
67 */
68 protected $app = '';
69 /**
70 * Represents `Sec-CH-UA-Form-Factors` header field: form factor device type name
71 *
72 * @var array
73 */
74 protected $formFactors = [];
75 /**
76 * Constructor
77 *
78 * @param string $model `Sec-CH-UA-Model` header field
79 * @param string $platform `Sec-CH-UA-Platform` header field
80 * @param string $platformVersion `Sec-CH-UA-Platform-Version` header field
81 * @param string $uaFullVersion `Sec-CH-UA-Full-Version` header field
82 * @param array $fullVersionList `Sec-CH-UA-Full-Version-List` header field
83 * @param bool $mobile `Sec-CH-UA-Mobile` header field
84 * @param string $architecture `Sec-CH-UA-Arch` header field
85 * @param string $bitness `Sec-CH-UA-Bitness`
86 * @param string $app `HTTP_X-REQUESTED-WITH`
87 * @param array $formFactors `Sec-CH-UA-Form-Factors` header field
88 */
89 public function __construct(string $model = '', string $platform = '', string $platformVersion = '', string $uaFullVersion = '', array $fullVersionList = [], bool $mobile = \false, string $architecture = '', string $bitness = '', string $app = '', array $formFactors = [])
90 {
91 $this->model = $model;
92 $this->platform = $platform;
93 $this->platformVersion = $platformVersion;
94 $this->uaFullVersion = $uaFullVersion;
95 $this->fullVersionList = $fullVersionList;
96 $this->mobile = $mobile;
97 $this->architecture = $architecture;
98 $this->bitness = $bitness;
99 $this->app = $app;
100 $this->formFactors = $formFactors;
101 }
102 /**
103 * Magic method to directly allow accessing the protected properties
104 *
105 * @param string $variable
106 *
107 * @return mixed
108 *
109 * @throws \Exception
110 */
111 public function __get(string $variable)
112 {
113 if (\property_exists($this, $variable)) {
114 return $this->{$variable};
115 }
116 throw new \Exception('Invalid ClientHint property requested.');
117 }
118 /**
119 * Returns if the client hints
120 *
121 * @return bool
122 */
123 public function isMobile() : bool
124 {
125 return $this->mobile;
126 }
127 /**
128 * Returns the Architecture
129 *
130 * @return string
131 */
132 public function getArchitecture() : string
133 {
134 return $this->architecture;
135 }
136 /**
137 * Returns the Bitness
138 *
139 * @return string
140 */
141 public function getBitness() : string
142 {
143 return $this->bitness;
144 }
145 /**
146 * Returns the device model
147 *
148 * @return string
149 */
150 public function getModel() : string
151 {
152 return $this->model;
153 }
154 /**
155 * Returns the Operating System
156 *
157 * @return string
158 */
159 public function getOperatingSystem() : string
160 {
161 return $this->platform;
162 }
163 /**
164 * Returns the Operating System version
165 *
166 * @return string
167 */
168 public function getOperatingSystemVersion() : string
169 {
170 return $this->platformVersion;
171 }
172 /**
173 * Returns the Browser name
174 *
175 * @return array<string, string>
176 */
177 public function getBrandList() : array
178 {
179 if (\is_array($this->fullVersionList) && \count($this->fullVersionList)) {
180 $brands = \array_column($this->fullVersionList, 'brand');
181 $versions = \array_column($this->fullVersionList, 'version');
182 if (\count($brands) === \count($versions)) {
183 // @phpstan-ignore-next-line
184 return \array_combine($brands, $versions);
185 }
186 }
187 return [];
188 }
189 /**
190 * Returns the Browser version
191 *
192 * @return string
193 */
194 public function getBrandVersion() : string
195 {
196 if (!empty($this->uaFullVersion)) {
197 return $this->uaFullVersion;
198 }
199 return '';
200 }
201 /**
202 * Returns the Android app id
203 *
204 * @return string
205 */
206 public function getApp() : string
207 {
208 return $this->app;
209 }
210 /**
211 * Returns the formFactor device type name
212 *
213 * @return array
214 */
215 public function getFormFactors() : array
216 {
217 return $this->formFactors;
218 }
219 /**
220 * Factory method to easily instantiate this class using an array containing all available (client hint) headers
221 *
222 * @param array $headers
223 *
224 * @return ClientHints
225 */
226 public static function factory(array $headers) : ClientHints
227 {
228 $model = $platform = $platformVersion = $uaFullVersion = $architecture = $bitness = '';
229 $app = '';
230 $mobile = \false;
231 $fullVersionList = [];
232 $formFactors = [];
233 foreach ($headers as $name => $value) {
234 if (empty($value)) {
235 continue;
236 }
237 // any kind of html tag is unexpected as part of those headers, so discard values that contain some.
238 if (\is_string($value) && \strip_tags($value) !== $value) {
239 continue;
240 }
241 switch (\str_replace('_', '-', \strtolower((string) $name))) {
242 case 'http-sec-ch-ua-arch':
243 case 'sec-ch-ua-arch':
244 case 'arch':
245 case 'architecture':
246 if (\is_string($value)) {
247 $architecture = \trim($value, '"');
248 }
249 break;
250 case 'http-sec-ch-ua-bitness':
251 case 'sec-ch-ua-bitness':
252 case 'bitness':
253 if (\is_string($value)) {
254 $bitness = \trim($value, '"');
255 }
256 break;
257 case 'http-sec-ch-ua-mobile':
258 case 'sec-ch-ua-mobile':
259 case 'mobile':
260 $mobile = \in_array($value, [\true, '1', '?1'], \true);
261 break;
262 case 'http-sec-ch-ua-model':
263 case 'sec-ch-ua-model':
264 case 'model':
265 if (\is_string($value)) {
266 $model = \trim($value, '"');
267 }
268 break;
269 case 'http-sec-ch-ua-full-version':
270 case 'sec-ch-ua-full-version':
271 case 'uafullversion':
272 if (\is_string($value)) {
273 $uaFullVersion = \trim($value, '"');
274 }
275 break;
276 case 'http-sec-ch-ua-platform':
277 case 'sec-ch-ua-platform':
278 case 'platform':
279 if (\is_string($value)) {
280 $platform = \trim($value, '"');
281 }
282 break;
283 case 'http-sec-ch-ua-platform-version':
284 case 'sec-ch-ua-platform-version':
285 case 'platformversion':
286 if (\is_string($value)) {
287 $platformVersion = \trim($value, '"');
288 }
289 break;
290 case 'brands':
291 if (!empty($fullVersionList)) {
292 break;
293 }
294 // use this only if no other header already set the list
295 case 'fullversionlist':
296 $fullVersionList = \is_array($value) ? $value : $fullVersionList;
297 break;
298 case 'http-sec-ch-ua':
299 case 'sec-ch-ua':
300 if (!empty($fullVersionList)) {
301 break;
302 }
303 // use this only if no other header already set the list
304 case 'http-sec-ch-ua-full-version-list':
305 case 'sec-ch-ua-full-version-list':
306 if (!\is_string($value)) {
307 break;
308 }
309 $reg = '/^"([^"]+)"; ?v="([^"]+)"(?:, )?/';
310 $list = [];
311 while (\preg_match($reg, $value, $matches)) {
312 $list[] = ['brand' => $matches[1], 'version' => $matches[2]];
313 $value = \substr($value, \strlen($matches[0]));
314 }
315 if (\count($list)) {
316 $fullVersionList = $list;
317 }
318 break;
319 case 'http-x-requested-with':
320 case 'x-requested-with':
321 if (\is_string($value) && 'xmlhttprequest' !== \strtolower($value)) {
322 $app = $value;
323 }
324 break;
325 case 'formfactors':
326 case 'http-sec-ch-ua-form-factors':
327 case 'sec-ch-ua-form-factors':
328 if (\is_array($value)) {
329 $stringValues = \array_filter($value, '\\is_string');
330 if (\count($stringValues) === \count($value)) {
331 $formFactors = \array_map('\\strtolower', $value);
332 }
333 } elseif (\is_string($value) && \preg_match_all('~"([a-z]+)"~i', \strtolower($value), $matches)) {
334 $formFactors = $matches[1];
335 }
336 break;
337 }
338 }
339 return new self($model, $platform, $platformVersion, $uaFullVersion, $fullVersionList, $mobile, $architecture, $bitness, $app, $formFactors);
340 }
341 }
342