Test Failed
Pull Request — master (#85)
by Gabriel
02:47
created

BrowserDetector::checkBrowserInternetExplorer()   D

Complexity

Conditions 22
Paths 37

Size

Total Lines 112
Code Lines 64

Duplication

Lines 9
Ratio 8.04 %

Code Coverage

Tests 44
CRAP Score 58.141

Importance

Changes 3
Bugs 0 Features 0
Metric Value
dl 9
loc 112
rs 4.6625
c 3
b 0
f 0
ccs 44
cts 76
cp 0.5789
cc 22
eloc 64
nc 37
nop 0
crap 58.141

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
3
namespace Sinergi\BrowserDetector;
4
5
class BrowserDetector implements DetectorInterface
6
{
7
    const FUNC_PREFIX = 'checkBrowser';
8
9
    protected static $userAgentString;
10
11
    /**
12
     * @var Browser
13
     */
14
    protected static $browser;
15
16
    protected static $browsersList = array(
17
        // well-known, well-used
18
        // Special Notes:
19
        // (1) Opera must be checked before FireFox due to the odd
20
        //     user agents used in some older versions of Opera
21
        // (2) WebTV is strapped onto Internet Explorer so we must
22
        //     check for WebTV before IE
23
        // (3) Because of Internet Explorer 11 using
24
        //     "Mozilla/5.0 ([...] Trident/7.0; rv:11.0) like Gecko"
25
        //     as user agent, tests for IE must be run before any
26
        //     tests checking for "Mozilla"
27
        // (4) (deprecated) Galeon is based on Firefox and needs to be
28
        //     tested before Firefox is tested
29
        // (5) OmniWeb is based on Safari so OmniWeb check must occur
30
        //     before Safari
31
        // (6) Netscape 9+ is based on Firefox so Netscape checks
32
        //     before FireFox are necessary
33
        // (7) Microsoft Edge must be checked before Chrome and Safari
34
        // (7) Vivaldi must be checked before Chrome
35
        'WebTv',
36
        'InternetExplorer',
37
        'Edge',
38
        'Opera',
39
        'Vivaldi',
40
        'Dragon',
41
        'Galeon',
42
        'NetscapeNavigator9Plus',
43
        'SeaMonkey',
44
        'Firefox',
45
        'Yandex',
46
        'Samsung',
47
        'Chrome',
48
        'OmniWeb',
49
        'UCBrowser', //before Android
50
        // common mobile
51
        'Android',
52
        'BlackBerry',
53
        'Nokia',
54
        'Gsa',
55
        // WebKit base check (post mobile and others)
56
        'AppleNews',
57
        'Safari',
58
        // everyone else
59
        'NetPositive',
60
        'Firebird',
61
        'Konqueror',
62
        'Icab',
63
        'Phoenix',
64
        'Amaya',
65
        'Lynx',
66
        'NSPlayer',
67
        'Office',
68
        'Shiretoko',
69
        'IceCat',
70
        'Iceweasel',
71
        'Mozilla', /* Mozilla is such an open standard that you must check it last */
72
    );
73
74
    //https://en.wikipedia.org/wiki/Microsoft_Edge
75
    protected static $edgeHTML = [
76
        "12.10049" => "0.10.10049",
77
        "12.10051" => "0.11.10051",
78
        "12.10052" => "0.11.10052",
79
        "12.10061" => "0.11.10061",
80
        "12.10074" => "0.11.10074",
81
        "12.1008" => "0.11.10080",
82 8
        "12.10122" => "13.10122",
83
        "12.1013" => "15.1013",
84 8
        "12.10136" => "16.10136",
85 8
        "12.10149" => "19.10149",
86
        "12.10158" => "20.10158",
87
        "12.10159" => "20.10159",
88 8
        "12.10162" => "20.10162",
89
        "12.10166" => "20.10166",
90 8
        "12.1024" => "20.1024",
91 8
        "12.10512" => "20.10512",
92
        "12.10514" => "20.10514",
93 8
        "12.10525" => "20.10525",
94 8
        "12.10532" => "20.10532",
95
        "12.10536" => "20.10536",
96 8
        "13.10547" => "21.10547",
97 8
        "13.10549" => "21.10549",
98
        "13.10565" => "23.10565",
99 8
        "13.10572" => "25.10572",
100 7
        "13.10576" => "25.10576",
101
        "13.10581" => "25.10581",
102 8
        "13.10586" => "25.10586",
103
        "13.11082" => "25.11082",
104 1
        "13.11099" => "27.11099",
105
        "13.11102" => "28.11102",
106
        "13.14251" => "28.14251",
107
        "13.14257" => "28.14257",
108
        "14.14267" => "31.14267",
109
        "14.14271" => "31.14271",
110
        "14.14279" => "31.14279",
111
        "14.14283" => "31.14283",
112 8
        "14.14291" => "34.14291",
113
        "14.14295" => "34.14295",
114 8
        "14.143" => "34.143",
115
        "14.14316" => "37.14316",
116
        "14.14322" => "37.14322",
117
        "14.14327" => "37.14327",
118
        "14.14328" => "37.14328",
119
        "14.14332" => "37.14332",
120 8
        "14.14342" => "38.14342",
121
        "14.14352" => "38.14352",
122
        "14.14393" => "38.14393",
123
        "14.14901" => "39.14901",
124
        "14.14905" => "39.14905",
125
        "14.14915" => "39.14915",
126
        "14.14926" => "39.14926",
127
        "14.14931" => "39.14931",
128 8
        "14.14936" => "39.14936",
129
        "15.14942" => "39.14942",
130 8
        "15.14946" => "39.14946",
131 1
        "15.14951" => "39.14951",
132
        "15.14955" => "39.14955",
133 1
        "15.14959" => "39.14959",
134
        "15.14965" => "39.14965",
135
        "15.14971" => "39.14971",
136 7
        "15.14977" => "39.14977",
137
        "15.14986" => "39.14986"
138
    ];
139
140
    /**
141
     * Routine to determine the browser type.
142
     *
143
     * @param Browser $browser
144 3
     * @param UserAgent $userAgent
145
     *
146 3
     * @return bool
147 2
     */
148 1
    public static function detect(Browser $browser, UserAgent $userAgent = null)
149 1
    {
150 1
        self::$browser = $browser;
151 1
        if (is_null($userAgent)) {
152 1
            $userAgent = self::$browser->getUserAgent();
153 1
        }
154 1
        self::$userAgentString = $userAgent->getUserAgentString();
155 1
156 1
        self::$browser->setName(Browser::UNKNOWN);
157 1
        self::$browser->setVersion(Browser::VERSION_UNKNOWN);
158 1
159
        self::checkChromeFrame();
160 2
        self::checkFacebookWebView();
161
        self::checkTwitterWebView();
162 2
        self::checkWebkit();
163 2
164 1
        foreach (self::$browsersList as $browserName) {
165 1
            $funcName = self::FUNC_PREFIX . $browserName;
166 1
167 1
            if (self::$funcName()) {
168 1
                return true;
169 1
            }
170 1
        }
171
172
        return false;
173 2
    }
174
175
    /**
176
     * Determine if the user is using Chrome Frame.
177
     *
178
     * @return bool
179
     */
180
    public static function checkChromeFrame()
181 2
    {
182
        if (strpos(self::$userAgentString, 'chromeframe') !== false) {
183 2
            self::$browser->setIsChromeFrame(true);
184 2
185 2
            return true;
186 2
        }
187
188
        return false;
189
    }
190
191
    /**
192 2
     * Determine if the browser is a wekit webview.
193
     *
194
     * @return bool
195
     */
196
    public static function checkWebkit()
197
    {
198
        if (strpos(self::$userAgentString, 'AppleWebKit/') !== false) {
199
            self::$browser->setIsWebkit(true);
200 8
201
            return true;
202
        }
203 8
204
        return false;
205
    }
206
207
    /**
208
     * Determine if the user is using Facebook.
209
     *
210
     * @return bool
211
     */
212
    public static function checkFacebookWebView()
213
    {
214 8
        if (strpos(self::$userAgentString, 'FBAV') !== false) {
215 8
            self::$browser->setIsFacebookWebView(true);
216
217 2
            return true;
218
        }
219
220
        return false;
221
    }
222
223
    /**
224
     * Determine if the user is using Twitter.
225
     *
226 2
     * @return bool
227 2
     */
228 2
    public static function checkTwitterWebView()
229 2
    {
230 2
        if (strpos(self::$userAgentString, 'Twitter for') !== false) {
231
            self::$browser->setIsTwitterWebView(true);
232
233 2
            return true;
234 2
        }
235 2
236 1
        return false;
237 1
    }
238
239
    /**
240
     * Determine if the user is using a BlackBerry.
241
     *
242
     * @return bool
243
     */
244
    public static function checkBrowserBlackBerry()
245
    {
246
        if (stripos(self::$userAgentString, 'blackberry') !== false) {
247 2
            if (stripos(self::$userAgentString, 'Version/') !== false) {
248 1
                $aresult = explode('Version/', self::$userAgentString);
249
                if (isset($aresult[1])) {
250 1
                    $aversion = explode(' ', $aresult[1]);
251 1
                    self::$browser->setVersion($aversion[0]);
252 1
                }
253
            } else {
254 1
                $aresult = explode('/', stristr(self::$userAgentString, 'BlackBerry'));
255 1
                if (isset($aresult[1])) {
256 1
                    $aversion = explode(' ', $aresult[1]);
257
                    self::$browser->setVersion($aversion[0]);
258 1
                }
259 1
            }
260 1
            self::$browser->setName(Browser::BLACKBERRY);
261
262 1
            return true;
263 1
        } elseif (stripos(self::$userAgentString, 'BB10') !== false) {
264 1
            $aresult = explode('Version/10.', self::$userAgentString);
265 1
            if (isset($aresult[1])) {
266 2
                $aversion = explode(' ', $aresult[1]);
267
                self::$browser->setVersion('10.' . $aversion[0]);
268 2
            }
269
            self::$browser->setName(Browser::BLACKBERRY);
270
            return true;
271 8
        }
272 1
273
        return false;
274 1
    }
275 1
276 1
    /**
277
     * Determine if the browser is Internet Explorer.
278 1
     *
279
     * @return bool
280
     */
281
    public static function checkBrowserInternetExplorer()
282
    {
283
        // Test for v1 - v1.5 IE
284 7
        if (stripos(self::$userAgentString, 'microsoft internet explorer') !== false) {
285 7
            self::$browser->setName(Browser::IE);
286 7
            self::$browser->setVersion('1.0');
287
            $aresult = stristr(self::$userAgentString, '/');
288 7
            if (preg_match('/308|425|426|474|0b1/i', $aresult)) {
289 7
                self::$browser->setVersion('1.5');
290
            }
291
292
            return true;
293
        } // Test for versions > 1.5 and < 11 and some cases of 11
294
        else {
295
            if (stripos(self::$userAgentString, 'msie') !== false && stripos(self::$userAgentString, 'opera') === false
296
            ) {
297
                // See if the browser is the odd MSN Explorer
298 View Code Duplication
                if (stripos(self::$userAgentString, 'msnb') !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
299
                    $aresult = explode(' ', stristr(str_replace(';', '; ', self::$userAgentString), 'MSN'));
300
                    self::$browser->setName(Browser::MSN);
301
                    if (isset($aresult[1])) {
302
                        self::$browser->setVersion(str_replace(array('(', ')', ';'), '', $aresult[1]));
303
                    }
304
305
                    return true;
306
                }
307
                $aresult = explode(' ', stristr(str_replace(';', '; ', self::$userAgentString), 'msie'));
308
                self::$browser->setName(Browser::IE);
309
                if (isset($aresult[1])) {
310 7
                    self::$browser->setVersion(str_replace(array('(', ')', ';'), '', $aresult[1]));
311
                }
312
                // See https://msdn.microsoft.com/en-us/library/ie/hh869301%28v=vs.85%29.aspx
313
                // Might be 11, anyway !
314
                if (stripos(self::$userAgentString, 'trident') !== false) {
315
                    preg_match('/rv:(\d+\.\d+)/', self::$userAgentString, $matches);
316
                    if (isset($matches[1])) {
317
                        self::$browser->setVersion($matches[1]);
318 7
                    }
319
320 7
                    // At this poing in the method, we know the MSIE and Trident
321
                    // strings are present in the $userAgentString. If we're in
322
                    // compatibility mode, we need to determine the true version.
323
                    // If the MSIE version is 7.0, we can look at the Trident
324
                    // version to *approximate* the true IE version. If we don't
325
                    // find a matching pair, ( e.g. MSIE 7.0 && Trident/7.0 )
326
                    // we're *not* in compatibility mode and the browser really
327
                    // is version 7.0.
328
                    if (stripos(self::$userAgentString, 'MSIE 7.0;')) {
329
                        if (stripos(self::$userAgentString, 'Trident/7.0;')) {
330
                            // IE11 in compatibility mode
331
                            self::$browser->setVersion('11.0');
332
                            self::$browser->setIsCompatibilityMode(true);
333
                        } elseif (stripos(self::$userAgentString, 'Trident/6.0;')) {
334
                            // IE10 in compatibility mode
335
                            self::$browser->setVersion('10.0');
336
                            self::$browser->setIsCompatibilityMode(true);
337 7
                        } elseif (stripos(self::$userAgentString, 'Trident/5.0;')) {
338 1
                            // IE9 in compatibility mode
339 1
                            self::$browser->setVersion('9.0');
340 1
                            self::$browser->setIsCompatibilityMode(true);
341 1
                        } elseif (stripos(self::$userAgentString, 'Trident/4.0;')) {
342 1
                            // IE8 in compatibility mode
343 1
                            self::$browser->setVersion('8.0');
344
                            self::$browser->setIsCompatibilityMode(true);
345 1
                        }
346 7
                    }
347 1
                }
348 1
349 1
                return true;
350 1
            } // Test for versions >= 11
351 1
            else {
352 1
                if (stripos(self::$userAgentString, 'trident') !== false) {
353
                    self::$browser->setName(Browser::IE);
354
355
                    preg_match('/rv:(\d+\.\d+)/', self::$userAgentString, $matches);
356
                    if (isset($matches[1])) {
357
                        self::$browser->setVersion($matches[1]);
358
359 1
                        return true;
360 1
                    } else {
361
                        return false;
362 1
                    }
363
                } // Test for Pocket IE
364 1
                else {
365 6
                    if (stripos(self::$userAgentString, 'mspie') !== false ||
366 1
                        stripos(
367 1
                            self::$userAgentString,
368 1
                            'pocket'
369 1
                        ) !== false
370 1
                    ) {
371 1
                        $aresult = explode(' ', stristr(self::$userAgentString, 'mspie'));
372
                        self::$browser->setName(Browser::POCKET_IE);
373 1
374
                        if (stripos(self::$userAgentString, 'mspie') !== false) {
375
                            if (isset($aresult[1])) {
376 6
                                self::$browser->setVersion($aresult[1]);
377
                            }
378
                        } else {
379
                            $aversion = explode('/', self::$userAgentString);
380
                            if (isset($aversion[1])) {
381
                                self::$browser->setVersion($aversion[1]);
382
                            }
383
                        }
384 4
385
                        return true;
386 4
                    }
387 1
                }
388 1
            }
389 1
        }
390 1
391 1
        return false;
392 1
    }
393
394 1
    /**
395
     * Determine if the browser is Opera.
396
     *
397 4
     * @return bool
398
     */
399
    public static function checkBrowserOpera()
400
    {
401
        if (stripos(self::$userAgentString, 'opera mini') !== false) {
402
            $resultant = stristr(self::$userAgentString, 'opera mini');
403
            if (preg_match('/\//', $resultant)) {
404
                $aresult = explode('/', $resultant);
405 4
                if (isset($aresult[1])) {
406
                    $aversion = explode(' ', $aresult[1]);
407 4
                    self::$browser->setVersion($aversion[0]);
408 2
                }
409 2
            } else {
410 2
                $aversion = explode(' ', stristr($resultant, 'opera mini'));
411 2
                if (isset($aversion[1])) {
412 2
                    self::$browser->setVersion($aversion[1]);
413 2
                }
414
            }
415 2
            self::$browser->setName(Browser::OPERA_MINI);
416 3
417 1
            return true;
418 1
        } elseif (stripos(self::$userAgentString, 'OPiOS') !== false) {
419 1
            $aresult = explode('/', stristr(self::$userAgentString, 'OPiOS'));
420 1
            if (isset($aresult[1])) {
421 1
                $aversion = explode(' ', $aresult[1]);
422 1
                self::$browser->setVersion($aversion[0]);
423
            }
424 1
            self::$browser->setName(Browser::OPERA_MINI);
425
426
            return true;
427 3
        } elseif (stripos(self::$userAgentString, 'opera') !== false) {
428
            $resultant = stristr(self::$userAgentString, 'opera');
429
            if (preg_match('/Version\/(1[0-2].*)$/', $resultant, $matches)) {
430
                if (isset($matches[1])) {
431
                    self::$browser->setVersion($matches[1]);
432
                }
433
            } elseif (preg_match('/\//', $resultant)) {
434
                $aresult = explode('/', str_replace('(', ' ', $resultant));
435 6
                if (isset($aresult[1])) {
436
                    $aversion = explode(' ', $aresult[1]);
437 6
                    self::$browser->setVersion($aversion[0]);
438 1
                }
439 1
            } else {
440 1
                $aversion = explode(' ', stristr($resultant, 'opera'));
441 1
                self::$browser->setVersion(isset($aversion[1]) ? $aversion[1] : '');
442 1
            }
443 1
            self::$browser->setName(Browser::OPERA);
444
445 1
            return true;
446
        } elseif (stripos(self::$userAgentString, ' OPR/') !== false) {
447
            self::$browser->setName(Browser::OPERA);
448 6
            if (preg_match('/OPR\/([\d\.]*)/', self::$userAgentString, $matches)) {
449
                if (isset($matches[1])) {
450
                    self::$browser->setVersion($matches[1]);
451
                }
452
            }
453
454
            return true;
455
        }
456 7
457
        return false;
458 7
    }
459 1
460 1
    /**
461 1
     * Determine if the browser is Samsung.
462 1
     *
463 1
     * @return bool
464
     */
465 1 View Code Duplication
    public static function checkBrowserSamsung()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
466
    {
467
        if (stripos(self::$userAgentString, 'SamsungBrowser') !== false) {
468 7
            $aresult = explode('/', stristr(self::$userAgentString, 'SamsungBrowser'));
469
            if (isset($aresult[1])) {
470
                $aversion = explode(' ', $aresult[1]);
471
                self::$browser->setVersion($aversion[0]);
472
            }
473
            self::$browser->setName(Browser::SAMSUNG_BROWSER);
474
475
            return true;
476 2
        }
477
478 2
        return false;
479
    }
480
481
    /**
482
     * Determine if the browser is Chrome.
483
     *
484
     * @return bool
485
     */
486
    public static function checkBrowserChrome()
487
    {
488
        if (stripos(self::$userAgentString, 'Chrome') !== false) {
489 2
            $aresult = explode('/', stristr(self::$userAgentString, 'Chrome'));
490
            if (isset($aresult[1])) {
491
                $aversion = explode(' ', $aresult[1]);
492
                self::$browser->setVersion($aversion[0]);
493
            }
494
            self::$browser->setName(Browser::CHROME);
495
496
            return true;
497 8
        } elseif (stripos(self::$userAgentString, 'CriOS') !== false) {
498
            $aresult = explode('/', stristr(self::$userAgentString, 'CriOS'));
499 8
            if (isset($aresult[1])) {
500
                $aversion = explode(' ', $aresult[1]);
501
                self::$browser->setVersion($aversion[0]);
502
            }
503
            self::$browser->setName(Browser::CHROME);
504
505
            return true;
506
        }
507
508
        return false;
509
    }
510 8
511
    /**
512
     * Determine if the browser is Vivaldi.
513
     *
514
     * @return bool
515
     */
516 View Code Duplication
    public static function checkBrowserVivaldi()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
517
    {
518 1
        if (stripos(self::$userAgentString, 'Vivaldi') !== false) {
519
            $aresult = explode('/', stristr(self::$userAgentString, 'Vivaldi'));
520 1
            if (isset($aresult[1])) {
521
                $aversion = explode(' ', $aresult[1]);
522
                self::$browser->setVersion($aversion[0]);
523
            }
524
            self::$browser->setName(Browser::VIVALDI);
525
526
            return true;
527
        }
528
529
        return false;
530
    }
531 1
532
    /**
533
     * Determine if the browser is Microsoft Edge.
534
     *
535
     * @return bool
536
     */
537
    public static function checkBrowserEdge()
538
    {
539 6
        if (stripos(self::$userAgentString, 'Edge') !== false) {
540
            preg_match('/Edge[\\/ \\(]([a-zA-Z\\d\\.]*)/i', self::$userAgentString, $matches);
541 6
            if (sizeof($matches)>1)
542
            {
543
                if (isset(self::$edgeHTML[$matches[1]]))
544
                {
545
                    self::$browser->setName(Browser::EDGE);
546
                    self::$browser->setVersion(self::$edgeHTML[$matches[1]]);
547
                }
548
                else
0 ignored issues
show
Coding Style introduced by
Expected 1 space after ELSE keyword; newline found
Loading history...
549
                {
550
                    self::$browser->setName(Browser::EDGE_HTML);
551
                    self::$browser->setVersion($matches[1]);
552 6
                }
553
            }
554
            else
0 ignored issues
show
Coding Style introduced by
Expected 1 space after ELSE keyword; newline found
Loading history...
555
            {
556
                self::$browser->setName(Browser::EDGE);
557
            }
558
559
            return true;
560 1
        }
561
562 1
        return false;
563
    }
564
565
    /**
566
     * Determine if the browser is Google Search Appliance.
567
     *
568
     * @return bool
569
     */
570 View Code Duplication
    public static function checkBrowserGsa()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
571
    {
572
        if (stripos(self::$userAgentString, 'GSA') !== false) {
573 1
            $aresult = explode('/', stristr(self::$userAgentString, 'GSA'));
574
            if (isset($aresult[1])) {
575
                $aversion = explode(' ', $aresult[1]);
576
                self::$browser->setVersion($aversion[0]);
577
            }
578
            self::$browser->setName(Browser::GSA);
579
580
            return true;
581 1
        }
582
583 1
        return false;
584
    }
585
586
    /**
587
     * Determine if the browser is WebTv.
588
     *
589
     * @return bool
590
     */
591 View Code Duplication
    public static function checkBrowserWebTv()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
592
    {
593 1
        if (stripos(self::$userAgentString, 'webtv') !== false) {
594
            $aresult = explode('/', stristr(self::$userAgentString, 'webtv'));
595
            if (isset($aresult[1])) {
596
                $aversion = explode(' ', $aresult[1]);
597
                self::$browser->setVersion($aversion[0]);
598
            }
599
            self::$browser->setName(Browser::WEBTV);
600
601 3
            return true;
602
        }
603 3
604
        return false;
605
    }
606
607
    /**
608
     * Determine if the browser is NetPositive.
609
     *
610
     * @return bool
611
     */
612 3
    public static function checkBrowserNetPositive()
613
    {
614 View Code Duplication
        if (stripos(self::$userAgentString, 'NetPositive') !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
615
            $aresult = explode('/', stristr(self::$userAgentString, 'NetPositive'));
616
            if (isset($aresult[1])) {
617
                $aversion = explode(' ', $aresult[1]);
618
                self::$browser->setVersion(str_replace(array('(', ')', ';'), '', $aversion[0]));
619
            }
620 1
            self::$browser->setName(Browser::NETPOSITIVE);
621
622 1
            return true;
623
        }
624
625
        return false;
626
    }
627
628
    /**
629
     * Determine if the browser is Galeon.
630
     *
631
     * @return bool
632 1
     */
633 View Code Duplication
    public static function checkBrowserGaleon()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
634
    {
635
        if (stripos(self::$userAgentString, 'galeon') !== false) {
636
            $aresult = explode(' ', stristr(self::$userAgentString, 'galeon'));
637
            $aversion = explode('/', $aresult[0]);
638
            if (isset($aversion[1])) {
639
                self::$browser->setVersion($aversion[1]);
640 1
            }
641
            self::$browser->setName(Browser::GALEON);
642 1
643
            return true;
644
        }
645
646
        return false;
647
    }
648
649
    /**
650
     * Determine if the browser is Konqueror.
651
     *
652 1
     * @return bool
653
     */
654 View Code Duplication
    public static function checkBrowserKonqueror()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
655
    {
656
        if (stripos(self::$userAgentString, 'Konqueror') !== false) {
657
            $aresult = explode(' ', stristr(self::$userAgentString, 'Konqueror'));
658
            $aversion = explode('/', $aresult[0]);
659
            if (isset($aversion[1])) {
660 6
                self::$browser->setVersion($aversion[1]);
661
            }
662 6
            self::$browser->setName(Browser::KONQUEROR);
663 2
664 6
            return true;
665
        }
666
667
        return false;
668
    }
669
670
    /**
671 6
     * Determine if the browser is iCab.
672 5
     *
673 6
     * @return bool
674
     */
675 View Code Duplication
    public static function checkBrowserIcab()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
676
    {
677
        if (stripos(self::$userAgentString, 'icab') !== false) {
678
            $aversion = explode(' ', stristr(str_replace('/', ' ', self::$userAgentString), 'icab'));
679
            if (isset($aversion[1])) {
680
                self::$browser->setVersion($aversion[1]);
681
            }
682 6
            self::$browser->setName(Browser::ICAB);
683
684
            return true;
685
        }
686
687
        return false;
688
    }
689
690 1
    /**
691
     * Determine if the browser is OmniWeb.
692 1
     *
693
     * @return bool
694 1
     */
695 View Code Duplication
    public static function checkBrowserOmniWeb()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
696
    {
697
        if (stripos(self::$userAgentString, 'omniweb') !== false) {
698
            $aresult = explode('/', stristr(self::$userAgentString, 'omniweb'));
699
            $aversion = explode(' ', isset($aresult[1]) ? $aresult[1] : '');
700
            self::$browser->setVersion($aversion[0]);
701
            self::$browser->setName(Browser::OMNIWEB);
702
703 1
            return true;
704
        }
705
706
        return false;
707
    }
708
709
    /**
710
     * Determine if the browser is Phoenix.
711 1
     *
712
     * @return bool
713 1
     */
714
    public static function checkBrowserPhoenix()
715 1
    {
716 View Code Duplication
        if (stripos(self::$userAgentString, 'Phoenix') !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
717
            $aversion = explode('/', stristr(self::$userAgentString, 'Phoenix'));
718
            if (isset($aversion[1])) {
719
                self::$browser->setVersion($aversion[1]);
720
            }
721
            self::$browser->setName(Browser::PHOENIX);
722
723
            return true;
724 1
        }
725
726
        return false;
727
    }
728
729
    /**
730
     * Determine if the browser is Firebird.
731
     *
732 2
     * @return bool
733
     */
734 2
    public static function checkBrowserFirebird()
735
    {
736 View Code Duplication
        if (stripos(self::$userAgentString, 'Firebird') !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
737
            $aversion = explode('/', stristr(self::$userAgentString, 'Firebird'));
738
            if (isset($aversion[1])) {
739
                self::$browser->setVersion($aversion[1]);
740
            }
741
            self::$browser->setName(Browser::FIREBIRD);
742
743
            return true;
744
        }
745
746
        return false;
747 2
    }
748
749
    /**
750
     * Determine if the browser is Netscape Navigator 9+.
751
     *
752
     * @return bool
753
     */
754
    public static function checkBrowserNetscapeNavigator9Plus()
755 5
    {
756
        if (stripos(self::$userAgentString, 'Firefox') !== false &&
757 5
            preg_match('/Navigator\/([^ ]*)/i', self::$userAgentString, $matches)
758 4
        ) {
759 2
            if (isset($matches[1])) {
760 2
                self::$browser->setVersion($matches[1]);
761 2
            }
762 2
            self::$browser->setName(Browser::NETSCAPE_NAVIGATOR);
763
764 2
            return true;
765 2
        } elseif (stripos(self::$userAgentString, 'Firefox') === false &&
766
            preg_match('/Netscape6?\/([^ ]*)/i', self::$userAgentString, $matches)
767
        ) {
768
            if (isset($matches[1])) {
769
                self::$browser->setVersion($matches[1]);
770
            }
771 2
            self::$browser->setName(Browser::NETSCAPE_NAVIGATOR);
772
773 4
            return true;
774
        }
775
776
        return false;
777
    }
778
779
    /**
780
     * Determine if the browser is Shiretoko.
781 6
     *
782
     * @return bool
783 6
     */
784 5
    public static function checkBrowserShiretoko()
785 1
    {
786 1
        if (stripos(self::$userAgentString, 'Mozilla') !== false &&
787 1
            preg_match('/Shiretoko\/([^ ]*)/i', self::$userAgentString, $matches)
788 1
        ) {
789
            if (isset($matches[1])) {
790 1
                self::$browser->setVersion($matches[1]);
791 4
            }
792
            self::$browser->setName(Browser::SHIRETOKO);
793
794
            return true;
795
        }
796
797 4
        return false;
798
    }
799 5
800
    /**
801
     * Determine if the browser is Ice Cat.
802
     *
803
     * @return bool
804
     */
805
    public static function checkBrowserIceCat()
806
    {
807 1
        if (stripos(self::$userAgentString, 'Mozilla') !== false &&
808
            preg_match('/IceCat\/([^ ]*)/i', self::$userAgentString, $matches)
809 1
        ) {
810
            if (isset($matches[1])) {
811
                self::$browser->setVersion($matches[1]);
812
            }
813
            self::$browser->setName(Browser::ICECAT);
814
815
            return true;
816
        }
817
818
        return false;
819
    }
820 1
821
    /**
822
     * Determine if the browser is Nokia.
823
     *
824
     * @return bool
825
     */
826
    public static function checkBrowserNokia()
827
    {
828 1
        if (preg_match("/Nokia([^\\/]+)\\/([^ SP]+)/i", self::$userAgentString, $matches)) {
829
            self::$browser->setVersion($matches[2]);
830 1
            if (stripos(self::$userAgentString, 'Series60') !== false ||
831 1
                strpos(self::$userAgentString, 'S60') !== false
832
            ) {
833 1
                self::$browser->setName(Browser::NOKIA_S60);
834
            } else {
835
                self::$browser->setName(Browser::NOKIA);
836
            }
837
838
            return true;
839
        }
840 1
841 1
        return false;
842
    }
843 1
844
    /**
845
     * Determine if the browser is Firefox.
846
     *
847
     * @return bool
848
     */
849 1 View Code Duplication
    public static function checkBrowserFirefox()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
850 1
    {
851
        if (stripos(self::$userAgentString, 'safari') === false) {
852 1
            if (preg_match("/Firefox[\\/ \\(]([a-zA-Z\\d\\.]*)/i", self::$userAgentString, $matches)) {
853
                if (isset($matches[1])) {
854
                    self::$browser->setVersion($matches[1]);
855
                }
856
                self::$browser->setName(Browser::FIREFOX);
857
858
                return true;
859
            } elseif (preg_match('/Firefox$/i', self::$userAgentString, $matches)) {
860
                self::$browser->setVersion('');
861 1
                self::$browser->setName(Browser::FIREFOX);
862
863
                return true;
864
            }
865
        }
866
867
        return false;
868
    }
869 1
870
    /**
871 1
     * Determine if the browser is SeaMonkey.
872
     *
873
     * @return bool
874
     */
875 View Code Duplication
    public static function checkBrowserSeaMonkey()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
876
    {
877
        if (stripos(self::$userAgentString, 'safari') === false) {
878
            if (preg_match("/SeaMonkey[\\/ \\(]([a-zA-Z\\d\\.]*)/i", self::$userAgentString, $matches)) {
879
                if (isset($matches[1])) {
880 1
                    self::$browser->setVersion($matches[1]);
881
                }
882
                self::$browser->setName(Browser::SEAMONKEY);
883
884
                return true;
885
            } elseif (preg_match('/SeaMonkey$/i', self::$userAgentString, $matches)) {
886
                self::$browser->setVersion('');
887
                self::$browser->setName(Browser::SEAMONKEY);
888 1
889
                return true;
890 1
            }
891
        }
892
893
        return false;
894
    }
895
896
    /**
897
     * Determine if the browser is Iceweasel.
898
     *
899
     * @return bool
900
     */
901 1 View Code Duplication
    public static function checkBrowserIceweasel()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
902
    {
903
        if (stripos(self::$userAgentString, 'Iceweasel') !== false) {
904
            $aresult = explode('/', stristr(self::$userAgentString, 'Iceweasel'));
905
            if (isset($aresult[1])) {
906
                $aversion = explode(' ', $aresult[1]);
907
                self::$browser->setVersion($aversion[0]);
908
            }
909 2
            self::$browser->setName(Browser::ICEWEASEL);
910
911 2
            return true;
912 1
        }
913 1
914
        return false;
915
    }
916 2
917
    /**
918
     * Determine if the browser is Mozilla.
919
     *
920
     * @return bool
921
     */
922
    public static function checkBrowserMozilla()
923 2
    {
924
        if (stripos(self::$userAgentString, 'mozilla') !== false &&
925 2
            preg_match('/rv:[0-9].[0-9][a-b]?/i', self::$userAgentString) &&
926 1
            stripos(self::$userAgentString, 'netscape') === false
927 1
        ) {
928 1
            $aversion = explode(' ', stristr(self::$userAgentString, 'rv:'));
929 1
            preg_match('/rv:[0-9].[0-9][a-b]?/i', self::$userAgentString, $aversion);
930 1
            self::$browser->setVersion(str_replace('rv:', '', $aversion[0]));
931
            self::$browser->setName(Browser::MOZILLA);
932
933 1
            return true;
934
        } elseif (stripos(self::$userAgentString, 'mozilla') !== false &&
935 1
            preg_match('/rv:[0-9]\.[0-9]/i', self::$userAgentString) &&
936
            stripos(self::$userAgentString, 'netscape') === false
937
        ) {
938 1
            $aversion = explode('', stristr(self::$userAgentString, 'rv:'));
939
            self::$browser->setVersion(str_replace('rv:', '', $aversion[0]));
940
            self::$browser->setName(Browser::MOZILLA);
941
942
            return true;
943
        } elseif (stripos(self::$userAgentString, 'mozilla') !== false &&
944
            preg_match('/mozilla\/([^ ]*)/i', self::$userAgentString, $matches) &&
945
            stripos(self::$userAgentString, 'netscape') === false
946 4
        ) {
947
            if (isset($matches[1])) {
948 4
                self::$browser->setVersion($matches[1]);
949 1
            }
950 1
            self::$browser->setName(Browser::MOZILLA);
951 1
952 1
            return true;
953 1
        }
954 1
955
        return false;
956 1
    }
957
958
    /**
959 4
     * Determine if the browser is Lynx.
960
     *
961
     * @return bool
962
     */
963 View Code Duplication
    public static function checkBrowserLynx()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
964
    {
965
        if (stripos(self::$userAgentString, 'lynx') !== false) {
966
            $aresult = explode('/', stristr(self::$userAgentString, 'Lynx'));
967 6
            $aversion = explode(' ', (isset($aresult[1]) ? $aresult[1] : ''));
968
            self::$browser->setVersion($aversion[0]);
969 6
            self::$browser->setName(Browser::LYNX);
970 1
971 1
            return true;
972 1
        }
973 1
974 1
        return false;
975 1
    }
976
977 1
    /**
978
     * Determine if the browser is Amaya.
979
     *
980 6
     * @return bool
981
     */
982 View Code Duplication
    public static function checkBrowserAmaya()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
983
    {
984
        if (stripos(self::$userAgentString, 'amaya') !== false) {
985
            $aresult = explode('/', stristr(self::$userAgentString, 'Amaya'));
986
            if (isset($aresult[1])) {
987
                $aversion = explode(' ', $aresult[1]);
988 3
                self::$browser->setVersion($aversion[0]);
989
            }
990
            self::$browser->setName(Browser::AMAYA);
991 3
992
            return true;
993
        }
994
995
        return false;
996
    }
997
998
999
    /**
1000
     * Determine if the browser is Safari.
1001
     *
1002
     * @return bool
1003
     */
1004 3
    public static function checkBrowserSafari()
1005
    {
1006
        if (stripos(self::$userAgentString, 'Safari') !== false) {
1007
            $aresult = explode('/', stristr(self::$userAgentString, 'Version'));
1008
            if (isset($aresult[1])) {
1009
                $aversion = explode(' ', $aresult[1]);
1010
                self::$browser->setVersion($aversion[0]);
1011
            } else {
1012
                self::$browser->setVersion(Browser::VERSION_UNKNOWN);
1013
            }
1014
            self::$browser->setName(Browser::SAFARI);
1015
1016
            return true;
1017
        }
1018
1019
        return false;
1020
    }
1021
1022
    /**
1023
     * Determine if the browser is Yandex.
1024
     *
1025
     * @return bool
1026
     */
1027 View Code Duplication
    public static function checkBrowserYandex()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1028
    {
1029
        if (stripos(self::$userAgentString, 'YaBrowser') !== false) {
1030
            $aresult = explode('/', stristr(self::$userAgentString, 'YaBrowser'));
1031
            if (isset($aresult[1])) {
1032
                $aversion = explode(' ', $aresult[1]);
1033
                self::$browser->setVersion($aversion[0]);
1034
            }
1035
            self::$browser->setName(Browser::YANDEX);
1036
1037
            return true;
1038
        }
1039
1040
        return false;
1041
    }
1042
1043
    /**
1044
     * Determine if the browser is Comodo Dragon / Ice Dragon / Chromodo.
1045
     *
1046
     * @return bool
1047
     */
1048 View Code Duplication
    public static function checkBrowserDragon()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1049
    {
1050
        if (stripos(self::$userAgentString, 'Dragon') !== false) {
1051
            $aresult = explode('/', stristr(self::$userAgentString, 'Dragon'));
1052
            if (isset($aresult[1])) {
1053
                $aversion = explode(' ', $aresult[1]);
1054
                self::$browser->setVersion($aversion[0]);
1055
            }
1056
            self::$browser->setName(Browser::DRAGON);
1057
1058
            return true;
1059
        }
1060
1061
        return false;
1062
    }
1063
1064
    /**
1065
     * Determine if the browser is Android.
1066
     *
1067
     * @return bool
1068
     */
1069
    public static function checkBrowserAndroid()
1070
    {
1071
        // Android Navigator
1072 View Code Duplication
        if (stripos(self::$userAgentString, 'Android') !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1073
            if (preg_match('/Version\/([\d\.]*)/i', self::$userAgentString, $matches)) {
1074
                if (isset($matches[1])) {
1075
                    self::$browser->setVersion($matches[1]);
1076
                }
1077
            } else {
1078
                self::$browser->setVersion(Browser::VERSION_UNKNOWN);
1079
            }
1080
            self::$browser->setName(Browser::NAVIGATOR);
1081
1082
            return true;
1083
        }
1084
1085
        // Dalvik (Android OS)
1086
        if (stripos(self::$userAgentString, 'Dalvik/') !== false) {
1087
            $aresult = explode('/', stristr(self::$userAgentString, 'Dalvik'));
1088
            if (isset($aresult[1])) {
1089
                $aversion = explode(' ', $aresult[1]);
1090
                self::$browser->setVersion($aversion[0]);
1091
            }
1092
            self::$browser->setName(Browser::DALVIK);
1093
1094
            return true;
1095
        }
1096
1097
        return false;
1098
    }
1099
1100
    /**
1101
     * Determine if the browser is UCBrowser.
1102
     *
1103
     * @return bool
1104
     */
1105 View Code Duplication
    public static function checkBrowserUCBrowser()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1106
    {
1107
        // Navigator
1108
        if (stripos(self::$userAgentString, 'UCBrowser/') !== false) {
1109
            $aresult = explode('/', stristr(self::$userAgentString, 'UCBrowser'));
1110
            if (isset($aresult[1])) {
1111
                $aversion = explode(' ', $aresult[1]);
1112
                self::$browser->setVersion($aversion[0]);
1113
            }
1114
            self::$browser->setName(Browser::UCBROWSER);
1115
1116
            return true;
1117
        }
1118
1119
        return false;
1120
    }
1121
1122
    /**
1123
     * Determine if the browser is Windows Media Player.
1124
     *
1125
     * @return bool
1126
     */
1127 View Code Duplication
    public static function checkBrowserNSPlayer()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1128
    {
1129
        // Navigator
1130
        if (stripos(self::$userAgentString, 'NSPlayer/') !== false) {
1131
            $aresult = explode('/', stristr(self::$userAgentString, 'NSPlayer'));
1132
            if (isset($aresult[1])) {
1133
                $aversion = explode(' ', $aresult[1]);
1134
                self::$browser->setVersion($aversion[0]);
1135
            }
1136
            self::$browser->setName(Browser::NSPLAYER);
1137
1138
            return true;
1139
        }
1140
1141
        return false;
1142
    }
1143
1144
    /**
1145
     * Determine if the browser is Microsoft Office.
1146
     *
1147
     * @return bool
1148
     */
1149
    public static function checkBrowserOffice()
1150
    {
1151
        // Navigator
1152
        if (stripos(self::$userAgentString, 'Microsoft Office') !== false) {
1153
            self::$browser->setVersion(Browser::VERSION_UNKNOWN);
1154
            self::$browser->setName(Browser::NSPLAYER);
1155
1156
            return true;
1157
        }
1158
1159
        return false;
1160
    }
1161
1162
    /**
1163
     * Determine if the browser is the Apple News app.
1164
     *
1165
     * @return bool
1166
     */
1167
    public static function checkBrowserAppleNews()
1168
    {
1169
        // Navigator
1170 View Code Duplication
        if (stripos(self::$userAgentString, 'AppleNews/') !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1171
            if (preg_match('/Version\/([\d\.]*)/i', self::$userAgentString, $matches)) {
1172
                if (isset($matches[1])) {
1173
                    self::$browser->setVersion($matches[1]);
1174
                }
1175
            } else {
1176
                self::$browser->setVersion(Browser::VERSION_UNKNOWN);
1177
            }
1178
            self::$browser->setName(Browser::APPLE_NEWS);
1179
1180
            return true;
1181
        }
1182
1183
        return false;
1184
    }
1185
}
1186