Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
69 / 69
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
UADeviceDetector
100.00% covered (success)
100.00%
69 / 69
100.00% covered (success)
100.00%
3 / 3
5
100.00% covered (success)
100.00%
1 / 1
 detectDeviceProperties
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 detectMobileDevice
100.00% covered (success)
100.00%
61 / 61
100.00% covered (success)
100.00%
1 / 1
2
 detectTabletDevice
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3/**
4 * Copyright (c) 2011 Patrick Reilly
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * http://www.gnu.org/copyleft/gpl.html
20 *
21 * @file
22 */
23
24namespace MobileFrontend\Devices;
25
26use MediaWiki\Request\WebRequest;
27
28/**
29 * Detect mobile and tablet devices by testing whether the User-Agent request
30 * header matches a list of regular expressions.
31 */
32class UADeviceDetector implements DeviceDetector {
33
34    /**
35     * @inheritDoc
36     */
37    public function detectDeviceProperties( WebRequest $request, array $server ) {
38        $userAgent = $request->getHeader( 'User-Agent' );
39
40        return new DeviceProperties(
41            $this->detectMobileDevice( $userAgent ),
42            $this->detectTabletDevice( $userAgent )
43        );
44    }
45
46    /**
47     * Tests whether the UA is known to be sent on behalf of users using a mobile
48     * device.
49     *
50     * @author Patrick Reilly
51     *
52     * @param string $userAgent
53     * @return bool
54     */
55    private function detectMobileDevice( $userAgent ) {
56        $patterns = [
57            'mobi',
58            '240x240',
59            '240x320',
60            '320x320',
61            'alcatel',
62            'android',
63            'audiovox',
64            'bada',
65            'benq',
66            'blackberry',
67            'cdm-',
68            'compal-',
69            'docomo',
70            'ericsson',
71            'hiptop',
72            'htc[-_]',
73            'huawei',
74            'ipod',
75            'kddi-',
76            'kindle',
77            'meego',
78            'midp',
79            'mitsu',
80            'mmp\/',
81            'mot-',
82            'motor',
83            'ngm_',
84            'nintendo',
85            'opera.m',
86            'palm',
87            'panasonic',
88            'philips',
89            'phone',
90            'playstation',
91            'portalmmm',
92            'sagem-',
93            'samsung',
94            'sanyo',
95            'sec-',
96            'sendo',
97            'sharp',
98            'silk',
99            'softbank',
100            'symbian',
101            'teleca',
102            'up.browser',
103            'webos',
104        ];
105        $patternsStart = [
106            'lg-',
107            'sie-',
108            'nec-',
109            'lge-',
110            'sgh-',
111            'pg-',
112        ];
113        $regex = '/^(' . implode( '|', $patternsStart ) . ')|(' . implode( '|', $patterns ) . ')/i';
114        $exceptionRegex = '/SMART-TV.*SamsungBrowser/';
115
116        return preg_match( $regex, $userAgent )
117            && !preg_match( $exceptionRegex, $userAgent );
118    }
119
120    /**
121     * Tests whether the UA is known to be sent on behalf of users using a tablet
122     * device.
123     *
124     * @author Patrick Reilly
125     *
126     * @param string $userAgent
127     * @return bool
128     */
129    private function detectTabletDevice( $userAgent ) {
130        // The only way to distinguish Android browsers on tablet from Android
131        // browsers on mobile is that Android browsers on tablet usually don't
132        // include the word "mobile". We look for "mobi" instead of "mobile" due to
133        // Opera Mobile. Note that this test fails to detect some obscure tablets
134        // such as older Xoom tablets and Portablet tablets. See
135        // http://stackoverflow.com/questions/5341637 for more detail.
136        if ( preg_match( '/Android/i', $userAgent ) ) {
137            return !preg_match( '/mobi/i', $userAgent );
138        }
139
140        return (bool)preg_match( '/(iPad|Tablet|PlayBook|Wii|Silk)/i', $userAgent );
141    }
142}