File indexing completed on 2025-01-19 05:21:14
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Http_UserAgent 0017 * @subpackage UserAgent 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 */ 0021 0022 /** 0023 * Lists of User Agent chains for testing : 0024 * 0025 * - http://www.useragentstring.com/layout/useragentstring.php 0026 * - http://user-agent-string.info/list-of-ua 0027 * - http://www.user-agents.org/allagents.xml 0028 * - http://en.wikipedia.org/wiki/List_of_user_agents_for_mobile_phones 0029 * - http://www.mobilemultimedia.be/fr/ 0030 * 0031 * @category Zend 0032 * @package Zend_Http_UserAgent 0033 * @subpackage UserAgent 0034 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0035 * @license http://framework.zend.com/license/new-bsd New BSD License 0036 */ 0037 class Zend_Http_UserAgent implements Serializable 0038 { 0039 /** 0040 * 'desktop' by default if the sequence return false for each item or is empty 0041 */ 0042 const DEFAULT_IDENTIFICATION_SEQUENCE = 'mobile,desktop'; 0043 0044 /** 0045 * Default persitent storage adapter : Session or NonPersitent 0046 */ 0047 const DEFAULT_PERSISTENT_STORAGE_ADAPTER = 'Session'; 0048 0049 /** 0050 * 'desktop' by default if the sequence return false for each item 0051 */ 0052 const DEFAULT_BROWSER_TYPE = 'desktop'; 0053 0054 /** 0055 * Default User Agent chain to prevent empty value 0056 */ 0057 const DEFAULT_HTTP_USER_AGENT = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)'; 0058 0059 /** 0060 * Default Http Accept param to prevent empty value 0061 */ 0062 const DEFAULT_HTTP_ACCEPT = "application/xhtml+xml"; 0063 0064 /** 0065 * Default markup language 0066 */ 0067 const DEFAULT_MARKUP_LANGUAGE = "xhtml"; 0068 0069 /** 0070 * Browser type 0071 * 0072 * @var string 0073 */ 0074 protected $_browserType; 0075 0076 /** 0077 * Browser type class 0078 * 0079 * Map of browser types to classes. 0080 * 0081 * @var array 0082 */ 0083 protected $_browserTypeClass = array(); 0084 0085 /** 0086 * Array to store config 0087 * 0088 * Default values are provided to ensure specific keys are present at 0089 * instantiation. 0090 * 0091 * @var array 0092 */ 0093 protected $_config = array( 0094 'identification_sequence' => self::DEFAULT_IDENTIFICATION_SEQUENCE, 0095 'storage' => array( 0096 'adapter' => self::DEFAULT_PERSISTENT_STORAGE_ADAPTER, 0097 ), 0098 ); 0099 0100 /** 0101 * Identified device 0102 * 0103 * @var Zend_Http_UserAgent_Device 0104 */ 0105 protected $_device; 0106 0107 /** 0108 * Whether or not this instance is immutable. 0109 * 0110 * If true, none of the following may be modified: 0111 * - $_server 0112 * - $_browserType 0113 * - User-Agent (defined in $_server) 0114 * - HTTP Accept value (defined in $_server) 0115 * - $_storage 0116 * 0117 * @var bool 0118 */ 0119 protected $_immutable = false; 0120 0121 /** 0122 * Plugin loaders 0123 * @var array 0124 */ 0125 protected $_loaders = array(); 0126 0127 /** 0128 * Valid plugin loader types 0129 * @var array 0130 */ 0131 protected $_loaderTypes = array('storage', 'device'); 0132 0133 /** 0134 * Trace of items matched to identify the browser type 0135 * 0136 * @var array 0137 */ 0138 protected $_matchLog = array(); 0139 0140 /** 0141 * Server variable 0142 * 0143 * @var array 0144 */ 0145 protected $_server; 0146 0147 /** 0148 * Persistent storage handler 0149 * 0150 * @var Zend_Http_UserAgent_Storage 0151 */ 0152 protected $_storage; 0153 0154 /** 0155 * Constructor 0156 * 0157 * @param null|array|Zend_Config|ArrayAccess $options 0158 * @return void 0159 */ 0160 public function __construct($options = null) 0161 { 0162 if (null !== $options) { 0163 $this->setOptions($options); 0164 } 0165 } 0166 0167 /** 0168 * Serialized representation of the object 0169 * 0170 * @return string 0171 */ 0172 public function serialize() 0173 { 0174 $device = $this->getDevice(); 0175 $spec = array( 0176 'browser_type' => $this->_browserType, 0177 'config' => $this->_config, 0178 'device_class' => get_class($device), 0179 'device' => $device->serialize(), 0180 'user_agent' => $this->getServerValue('http_user_agent'), 0181 'http_accept' => $this->getServerValue('http_accept'), 0182 ); 0183 return serialize($spec); 0184 } 0185 0186 /** 0187 * Unserialize a previous representation of the object 0188 * 0189 * @param string $serialized 0190 * @return void 0191 */ 0192 public function unserialize($serialized) 0193 { 0194 $spec = unserialize($serialized); 0195 0196 $this->setOptions($spec); 0197 0198 // Determine device class and ensure the class is loaded 0199 $deviceClass = $spec['device_class']; 0200 if (!class_exists($deviceClass)) { 0201 $this->_getUserAgentDevice($this->getBrowserType()); 0202 } 0203 0204 // Get device specification and instantiate 0205 $deviceSpec = unserialize($spec['device']); 0206 $deviceSpec['_config'] = $this->getConfig(); 0207 $deviceSpec['_server'] = $this->getServer(); 0208 $this->_device = new $deviceClass($deviceSpec); 0209 } 0210 0211 /** 0212 * Configure instance 0213 * 0214 * @param array|Zend_Config|ArrayAccess $options 0215 * @return Zend_Http_UserAgent 0216 */ 0217 public function setOptions($options) 0218 { 0219 if ($options instanceof Zend_Config) { 0220 $options = $options->toArray(); 0221 } 0222 0223 if (!is_array($options) 0224 && !$options instanceof ArrayAccess 0225 && !$options instanceof Traversable 0226 ) { 0227 // require_once 'Zend/Http/UserAgent/Exception.php'; 0228 throw new Zend_Http_UserAgent_Exception(sprintf( 0229 'Invalid argument; expected array, Zend_Config object, or object implementing ArrayAccess and Traversable; received %s', 0230 (is_object($options) ? get_class($options) : gettype($options)) 0231 )); 0232 } 0233 0234 // Set $_SERVER first 0235 if (isset($options['server'])) { 0236 $this->setServer($options['server']); 0237 unset($options['server']); 0238 } 0239 0240 // Get plugin loaders sorted 0241 if (isset($options['plugin_loader'])) { 0242 $plConfig = $options['plugin_loader']; 0243 if (is_array($plConfig) || $plConfig instanceof Traversable) { 0244 foreach ($plConfig as $type => $class) { 0245 $this->setPluginLoader($type, $class); 0246 } 0247 } 0248 unset($plConfig, $options['plugin_loader']); 0249 } 0250 0251 // And then loop through the remaining options 0252 $config = array(); 0253 foreach ($options as $key => $value) { 0254 switch (strtolower($key)) { 0255 case 'browser_type': 0256 $this->setBrowserType($value); 0257 break; 0258 case 'http_accept': 0259 $this->setHttpAccept($value); 0260 break; 0261 case 'user_agent': 0262 $this->setUserAgent($value); 0263 break; 0264 default: 0265 // Cache remaining options for $_config 0266 $config[$key] = $value; 0267 break; 0268 } 0269 } 0270 $this->setConfig($config); 0271 0272 return $this; 0273 } 0274 0275 /** 0276 * Comparison of the UserAgent chain and browser signatures. 0277 * 0278 * The comparison is case-insensitive : the browser signatures must be in lower 0279 * case 0280 * 0281 * @param string $deviceClass Name of class against which a match will be attempted 0282 * @return bool 0283 */ 0284 protected function _match($deviceClass) 0285 { 0286 // Validate device class 0287 $r = new ReflectionClass($deviceClass); 0288 if (!$r->implementsInterface('Zend_Http_UserAgent_Device')) { 0289 throw new Zend_Http_UserAgent_Exception(sprintf( 0290 'Invalid device class provided ("%s"); must implement Zend_Http_UserAgent_Device', 0291 $deviceClass 0292 )); 0293 } 0294 0295 $userAgent = $this->getUserAgent(); 0296 0297 // Call match method on device class 0298 return call_user_func( 0299 array($deviceClass, 'match'), 0300 $userAgent, 0301 $this->getServer() 0302 ); 0303 } 0304 0305 /** 0306 * Loads class for a user agent device 0307 * 0308 * @param string $browserType Browser type 0309 * @return string 0310 * @throws Zend_Loader_PluginLoader_Exception if unable to load UA device 0311 */ 0312 protected function _getUserAgentDevice($browserType) 0313 { 0314 $browserType = strtolower($browserType); 0315 if (isset($this->_browserTypeClass[$browserType])) { 0316 return $this->_browserTypeClass[$browserType]; 0317 } 0318 0319 if (isset($this->_config[$browserType]) 0320 && isset($this->_config[$browserType]['device']) 0321 ) { 0322 $deviceConfig = $this->_config[$browserType]['device']; 0323 if (is_array($deviceConfig) && isset($deviceConfig['classname'])) { 0324 $device = (string) $deviceConfig['classname']; 0325 if (!class_exists($device)) { 0326 // require_once 'Zend/Http/UserAgent/Exception.php'; 0327 throw new Zend_Http_UserAgent_Exception(sprintf( 0328 'Invalid classname "%s" provided in device configuration for browser type "%s"', 0329 $device, 0330 $browserType 0331 )); 0332 } 0333 } elseif (is_array($deviceConfig) && isset($deviceConfig['path'])) { 0334 $loader = $this->getPluginLoader('device'); 0335 $path = $deviceConfig['path']; 0336 $prefix = isset($deviceConfig['prefix']) ? $deviceConfig['prefix'] : 'Zend_Http_UserAgent'; 0337 $loader->addPrefixPath($prefix, $path); 0338 0339 $device = $loader->load($browserType); 0340 } else { 0341 $loader = $this->getPluginLoader('device'); 0342 $device = $loader->load($browserType); 0343 } 0344 } else { 0345 $loader = $this->getPluginLoader('device'); 0346 $device = $loader->load($browserType); 0347 } 0348 0349 $this->_browserTypeClass[$browserType] = $device; 0350 0351 return $device; 0352 } 0353 0354 /** 0355 * Returns the User Agent value 0356 * 0357 * If $userAgent param is null, the value of $_server['HTTP_USER_AGENT'] is 0358 * returned. 0359 * 0360 * @return string 0361 */ 0362 public function getUserAgent() 0363 { 0364 if (null === ($ua = $this->getServerValue('http_user_agent'))) { 0365 $ua = self::DEFAULT_HTTP_USER_AGENT; 0366 $this->setUserAgent($ua); 0367 } 0368 0369 return $ua; 0370 } 0371 0372 /** 0373 * Force or replace the UA chain in $_server variable 0374 * 0375 * @param string $userAgent Forced UserAgent chain 0376 * @return Zend_Http_UserAgent 0377 */ 0378 public function setUserAgent($userAgent) 0379 { 0380 $this->setServerValue('http_user_agent', $userAgent); 0381 return $this; 0382 } 0383 0384 /** 0385 * Returns the HTTP Accept server param 0386 * 0387 * @param string $httpAccept (option) forced HTTP Accept chain 0388 * @return string 0389 */ 0390 public function getHttpAccept($httpAccept = null) 0391 { 0392 if (null === ($accept = $this->getServerValue('http_accept'))) { 0393 $accept = self::DEFAULT_HTTP_ACCEPT; 0394 $this->setHttpAccept($accept); 0395 } 0396 return $accept; 0397 } 0398 0399 /** 0400 * Force or replace the HTTP_ACCEPT chain in self::$_server variable 0401 * 0402 * @param string $httpAccept Forced HTTP Accept chain 0403 * @return Zend_Http_UserAgent 0404 */ 0405 public function setHttpAccept($httpAccept) 0406 { 0407 $this->setServerValue('http_accept', $httpAccept); 0408 return $this; 0409 } 0410 0411 /** 0412 * Returns the persistent storage handler 0413 * 0414 * Session storage is used by default unless a different storage adapter 0415 * has been set via the "persistent_storage_adapter" key. That key should 0416 * contain either a fully qualified class name, or a short name that 0417 * resolves via the plugin loader. 0418 * 0419 * @param string $browser Browser identifier (User Agent chain) 0420 * @return Zend_Http_UserAgent_Storage 0421 */ 0422 public function getStorage($browser = null) 0423 { 0424 if (null === $browser) { 0425 $browser = $this->getUserAgent(); 0426 } 0427 if (null === $this->_storage) { 0428 $config = $this->_config['storage']; 0429 $adapter = $config['adapter']; 0430 if (!class_exists($adapter)) { 0431 $loader = $this->getPluginLoader('storage'); 0432 $adapter = $loader->load($adapter); 0433 $loader = $this->getPluginLoader('storage'); 0434 } 0435 $options = array('browser_type' => $browser); 0436 if (isset($config['options'])) { 0437 $options = array_merge($options, $config['options']); 0438 } 0439 $this->setStorage(new $adapter($options)); 0440 } 0441 return $this->_storage; 0442 } 0443 0444 /** 0445 * Sets the persistent storage handler 0446 * 0447 * @param Zend_Http_UserAgent_Storage $storage 0448 * @return Zend_Http_UserAgent 0449 */ 0450 public function setStorage(Zend_Http_UserAgent_Storage $storage) 0451 { 0452 if ($this->_immutable) { 0453 // require_once 'Zend/Http/UserAgent/Exception.php'; 0454 throw new Zend_Http_UserAgent_Exception( 0455 'The User-Agent device object has already been retrieved; the storage object is now immutable' 0456 ); 0457 } 0458 0459 $this->_storage = $storage; 0460 return $this; 0461 } 0462 0463 /** 0464 * Clean the persistent storage 0465 * 0466 * @param string $browser Browser identifier (User Agent chain) 0467 * @return void 0468 */ 0469 public function clearStorage($browser = null) 0470 { 0471 $this->getStorage($browser)->clear(); 0472 } 0473 0474 /** 0475 * Get user configuration 0476 * 0477 * @return array 0478 */ 0479 public function getConfig() 0480 { 0481 return $this->_config; 0482 } 0483 0484 /** 0485 * Config parameters is an Array or a Zend_Config object 0486 * 0487 * The allowed parameters are : 0488 * - the identification sequence (can be empty) => desktop browser type is the 0489 * default browser type returned 0490 * $config['identification_sequence'] : ',' separated browser types 0491 * - the persistent storage adapter 0492 * $config['persistent_storage_adapter'] = "Session" or "NonPersistent" 0493 * - to add or replace a browser type device 0494 * $config[(type)]['device']['path'] 0495 * $config[(type)]['device']['classname'] 0496 * - to add or replace a browser type features adapter 0497 * $config[(type)]['features']['path'] 0498 * $config[(type)]['features']['classname'] 0499 * 0500 * @param mixed $config (option) Config array 0501 * @return Zend_Http_UserAgent 0502 */ 0503 public function setConfig($config = array()) 0504 { 0505 if ($config instanceof Zend_Config) { 0506 $config = $config->toArray(); 0507 } 0508 0509 // Verify that Config parameters are in an array. 0510 if (!is_array($config) && !$config instanceof Traversable) { 0511 // require_once 'Zend/Http/UserAgent/Exception.php'; 0512 throw new Zend_Http_UserAgent_Exception(sprintf( 0513 'Config parameters must be in an array or a Traversable object; received "%s"', 0514 (is_object($config) ? get_class($config) : gettype($config)) 0515 )); 0516 } 0517 0518 if ($config instanceof Traversable) { 0519 $tmp = array(); 0520 foreach ($config as $key => $value) { 0521 $tmp[$key] = $value; 0522 } 0523 $config = $tmp; 0524 unset($tmp); 0525 } 0526 0527 $this->_config = array_merge($this->_config, $config); 0528 return $this; 0529 } 0530 0531 /** 0532 * Returns the device object 0533 * 0534 * This is the object that will contain the various discovered device 0535 * capabilities. 0536 * 0537 * @return Zend_Http_UserAgent_Device $device 0538 */ 0539 public function getDevice() 0540 { 0541 if (null !== $this->_device) { 0542 return $this->_device; 0543 } 0544 0545 $userAgent = $this->getUserAgent(); 0546 0547 // search an existing identification in the session 0548 $storage = $this->getStorage($userAgent); 0549 0550 if (!$storage->isEmpty()) { 0551 // If the user agent and features are already existing, the 0552 // Zend_Http_UserAgent object is serialized in the session 0553 $object = $storage->read(); 0554 $this->unserialize($object); 0555 } else { 0556 // Otherwise, the identification is made and stored in the session. 0557 // Find the browser type: 0558 $this->setBrowserType($this->_matchUserAgent()); 0559 $this->_createDevice(); 0560 0561 // put the result in storage: 0562 $this->getStorage($userAgent) 0563 ->write($this->serialize()); 0564 } 0565 0566 // Mark the object as immutable 0567 $this->_immutable = true; 0568 0569 // Return the device instance 0570 return $this->_device; 0571 } 0572 0573 /** 0574 * Retrieve the browser type 0575 * 0576 * @return string $browserType 0577 */ 0578 public function getBrowserType() 0579 { 0580 return $this->_browserType; 0581 } 0582 0583 /** 0584 * Set the browser "type" 0585 * 0586 * @param string $browserType 0587 * @return Zend_Http_UserAgent 0588 */ 0589 public function setBrowserType($browserType) 0590 { 0591 if ($this->_immutable) { 0592 // require_once 'Zend/Http/UserAgent/Exception.php'; 0593 throw new Zend_Http_UserAgent_Exception( 0594 'The User-Agent device object has already been retrieved; the browser type is now immutable' 0595 ); 0596 } 0597 0598 $this->_browserType = $browserType; 0599 return $this; 0600 } 0601 0602 /** 0603 * Retrieve the "$_SERVER" array 0604 * 0605 * Basically, the $_SERVER array or an equivalent container storing the 0606 * data that will be introspected. 0607 * 0608 * If the value has not been previously set, it sets itself from the 0609 * $_SERVER superglobal. 0610 * 0611 * @return array 0612 */ 0613 public function getServer() 0614 { 0615 if (null === $this->_server) { 0616 $this->setServer($_SERVER); 0617 } 0618 return $this->_server; 0619 } 0620 0621 /** 0622 * Set the "$_SERVER" array 0623 * 0624 * Basically, the $_SERVER array or an equivalent container storing the 0625 * data that will be introspected. 0626 * 0627 * @param array|ArrayAccess $server 0628 * @return void 0629 * @throws Zend_Http_UserAgent_Exception on invalid parameter 0630 */ 0631 public function setServer($server) 0632 { 0633 if ($this->_immutable) { 0634 // require_once 'Zend/Http/UserAgent/Exception.php'; 0635 throw new Zend_Http_UserAgent_Exception( 0636 'The User-Agent device object has already been retrieved; the server array is now immutable' 0637 ); 0638 } 0639 0640 if (!is_array($server) && !$server instanceof Traversable) { 0641 // require_once 'Zend/Http/UserAgent/Exception.php'; 0642 throw new Zend_Http_UserAgent_Exception(sprintf( 0643 'Expected an array or object implementing Traversable; received %s', 0644 (is_object($server) ? get_class($server) : gettype($server)) 0645 )); 0646 } 0647 0648 // Get an array if we don't have one 0649 if ($server instanceof ArrayObject) { 0650 $server = $server->getArrayCopy(); 0651 } elseif ($server instanceof Traversable) { 0652 $tmp = array(); 0653 foreach ($server as $key => $value) { 0654 $tmp[$key] = $value; 0655 } 0656 $server = $tmp; 0657 unset($tmp); 0658 } 0659 0660 // Normalize key case 0661 $server = array_change_key_case($server, CASE_LOWER); 0662 0663 $this->_server = $server; 0664 return $this; 0665 } 0666 0667 /** 0668 * Retrieve a server value 0669 * 0670 * @param string $key 0671 * @return mixed 0672 */ 0673 public function getServerValue($key) 0674 { 0675 $key = strtolower($key); 0676 $server = $this->getServer(); 0677 $return = null; 0678 if (isset($server[$key])) { 0679 $return = $server[$key]; 0680 } 0681 unset($server); 0682 return $return; 0683 } 0684 0685 /** 0686 * Set a server value 0687 * 0688 * @param string|int|float $key 0689 * @param mixed $value 0690 * @return void 0691 */ 0692 public function setServerValue($key, $value) 0693 { 0694 if ($this->_immutable) { 0695 // require_once 'Zend/Http/UserAgent/Exception.php'; 0696 throw new Zend_Http_UserAgent_Exception( 0697 'The User-Agent device object has already been retrieved; the server array is now immutable' 0698 ); 0699 } 0700 0701 $server = $this->getServer(); // ensure it's been initialized 0702 $key = strtolower($key); 0703 $this->_server[$key] = $value; 0704 return $this; 0705 } 0706 0707 /** 0708 * Set plugin loader 0709 * 0710 * @param string $type Type of plugin loader; one of 'storage', (?) 0711 * @param string|Zend_Loader_PluginLoader $loader 0712 * @return Zend_Http_UserAgent 0713 */ 0714 public function setPluginLoader($type, $loader) 0715 { 0716 $type = $this->_validateLoaderType($type); 0717 0718 if (is_string($loader)) { 0719 if (!class_exists($loader)) { 0720 // require_once 'Zend/Loader.php'; 0721 Zend_Loader::loadClass($loader); 0722 } 0723 $loader = new $loader(); 0724 } elseif (!is_object($loader)) { 0725 // require_once 'Zend/Http/UserAgent/Exception.php'; 0726 throw new Zend_Http_UserAgent_Exception(sprintf( 0727 'Expected a plugin loader class or object; received %s', 0728 gettype($loader) 0729 )); 0730 } 0731 if (!$loader instanceof Zend_Loader_PluginLoader) { 0732 // require_once 'Zend/Http/UserAgent/Exception.php'; 0733 throw new Zend_Http_UserAgent_Exception(sprintf( 0734 'Expected an object extending Zend_Loader_PluginLoader; received %s', 0735 get_class($loader) 0736 )); 0737 } 0738 0739 $basePrefix = 'Zend_Http_UserAgent_'; 0740 $basePath = 'Zend/Http/UserAgent/'; 0741 switch ($type) { 0742 case 'storage': 0743 $prefix = $basePrefix . 'Storage'; 0744 $path = $basePath . 'Storage'; 0745 break; 0746 case 'device': 0747 $prefix = $basePrefix; 0748 $path = $basePath; 0749 break; 0750 } 0751 $loader->addPrefixPath($prefix, $path); 0752 $this->_loaders[$type] = $loader; 0753 return $this; 0754 } 0755 0756 /** 0757 * Get a plugin loader 0758 * 0759 * @param string $type A valid plugin loader type; see {@link $_loaderTypes} 0760 * @return Zend_Loader_PluginLoader 0761 */ 0762 public function getPluginLoader($type) 0763 { 0764 $type = $this->_validateLoaderType($type); 0765 if (!isset($this->_loaders[$type])) { 0766 // require_once 'Zend/Loader/PluginLoader.php'; 0767 $this->setPluginLoader($type, new Zend_Loader_PluginLoader()); 0768 } 0769 return $this->_loaders[$type]; 0770 } 0771 0772 /** 0773 * Validate a plugin loader type 0774 * 0775 * Verifies that it is in {@link $_loaderTypes}, and returns a normalized 0776 * version of the type. 0777 * 0778 * @param string $type 0779 * @return string 0780 * @throws Zend_Http_UserAgent_Exception on invalid type 0781 */ 0782 protected function _validateLoaderType($type) 0783 { 0784 $type = strtolower($type); 0785 if (!in_array($type, $this->_loaderTypes)) { 0786 $types = implode(', ', $this->_loaderTypes); 0787 0788 // require_once 'Zend/Http/UserAgent/Exception.php'; 0789 throw new Zend_Http_UserAgent_Exception(sprintf( 0790 'Expected one of "%s" for plugin loader type; received "%s"', 0791 $types, 0792 (string) $type 0793 )); 0794 } 0795 return $type; 0796 } 0797 0798 /** 0799 * Run the identification sequence to match the right browser type according to the 0800 * user agent 0801 * 0802 * @return Zend_Http_UserAgent_Result 0803 */ 0804 protected function _matchUserAgent() 0805 { 0806 $type = self::DEFAULT_BROWSER_TYPE; 0807 0808 // If we have no identification sequence, just return the default type 0809 if (empty($this->_config['identification_sequence'])) { 0810 return $type; 0811 } 0812 0813 // Get sequence against which to match 0814 $sequence = explode(',', $this->_config['identification_sequence']); 0815 0816 // If a browser type is already configured, push that to the front of the list 0817 if (null !== ($browserType = $this->getBrowserType())) { 0818 array_unshift($sequence, $browserType); 0819 } 0820 0821 // Append the default browser type to the list if not alread in the list 0822 if (!in_array($type, $sequence)) { 0823 $sequence[] = $type; 0824 } 0825 0826 // Test each type until we find a match 0827 foreach ($sequence as $browserType) { 0828 $browserType = trim($browserType); 0829 $className = $this->_getUserAgentDevice($browserType); 0830 0831 // Attempt to match this device class 0832 if ($this->_match($className)) { 0833 $type = $browserType; 0834 $this->_browserTypeClass[$type] = $className; 0835 break; 0836 } 0837 } 0838 0839 return $type; 0840 } 0841 0842 /** 0843 * Creates device object instance 0844 * 0845 * @return void 0846 */ 0847 protected function _createDevice() 0848 { 0849 $browserType = $this->getBrowserType(); 0850 $classname = $this->_getUserAgentDevice($browserType); 0851 $this->_device = new $classname($this->getUserAgent(), $this->getServer(), $this->getConfig()); 0852 } 0853 }