MediaWiki  REL1_20
DeviceDetection.php
Go to the documentation of this file.
00001 <?php
00030 interface IDeviceProperties {
00034         function format();
00035 
00039         function supportsJavaScript();
00040 
00044         function supportsJQuery();
00045 
00049         function disableZoom();
00050 }
00051 
00055 interface IDeviceDetector {
00061         function detectDeviceProperties( $userAgent, $acceptHeader = '' );
00062 
00067         function getDeviceProperties( $deviceName );
00068 
00074         function detectDeviceName( $userAgent, $acceptHeader = '' );
00075 }
00076 
00080 final class DeviceProperties implements IDeviceProperties {
00081         private $device;
00082 
00083         public function __construct( array $deviceCapabilities ) {
00084                 $this->device = $deviceCapabilities;
00085         }
00086 
00090         function format() {
00091                 return $this->device['view_format'];
00092         }
00093 
00097         function supportsJavaScript() {
00098                 return $this->device['supports_javascript'];
00099         }
00100 
00104         function supportsJQuery() {
00105                 return $this->device['supports_jquery'];
00106         }
00107 
00111         function disableZoom() {
00112                 return $this->device['disable_zoom'];
00113         }
00114 }
00115 
00122 class DeviceDetection implements IDeviceDetector {
00123 
00124         private static $formats = array (
00125                         'html' => array (
00126                                 'view_format' => 'html',
00127                                 'css_file_name' => 'default',
00128                                 'supports_javascript' => false,
00129                                 'supports_jquery' => false,
00130                                 'disable_zoom' => true,
00131                         ),
00132                         'capable' => array (
00133                                 'view_format' => 'html',
00134                                 'css_file_name' => 'default',
00135                                 'supports_javascript' => true,
00136                                 'supports_jquery' => true,
00137                                 'disable_zoom' => true,
00138                         ),
00139                         'webkit' => array (
00140                                 'view_format' => 'html',
00141                                 'css_file_name' => 'webkit',
00142                                 'supports_javascript' => true,
00143                                 'supports_jquery' => true,
00144                                 'disable_zoom' => false,
00145                         ),
00146                         'ie' => array (
00147                                 'view_format' => 'html',
00148                                 'css_file_name' => 'default',
00149                                 'supports_javascript' => true,
00150                                 'supports_jquery' => true,
00151                                 'disable_zoom' => false,
00152                         ),
00153                         'android' => array (
00154                                 'view_format' => 'html',
00155                                 'css_file_name' => 'android',
00156                                 'supports_javascript' => true,
00157                                 'supports_jquery' => true,
00158                                 'disable_zoom' => false,
00159                         ),
00160                         'iphone' => array (
00161                                 'view_format' => 'html',
00162                                 'css_file_name' => 'iphone',
00163                                 'supports_javascript' => true,
00164                                 'supports_jquery' => true,
00165                                 'disable_zoom' => false,
00166                         ),
00167                         'iphone2' => array (
00168                                 'view_format' => 'html',
00169                                 'css_file_name' => 'iphone2',
00170                                 'supports_javascript' => true,
00171                                 'supports_jquery' => true,
00172                                 'disable_zoom' => true,
00173                         ),
00174                         'native_iphone' => array (
00175                                 'view_format' => 'html',
00176                                 'css_file_name' => 'default',
00177                                 'supports_javascript' => true,
00178                                 'supports_jquery' => true,
00179                                 'disable_zoom' => false,
00180                         ),
00181                         'palm_pre' => array (
00182                                 'view_format' => 'html',
00183                                 'css_file_name' => 'palm_pre',
00184                                 'supports_javascript' => true,
00185                                 'supports_jquery' => false,
00186                                 'disable_zoom' => true,
00187                         ),
00188                         'kindle' => array (
00189                                 'view_format' => 'html',
00190                                 'css_file_name' => 'kindle',
00191                                 'supports_javascript' => false,
00192                                 'supports_jquery' => false,
00193                                 'disable_zoom' => true,
00194                         ),
00195                         'kindle2' => array (
00196                                 'view_format' => 'html',
00197                                 'css_file_name' => 'kindle',
00198                                 'supports_javascript' => false,
00199                                 'supports_jquery' => false,
00200                                 'disable_zoom' => true,
00201                         ),
00202                         'blackberry' => array (
00203                                 'view_format' => 'html',
00204                                 'css_file_name' => 'blackberry',
00205                                 'supports_javascript' => true,
00206                                 'supports_jquery' => false,
00207                                 'disable_zoom' => true,
00208                         ),
00209                         'blackberry-lt5' => array (
00210                                 'view_format' => 'html',
00211                                 'css_file_name' => 'blackberry',
00212                                 'supports_javascript' => false,
00213                                 'supports_jquery' => false,
00214                                 'disable_zoom' => true,
00215                         ),
00216                         'netfront' => array (
00217                                 'view_format' => 'html',
00218                                 'css_file_name' => 'simple',
00219                                 'supports_javascript' => false,
00220                                 'supports_jquery' => false,
00221                                 'disable_zoom' => true,
00222                         ),
00223                         'wap2' => array (
00224                                 'view_format' => 'html',
00225                                 'css_file_name' => 'simple',
00226                                 'supports_javascript' => false,
00227                                 'supports_jquery' => false,
00228                                 'disable_zoom' => true,
00229                         ),
00230                         'psp' => array (
00231                                 'view_format' => 'html',
00232                                 'css_file_name' => 'psp',
00233                                 'supports_javascript' => false,
00234                                 'supports_jquery' => false,
00235                                 'disable_zoom' => true,
00236                         ),
00237                         'ps3' => array (
00238                                 'view_format' => 'html',
00239                                 'css_file_name' => 'simple',
00240                                 'supports_javascript' => false,
00241                                 'supports_jquery' => false,
00242                                 'disable_zoom' => true,
00243                         ),
00244                         'wii' => array (
00245                                 'view_format' => 'html',
00246                                 'css_file_name' => 'wii',
00247                                 'supports_javascript' => true,
00248                                 'supports_jquery' => true,
00249                                 'disable_zoom' => true,
00250                         ),
00251                         'operamini' => array (
00252                                 'view_format' => 'html',
00253                                 'css_file_name' => 'operamini',
00254                                 'supports_javascript' => false,
00255                                 'supports_jquery' => false,
00256                                 'disable_zoom' => true,
00257                         ),
00258                         'operamobile' => array (
00259                                 'view_format' => 'html',
00260                                 'css_file_name' => 'operamobile',
00261                                 'supports_javascript' => true,
00262                                 'supports_jquery' => true,
00263                                 'disable_zoom' => true,
00264                         ),
00265                         'nokia' => array (
00266                                 'view_format' => 'html',
00267                                 'css_file_name' => 'nokia',
00268                                 'supports_javascript' => true,
00269                                 'supports_jquery' => false,
00270                                 'disable_zoom' => true,
00271                         ),
00272                         'wml' => array (
00273                                 'view_format' => 'wml',
00274                                 'css_file_name' => null,
00275                                 'supports_javascript' => false,
00276                                 'supports_jquery' => false,
00277                                 'disable_zoom' => true,
00278                         ),
00279                 );
00280 
00285         public static function factory() {
00286                 global $wgDeviceDetectionClass;
00287 
00288                 static $instance = null;
00289                 if ( !$instance ) {
00290                         $instance = new $wgDeviceDetectionClass();
00291                 }
00292                 return $instance;
00293         }
00294 
00301         public function detectDevice( $userAgent, $acceptHeader = '' ) {
00302                 $formatName = $this->detectFormatName( $userAgent, $acceptHeader );
00303                 return $this->getDevice( $formatName );
00304         }
00305 
00311         public function detectDeviceProperties( $userAgent, $acceptHeader = '' ) {
00312                 $deviceName = $this->detectDeviceName( $userAgent, $acceptHeader );
00313                 return $this->getDeviceProperties( $deviceName );
00314         }
00315 
00321         public function getDevice( $formatName ) {
00322                 return ( isset( self::$formats[$formatName] ) ) ? self::$formats[$formatName] : array();
00323         }
00324 
00329         public function getDeviceProperties( $deviceName ) {
00330                 if ( isset( self::$formats[$deviceName] ) ) {
00331                         return new DeviceProperties( self::$formats[$deviceName] );
00332                 } else {
00333                         return new DeviceProperties( array(
00334                                 'view_format' => 'html',
00335                                 'css_file_name' => 'default',
00336                                 'supports_javascript' => true,
00337                                 'supports_jquery' => true,
00338                                 'disable_zoom' => true,
00339                         ) );
00340                 }
00341         }
00342 
00349         public function detectFormatName( $userAgent, $acceptHeader = '' ) {
00350                 return $this->detectDeviceName( $userAgent, $acceptHeader );
00351         }
00352 
00358         public function detectDeviceName( $userAgent, $acceptHeader = '' ) {
00359                 wfProfileIn( __METHOD__ );
00360 
00361                 $deviceName = '';
00362                 if ( preg_match( '/Android/', $userAgent ) ) {
00363                         $deviceName = 'android';
00364                         if ( strpos( $userAgent, 'Opera Mini' ) !== false ) {
00365                                 $deviceName = 'operamini';
00366                         } elseif ( strpos( $userAgent, 'Opera Mobi' ) !== false ) {
00367                                 $deviceName = 'operamobile';
00368                         }
00369                 } elseif ( preg_match( '/MSIE 9.0/', $userAgent ) ||
00370                                 preg_match( '/MSIE 8.0/', $userAgent ) ) {
00371                         $deviceName = 'ie';
00372                 } elseif( preg_match( '/MSIE/', $userAgent ) ) {
00373                         $deviceName = 'html';
00374                 } elseif ( strpos( $userAgent, 'Opera Mobi' ) !== false ) {
00375                         $deviceName = 'operamobile';
00376                 } elseif ( preg_match( '/iPad.* Safari/', $userAgent ) ) {
00377                         $deviceName = 'iphone';
00378                 } elseif ( preg_match( '/iPhone.* Safari/', $userAgent ) ) {
00379                         if ( strpos( $userAgent, 'iPhone OS 2' ) !== false ) {
00380                                 $deviceName = 'iphone2';
00381                         } else {
00382                                 $deviceName = 'iphone';
00383                         }
00384                 } elseif ( preg_match( '/iPhone/', $userAgent ) ) {
00385                         if ( strpos( $userAgent, 'Opera' ) !== false ) {
00386                                 $deviceName = 'operamini';
00387                         } else {
00388                                 $deviceName = 'native_iphone';
00389                         }
00390                 } elseif ( preg_match( '/WebKit/', $userAgent ) ) {
00391                         if ( preg_match( '/Series60/', $userAgent ) ) {
00392                                 $deviceName = 'nokia';
00393                         } elseif ( preg_match( '/webOS/', $userAgent ) ) {
00394                                 $deviceName = 'palm_pre';
00395                         } else {
00396                                 $deviceName = 'webkit';
00397                         }
00398                 } elseif ( preg_match( '/Opera/', $userAgent ) ) {
00399                         if ( strpos( $userAgent, 'Nintendo Wii' ) !== false ) {
00400                                 $deviceName = 'wii';
00401                         } elseif ( strpos( $userAgent, 'Opera Mini' ) !== false ) {
00402                                 $deviceName = 'operamini';
00403                         } else {
00404                                 $deviceName = 'operamobile';
00405                         }
00406                 } elseif ( preg_match( '/Kindle\/1.0/', $userAgent ) ) {
00407                         $deviceName = 'kindle';
00408                 } elseif ( preg_match( '/Kindle\/2.0/', $userAgent ) ) {
00409                         $deviceName = 'kindle2';
00410                 } elseif ( preg_match( '/Firefox/', $userAgent ) ) {
00411                         $deviceName = 'capable';
00412                 } elseif ( preg_match( '/NetFront/', $userAgent ) ) {
00413                         $deviceName = 'netfront';
00414                 } elseif ( preg_match( '/SEMC-Browser/', $userAgent ) ) {
00415                         $deviceName = 'wap2';
00416                 } elseif ( preg_match( '/Series60/', $userAgent ) ) {
00417                         $deviceName = 'wap2';
00418                 } elseif ( preg_match( '/PlayStation Portable/', $userAgent ) ) {
00419                         $deviceName = 'psp';
00420                 } elseif ( preg_match( '/PLAYSTATION 3/', $userAgent ) ) {
00421                         $deviceName = 'ps3';
00422                 } elseif ( preg_match( '/SAMSUNG/', $userAgent ) ) {
00423                         $deviceName = 'capable';
00424                 } elseif ( preg_match( '/BlackBerry/', $userAgent ) ) {
00425                         if( preg_match( '/BlackBerry[^\/]*\/[1-4]\./', $userAgent ) ) {
00426                                 $deviceName = 'blackberry-lt5';
00427                         } else {
00428                                 $deviceName = 'blackberry';
00429                         }
00430                 }
00431 
00432                 if ( $deviceName === '' ) {
00433                         if ( strpos( $acceptHeader, 'application/vnd.wap.xhtml+xml' ) !== false ) {
00434                                 // Should be wap2
00435                                 $deviceName = 'html';
00436                         } elseif ( strpos( $acceptHeader, 'vnd.wap.wml' ) !== false ) {
00437                                 $deviceName = 'wml';
00438                         } else {
00439                                 $deviceName = 'html';
00440                         }
00441                 }
00442                 wfProfileOut( __METHOD__ );
00443                 return $deviceName;
00444         }
00445 
00449         public function getCssFiles() {
00450                 $files = array();
00451 
00452                 foreach ( self::$formats as $dev ) {
00453                         if ( isset( $dev['css_file_name'] ) ) {
00454                                 $files[] = $dev['css_file_name'];
00455                         }
00456                 }
00457                 return array_unique( $files );
00458         }
00459 }