PageRenderTime 44ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/Zend/Http/UserAgent.php

https://bitbucket.org/andrewjleavitt/magestudy
PHP | 847 lines | 419 code | 84 blank | 344 comment | 53 complexity | 6bae819a64905b348577f51ad406a070 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, GPL-2.0, WTFPL
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Http_UserAgent
  17. * @subpackage UserAgent
  18. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. */
  21. /**
  22. * Lists of User Agent chains for testing :
  23. *
  24. * - http://www.useragentstring.com/layout/useragentstring.php
  25. * - http://user-agent-string.info/list-of-ua
  26. * - http://www.user-agents.org/allagents.xml
  27. * - http://en.wikipedia.org/wiki/List_of_user_agents_for_mobile_phones
  28. * - http://www.mobilemultimedia.be/fr/
  29. *
  30. * @category Zend
  31. * @package Zend_Http_UserAgent
  32. * @subpackage UserAgent
  33. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  34. * @license http://framework.zend.com/license/new-bsd New BSD License
  35. */
  36. class Zend_Http_UserAgent implements Serializable
  37. {
  38. /**
  39. * 'desktop' by default if the sequence return false for each item or is empty
  40. */
  41. const DEFAULT_IDENTIFICATION_SEQUENCE = 'mobile,desktop';
  42. /**
  43. * Default persitent storage adapter : Session or NonPersitent
  44. */
  45. const DEFAULT_PERSISTENT_STORAGE_ADAPTER = 'Session';
  46. /**
  47. * 'desktop' by default if the sequence return false for each item
  48. */
  49. const DEFAULT_BROWSER_TYPE = 'desktop';
  50. /**
  51. * Default User Agent chain to prevent empty value
  52. */
  53. const DEFAULT_HTTP_USER_AGENT = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)';
  54. /**
  55. * Default Http Accept param to prevent empty value
  56. */
  57. const DEFAULT_HTTP_ACCEPT = "application/xhtml+xml";
  58. /**
  59. * Default markup language
  60. */
  61. const DEFAULT_MARKUP_LANGUAGE = "xhtml";
  62. /**
  63. * Browser type
  64. *
  65. * @var string
  66. */
  67. protected $_browserType;
  68. /**
  69. * Browser type class
  70. *
  71. * Map of browser types to classes.
  72. *
  73. * @var array
  74. */
  75. protected $_browserTypeClass = array();
  76. /**
  77. * Array to store config
  78. *
  79. * Default values are provided to ensure specific keys are present at
  80. * instantiation.
  81. *
  82. * @var array
  83. */
  84. protected $_config = array(
  85. 'identification_sequence' => self::DEFAULT_IDENTIFICATION_SEQUENCE,
  86. 'storage' => array(
  87. 'adapter' => self::DEFAULT_PERSISTENT_STORAGE_ADAPTER,
  88. ),
  89. );
  90. /**
  91. * Identified device
  92. *
  93. * @var Zend_Http_UserAgent_Device
  94. */
  95. protected $_device;
  96. /**
  97. * Whether or not this instance is immutable.
  98. *
  99. * If true, none of the following may be modified:
  100. * - $_server
  101. * - $_browserType
  102. * - User-Agent (defined in $_server)
  103. * - HTTP Accept value (defined in $_server)
  104. * - $_storage
  105. *
  106. * @var bool
  107. */
  108. protected $_immutable = false;
  109. /**
  110. * Plugin loaders
  111. * @var array
  112. */
  113. protected $_loaders = array();
  114. /**
  115. * Valid plugin loader types
  116. * @var array
  117. */
  118. protected $_loaderTypes = array('storage', 'device');
  119. /**
  120. * Trace of items matched to identify the browser type
  121. *
  122. * @var array
  123. */
  124. protected $_matchLog = array();
  125. /**
  126. * Server variable
  127. *
  128. * @var array
  129. */
  130. protected $_server;
  131. /**
  132. * Persistent storage handler
  133. *
  134. * @var Zend_Http_UserAgent_Storage
  135. */
  136. protected $_storage;
  137. /**
  138. * Constructor
  139. *
  140. * @param null|array|Zend_Config|ArrayAccess $options
  141. * @return void
  142. */
  143. public function __construct($options = null)
  144. {
  145. if (null !== $options) {
  146. $this->setOptions($options);
  147. }
  148. }
  149. /**
  150. * Serialized representation of the object
  151. *
  152. * @return string
  153. */
  154. public function serialize()
  155. {
  156. $spec = array(
  157. 'browser_type' => $this->_browserType,
  158. 'config' => $this->_config,
  159. 'device_class' => get_class($this->_device),
  160. 'device' => $this->_device->serialize(),
  161. 'user_agent' => $this->getServerValue('http_user_agent'),
  162. 'http_accept' => $this->getServerValue('http_accept'),
  163. );
  164. return serialize($spec);
  165. }
  166. /**
  167. * Unserialize a previous representation of the object
  168. *
  169. * @param string $serialized
  170. * @return void
  171. */
  172. public function unserialize($serialized)
  173. {
  174. $spec = unserialize($serialized);
  175. $this->setOptions($spec);
  176. // Determine device class and ensure the class is loaded
  177. $deviceClass = $spec['device_class'];
  178. if (!class_exists($deviceClass)) {
  179. $this->_getUserAgentDevice($this->getBrowserType());
  180. }
  181. // Get device specification and instantiate
  182. $deviceSpec = unserialize($spec['device']);
  183. $deviceSpec['_config'] = $this->getConfig();
  184. $deviceSpec['_server'] = $this->getServer();
  185. $this->_device = new $deviceClass($deviceSpec);
  186. }
  187. /**
  188. * Configure instance
  189. *
  190. * @param array|Zend_Config|ArrayAccess $options
  191. * @return Zend_Http_UserAgent
  192. */
  193. public function setOptions($options)
  194. {
  195. if ($options instanceof Zend_Config) {
  196. $options = $options->toArray();
  197. }
  198. if (!is_array($options)
  199. && !$options instanceof ArrayAccess
  200. && !$options instanceof Traversable
  201. ) {
  202. #require_once 'Zend/Http/UserAgent/Exception.php';
  203. throw new Zend_Http_UserAgent_Exception(sprintf(
  204. 'Invalid argument; expected array, Zend_Config object, or object implementing ArrayAccess and Traversable; received %s',
  205. (is_object($options) ? get_class($options) : gettype($options))
  206. ));
  207. }
  208. // Set $_SERVER first
  209. if (isset($options['server'])) {
  210. $this->setServer($options['server']);
  211. unset($options['server']);
  212. }
  213. // Get plugin loaders sorted
  214. if (isset($options['plugin_loader'])) {
  215. $plConfig = $options['plugin_loader'];
  216. if (is_array($plConfig) || $plConfig instanceof Traversable) {
  217. foreach ($plConfig as $type => $class) {
  218. $this->setPluginLoader($type, $class);
  219. }
  220. }
  221. unset($plConfig, $options['plugin_loader']);
  222. }
  223. // And then loop through the remaining options
  224. $config = array();
  225. foreach ($options as $key => $value) {
  226. switch (strtolower($key)) {
  227. case 'browser_type':
  228. $this->setBrowserType($value);
  229. break;
  230. case 'http_accept':
  231. $this->setHttpAccept($value);
  232. break;
  233. case 'user_agent':
  234. $this->setUserAgent($value);
  235. break;
  236. default:
  237. // Cache remaining options for $_config
  238. $config[$key] = $value;
  239. break;
  240. }
  241. }
  242. $this->setConfig($config);
  243. return $this;
  244. }
  245. /**
  246. * Comparison of the UserAgent chain and browser signatures.
  247. *
  248. * The comparison is case-insensitive : the browser signatures must be in lower
  249. * case
  250. *
  251. * @param string $deviceClass Name of class against which a match will be attempted
  252. * @return bool
  253. */
  254. protected function _match($deviceClass)
  255. {
  256. // Validate device class
  257. $r = new ReflectionClass($deviceClass);
  258. if (!$r->implementsInterface('Zend_Http_UserAgent_Device')) {
  259. throw new Zend_Http_UserAgent_Exception(sprintf(
  260. 'Invalid device class provided ("%s"); must implement Zend_Http_UserAgent_Device',
  261. $deviceClass
  262. ));
  263. }
  264. $userAgent = $this->getUserAgent();
  265. // Call match method on device class
  266. return call_user_func(
  267. array($deviceClass, 'match'),
  268. $userAgent,
  269. $this->getServer()
  270. );
  271. }
  272. /**
  273. * Loads class for a user agent device
  274. *
  275. * @param string $browserType Browser type
  276. * @return string
  277. * @throws Zend_Loader_PluginLoader_Exception if unable to load UA device
  278. */
  279. protected function _getUserAgentDevice($browserType)
  280. {
  281. $browserType = strtolower($browserType);
  282. if (isset($this->_browserTypeClass[$browserType])) {
  283. return $this->_browserTypeClass[$browserType];
  284. }
  285. if (isset($this->_config[$browserType])
  286. && isset($this->_config[$browserType]['device'])
  287. ) {
  288. $deviceConfig = $this->_config[$browserType]['device'];
  289. if (is_array($deviceConfig) && isset($deviceConfig['classname'])) {
  290. $device = (string) $deviceConfig['classname'];
  291. if (!class_exists($device)) {
  292. #require_once 'Zend/Http/UserAgent/Exception.php';
  293. throw new Zend_Http_UserAgent_Exception(sprintf(
  294. 'Invalid classname "%s" provided in device configuration for browser type "%s"',
  295. $device,
  296. $browserType
  297. ));
  298. }
  299. } elseif (is_array($deviceConfig) && isset($deviceConfig['path'])) {
  300. $loader = $this->getPluginLoader('device');
  301. $path = $deviceConfig['path'];
  302. $prefix = isset($deviceConfig['prefix']) ? $deviceConfig['prefix'] : 'Zend_Http_UserAgent';
  303. $loader->addPrefixPath($prefix, $path);
  304. $device = $loader->load($browserType);
  305. } else {
  306. $loader = $this->getPluginLoader('device');
  307. $device = $loader->load($browserType);
  308. }
  309. } else {
  310. $loader = $this->getPluginLoader('device');
  311. $device = $loader->load($browserType);
  312. }
  313. $this->_browserTypeClass[$browserType] = $device;
  314. return $device;
  315. }
  316. /**
  317. * Returns the User Agent value
  318. *
  319. * If $userAgent param is null, the value of $_server['HTTP_USER_AGENT'] is
  320. * returned.
  321. *
  322. * @return string
  323. */
  324. public function getUserAgent()
  325. {
  326. if (null === ($ua = $this->getServerValue('http_user_agent'))) {
  327. $ua = self::DEFAULT_HTTP_USER_AGENT;
  328. $this->setUserAgent($ua);
  329. }
  330. return $ua;
  331. }
  332. /**
  333. * Force or replace the UA chain in $_server variable
  334. *
  335. * @param string $userAgent Forced UserAgent chain
  336. * @return Zend_Http_UserAgent
  337. */
  338. public function setUserAgent($userAgent)
  339. {
  340. $this->setServerValue('http_user_agent', $userAgent);
  341. return $this;
  342. }
  343. /**
  344. * Returns the HTTP Accept server param
  345. *
  346. * @param string $httpAccept (option) forced HTTP Accept chain
  347. * @return string
  348. */
  349. public function getHttpAccept($httpAccept = null)
  350. {
  351. if (null === ($accept = $this->getServerValue('http_accept'))) {
  352. $accept = self::DEFAULT_HTTP_ACCEPT;
  353. $this->setHttpAccept($accept);
  354. }
  355. return $accept;
  356. }
  357. /**
  358. * Force or replace the HTTP_ACCEPT chain in self::$_server variable
  359. *
  360. * @param string $httpAccept Forced HTTP Accept chain
  361. * @return Zend_Http_UserAgent
  362. */
  363. public function setHttpAccept($httpAccept)
  364. {
  365. $this->setServerValue('http_accept', $httpAccept);
  366. return $this;
  367. }
  368. /**
  369. * Returns the persistent storage handler
  370. *
  371. * Session storage is used by default unless a different storage adapter
  372. * has been set via the "persistent_storage_adapter" key. That key should
  373. * contain either a fully qualified class name, or a short name that
  374. * resolves via the plugin loader.
  375. *
  376. * @param string $browser Browser identifier (User Agent chain)
  377. * @return Zend_Http_UserAgent_Storage
  378. */
  379. public function getStorage($browser = null)
  380. {
  381. if (null === $browser) {
  382. $browser = $this->getUserAgent();
  383. }
  384. if (null === $this->_storage) {
  385. $config = $this->_config['storage'];
  386. $adapter = $config['adapter'];
  387. if (!class_exists($adapter)) {
  388. $loader = $this->getPluginLoader('storage');
  389. $adapter = $loader->load($adapter);
  390. $loader = $this->getPluginLoader('storage');
  391. }
  392. $options = array('browser_type' => $browser);
  393. if (isset($config['options'])) {
  394. $options = array_merge($options, $config['options']);
  395. }
  396. $this->setStorage(new $adapter($options));
  397. }
  398. return $this->_storage;
  399. }
  400. /**
  401. * Sets the persistent storage handler
  402. *
  403. * @param Zend_Http_UserAgent_Storage $storage
  404. * @return Zend_Http_UserAgent
  405. */
  406. public function setStorage(Zend_Http_UserAgent_Storage $storage)
  407. {
  408. if ($this->_immutable) {
  409. #require_once 'Zend/Http/UserAgent/Exception.php';
  410. throw new Zend_Http_UserAgent_Exception(
  411. 'The User-Agent device object has already been retrieved; the storage object is now immutable'
  412. );
  413. }
  414. $this->_storage = $storage;
  415. return $this;
  416. }
  417. /**
  418. * Clean the persistent storage
  419. *
  420. * @param string $browser Browser identifier (User Agent chain)
  421. * @return void
  422. */
  423. public function clearStorage($browser = null)
  424. {
  425. $this->getStorage($browser)->clear();
  426. }
  427. /**
  428. * Get user configuration
  429. *
  430. * @return array
  431. */
  432. public function getConfig()
  433. {
  434. return $this->_config;
  435. }
  436. /**
  437. * Config parameters is an Array or a Zend_Config object
  438. *
  439. * The allowed parameters are :
  440. * - the identification sequence (can be empty) => desktop browser type is the
  441. * default browser type returned
  442. * $config['identification_sequence'] : ',' separated browser types
  443. * - the persistent storage adapter
  444. * $config['persistent_storage_adapter'] = "Session" or "NonPersistent"
  445. * - to add or replace a browser type device
  446. * $config[(type)]['device']['path']
  447. * $config[(type)]['device']['classname']
  448. * - to add or replace a browser type features adapter
  449. * $config[(type)]['features']['path']
  450. * $config[(type)]['features']['classname']
  451. *
  452. * @param mixed $config (option) Config array
  453. * @return Zend_Http_UserAgent
  454. */
  455. public function setConfig($config = array())
  456. {
  457. if ($config instanceof Zend_Config) {
  458. $config = $config->toArray();
  459. }
  460. // Verify that Config parameters are in an array.
  461. if (!is_array($config) && !$config instanceof Traversable) {
  462. #require_once 'Zend/Http/UserAgent/Exception.php';
  463. throw new Zend_Http_UserAgent_Exception(sprintf(
  464. 'Config parameters must be in an array or a Traversable object; received "%s"',
  465. (is_object($config) ? get_class($config) : gettype($config))
  466. ));
  467. }
  468. if ($config instanceof Traversable) {
  469. $tmp = array();
  470. foreach ($config as $key => $value) {
  471. $tmp[$key] = $value;
  472. }
  473. $config = $tmp;
  474. unset($tmp);
  475. }
  476. $this->_config = array_merge($this->_config, $config);
  477. return $this;
  478. }
  479. /**
  480. * @return the $device
  481. */
  482. public function getDevice()
  483. {
  484. if (null !== $this->_device) {
  485. return $this->_device;
  486. }
  487. $userAgent = $this->getUserAgent();
  488. // search an existing identification in the session
  489. $storage = $this->getStorage($userAgent);
  490. if (!$storage->isEmpty()) {
  491. // If the user agent and features are already existing, the
  492. // Zend_Http_UserAgent object is serialized in the session
  493. $object = $storage->read();
  494. $this->unserialize($object);
  495. } else {
  496. // Otherwise, the identification is made and stored in the session.
  497. // Find the browser type:
  498. $this->setBrowserType($this->_matchUserAgent());
  499. $this->_createDevice();
  500. // put the result in storage:
  501. $this->getStorage($userAgent)
  502. ->write($this->serialize());
  503. }
  504. // Mark the object as immutable
  505. $this->_immutable = true;
  506. // Return the device instance
  507. return $this->_device;
  508. }
  509. /**
  510. * Retrieve the browser type
  511. *
  512. * @return string $browserType
  513. */
  514. public function getBrowserType()
  515. {
  516. return $this->_browserType;
  517. }
  518. /**
  519. * Set the browser "type"
  520. *
  521. * @param string $browserType
  522. * @return Zend_Http_UserAgent
  523. */
  524. public function setBrowserType($browserType)
  525. {
  526. if ($this->_immutable) {
  527. #require_once 'Zend/Http/UserAgent/Exception.php';
  528. throw new Zend_Http_UserAgent_Exception(
  529. 'The User-Agent device object has already been retrieved; the browser type is now immutable'
  530. );
  531. }
  532. $this->_browserType = $browserType;
  533. return $this;
  534. }
  535. /**
  536. * Retrieve the "$_SERVER" array
  537. *
  538. * Basically, the $_SERVER array or an equivalent container storing the
  539. * data that will be introspected.
  540. *
  541. * If the value has not been previously set, it sets itself from the
  542. * $_SERVER superglobal.
  543. *
  544. * @return array
  545. */
  546. public function getServer()
  547. {
  548. if (null === $this->_server) {
  549. $this->setServer($_SERVER);
  550. }
  551. return $this->_server;
  552. }
  553. /**
  554. * Retrieve the "$_SERVER" array
  555. *
  556. * Basically, the $_SERVER array or an equivalent container storing the
  557. * data that will be introspected.
  558. *
  559. * @param array|ArrayAccess $server
  560. * @return void
  561. * @throws Zend_Http_UserAgent_Exception on invalid parameter
  562. */
  563. public function setServer($server)
  564. {
  565. if ($this->_immutable) {
  566. #require_once 'Zend/Http/UserAgent/Exception.php';
  567. throw new Zend_Http_UserAgent_Exception(
  568. 'The User-Agent device object has already been retrieved; the server array is now immutable'
  569. );
  570. }
  571. if (!is_array($server) && !$server instanceof Traversable) {
  572. #require_once 'Zend/Http/UserAgent/Exception.php';
  573. throw new Zend_Http_UserAgent_Exception(sprintf(
  574. 'Expected an array or object implementing Traversable; received %s',
  575. (is_object($server) ? get_class($server) : gettype($server))
  576. ));
  577. }
  578. // Get an array if we don't have one
  579. if ($server instanceof ArrayObject) {
  580. $server = $server->getArrayCopy();
  581. } elseif ($server instanceof Traversable) {
  582. $tmp = array();
  583. foreach ($server as $key => $value) {
  584. $tmp[$key] = $value;
  585. }
  586. $server = $tmp;
  587. unset($tmp);
  588. }
  589. // Normalize key case
  590. $server = array_change_key_case($server, CASE_LOWER);
  591. $this->_server = $server;
  592. return $this;
  593. }
  594. /**
  595. * Retrieve a server value
  596. *
  597. * @param string $key
  598. * @return mixed
  599. */
  600. public function getServerValue($key)
  601. {
  602. $key = strtolower($key);
  603. $server = $this->getServer();
  604. $return = null;
  605. if (isset($server[$key])) {
  606. $return = $server[$key];
  607. }
  608. unset($server);
  609. return $return;
  610. }
  611. /**
  612. * Set a server value
  613. *
  614. * @param string|int|float $key
  615. * @param mixed $value
  616. * @return void
  617. */
  618. public function setServerValue($key, $value)
  619. {
  620. if ($this->_immutable) {
  621. #require_once 'Zend/Http/UserAgent/Exception.php';
  622. throw new Zend_Http_UserAgent_Exception(
  623. 'The User-Agent device object has already been retrieved; the server array is now immutable'
  624. );
  625. }
  626. $server = $this->getServer(); // ensure it's been initialized
  627. $key = strtolower($key);
  628. $this->_server[$key] = $value;
  629. return $this;
  630. }
  631. /**
  632. * Set plugin loader
  633. *
  634. * @param string $type Type of plugin loader; one of 'storage', (?)
  635. * @param string|Zend_Loader_PluginLoader $loader
  636. * @return Zend_Http_UserAgent
  637. */
  638. public function setPluginLoader($type, $loader)
  639. {
  640. $type = $this->_validateLoaderType($type);
  641. if (is_string($loader)) {
  642. if (!class_exists($loader)) {
  643. #require_once 'Zend/Loader.php';
  644. Zend_Loader::loadClass($loader);
  645. }
  646. $loader = new $loader();
  647. } elseif (!is_object($loader)) {
  648. #require_once 'Zend/Http/UserAgent/Exception.php';
  649. throw new Zend_Http_UserAgent_Exception(sprintf(
  650. 'Expected a plugin loader class or object; received %s',
  651. gettype($loader)
  652. ));
  653. }
  654. if (!$loader instanceof Zend_Loader_PluginLoader) {
  655. #require_once 'Zend/Http/UserAgent/Exception.php';
  656. throw new Zend_Http_UserAgent_Exception(sprintf(
  657. 'Expected an object extending Zend_Loader_PluginLoader; received %s',
  658. get_class($loader)
  659. ));
  660. }
  661. $basePrefix = 'Zend_Http_UserAgent_';
  662. $basePath = 'Zend/Http/UserAgent/';
  663. switch ($type) {
  664. case 'storage':
  665. $prefix = $basePrefix . 'Storage';
  666. $path = $basePath . 'Storage';
  667. break;
  668. case 'device':
  669. $prefix = $basePrefix;
  670. $path = $basePath;
  671. break;
  672. }
  673. $loader->addPrefixPath($prefix, $path);
  674. $this->_loaders[$type] = $loader;
  675. return $this;
  676. }
  677. /**
  678. * Get a plugin loader
  679. *
  680. * @param string $type A valid plugin loader type; see {@link $_loaderTypes}
  681. * @return Zend_Loader_PluginLoader
  682. */
  683. public function getPluginLoader($type)
  684. {
  685. $type = $this->_validateLoaderType($type);
  686. if (!isset($this->_loaders[$type])) {
  687. #require_once 'Zend/Loader/PluginLoader.php';
  688. $this->setPluginLoader($type, new Zend_Loader_PluginLoader());
  689. }
  690. return $this->_loaders[$type];
  691. }
  692. /**
  693. * Validate a plugin loader type
  694. *
  695. * Verifies that it is in {@link $_loaderTypes}, and returns a normalized
  696. * version of the type.
  697. *
  698. * @param string $type
  699. * @return string
  700. * @throws Zend_Http_UserAgent_Exception on invalid type
  701. */
  702. protected function _validateLoaderType($type)
  703. {
  704. $type = strtolower($type);
  705. if (!in_array($type, $this->_loaderTypes)) {
  706. $types = implode(', ', $this->_loaderTypes);
  707. #require_once 'Zend/Http/UserAgent/Exception.php';
  708. throw new Zend_Http_UserAgent_Exception(sprintf(
  709. 'Expected one of "%s" for plugin loader type; received "%s"',
  710. $types,
  711. (string) $type
  712. ));
  713. }
  714. return $type;
  715. }
  716. /**
  717. * Run the identification sequence to match the right browser type according to the
  718. * user agent
  719. *
  720. * @return Zend_Http_UserAgent_Result
  721. */
  722. protected function _matchUserAgent()
  723. {
  724. $type = self::DEFAULT_BROWSER_TYPE;
  725. // If we have no identification sequence, just return the default type
  726. if (empty($this->_config['identification_sequence'])) {
  727. return $type;
  728. }
  729. // Get sequence against which to match
  730. $sequence = explode(',', $this->_config['identification_sequence']);
  731. // If a browser type is already configured, push that to the front of the list
  732. if (null !== ($browserType = $this->getBrowserType())) {
  733. array_unshift($sequence, $browserType);
  734. }
  735. // Append the default browser type to the list if not alread in the list
  736. if (!in_array($type, $sequence)) {
  737. $sequence[] = $type;
  738. }
  739. // Test each type until we find a match
  740. foreach ($sequence as $browserType) {
  741. $browserType = trim($browserType);
  742. $className = $this->_getUserAgentDevice($browserType);
  743. // Attempt to match this device class
  744. if ($this->_match($className)) {
  745. $type = $browserType;
  746. $this->_browserTypeClass[$type] = $className;
  747. break;
  748. }
  749. }
  750. return $type;
  751. }
  752. /**
  753. * Creates device object instance
  754. *
  755. * @return void
  756. */
  757. protected function _createDevice()
  758. {
  759. $browserType = $this->getBrowserType();
  760. $classname = $this->_getUserAgentDevice($browserType);
  761. $this->_device = new $classname($this->getUserAgent(), $this->getServer(), $this->getConfig());
  762. }
  763. }