web/lib/Zend/Http/UserAgent.php
changeset 807 877f952ae2bd
parent 207 621fa6caec0c
child 1230 68c69c656a2c
equal deleted inserted replaced
805:5e7a0fedabdf 807:877f952ae2bd
    13  * to license@zend.com so we can send you a copy immediately.
    13  * to license@zend.com so we can send you a copy immediately.
    14  *
    14  *
    15  * @category   Zend
    15  * @category   Zend
    16  * @package    Zend_Http_UserAgent
    16  * @package    Zend_Http_UserAgent
    17  * @subpackage UserAgent
    17  * @subpackage UserAgent
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
    18  * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    20  */
    20  */
    21 
    21 
    22 /**
    22 /**
    23  * Lists of User Agent chains for testing :
    23  * Lists of User Agent chains for testing :
    29  * - http://www.mobilemultimedia.be/fr/
    29  * - http://www.mobilemultimedia.be/fr/
    30  *
    30  *
    31  * @category   Zend
    31  * @category   Zend
    32  * @package    Zend_Http_UserAgent
    32  * @package    Zend_Http_UserAgent
    33  * @subpackage UserAgent
    33  * @subpackage UserAgent
    34  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
    34  * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
    35  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    35  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    36  */
    36  */
    37 class Zend_Http_UserAgent implements Serializable
    37 class Zend_Http_UserAgent implements Serializable
    38 {
    38 {
    39     /**
    39     /**
    50      * 'desktop' by default if the sequence return false for each item
    50      * 'desktop' by default if the sequence return false for each item
    51      */
    51      */
    52     const DEFAULT_BROWSER_TYPE = 'desktop';
    52     const DEFAULT_BROWSER_TYPE = 'desktop';
    53 
    53 
    54     /**
    54     /**
    55      * Default User Agent chain to prevent empty value 
    55      * Default User Agent chain to prevent empty value
    56      */
    56      */
    57     const DEFAULT_HTTP_USER_AGENT = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)';
    57     const DEFAULT_HTTP_USER_AGENT = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)';
    58 
    58 
    59     /**
    59     /**
    60      * Default Http Accept param to prevent empty value 
    60      * Default Http Accept param to prevent empty value
    61      */
    61      */
    62     const DEFAULT_HTTP_ACCEPT = "application/xhtml+xml";
    62     const DEFAULT_HTTP_ACCEPT = "application/xhtml+xml";
    63 
    63 
    64     /**
    64     /**
    65      * Default markup language 
    65      * Default markup language
    66      */
    66      */
    67     const DEFAULT_MARKUP_LANGUAGE = "xhtml";
    67     const DEFAULT_MARKUP_LANGUAGE = "xhtml";
    68 
    68 
    69     /**
    69     /**
    70      * Browser type
    70      * Browser type
    83     protected $_browserTypeClass = array();
    83     protected $_browserTypeClass = array();
    84 
    84 
    85     /**
    85     /**
    86      * Array to store config
    86      * Array to store config
    87      *
    87      *
    88      * Default values are provided to ensure specific keys are present at 
    88      * Default values are provided to ensure specific keys are present at
    89      * instantiation.
    89      * instantiation.
    90      * 
    90      *
    91      * @var array
    91      * @var array
    92      */
    92      */
    93     protected $_config = array(
    93     protected $_config = array(
    94         'identification_sequence' => self::DEFAULT_IDENTIFICATION_SEQUENCE,
    94         'identification_sequence' => self::DEFAULT_IDENTIFICATION_SEQUENCE,
    95         'storage'                 => array(
    95         'storage'                 => array(
   111      * - $_server
   111      * - $_server
   112      * - $_browserType
   112      * - $_browserType
   113      * - User-Agent (defined in $_server)
   113      * - User-Agent (defined in $_server)
   114      * - HTTP Accept value (defined in $_server)
   114      * - HTTP Accept value (defined in $_server)
   115      * - $_storage
   115      * - $_storage
   116      * 
   116      *
   117      * @var bool
   117      * @var bool
   118      */
   118      */
   119     protected $_immutable = false;
   119     protected $_immutable = false;
   120 
   120 
   121     /**
   121     /**
   137      */
   137      */
   138     protected $_matchLog = array();
   138     protected $_matchLog = array();
   139 
   139 
   140     /**
   140     /**
   141      * Server variable
   141      * Server variable
   142      * 
   142      *
   143      * @var array
   143      * @var array
   144      */
   144      */
   145     protected $_server;
   145     protected $_server;
   146 
   146 
   147     /**
   147     /**
   151      */
   151      */
   152     protected $_storage;
   152     protected $_storage;
   153 
   153 
   154     /**
   154     /**
   155      * Constructor
   155      * Constructor
   156      * 
   156      *
   157      * @param  null|array|Zend_Config|ArrayAccess $options 
   157      * @param  null|array|Zend_Config|ArrayAccess $options
   158      * @return void
   158      * @return void
   159      */
   159      */
   160     public function __construct($options = null)
   160     public function __construct($options = null)
   161     {
   161     {
   162         if (null !== $options) {
   162         if (null !== $options) {
   164         }
   164         }
   165     }
   165     }
   166 
   166 
   167     /**
   167     /**
   168      * Serialized representation of the object
   168      * Serialized representation of the object
   169      * 
   169      *
   170      * @return string
   170      * @return string
   171      */
   171      */
   172     public function serialize()
   172     public function serialize()
   173     {
   173     {
       
   174         $device = $this->getDevice();
   174         $spec = array(
   175         $spec = array(
   175             'browser_type' => $this->_browserType,
   176             'browser_type' => $this->_browserType,
   176             'config'       => $this->_config,
   177             'config'       => $this->_config,
   177             'device_class' => get_class($this->_device),
   178             'device_class' => get_class($device),
   178             'device'       => $this->_device->serialize(),
   179             'device'       => $device->serialize(),
   179             'user_agent'   => $this->getServerValue('http_user_agent'),
   180             'user_agent'   => $this->getServerValue('http_user_agent'),
   180             'http_accept'  => $this->getServerValue('http_accept'),
   181             'http_accept'  => $this->getServerValue('http_accept'),
   181         );
   182         );
   182         return serialize($spec);
   183         return serialize($spec);
   183     }
   184     }
   184 
   185 
   185     /**
   186     /**
   186      * Unserialize a previous representation of the object
   187      * Unserialize a previous representation of the object
   187      * 
   188      *
   188      * @param  string $serialized
   189      * @param  string $serialized
   189      * @return void
   190      * @return void
   190      */
   191      */
   191     public function unserialize($serialized)
   192     public function unserialize($serialized)
   192     {
   193     {
   207         $this->_device = new $deviceClass($deviceSpec);
   208         $this->_device = new $deviceClass($deviceSpec);
   208     }
   209     }
   209 
   210 
   210     /**
   211     /**
   211      * Configure instance
   212      * Configure instance
   212      * 
   213      *
   213      * @param  array|Zend_Config|ArrayAccess $options 
   214      * @param  array|Zend_Config|ArrayAccess $options
   214      * @return Zend_Http_UserAgent
   215      * @return Zend_Http_UserAgent
   215      */
   216      */
   216     public function setOptions($options)
   217     public function setOptions($options)
   217     {
   218     {
   218         if ($options instanceof Zend_Config) {
   219         if ($options instanceof Zend_Config) {
   219             $options = $options->toArray();
   220             $options = $options->toArray();
   220         }
   221         }
   221 
   222 
   222         if (!is_array($options) 
   223         if (!is_array($options)
   223             && !$options instanceof ArrayAccess 
   224             && !$options instanceof ArrayAccess
   224             && !$options instanceof Traversable
   225             && !$options instanceof Traversable
   225         ) {
   226         ) {
   226             require_once 'Zend/Http/UserAgent/Exception.php';
   227             require_once 'Zend/Http/UserAgent/Exception.php';
   227             throw new Zend_Http_UserAgent_Exception(sprintf(
   228             throw new Zend_Http_UserAgent_Exception(sprintf(
   228                 'Invalid argument; expected array, Zend_Config object, or object implementing ArrayAccess and Traversable; received %s',
   229                 'Invalid argument; expected array, Zend_Config object, or object implementing ArrayAccess and Traversable; received %s',
   271         return $this;
   272         return $this;
   272     }
   273     }
   273 
   274 
   274     /**
   275     /**
   275      * Comparison of the UserAgent chain and browser signatures.
   276      * Comparison of the UserAgent chain and browser signatures.
   276      * 
   277      *
   277      * The comparison is case-insensitive : the browser signatures must be in lower
   278      * The comparison is case-insensitive : the browser signatures must be in lower
   278      * case
   279      * case
   279      *
   280      *
   280      * @param  string $deviceClass Name of class against which a match will be attempted
   281      * @param  string $deviceClass Name of class against which a match will be attempted
   281      * @return bool
   282      * @return bool
   293 
   294 
   294         $userAgent = $this->getUserAgent();
   295         $userAgent = $this->getUserAgent();
   295 
   296 
   296         // Call match method on device class
   297         // Call match method on device class
   297         return call_user_func(
   298         return call_user_func(
   298             array($deviceClass, 'match'), 
   299             array($deviceClass, 'match'),
   299             $userAgent, 
   300             $userAgent,
   300             $this->getServer()
   301             $this->getServer()
   301         );
   302         );
   302     }
   303     }
   303 
   304 
   304     /**
   305     /**
   313         $browserType = strtolower($browserType);
   314         $browserType = strtolower($browserType);
   314         if (isset($this->_browserTypeClass[$browserType])) {
   315         if (isset($this->_browserTypeClass[$browserType])) {
   315             return $this->_browserTypeClass[$browserType];
   316             return $this->_browserTypeClass[$browserType];
   316         }
   317         }
   317 
   318 
   318         if (isset($this->_config[$browserType]) 
   319         if (isset($this->_config[$browserType])
   319             && isset($this->_config[$browserType]['device'])
   320             && isset($this->_config[$browserType]['device'])
   320         ) {
   321         ) {
   321             $deviceConfig = $this->_config[$browserType]['device'];
   322             $deviceConfig = $this->_config[$browserType]['device'];
   322             if (is_array($deviceConfig) && isset($deviceConfig['classname'])) {
   323             if (is_array($deviceConfig) && isset($deviceConfig['classname'])) {
   323                 $device = (string) $deviceConfig['classname'];
   324                 $device = (string) $deviceConfig['classname'];
   408     }
   409     }
   409 
   410 
   410     /**
   411     /**
   411      * Returns the persistent storage handler
   412      * Returns the persistent storage handler
   412      *
   413      *
   413      * Session storage is used by default unless a different storage adapter 
   414      * Session storage is used by default unless a different storage adapter
   414      * has been set via the "persistent_storage_adapter" key. That key should 
   415      * has been set via the "persistent_storage_adapter" key. That key should
   415      * contain either a fully qualified class name, or a short name that 
   416      * contain either a fully qualified class name, or a short name that
   416      * resolves via the plugin loader.
   417      * resolves via the plugin loader.
   417      *
   418      *
   418      * @param  string $browser Browser identifier (User Agent chain)
   419      * @param  string $browser Browser identifier (User Agent chain)
   419      * @return Zend_Http_UserAgent_Storage
   420      * @return Zend_Http_UserAgent_Storage
   420      */
   421      */
   480         return $this->_config;
   481         return $this->_config;
   481     }
   482     }
   482 
   483 
   483     /**
   484     /**
   484      * Config parameters is an Array or a Zend_Config object
   485      * Config parameters is an Array or a Zend_Config object
   485      * 
   486      *
   486      * The allowed parameters are :
   487      * The allowed parameters are :
   487      * - the identification sequence (can be empty) => desktop browser type is the
   488      * - the identification sequence (can be empty) => desktop browser type is the
   488      * default browser type returned
   489      * default browser type returned
   489      * $config['identification_sequence'] : ',' separated browser types
   490      * $config['identification_sequence'] : ',' separated browser types
   490      * - the persistent storage adapter 
   491      * - the persistent storage adapter
   491      * $config['persistent_storage_adapter'] = "Session" or "NonPersistent"
   492      * $config['persistent_storage_adapter'] = "Session" or "NonPersistent"
   492      * - to add or replace a browser type device 
   493      * - to add or replace a browser type device
   493      * $config[(type)]['device']['path']
   494      * $config[(type)]['device']['path']
   494      * $config[(type)]['device']['classname']
   495      * $config[(type)]['device']['classname']
   495      * - to add or replace a browser type features adapter 
   496      * - to add or replace a browser type features adapter
   496      * $config[(type)]['features']['path']
   497      * $config[(type)]['features']['path']
   497      * $config[(type)]['features']['classname']
   498      * $config[(type)]['features']['classname']
   498      * 
   499      *
   499      * @param  mixed $config (option) Config array
   500      * @param  mixed $config (option) Config array
   500      * @return Zend_Http_UserAgent
   501      * @return Zend_Http_UserAgent
   501      */
   502      */
   502     public function setConfig($config = array())
   503     public function setConfig($config = array())
   503     {
   504     {
   504         if ($config instanceof Zend_Config) {
   505         if ($config instanceof Zend_Config) {
   505             $config = $config->toArray();
   506             $config = $config->toArray();
   506         }
   507         }
   507         
   508 
   508         // Verify that Config parameters are in an array.
   509         // Verify that Config parameters are in an array.
   509         if (!is_array($config) && !$config instanceof Traversable) {
   510         if (!is_array($config) && !$config instanceof Traversable) {
   510             require_once 'Zend/Http/UserAgent/Exception.php';
   511             require_once 'Zend/Http/UserAgent/Exception.php';
   511             throw new Zend_Http_UserAgent_Exception(sprintf(
   512             throw new Zend_Http_UserAgent_Exception(sprintf(
   512                 'Config parameters must be in an array or a Traversable object; received "%s"',
   513                 'Config parameters must be in an array or a Traversable object; received "%s"',
   526         $this->_config = array_merge($this->_config, $config);
   527         $this->_config = array_merge($this->_config, $config);
   527         return $this;
   528         return $this;
   528     }
   529     }
   529 
   530 
   530     /**
   531     /**
   531      * @return the $device
   532      * Returns the device object
       
   533      *
       
   534      * This is the object that will contain the various discovered device
       
   535      * capabilities.
       
   536      *
       
   537      * @return Zend_Http_UserAgent_Device $device
   532      */
   538      */
   533     public function getDevice()
   539     public function getDevice()
   534     {
   540     {
   535         if (null !== $this->_device) {
   541         if (null !== $this->_device) {
   536             return $this->_device;
   542             return $this->_device;
   538 
   544 
   539         $userAgent = $this->getUserAgent();
   545         $userAgent = $this->getUserAgent();
   540 
   546 
   541         // search an existing identification in the session
   547         // search an existing identification in the session
   542         $storage = $this->getStorage($userAgent);
   548         $storage = $this->getStorage($userAgent);
   543         
   549 
   544         if (!$storage->isEmpty()) {
   550         if (!$storage->isEmpty()) {
   545             // If the user agent and features are already existing, the 
   551             // If the user agent and features are already existing, the
   546             // Zend_Http_UserAgent object is serialized in the session
   552             // Zend_Http_UserAgent object is serialized in the session
   547             $object = $storage->read();
   553             $object = $storage->read();
   548             $this->unserialize($object);
   554             $this->unserialize($object);
   549         } else {
   555         } else {
   550             // Otherwise, the identification is made and stored in the session.
   556             // Otherwise, the identification is made and stored in the session.
   551             // Find the browser type:
   557             // Find the browser type:
   552             $this->setBrowserType($this->_matchUserAgent());
   558             $this->setBrowserType($this->_matchUserAgent());
   553             $this->_createDevice();
   559             $this->_createDevice();
   554             
   560 
   555             // put the result in storage:
   561             // put the result in storage:
   556             $this->getStorage($userAgent)
   562             $this->getStorage($userAgent)
   557                  ->write($this->serialize());
   563                  ->write($this->serialize());
   558         }
   564         }
   559 
   565 
   594     }
   600     }
   595 
   601 
   596     /**
   602     /**
   597      * Retrieve the "$_SERVER" array
   603      * Retrieve the "$_SERVER" array
   598      *
   604      *
   599      * Basically, the $_SERVER array or an equivalent container storing the 
   605      * Basically, the $_SERVER array or an equivalent container storing the
   600      * data that will be introspected.
   606      * data that will be introspected.
   601      *
   607      *
   602      * If the value has not been previously set, it sets itself from the 
   608      * If the value has not been previously set, it sets itself from the
   603      * $_SERVER superglobal.
   609      * $_SERVER superglobal.
   604      *
   610      *
   605      * @return array
   611      * @return array
   606      */
   612      */
   607     public function getServer()
   613     public function getServer()
   611         }
   617         }
   612         return $this->_server;
   618         return $this->_server;
   613     }
   619     }
   614 
   620 
   615     /**
   621     /**
   616      * Retrieve the "$_SERVER" array
   622      * Set the "$_SERVER" array
   617      *
   623      *
   618      * Basically, the $_SERVER array or an equivalent container storing the 
   624      * Basically, the $_SERVER array or an equivalent container storing the
   619      * data that will be introspected.
   625      * data that will be introspected.
   620      *
   626      *
   621      * @param  array|ArrayAccess $server
   627      * @param  array|ArrayAccess $server
   622      * @return void
   628      * @return void
   623      * @throws Zend_Http_UserAgent_Exception on invalid parameter
   629      * @throws Zend_Http_UserAgent_Exception on invalid parameter
   658         return $this;
   664         return $this;
   659     }
   665     }
   660 
   666 
   661     /**
   667     /**
   662      * Retrieve a server value
   668      * Retrieve a server value
   663      * 
   669      *
   664      * @param  string $key
   670      * @param  string $key
   665      * @return mixed
   671      * @return mixed
   666      */
   672      */
   667     public function getServerValue($key)
   673     public function getServerValue($key)
   668     {
   674     {
   698         return $this;
   704         return $this;
   699     }
   705     }
   700 
   706 
   701     /**
   707     /**
   702      * Set plugin loader
   708      * Set plugin loader
   703      * 
   709      *
   704      * @param  string $type Type of plugin loader; one of 'storage', (?)
   710      * @param  string $type Type of plugin loader; one of 'storage', (?)
   705      * @param  string|Zend_Loader_PluginLoader $loader 
   711      * @param  string|Zend_Loader_PluginLoader $loader
   706      * @return Zend_Http_UserAgent
   712      * @return Zend_Http_UserAgent
   707      */
   713      */
   708     public function setPluginLoader($type, $loader)
   714     public function setPluginLoader($type, $loader)
   709     {
   715     {
   710         $type       = $this->_validateLoaderType($type);
   716         $type       = $this->_validateLoaderType($type);
   747         return $this;
   753         return $this;
   748     }
   754     }
   749 
   755 
   750     /**
   756     /**
   751      * Get a plugin loader
   757      * Get a plugin loader
   752      * 
   758      *
   753      * @param  string $type A valid plugin loader type; see {@link $_loaderTypes}
   759      * @param  string $type A valid plugin loader type; see {@link $_loaderTypes}
   754      * @return Zend_Loader_PluginLoader
   760      * @return Zend_Loader_PluginLoader
   755      */
   761      */
   756     public function getPluginLoader($type)
   762     public function getPluginLoader($type)
   757     {
   763     {
   764     }
   770     }
   765 
   771 
   766     /**
   772     /**
   767      * Validate a plugin loader type
   773      * Validate a plugin loader type
   768      *
   774      *
   769      * Verifies that it is in {@link $_loaderTypes}, and returns a normalized 
   775      * Verifies that it is in {@link $_loaderTypes}, and returns a normalized
   770      * version of the type.
   776      * version of the type.
   771      * 
   777      *
   772      * @param  string $type 
   778      * @param  string $type
   773      * @return string
   779      * @return string
   774      * @throws Zend_Http_UserAgent_Exception on invalid type
   780      * @throws Zend_Http_UserAgent_Exception on invalid type
   775      */
   781      */
   776     protected function _validateLoaderType($type)
   782     protected function _validateLoaderType($type)
   777     {
   783     {