Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
67 / 67
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
UADeviceDetector
100.00% covered (success)
100.00%
67 / 67
100.00% covered (success)
100.00%
3 / 3
4
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%
59 / 59
100.00% covered (success)
100.00%
1 / 1
1
 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            // T405279: Match legacy device tokens like "SAMSUNG-S8000" but not "SamsungBrowser".
94            'samsung-',
95            'sanyo',
96            'sec-',
97            'sendo',
98            'sharp',
99            'silk',
100            'softbank',
101            'symbian',
102            'teleca',
103            'up.browser',
104            'webos',
105        ];
106        $patternsStart = [
107            'lg-',
108            'sie-',
109            'nec-',
110            'lge-',
111            'sgh-',
112            'pg-',
113        ];
114        $regex = '/^(' . implode( '|', $patternsStart ) . ')|(' . implode( '|', $patterns ) . ')/i';
115
116        return preg_match( $regex, $userAgent );
117    }
118
119    /**
120     * Tests whether the UA is known to be sent on behalf of users using a tablet
121     * device.
122     *
123     * @author Patrick Reilly
124     *
125     * @param string $userAgent
126     * @return bool
127     */
128    private function detectTabletDevice( $userAgent ) {
129        // The only way to distinguish Android browsers on tablet from Android
130        // browsers on mobile is that Android browsers on tablet usually don't
131        // include the word "mobile". We look for "mobi" instead of "mobile" due to
132        // Opera Mobile. Note that this test fails to detect some obscure tablets
133        // such as older Xoom tablets and Portablet tablets. See
134        // http://stackoverflow.com/questions/5341637 for more detail.
135        if ( preg_match( '/Android/i', $userAgent ) ) {
136            return !preg_match( '/mobi/i', $userAgent );
137        }
138
139        return (bool)preg_match( '/(iPad|Tablet|PlayBook|Wii|Silk)/i', $userAgent );
140    }
141}