3 * Device detection class
5 * Copyright © 2011 Patrick Reilly
6 * http://www.mediawiki.org/
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * http://www.gnu.org/copyleft/gpl.html
27 * Provides abstraction for a device.
28 * A device can select which format a request should receive and
29 * may be extended to provide access to particular device functionality.
32 class DeviceDetection
{
37 public function getAvailableFormats() {
40 'view_format' => 'html',
41 'search_bar' => 'default',
42 'footmenu' => 'default',
43 'with_layout' => 'application',
44 'css_file_name' => 'default',
45 'supports_javascript' => false,
46 'supports_jquery' => false,
47 'disable_zoom' => true,
49 'disable_links' => true,
52 'view_format' => 'html',
53 'search_bar' => 'default',
54 'footmenu' => 'default',
55 'with_layout' => 'application',
56 'css_file_name' => 'default',
57 'supports_javascript' => true,
58 'supports_jquery' => true,
59 'disable_zoom' => true,
61 'disable_links' => true,
64 'view_format' => 'html',
65 'search_bar' => 'webkit',
66 'footmenu' => 'default',
67 'with_layout' => 'application',
68 'css_file_name' => 'webkit',
69 'supports_javascript' => true,
70 'supports_jquery' => true,
71 'disable_zoom' => false,
73 'disable_links' => true,
76 'view_format' => 'html',
77 'search_bar' => 'default',
78 'footmenu' => 'default',
79 'with_layout' => 'application',
80 'css_file_name' => 'default',
81 'supports_javascript' => true,
82 'supports_jquery' => true,
83 'disable_zoom' => false,
85 'disable_links' => true,
88 'view_format' => 'html',
89 'search_bar' => 'default',
90 'footmenu' => 'default',
91 'with_layout' => 'application',
92 'css_file_name' => 'android',
93 'supports_javascript' => true,
94 'supports_jquery' => true,
95 'disable_zoom' => false,
97 'disable_links' => true,
100 'view_format' => 'html',
101 'search_bar' => 'webkit',
102 'footmenu' => 'default',
103 'with_layout' => 'application',
104 'css_file_name' => 'iphone',
105 'supports_javascript' => true,
106 'supports_jquery' => true,
107 'disable_zoom' => false,
109 'disable_links' => true,
112 'view_format' => 'html',
113 'search_bar' => 'default',
114 'footmenu' => 'default',
115 'with_layout' => 'application',
116 'css_file_name' => 'iphone2',
117 'supports_javascript' => true,
118 'supports_jquery' => true,
119 'disable_zoom' => true,
121 'disable_links' => true,
123 'native_iphone' => array (
124 'view_format' => 'html',
125 'search_bar' => false,
126 'footmenu' => 'default',
127 'with_layout' => 'application',
128 'css_file_name' => 'default',
129 'supports_javascript' => true,
130 'supports_jquery' => true,
131 'disable_zoom' => false,
133 'disable_links' => false,
135 'palm_pre' => array (
136 'view_format' => 'html',
137 'search_bar' => 'default',
138 'footmenu' => 'default',
139 'with_layout' => 'application',
140 'css_file_name' => 'palm_pre',
141 'supports_javascript' => true,
142 'supports_jquery' => false,
143 'disable_zoom' => true,
145 'disable_links' => true,
148 'view_format' => 'html',
149 'search_bar' => 'kindle',
150 'footmenu' => 'default',
151 'with_layout' => 'application',
152 'css_file_name' => 'kindle',
153 'supports_javascript' => false,
154 'supports_jquery' => false,
155 'disable_zoom' => true,
157 'disable_links' => true,
160 'view_format' => 'html',
161 'search_bar' => 'kindle',
162 'footmenu' => 'default',
163 'with_layout' => 'application',
164 'css_file_name' => 'kindle',
165 'supports_javascript' => false,
166 'supports_jquery' => false,
167 'disable_zoom' => true,
169 'disable_links' => true,
171 'blackberry' => array (
172 'view_format' => 'html',
173 'search_bar' => 'default',
174 'footmenu' => 'default',
175 'with_layout' => 'application',
176 'css_file_name' => 'blackberry',
177 'supports_javascript' => true,
178 'supports_jquery' => false,
179 'disable_zoom' => true,
181 'disable_links' => true,
183 'blackberry-lt5' => array (
184 'view_format' => 'html',
185 'search_bar' => 'default',
186 'footmenu' => 'default',
187 'with_layout' => 'application',
188 'css_file_name' => 'blackberry',
189 'supports_javascript' => false,
190 'supports_jquery' => false,
191 'disable_zoom' => true,
193 'disable_links' => true,
195 'netfront' => array (
196 'view_format' => 'html',
197 'search_bar' => 'simple',
198 'footmenu' => 'simple',
199 'with_layout' => 'application',
200 'css_file_name' => 'simple',
201 'supports_javascript' => false,
202 'supports_jquery' => false,
203 'disable_zoom' => true,
205 'disable_links' => true,
208 'view_format' => 'html',
209 'search_bar' => 'simple',
210 'footmenu' => 'simple',
211 'with_layout' => 'application',
212 'css_file_name' => 'simple',
213 'supports_javascript' => false,
214 'supports_jquery' => false,
215 'disable_zoom' => true,
217 'disable_links' => true,
220 'view_format' => 'html',
221 'search_bar' => 'simple',
222 'footmenu' => 'simple',
223 'with_layout' => 'application',
224 'css_file_name' => 'psp',
225 'supports_javascript' => false,
226 'supports_jquery' => false,
227 'disable_zoom' => true,
229 'disable_links' => true,
232 'view_format' => 'html',
233 'search_bar' => 'simple',
234 'footmenu' => 'simple',
235 'with_layout' => 'application',
236 'css_file_name' => 'simple',
237 'supports_javascript' => false,
238 'supports_jquery' => false,
239 'disable_zoom' => true,
241 'disable_links' => true,
244 'view_format' => 'html',
245 'search_bar' => 'wii',
246 'footmenu' => 'default',
247 'with_layout' => 'application',
248 'css_file_name' => 'wii',
249 'supports_javascript' => true,
250 'supports_jquery' => true,
251 'disable_zoom' => true,
253 'disable_links' => true,
255 'operamini' => array (
256 'view_format' => 'html',
257 'search_bar' => 'simple',
258 'footmenu' => 'simple',
259 'with_layout' => 'application',
260 'css_file_name' => 'operamini',
261 'supports_javascript' => false,
262 'supports_jquery' => false,
263 'disable_zoom' => true,
265 'disable_links' => true,
267 'operamobile' => array (
268 'view_format' => 'html',
269 'search_bar' => 'simple',
270 'footmenu' => 'simple',
271 'with_layout' => 'application',
272 'css_file_name' => 'operamobile',
273 'supports_javascript' => true,
274 'supports_jquery' => true,
275 'disable_zoom' => true,
277 'disable_links' => true,
280 'view_format' => 'html',
281 'search_bar' => 'webkit',
282 'footmenu' => 'default',
283 'with_layout' => 'application',
284 'css_file_name' => 'nokia',
285 'supports_javascript' => true,
286 'supports_jquery' => false,
287 'disable_zoom' => true,
289 'disable_links' => true,
292 'view_format' => 'wml',
293 'search_bar' => 'wml',
294 'supports_javascript' => false,
295 'supports_jquery' => false,
304 * @param string $acceptHeader
307 public function detectDevice( $userAgent, $acceptHeader = '' ) {
308 $formatName = $this->detectFormatName( $userAgent, $acceptHeader );
309 return $this->getDevice( $formatName );
316 public function getDevice( $formatName ) {
317 $format = $this->getAvailableFormats();
318 return ( isset( $format[$formatName] ) ) ?
$format[$formatName] : array();
322 * @param $userAgent string
323 * @param $acceptHeader string
326 public function detectFormatName( $userAgent, $acceptHeader = '' ) {
329 if ( preg_match( '/Android/', $userAgent ) ) {
330 $formatName = 'android';
331 if ( strpos( $userAgent, 'Opera Mini' ) !== false ) {
332 $formatName = 'operamini';
334 } else if ( preg_match( '/MSIE 9.0/', $userAgent ) ||
335 preg_match( '/MSIE 8.0/', $userAgent ) ) {
337 } else if( preg_match( '/MSIE/', $userAgent ) ) {
338 $formatName = 'html';
339 } else if ( strpos( $userAgent, 'Opera Mobi' ) !== false ) {
340 $formatName = 'operamobile';
341 } elseif ( preg_match( '/iPad.* Safari/', $userAgent ) ) {
342 $formatName = 'iphone';
343 } elseif ( preg_match( '/iPhone.* Safari/', $userAgent ) ) {
344 if ( strpos( $userAgent, 'iPhone OS 2' ) !== false ) {
345 $formatName = 'iphone2';
347 $formatName = 'iphone';
349 } elseif ( preg_match( '/iPhone/', $userAgent ) ) {
350 if ( strpos( $userAgent, 'Opera' ) !== false ) {
351 $formatName = 'operamini';
353 $formatName = 'native_iphone';
355 } elseif ( preg_match( '/WebKit/', $userAgent ) ) {
356 if ( preg_match( '/Series60/', $userAgent ) ) {
357 $formatName = 'nokia';
358 } elseif ( preg_match( '/webOS/', $userAgent ) ) {
359 $formatName = 'palm_pre';
361 $formatName = 'webkit';
363 } elseif ( preg_match( '/Opera/', $userAgent ) ) {
364 if ( strpos( $userAgent, 'Nintendo Wii' ) !== false ) {
366 } elseif ( strpos( $userAgent, 'Opera Mini' ) !== false ) {
367 $formatName = 'operamini';
368 } elseif ( strpos( $userAgent, 'Opera Mobi' ) !== false ) {
369 $formatName = 'iphone';
371 $formatName = 'webkit';
373 } elseif ( preg_match( '/Kindle\/1.0/', $userAgent ) ) {
374 $formatName = 'kindle';
375 } elseif ( preg_match( '/Kindle\/2.0/', $userAgent ) ) {
376 $formatName = 'kindle2';
377 } elseif ( preg_match( '/Firefox/', $userAgent ) ) {
378 $formatName = 'capable';
379 } elseif ( preg_match( '/NetFront/', $userAgent ) ) {
380 $formatName = 'netfront';
381 } elseif ( preg_match( '/SEMC-Browser/', $userAgent ) ) {
382 $formatName = 'wap2';
383 } elseif ( preg_match( '/Series60/', $userAgent ) ) {
384 $formatName = 'wap2';
385 } elseif ( preg_match( '/PlayStation Portable/', $userAgent ) ) {
387 } elseif ( preg_match( '/PLAYSTATION 3/', $userAgent ) ) {
389 } elseif ( preg_match( '/SAMSUNG/', $userAgent ) ) {
390 $formatName = 'capable';
391 } elseif ( preg_match( '/BlackBerry/', $userAgent ) ) {
392 if( preg_match( '/BlackBerry[^\/]*\/[1-4]\./', $userAgent ) ) {
393 $formatName = 'blackberry-lt5';
395 $formatName = 'blackberry';
399 if ( $formatName === '' ) {
400 if ( strpos( $acceptHeader, 'application/vnd.wap.xhtml+xml' ) !== false ) {
402 $formatName = 'html';
403 } elseif ( strpos( $acceptHeader, 'vnd.wap.wml' ) !== false ) {
406 $formatName = 'html';
413 * @return array: List of all device-specific stylesheets
415 public function getCssFiles() {
416 $devices = $this->getAvailableFormats();
418 foreach ( $devices as $dev ) {
419 if ( isset( $dev['css_file_name'] ) ) {
420 $files[] = $dev['css_file_name'];
423 return array_unique( $files );