web/enmi/Zend/Gdata/App.php
changeset 19 1c2f13fd785c
parent 0 4eba9c11703f
equal deleted inserted replaced
18:bd595ad770fc 19:1c2f13fd785c
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * Zend Framework
       
     5  *
       
     6  * LICENSE
       
     7  *
       
     8  * This source file is subject to the new BSD license that is bundled
       
     9  * with this package in the file LICENSE.txt.
       
    10  * It is also available through the world-wide-web at this URL:
       
    11  * http://framework.zend.com/license/new-bsd
       
    12  * If you did not receive a copy of the license and are unable to
       
    13  * obtain it through the world-wide-web, please send an email
       
    14  * to license@zend.com so we can send you a copy immediately.
       
    15  *
       
    16  * @category   Zend
       
    17  * @package    Zend_Gdata
       
    18  * @subpackage App
       
    19  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    20  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    21  * @version    $Id: App.php 22972 2010-09-18 20:33:53Z ramon $
       
    22  */
       
    23 
       
    24 /**
       
    25  * Zend_Gdata_Feed
       
    26  */
       
    27 require_once 'Zend/Gdata/App/Feed.php';
       
    28 
       
    29 /**
       
    30  * Zend_Gdata_Http_Client
       
    31  */
       
    32 require_once 'Zend/Http/Client.php';
       
    33 
       
    34 /**
       
    35  * Zend_Version
       
    36  */
       
    37 require_once 'Zend/Version.php';
       
    38 
       
    39 /**
       
    40  * Zend_Gdata_App_MediaSource
       
    41  */
       
    42 require_once 'Zend/Gdata/App/MediaSource.php';
       
    43 
       
    44 /**
       
    45  * Provides Atom Publishing Protocol (APP) functionality.  This class and all
       
    46  * other components of Zend_Gdata_App are designed to work independently from
       
    47  * other Zend_Gdata components in order to interact with generic APP services.
       
    48  *
       
    49  * @category   Zend
       
    50  * @package    Zend_Gdata
       
    51  * @subpackage App
       
    52  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    53  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    54  */
       
    55 class Zend_Gdata_App
       
    56 {
       
    57 
       
    58     /** Default major protocol version.
       
    59       *
       
    60       * @see _majorProtocolVersion
       
    61       */
       
    62     const DEFAULT_MAJOR_PROTOCOL_VERSION = 1;
       
    63 
       
    64     /** Default minor protocol version.
       
    65       *
       
    66       * @see _minorProtocolVersion
       
    67       */
       
    68     const DEFAULT_MINOR_PROTOCOL_VERSION = null;
       
    69 
       
    70     /**
       
    71      * Client object used to communicate
       
    72      *
       
    73      * @var Zend_Http_Client
       
    74      */
       
    75     protected $_httpClient;
       
    76 
       
    77     /**
       
    78      * Client object used to communicate in static context
       
    79      *
       
    80      * @var Zend_Http_Client
       
    81      */
       
    82     protected static $_staticHttpClient = null;
       
    83 
       
    84     /**
       
    85      * Override HTTP PUT and DELETE request methods?
       
    86      *
       
    87      * @var boolean
       
    88      */
       
    89     protected static $_httpMethodOverride = false;
       
    90 
       
    91     /**
       
    92      * Enable gzipped responses?
       
    93      *
       
    94      * @var boolean
       
    95      */
       
    96     protected static $_gzipEnabled = false;
       
    97 
       
    98     /**
       
    99      * Use verbose exception messages.  In the case of HTTP errors,
       
   100      * use the body of the HTTP response in the exception message.
       
   101      *
       
   102      * @var boolean
       
   103      */
       
   104     protected static $_verboseExceptionMessages = true;
       
   105 
       
   106     /**
       
   107      * Default URI to which to POST.
       
   108      *
       
   109      * @var string
       
   110      */
       
   111     protected $_defaultPostUri = null;
       
   112 
       
   113     /**
       
   114      * Packages to search for classes when using magic __call method, in order.
       
   115      *
       
   116      * @var array
       
   117      */
       
   118     protected $_registeredPackages = array(
       
   119             'Zend_Gdata_App_Extension',
       
   120             'Zend_Gdata_App');
       
   121 
       
   122     /**
       
   123      * Maximum number of redirects to follow during HTTP operations
       
   124      *
       
   125      * @var int
       
   126      */
       
   127     protected static $_maxRedirects = 5;
       
   128 
       
   129     /**
       
   130       * Indicates the major protocol version that should be used.
       
   131       * At present, recognized values are either 1 or 2. However, any integer
       
   132       * value >= 1 is considered valid.
       
   133       *
       
   134       * Under most circumtances, this will be automatically set by
       
   135       * Zend_Gdata_App subclasses.
       
   136       *
       
   137       * @see setMajorProtocolVersion()
       
   138       * @see getMajorProtocolVersion()
       
   139       */
       
   140     protected $_majorProtocolVersion;
       
   141 
       
   142     /**
       
   143       * Indicates the minor protocol version that should be used. Can be set
       
   144       * to either an integer >= 0, or NULL if no minor version should be sent
       
   145       * to the server.
       
   146       *
       
   147       * At present, this field is not used by any Google services, but may be
       
   148       * used in the future.
       
   149       *
       
   150       * Under most circumtances, this will be automatically set by
       
   151       * Zend_Gdata_App subclasses.
       
   152       *
       
   153       * @see setMinorProtocolVersion()
       
   154       * @see getMinorProtocolVersion()
       
   155       */
       
   156     protected $_minorProtocolVersion;
       
   157 
       
   158     /**
       
   159      * Whether we want to use XML to object mapping when fetching data.
       
   160      *
       
   161      * @var boolean
       
   162      */
       
   163     protected $_useObjectMapping = true;
       
   164 
       
   165     /**
       
   166      * Create Gdata object
       
   167      *
       
   168      * @param Zend_Http_Client $client
       
   169      * @param string $applicationId
       
   170      */
       
   171     public function __construct($client = null, $applicationId = 'MyCompany-MyApp-1.0')
       
   172     {
       
   173         $this->setHttpClient($client, $applicationId);
       
   174         // Set default protocol version. Subclasses should override this as
       
   175         // needed once a given service supports a new version.
       
   176         $this->setMajorProtocolVersion(self::DEFAULT_MAJOR_PROTOCOL_VERSION);
       
   177         $this->setMinorProtocolVersion(self::DEFAULT_MINOR_PROTOCOL_VERSION);
       
   178     }
       
   179 
       
   180     /**
       
   181      * Adds a Zend Framework package to the $_registeredPackages array.
       
   182      * This array is searched when using the magic __call method below
       
   183      * to instantiante new objects.
       
   184      *
       
   185      * @param string $name The name of the package (eg Zend_Gdata_App)
       
   186      * @return void
       
   187      */
       
   188     public function registerPackage($name)
       
   189     {
       
   190         array_unshift($this->_registeredPackages, $name);
       
   191     }
       
   192 
       
   193     /**
       
   194      * Retrieve feed as string or object
       
   195      *
       
   196      * @param string $uri The uri from which to retrieve the feed
       
   197      * @param string $className The class which is used as the return type
       
   198      * @return string|Zend_Gdata_App_Feed Returns string only if the object
       
   199      *                                    mapping has been disabled explicitly
       
   200      *                                    by passing false to the
       
   201      *                                    useObjectMapping() function.
       
   202      */
       
   203     public function getFeed($uri, $className='Zend_Gdata_App_Feed')
       
   204     {
       
   205         return $this->importUrl($uri, $className, null);
       
   206     }
       
   207 
       
   208     /**
       
   209      * Retrieve entry as string or object
       
   210      *
       
   211      * @param string $uri
       
   212      * @param string $className The class which is used as the return type
       
   213      * @return string|Zend_Gdata_App_Entry Returns string only if the object
       
   214      *                                     mapping has been disabled explicitly
       
   215      *                                     by passing false to the
       
   216      *                                     useObjectMapping() function.
       
   217      */
       
   218     public function getEntry($uri, $className='Zend_Gdata_App_Entry')
       
   219     {
       
   220         return $this->importUrl($uri, $className, null);
       
   221     }
       
   222 
       
   223     /**
       
   224      * Get the Zend_Http_Client object used for communication
       
   225      *
       
   226      * @return Zend_Http_Client
       
   227      */
       
   228     public function getHttpClient()
       
   229     {
       
   230         return $this->_httpClient;
       
   231     }
       
   232 
       
   233     /**
       
   234      * Set the Zend_Http_Client object used for communication
       
   235      *
       
   236      * @param Zend_Http_Client $client The client to use for communication
       
   237      * @throws Zend_Gdata_App_HttpException
       
   238      * @return Zend_Gdata_App Provides a fluent interface
       
   239      */
       
   240     public function setHttpClient($client,
       
   241         $applicationId = 'MyCompany-MyApp-1.0')
       
   242     {
       
   243         if ($client === null) {
       
   244             $client = new Zend_Http_Client();
       
   245         }
       
   246         if (!$client instanceof Zend_Http_Client) {
       
   247             require_once 'Zend/Gdata/App/HttpException.php';
       
   248             throw new Zend_Gdata_App_HttpException(
       
   249                 'Argument is not an instance of Zend_Http_Client.');
       
   250         }
       
   251         $userAgent = $applicationId . ' Zend_Framework_Gdata/' .
       
   252             Zend_Version::VERSION;
       
   253         $client->setHeaders('User-Agent', $userAgent);
       
   254         $client->setConfig(array(
       
   255             'strictredirects' => true
       
   256             )
       
   257         );
       
   258         $this->_httpClient = $client;
       
   259         self::setStaticHttpClient($client);
       
   260         return $this;
       
   261     }
       
   262 
       
   263     /**
       
   264      * Set the static HTTP client instance
       
   265      *
       
   266      * Sets the static HTTP client object to use for retrieving the feed.
       
   267      *
       
   268      * @param  Zend_Http_Client $httpClient
       
   269      * @return void
       
   270      */
       
   271     public static function setStaticHttpClient(Zend_Http_Client $httpClient)
       
   272     {
       
   273         self::$_staticHttpClient = $httpClient;
       
   274     }
       
   275 
       
   276 
       
   277     /**
       
   278      * Gets the HTTP client object. If none is set, a new Zend_Http_Client will be used.
       
   279      *
       
   280      * @return Zend_Http_Client
       
   281      */
       
   282     public static function getStaticHttpClient()
       
   283     {
       
   284         if (!self::$_staticHttpClient instanceof Zend_Http_Client) {
       
   285             $client = new Zend_Http_Client();
       
   286             $userAgent = 'Zend_Framework_Gdata/' . Zend_Version::VERSION;
       
   287             $client->setHeaders('User-Agent', $userAgent);
       
   288             $client->setConfig(array(
       
   289                 'strictredirects' => true
       
   290                 )
       
   291             );
       
   292             self::$_staticHttpClient = $client;
       
   293         }
       
   294         return self::$_staticHttpClient;
       
   295     }
       
   296 
       
   297     /**
       
   298      * Toggle using POST instead of PUT and DELETE HTTP methods
       
   299      *
       
   300      * Some feed implementations do not accept PUT and DELETE HTTP
       
   301      * methods, or they can't be used because of proxies or other
       
   302      * measures. This allows turning on using POST where PUT and
       
   303      * DELETE would normally be used; in addition, an
       
   304      * X-Method-Override header will be sent with a value of PUT or
       
   305      * DELETE as appropriate.
       
   306      *
       
   307      * @param  boolean $override Whether to override PUT and DELETE with POST.
       
   308      * @return void
       
   309      */
       
   310     public static function setHttpMethodOverride($override = true)
       
   311     {
       
   312         self::$_httpMethodOverride = $override;
       
   313     }
       
   314 
       
   315     /**
       
   316      * Get the HTTP override state
       
   317      *
       
   318      * @return boolean
       
   319      */
       
   320     public static function getHttpMethodOverride()
       
   321     {
       
   322         return self::$_httpMethodOverride;
       
   323     }
       
   324 
       
   325     /**
       
   326      * Toggle requesting gzip encoded responses
       
   327      *
       
   328      * @param  boolean $enabled Whether or not to enable gzipped responses
       
   329      * @return void
       
   330      */
       
   331     public static function setGzipEnabled($enabled = false)
       
   332     {
       
   333         if ($enabled && !function_exists('gzinflate')) {
       
   334             require_once 'Zend/Gdata/App/InvalidArgumentException.php';
       
   335             throw new Zend_Gdata_App_InvalidArgumentException(
       
   336                     'You cannot enable gzipped responses if the zlib module ' .
       
   337                     'is not enabled in your PHP installation.');
       
   338 
       
   339         }
       
   340         self::$_gzipEnabled = $enabled;
       
   341     }
       
   342 
       
   343     /**
       
   344      * Get the HTTP override state
       
   345      *
       
   346      * @return boolean
       
   347      */
       
   348     public static function getGzipEnabled()
       
   349     {
       
   350         return self::$_gzipEnabled;
       
   351     }
       
   352 
       
   353     /**
       
   354      * Get whether to use verbose exception messages
       
   355      *
       
   356      * In the case of HTTP errors,  use the body of the HTTP response
       
   357      * in the exception message.
       
   358      *
       
   359      * @return boolean
       
   360      */
       
   361     public static function getVerboseExceptionMessages()
       
   362     {
       
   363         return self::$_verboseExceptionMessages;
       
   364     }
       
   365 
       
   366     /**
       
   367      * Set whether to use verbose exception messages
       
   368      *
       
   369      * In the case of HTTP errors, use the body of the HTTP response
       
   370      * in the exception message.
       
   371      *
       
   372      * @param boolean $verbose Whether to use verbose exception messages
       
   373      */
       
   374     public static function setVerboseExceptionMessages($verbose)
       
   375     {
       
   376         self::$_verboseExceptionMessages = $verbose;
       
   377     }
       
   378 
       
   379     /**
       
   380      * Set the maximum number of redirects to follow during HTTP operations
       
   381      *
       
   382      * @param int $maxRedirects Maximum number of redirects to follow
       
   383      * @return void
       
   384      */
       
   385     public static function setMaxRedirects($maxRedirects)
       
   386     {
       
   387         self::$_maxRedirects = $maxRedirects;
       
   388     }
       
   389 
       
   390     /**
       
   391      * Get the maximum number of redirects to follow during HTTP operations
       
   392      *
       
   393      * @return int Maximum number of redirects to follow
       
   394      */
       
   395     public static function getMaxRedirects()
       
   396     {
       
   397         return self::$_maxRedirects;
       
   398     }
       
   399 
       
   400     /**
       
   401      * Set the major protocol version that should be used. Values < 1 will
       
   402      * cause a Zend_Gdata_App_InvalidArgumentException to be thrown.
       
   403      *
       
   404      * @see _majorProtocolVersion
       
   405      * @param int $value The major protocol version to use.
       
   406      * @throws Zend_Gdata_App_InvalidArgumentException
       
   407      */
       
   408     public function setMajorProtocolVersion($value)
       
   409     {
       
   410         if (!($value >= 1)) {
       
   411             require_once('Zend/Gdata/App/InvalidArgumentException.php');
       
   412             throw new Zend_Gdata_App_InvalidArgumentException(
       
   413                     'Major protocol version must be >= 1');
       
   414         }
       
   415         $this->_majorProtocolVersion = $value;
       
   416     }
       
   417 
       
   418     /**
       
   419      * Get the major protocol version that is in use.
       
   420      *
       
   421      * @see _majorProtocolVersion
       
   422      * @return int The major protocol version in use.
       
   423      */
       
   424     public function getMajorProtocolVersion()
       
   425     {
       
   426         return $this->_majorProtocolVersion;
       
   427     }
       
   428 
       
   429     /**
       
   430      * Set the minor protocol version that should be used. If set to NULL, no
       
   431      * minor protocol version will be sent to the server. Values < 0 will
       
   432      * cause a Zend_Gdata_App_InvalidArgumentException to be thrown.
       
   433      *
       
   434      * @see _minorProtocolVersion
       
   435      * @param (int|NULL) $value The minor protocol version to use.
       
   436      * @throws Zend_Gdata_App_InvalidArgumentException
       
   437      */
       
   438     public function setMinorProtocolVersion($value)
       
   439     {
       
   440         if (!($value >= 0)) {
       
   441             require_once('Zend/Gdata/App/InvalidArgumentException.php');
       
   442             throw new Zend_Gdata_App_InvalidArgumentException(
       
   443                     'Minor protocol version must be >= 0');
       
   444         }
       
   445         $this->_minorProtocolVersion = $value;
       
   446     }
       
   447 
       
   448     /**
       
   449      * Get the minor protocol version that is in use.
       
   450      *
       
   451      * @see _minorProtocolVersion
       
   452      * @return (int|NULL) The major protocol version in use, or NULL if no
       
   453      *         minor version is specified.
       
   454      */
       
   455     public function getMinorProtocolVersion()
       
   456     {
       
   457         return $this->_minorProtocolVersion;
       
   458     }
       
   459 
       
   460     /**
       
   461      * Provides pre-processing for HTTP requests to APP services.
       
   462      *
       
   463      * 1. Checks the $data element and, if it's an entry, extracts the XML,
       
   464      *    multipart data, edit link (PUT,DELETE), etc.
       
   465      * 2. If $data is a string, sets the default content-type  header as
       
   466      *    'application/atom+xml' if it's not already been set.
       
   467      * 3. Adds a x-http-method override header and changes the HTTP method
       
   468      *    to 'POST' if necessary as per getHttpMethodOverride()
       
   469      *
       
   470      * @param string $method The HTTP method for the request - 'GET', 'POST',
       
   471      *                       'PUT', 'DELETE'
       
   472      * @param string $url The URL to which this request is being performed,
       
   473      *                    or null if found in $data
       
   474      * @param array $headers An associative array of HTTP headers for this
       
   475      *                       request
       
   476      * @param mixed $data The Zend_Gdata_App_Entry or XML for the
       
   477      *                    body of the request
       
   478      * @param string $contentTypeOverride The override value for the
       
   479      *                                    content type of the request body
       
   480      * @return array An associative array containing the determined
       
   481      *               'method', 'url', 'data', 'headers', 'contentType'
       
   482      */
       
   483     public function prepareRequest($method,
       
   484                                    $url = null,
       
   485                                    $headers = array(),
       
   486                                    $data = null,
       
   487                                    $contentTypeOverride = null)
       
   488     {
       
   489         // As a convenience, if $headers is null, we'll convert it back to
       
   490         // an empty array.
       
   491         if ($headers === null) {
       
   492             $headers = array();
       
   493         }
       
   494 
       
   495         $rawData = null;
       
   496         $finalContentType = null;
       
   497         if ($url == null) {
       
   498             $url = $this->_defaultPostUri;
       
   499         }
       
   500 
       
   501         if (is_string($data)) {
       
   502             $rawData = $data;
       
   503             if ($contentTypeOverride === null) {
       
   504                 $finalContentType = 'application/atom+xml';
       
   505             }
       
   506         } elseif ($data instanceof Zend_Gdata_App_MediaEntry) {
       
   507             $rawData = $data->encode();
       
   508             if ($data->getMediaSource() !== null) {
       
   509                 $finalContentType = $rawData->getContentType();
       
   510                 $headers['MIME-version'] = '1.0';
       
   511                 $headers['Slug'] = $data->getMediaSource()->getSlug();
       
   512             } else {
       
   513                 $finalContentType = 'application/atom+xml';
       
   514             }
       
   515             if ($method == 'PUT' || $method == 'DELETE') {
       
   516                 $editLink = $data->getEditLink();
       
   517                 if ($editLink != null && $url == null) {
       
   518                     $url = $editLink->getHref();
       
   519                 }
       
   520             }
       
   521         } elseif ($data instanceof Zend_Gdata_App_Entry) {
       
   522             $rawData = $data->saveXML();
       
   523             $finalContentType = 'application/atom+xml';
       
   524             if ($method == 'PUT' || $method == 'DELETE') {
       
   525                 $editLink = $data->getEditLink();
       
   526                 if ($editLink != null) {
       
   527                     $url = $editLink->getHref();
       
   528                 }
       
   529             }
       
   530         } elseif ($data instanceof Zend_Gdata_App_MediaSource) {
       
   531             $rawData = $data->encode();
       
   532             if ($data->getSlug() !== null) {
       
   533                 $headers['Slug'] = $data->getSlug();
       
   534             }
       
   535             $finalContentType = $data->getContentType();
       
   536         }
       
   537 
       
   538         if ($method == 'DELETE') {
       
   539             $rawData = null;
       
   540         }
       
   541 
       
   542         // Set an If-Match header if:
       
   543         //   - This isn't a DELETE
       
   544         //   - If this isn't a GET, the Etag isn't weak
       
   545         //   - A similar header (If-Match/If-None-Match) hasn't already been
       
   546         //     set.
       
   547         if ($method != 'DELETE' && (
       
   548                 !array_key_exists('If-Match', $headers) &&
       
   549                 !array_key_exists('If-None-Match', $headers)
       
   550                 ) ) {
       
   551             $allowWeak = $method == 'GET';
       
   552             if ($ifMatchHeader = $this->generateIfMatchHeaderData(
       
   553                     $data, $allowWeak)) {
       
   554                 $headers['If-Match'] = $ifMatchHeader;
       
   555             }
       
   556         }
       
   557 
       
   558         if ($method != 'POST' && $method != 'GET' && Zend_Gdata_App::getHttpMethodOverride()) {
       
   559             $headers['x-http-method-override'] = $method;
       
   560             $method = 'POST';
       
   561         } else {
       
   562             $headers['x-http-method-override'] = null;
       
   563         }
       
   564 
       
   565         if ($contentTypeOverride != null) {
       
   566             $finalContentType = $contentTypeOverride;
       
   567         }
       
   568 
       
   569         return array('method' => $method, 'url' => $url,
       
   570             'data' => $rawData, 'headers' => $headers,
       
   571             'contentType' => $finalContentType);
       
   572     }
       
   573 
       
   574     /**
       
   575      * Performs a HTTP request using the specified method
       
   576      *
       
   577      * @param string $method The HTTP method for the request - 'GET', 'POST',
       
   578      *                       'PUT', 'DELETE'
       
   579      * @param string $url The URL to which this request is being performed
       
   580      * @param array $headers An associative array of HTTP headers
       
   581      *                       for this request
       
   582      * @param string $body The body of the HTTP request
       
   583      * @param string $contentType The value for the content type
       
   584      *                                of the request body
       
   585      * @param int $remainingRedirects Number of redirects to follow if request
       
   586      *                              s results in one
       
   587      * @return Zend_Http_Response The response object
       
   588      */
       
   589     public function performHttpRequest($method, $url, $headers = null,
       
   590         $body = null, $contentType = null, $remainingRedirects = null)
       
   591     {
       
   592         require_once 'Zend/Http/Client/Exception.php';
       
   593         if ($remainingRedirects === null) {
       
   594             $remainingRedirects = self::getMaxRedirects();
       
   595         }
       
   596         if ($headers === null) {
       
   597             $headers = array();
       
   598         }
       
   599         // Append a Gdata version header if protocol v2 or higher is in use.
       
   600         // (Protocol v1 does not use this header.)
       
   601         $major = $this->getMajorProtocolVersion();
       
   602         $minor = $this->getMinorProtocolVersion();
       
   603         if ($major >= 2) {
       
   604             $headers['GData-Version'] = $major +
       
   605                     (($minor === null) ? '.' + $minor : '');
       
   606         }
       
   607 
       
   608         // check the overridden method
       
   609         if (($method == 'POST' || $method == 'PUT') && $body === null &&
       
   610             $headers['x-http-method-override'] != 'DELETE') {
       
   611                 require_once 'Zend/Gdata/App/InvalidArgumentException.php';
       
   612                 throw new Zend_Gdata_App_InvalidArgumentException(
       
   613                         'You must specify the data to post as either a ' .
       
   614                         'string or a child of Zend_Gdata_App_Entry');
       
   615         }
       
   616         if ($url === null) {
       
   617             require_once 'Zend/Gdata/App/InvalidArgumentException.php';
       
   618             throw new Zend_Gdata_App_InvalidArgumentException(
       
   619                 'You must specify an URI to which to post.');
       
   620         }
       
   621         $headers['Content-Type'] = $contentType;
       
   622         if (Zend_Gdata_App::getGzipEnabled()) {
       
   623             // some services require the word 'gzip' to be in the user-agent
       
   624             // header in addition to the accept-encoding header
       
   625             if (strpos($this->_httpClient->getHeader('User-Agent'),
       
   626                 'gzip') === false) {
       
   627                 $headers['User-Agent'] =
       
   628                     $this->_httpClient->getHeader('User-Agent') . ' (gzip)';
       
   629             }
       
   630             $headers['Accept-encoding'] = 'gzip, deflate';
       
   631         } else {
       
   632             $headers['Accept-encoding'] = 'identity';
       
   633         }
       
   634 
       
   635         // Make sure the HTTP client object is 'clean' before making a request
       
   636         // In addition to standard headers to reset via resetParameters(),
       
   637         // also reset the Slug and If-Match headers
       
   638         $this->_httpClient->resetParameters();
       
   639         $this->_httpClient->setHeaders(array('Slug', 'If-Match'));
       
   640 
       
   641         // Set the params for the new request to be performed
       
   642         $this->_httpClient->setHeaders($headers);
       
   643         require_once 'Zend/Uri/Http.php';
       
   644         $uri = Zend_Uri_Http::fromString($url);
       
   645         preg_match("/^(.*?)(\?.*)?$/", $url, $matches);
       
   646         $this->_httpClient->setUri($matches[1]);
       
   647         $queryArray = $uri->getQueryAsArray();
       
   648         foreach ($queryArray as $name => $value) {
       
   649             $this->_httpClient->setParameterGet($name, $value);
       
   650         }
       
   651 
       
   652 
       
   653         $this->_httpClient->setConfig(array('maxredirects' => 0));
       
   654 
       
   655         // Set the proper adapter if we are handling a streaming upload
       
   656         $usingMimeStream = false;
       
   657         $oldHttpAdapter = null;
       
   658 
       
   659         if ($body instanceof Zend_Gdata_MediaMimeStream) {
       
   660             $usingMimeStream = true;
       
   661             $this->_httpClient->setRawDataStream($body, $contentType);
       
   662             $oldHttpAdapter = $this->_httpClient->getAdapter();
       
   663 
       
   664             if ($oldHttpAdapter instanceof Zend_Http_Client_Adapter_Proxy) {
       
   665                 require_once 'Zend/Gdata/HttpAdapterStreamingProxy.php';
       
   666                 $newAdapter = new Zend_Gdata_HttpAdapterStreamingProxy();
       
   667             } else {
       
   668                 require_once 'Zend/Gdata/HttpAdapterStreamingSocket.php';
       
   669                 $newAdapter = new Zend_Gdata_HttpAdapterStreamingSocket();
       
   670             }
       
   671             $this->_httpClient->setAdapter($newAdapter);
       
   672         } else {
       
   673             $this->_httpClient->setRawData($body, $contentType);
       
   674         }
       
   675 
       
   676         try {
       
   677             $response = $this->_httpClient->request($method);
       
   678             // reset adapter
       
   679             if ($usingMimeStream) {
       
   680                 $this->_httpClient->setAdapter($oldHttpAdapter);
       
   681             }
       
   682         } catch (Zend_Http_Client_Exception $e) {
       
   683             // reset adapter
       
   684             if ($usingMimeStream) {
       
   685                 $this->_httpClient->setAdapter($oldHttpAdapter);
       
   686             }
       
   687             require_once 'Zend/Gdata/App/HttpException.php';
       
   688             throw new Zend_Gdata_App_HttpException($e->getMessage(), $e);
       
   689         }
       
   690         if ($response->isRedirect() && $response->getStatus() != '304') {
       
   691             if ($remainingRedirects > 0) {
       
   692                 $newUrl = $response->getHeader('Location');
       
   693                 $response = $this->performHttpRequest(
       
   694                     $method, $newUrl, $headers, $body,
       
   695                     $contentType, $remainingRedirects);
       
   696             } else {
       
   697                 require_once 'Zend/Gdata/App/HttpException.php';
       
   698                 throw new Zend_Gdata_App_HttpException(
       
   699                         'Number of redirects exceeds maximum', null, $response);
       
   700             }
       
   701         }
       
   702         if (!$response->isSuccessful()) {
       
   703             require_once 'Zend/Gdata/App/HttpException.php';
       
   704             $exceptionMessage = 'Expected response code 200, got ' .
       
   705                 $response->getStatus();
       
   706             if (self::getVerboseExceptionMessages()) {
       
   707                 $exceptionMessage .= "\n" . $response->getBody();
       
   708             }
       
   709             $exception = new Zend_Gdata_App_HttpException($exceptionMessage);
       
   710             $exception->setResponse($response);
       
   711             throw $exception;
       
   712         }
       
   713         return $response;
       
   714     }
       
   715 
       
   716     /**
       
   717      * Imports a feed located at $uri.
       
   718      *
       
   719      * @param  string $uri
       
   720      * @param  Zend_Http_Client $client The client used for communication
       
   721      * @param  string $className The class which is used as the return type
       
   722      * @throws Zend_Gdata_App_Exception
       
   723      * @return string|Zend_Gdata_App_Feed Returns string only if the object
       
   724      *                                    mapping has been disabled explicitly
       
   725      *                                    by passing false to the
       
   726      *                                    useObjectMapping() function.
       
   727      */
       
   728     public static function import($uri, $client = null,
       
   729         $className='Zend_Gdata_App_Feed')
       
   730     {
       
   731         $app = new Zend_Gdata_App($client);
       
   732         $requestData = $app->prepareRequest('GET', $uri);
       
   733         $response = $app->performHttpRequest(
       
   734             $requestData['method'], $requestData['url']);
       
   735 
       
   736         $feedContent = $response->getBody();
       
   737         if (!$this->_useObjectMapping) {
       
   738             return $feedContent;
       
   739         }
       
   740         $feed = self::importString($feedContent, $className);
       
   741         if ($client != null) {
       
   742             $feed->setHttpClient($client);
       
   743         }
       
   744         return $feed;
       
   745     }
       
   746 
       
   747     /**
       
   748      * Imports the specified URL (non-statically).
       
   749      *
       
   750      * @param  string $url The URL to import
       
   751      * @param  string $className The class which is used as the return type
       
   752      * @param array $extraHeaders Extra headers to add to the request, as an
       
   753      *        array of string-based key/value pairs.
       
   754      * @throws Zend_Gdata_App_Exception
       
   755      * @return string|Zend_Gdata_App_Feed Returns string only if the object
       
   756      *                                    mapping has been disabled explicitly
       
   757      *                                    by passing false to the
       
   758      *                                    useObjectMapping() function.
       
   759      */
       
   760     public function importUrl($url, $className='Zend_Gdata_App_Feed',
       
   761         $extraHeaders = array())
       
   762     {
       
   763         $response = $this->get($url, $extraHeaders);
       
   764 
       
   765         $feedContent = $response->getBody();
       
   766         if (!$this->_useObjectMapping) {
       
   767             return $feedContent;
       
   768         }
       
   769 
       
   770         $protocolVersionStr = $response->getHeader('GData-Version');
       
   771         $majorProtocolVersion = null;
       
   772         $minorProtocolVersion = null;
       
   773         if ($protocolVersionStr !== null) {
       
   774             // Extract protocol major and minor version from header
       
   775             $delimiterPos = strpos($protocolVersionStr, '.');
       
   776             $length = strlen($protocolVersionStr);
       
   777             $major = substr($protocolVersionStr, 0, $delimiterPos);
       
   778             $minor = substr($protocolVersionStr, $delimiterPos + 1, $length);
       
   779             $majorProtocolVersion = $major;
       
   780             $minorProtocolVersion = $minor;
       
   781         }
       
   782 
       
   783         $feed = self::importString($feedContent, $className,
       
   784             $majorProtocolVersion, $minorProtocolVersion);
       
   785         if ($this->getHttpClient() != null) {
       
   786             $feed->setHttpClient($this->getHttpClient());
       
   787         }
       
   788         $etag = $response->getHeader('ETag');
       
   789         if ($etag !== null) {
       
   790             $feed->setEtag($etag);
       
   791         }
       
   792         return $feed;
       
   793     }
       
   794 
       
   795 
       
   796     /**
       
   797      * Imports a feed represented by $string.
       
   798      *
       
   799      * @param string $string
       
   800      * @param string $className The class which is used as the return type
       
   801      * @param integer $majorProcolVersion (optional) The major protocol version
       
   802      *        of the data model object that is to be created.
       
   803      * @param integer $minorProcolVersion (optional) The minor protocol version
       
   804      *        of the data model object that is to be created.
       
   805      * @throws Zend_Gdata_App_Exception
       
   806      * @return Zend_Gdata_App_Feed
       
   807      */
       
   808     public static function importString($string,
       
   809         $className='Zend_Gdata_App_Feed', $majorProtocolVersion = null,
       
   810         $minorProtocolVersion = null)
       
   811     {
       
   812         if (!class_exists($className, false)) {
       
   813           require_once 'Zend/Loader.php';
       
   814           @Zend_Loader::loadClass($className);
       
   815         }
       
   816 
       
   817         // Load the feed as an XML DOMDocument object
       
   818         @ini_set('track_errors', 1);
       
   819         $doc = new DOMDocument();
       
   820         $success = @$doc->loadXML($string);
       
   821         @ini_restore('track_errors');
       
   822 
       
   823         if (!$success) {
       
   824             require_once 'Zend/Gdata/App/Exception.php';
       
   825             throw new Zend_Gdata_App_Exception(
       
   826                 "DOMDocument cannot parse XML: $php_errormsg");
       
   827         }
       
   828 
       
   829         $feed = new $className();
       
   830         $feed->setMajorProtocolVersion($majorProtocolVersion);
       
   831         $feed->setMinorProtocolVersion($minorProtocolVersion);
       
   832         $feed->transferFromXML($string);
       
   833         $feed->setHttpClient(self::getstaticHttpClient());
       
   834         return $feed;
       
   835     }
       
   836 
       
   837 
       
   838     /**
       
   839      * Imports a feed from a file located at $filename.
       
   840      *
       
   841      * @param  string $filename
       
   842      * @param  string $className The class which is used as the return type
       
   843      * @param  string $useIncludePath Whether the include_path should be searched
       
   844      * @throws Zend_Gdata_App_Exception
       
   845      * @return Zend_Gdata_App_Feed
       
   846      */
       
   847     public static function importFile($filename,
       
   848             $className='Zend_Gdata_App_Feed', $useIncludePath = false)
       
   849     {
       
   850         @ini_set('track_errors', 1);
       
   851         $feed = @file_get_contents($filename, $useIncludePath);
       
   852         @ini_restore('track_errors');
       
   853         if ($feed === false) {
       
   854             require_once 'Zend/Gdata/App/Exception.php';
       
   855             throw new Zend_Gdata_App_Exception(
       
   856                 "File could not be loaded: $php_errormsg");
       
   857         }
       
   858         return self::importString($feed, $className);
       
   859     }
       
   860 
       
   861     /**
       
   862      * GET a URI using client object.
       
   863      *
       
   864      * @param string $uri GET URI
       
   865      * @param array $extraHeaders Extra headers to add to the request, as an
       
   866      *        array of string-based key/value pairs.
       
   867      * @throws Zend_Gdata_App_HttpException
       
   868      * @return Zend_Http_Response
       
   869      */
       
   870     public function get($uri, $extraHeaders = array())
       
   871     {
       
   872         $requestData = $this->prepareRequest('GET', $uri, $extraHeaders);
       
   873         return $this->performHttpRequest(
       
   874             $requestData['method'], $requestData['url'],
       
   875             $requestData['headers']);
       
   876     }
       
   877 
       
   878     /**
       
   879      * POST data with client object
       
   880      *
       
   881      * @param mixed $data The Zend_Gdata_App_Entry or XML to post
       
   882      * @param string $uri POST URI
       
   883      * @param array $headers Additional HTTP headers to insert.
       
   884      * @param string $contentType Content-type of the data
       
   885      * @param array $extraHeaders Extra headers to add to the request, as an
       
   886      *        array of string-based key/value pairs.
       
   887      * @return Zend_Http_Response
       
   888      * @throws Zend_Gdata_App_Exception
       
   889      * @throws Zend_Gdata_App_HttpException
       
   890      * @throws Zend_Gdata_App_InvalidArgumentException
       
   891      */
       
   892     public function post($data, $uri = null, $remainingRedirects = null,
       
   893             $contentType = null, $extraHeaders = null)
       
   894     {
       
   895         $requestData = $this->prepareRequest(
       
   896             'POST', $uri, $extraHeaders, $data, $contentType);
       
   897         return $this->performHttpRequest(
       
   898                 $requestData['method'], $requestData['url'],
       
   899                 $requestData['headers'], $requestData['data'],
       
   900                 $requestData['contentType']);
       
   901     }
       
   902 
       
   903     /**
       
   904      * PUT data with client object
       
   905      *
       
   906      * @param mixed $data The Zend_Gdata_App_Entry or XML to post
       
   907      * @param string $uri PUT URI
       
   908      * @param array $headers Additional HTTP headers to insert.
       
   909      * @param string $contentType Content-type of the data
       
   910      * @param array $extraHeaders Extra headers to add to the request, as an
       
   911      *        array of string-based key/value pairs.
       
   912      * @return Zend_Http_Response
       
   913      * @throws Zend_Gdata_App_Exception
       
   914      * @throws Zend_Gdata_App_HttpException
       
   915      * @throws Zend_Gdata_App_InvalidArgumentException
       
   916      */
       
   917     public function put($data, $uri = null, $remainingRedirects = null,
       
   918             $contentType = null, $extraHeaders = null)
       
   919     {
       
   920         $requestData = $this->prepareRequest(
       
   921             'PUT', $uri, $extraHeaders, $data, $contentType);
       
   922         return $this->performHttpRequest(
       
   923                 $requestData['method'], $requestData['url'],
       
   924                 $requestData['headers'], $requestData['data'],
       
   925                 $requestData['contentType']);
       
   926     }
       
   927 
       
   928     /**
       
   929      * DELETE entry with client object
       
   930      *
       
   931      * @param mixed $data The Zend_Gdata_App_Entry or URL to delete
       
   932      * @return void
       
   933      * @throws Zend_Gdata_App_Exception
       
   934      * @throws Zend_Gdata_App_HttpException
       
   935      * @throws Zend_Gdata_App_InvalidArgumentException
       
   936      */
       
   937     public function delete($data, $remainingRedirects = null)
       
   938     {
       
   939         if (is_string($data)) {
       
   940             $requestData = $this->prepareRequest('DELETE', $data);
       
   941         } else {
       
   942             $headers = array();
       
   943 
       
   944             $requestData = $this->prepareRequest(
       
   945                 'DELETE', null, $headers, $data);
       
   946         }
       
   947         return $this->performHttpRequest($requestData['method'],
       
   948                                          $requestData['url'],
       
   949                                          $requestData['headers'],
       
   950                                          '',
       
   951                                          $requestData['contentType'],
       
   952                                          $remainingRedirects);
       
   953     }
       
   954 
       
   955     /**
       
   956      * Inserts an entry to a given URI and returns the response as a
       
   957      * fully formed Entry.
       
   958      *
       
   959      * @param mixed  $data The Zend_Gdata_App_Entry or XML to post
       
   960      * @param string $uri POST URI
       
   961      * @param string $className The class of entry to be returned.
       
   962      * @param array $extraHeaders Extra headers to add to the request, as an
       
   963      *        array of string-based key/value pairs.
       
   964      * @return Zend_Gdata_App_Entry The entry returned by the service after
       
   965      *         insertion.
       
   966      */
       
   967     public function insertEntry($data, $uri, $className='Zend_Gdata_App_Entry',
       
   968         $extraHeaders = array())
       
   969     {
       
   970         if (!class_exists($className, false)) {
       
   971           require_once 'Zend/Loader.php';
       
   972           @Zend_Loader::loadClass($className);
       
   973         }
       
   974 
       
   975         $response = $this->post($data, $uri, null, null, $extraHeaders);
       
   976 
       
   977         $returnEntry = new $className($response->getBody());
       
   978         $returnEntry->setHttpClient(self::getstaticHttpClient());
       
   979 
       
   980         $etag = $response->getHeader('ETag');
       
   981         if ($etag !== null) {
       
   982             $returnEntry->setEtag($etag);
       
   983         }
       
   984 
       
   985         return $returnEntry;
       
   986     }
       
   987 
       
   988     /**
       
   989      * Update an entry
       
   990      *
       
   991      * @param mixed $data Zend_Gdata_App_Entry or XML (w/ID and link rel='edit')
       
   992      * @param string|null The URI to send requests to, or null if $data
       
   993      *        contains the URI.
       
   994      * @param string|null The name of the class that should be deserialized
       
   995      *        from the server response. If null, then 'Zend_Gdata_App_Entry'
       
   996      *        will be used.
       
   997      * @param array $extraHeaders Extra headers to add to the request, as an
       
   998      *        array of string-based key/value pairs.
       
   999      * @return Zend_Gdata_App_Entry The entry returned from the server
       
  1000      * @throws Zend_Gdata_App_Exception
       
  1001      */
       
  1002     public function updateEntry($data, $uri = null, $className = null,
       
  1003         $extraHeaders = array())
       
  1004     {
       
  1005         if ($className === null && $data instanceof Zend_Gdata_App_Entry) {
       
  1006             $className = get_class($data);
       
  1007         } elseif ($className === null) {
       
  1008             $className = 'Zend_Gdata_App_Entry';
       
  1009         }
       
  1010 
       
  1011         if (!class_exists($className, false)) {
       
  1012           require_once 'Zend/Loader.php';
       
  1013           @Zend_Loader::loadClass($className);
       
  1014         }
       
  1015 
       
  1016         $response = $this->put($data, $uri, null, null, $extraHeaders);
       
  1017         $returnEntry = new $className($response->getBody());
       
  1018         $returnEntry->setHttpClient(self::getstaticHttpClient());
       
  1019 
       
  1020         $etag = $response->getHeader('ETag');
       
  1021         if ($etag !== null) {
       
  1022             $returnEntry->setEtag($etag);
       
  1023         }
       
  1024 
       
  1025         return $returnEntry;
       
  1026     }
       
  1027 
       
  1028     /**
       
  1029      * Provides a magic factory method to instantiate new objects with
       
  1030      * shorter syntax than would otherwise be required by the Zend Framework
       
  1031      * naming conventions.  For instance, to construct a new
       
  1032      * Zend_Gdata_Calendar_Extension_Color, a developer simply needs to do
       
  1033      * $gCal->newColor().  For this magic constructor, packages are searched
       
  1034      * in the same order as which they appear in the $_registeredPackages
       
  1035      * array
       
  1036      *
       
  1037      * @param string $method The method name being called
       
  1038      * @param array $args The arguments passed to the call
       
  1039      * @throws Zend_Gdata_App_Exception
       
  1040      */
       
  1041     public function __call($method, $args)
       
  1042     {
       
  1043         if (preg_match('/^new(\w+)/', $method, $matches)) {
       
  1044             $class = $matches[1];
       
  1045             $foundClassName = null;
       
  1046             foreach ($this->_registeredPackages as $name) {
       
  1047                  try {
       
  1048                      // Autoloading disabled on next line for compatibility
       
  1049                      // with magic factories. See ZF-6660.
       
  1050                      if (!class_exists($name . '_' . $class, false)) {
       
  1051                         require_once 'Zend/Loader.php';
       
  1052                         @Zend_Loader::loadClass($name . '_' . $class);
       
  1053                      }
       
  1054                      $foundClassName = $name . '_' . $class;
       
  1055                      break;
       
  1056                  } catch (Zend_Exception $e) {
       
  1057                      // package wasn't here- continue searching
       
  1058                  }
       
  1059             }
       
  1060             if ($foundClassName != null) {
       
  1061                 $reflectionObj = new ReflectionClass($foundClassName);
       
  1062                 $instance = $reflectionObj->newInstanceArgs($args);
       
  1063                 if ($instance instanceof Zend_Gdata_App_FeedEntryParent) {
       
  1064                     $instance->setHttpClient($this->_httpClient);
       
  1065 
       
  1066                     // Propogate version data
       
  1067                     $instance->setMajorProtocolVersion(
       
  1068                             $this->_majorProtocolVersion);
       
  1069                     $instance->setMinorProtocolVersion(
       
  1070                             $this->_minorProtocolVersion);
       
  1071                 }
       
  1072                 return $instance;
       
  1073             } else {
       
  1074                 require_once 'Zend/Gdata/App/Exception.php';
       
  1075                 throw new Zend_Gdata_App_Exception(
       
  1076                         "Unable to find '${class}' in registered packages");
       
  1077             }
       
  1078         } else {
       
  1079             require_once 'Zend/Gdata/App/Exception.php';
       
  1080             throw new Zend_Gdata_App_Exception("No such method ${method}");
       
  1081         }
       
  1082     }
       
  1083 
       
  1084     /**
       
  1085      * Retrieve all entries for a feed, iterating through pages as necessary.
       
  1086      * Be aware that calling this function on a large dataset will take a
       
  1087      * significant amount of time to complete. In some cases this may cause
       
  1088      * execution to timeout without proper precautions in place.
       
  1089      *
       
  1090      * @param $feed The feed to iterate through.
       
  1091      * @return mixed A new feed of the same type as the one originally
       
  1092      *          passed in, containing all relevent entries.
       
  1093      */
       
  1094     public function retrieveAllEntriesForFeed($feed) {
       
  1095         $feedClass = get_class($feed);
       
  1096         $reflectionObj = new ReflectionClass($feedClass);
       
  1097         $result = $reflectionObj->newInstance();
       
  1098         do {
       
  1099             foreach ($feed as $entry) {
       
  1100                 $result->addEntry($entry);
       
  1101             }
       
  1102 
       
  1103             $next = $feed->getLink('next');
       
  1104             if ($next !== null) {
       
  1105                 $feed = $this->getFeed($next->href, $feedClass);
       
  1106             } else {
       
  1107                 $feed = null;
       
  1108             }
       
  1109         }
       
  1110         while ($feed != null);
       
  1111         return $result;
       
  1112     }
       
  1113 
       
  1114     /**
       
  1115      * This method enables logging of requests by changing the
       
  1116      * Zend_Http_Client_Adapter used for performing the requests.
       
  1117      * NOTE: This will not work if you have customized the adapter
       
  1118      * already to use a proxy server or other interface.
       
  1119      *
       
  1120      * @param $logfile The logfile to use when logging the requests
       
  1121      */
       
  1122     public function enableRequestDebugLogging($logfile)
       
  1123     {
       
  1124         $this->_httpClient->setConfig(array(
       
  1125             'adapter' => 'Zend_Gdata_App_LoggingHttpClientAdapterSocket',
       
  1126             'logfile' => $logfile
       
  1127             ));
       
  1128     }
       
  1129 
       
  1130     /**
       
  1131      * Retrieve next set of results based on a given feed.
       
  1132      *
       
  1133      * @param Zend_Gdata_App_Feed $feed The feed from which to
       
  1134      *          retreive the next set of results.
       
  1135      * @param string $className (optional) The class of feed to be returned.
       
  1136      *          If null, the next feed (if found) will be the same class as
       
  1137      *          the feed that was given as the first argument.
       
  1138      * @return Zend_Gdata_App_Feed|null Returns a
       
  1139      *          Zend_Gdata_App_Feed or null if no next set of results
       
  1140      *          exists.
       
  1141      */
       
  1142     public function getNextFeed($feed, $className = null)
       
  1143     {
       
  1144         $nextLink = $feed->getNextLink();
       
  1145         if (!$nextLink) {
       
  1146             return null;
       
  1147         }
       
  1148         $nextLinkHref = $nextLink->getHref();
       
  1149 
       
  1150         if ($className === null) {
       
  1151             $className = get_class($feed);
       
  1152         }
       
  1153 
       
  1154         return $this->getFeed($nextLinkHref, $className);
       
  1155     }
       
  1156 
       
  1157     /**
       
  1158      * Retrieve previous set of results based on a given feed.
       
  1159      *
       
  1160      * @param Zend_Gdata_App_Feed $feed The feed from which to
       
  1161      *          retreive the previous set of results.
       
  1162      * @param string $className (optional) The class of feed to be returned.
       
  1163      *          If null, the previous feed (if found) will be the same class as
       
  1164      *          the feed that was given as the first argument.
       
  1165      * @return Zend_Gdata_App_Feed|null Returns a
       
  1166      *          Zend_Gdata_App_Feed or null if no previous set of results
       
  1167      *          exists.
       
  1168      */
       
  1169     public function getPreviousFeed($feed, $className = null)
       
  1170     {
       
  1171         $previousLink = $feed->getPreviousLink();
       
  1172         if (!$previousLink) {
       
  1173             return null;
       
  1174         }
       
  1175         $previousLinkHref = $previousLink->getHref();
       
  1176 
       
  1177         if ($className === null) {
       
  1178             $className = get_class($feed);
       
  1179         }
       
  1180 
       
  1181         return $this->getFeed($previousLinkHref, $className);
       
  1182     }
       
  1183 
       
  1184     /**
       
  1185      * Returns the data for an If-Match header based on the current Etag
       
  1186      * property. If Etags are not supported by the server or cannot be
       
  1187      * extracted from the data, then null will be returned.
       
  1188      *
       
  1189      * @param boolean $allowWeak If false, then if a weak Etag is detected,
       
  1190      *        then return null rather than the Etag.
       
  1191      * @return string|null $data
       
  1192      */
       
  1193     public function generateIfMatchHeaderData($data, $allowWeek)
       
  1194     {
       
  1195         $result = '';
       
  1196         // Set an If-Match header if an ETag has been set (version >= 2 only)
       
  1197         if ($this->_majorProtocolVersion >= 2 &&
       
  1198                 $data instanceof Zend_Gdata_App_Entry) {
       
  1199             $etag = $data->getEtag();
       
  1200             if (($etag !== null) &&
       
  1201                     ($allowWeek || substr($etag, 0, 2) != 'W/')) {
       
  1202                 $result = $data->getEtag();
       
  1203             }
       
  1204         }
       
  1205         return $result;
       
  1206     }
       
  1207 
       
  1208     /**
       
  1209      * Determine whether service object is using XML to object mapping.
       
  1210      *
       
  1211      * @return boolean True if service object is using XML to object mapping,
       
  1212      *                 false otherwise.
       
  1213      */
       
  1214     public function usingObjectMapping()
       
  1215     {
       
  1216         return $this->_useObjectMapping;
       
  1217     }
       
  1218 
       
  1219     /**
       
  1220      * Enable/disable the use of XML to object mapping.
       
  1221      *
       
  1222      * @param boolean $value Pass in true to use the XML to object mapping.
       
  1223      *                       Pass in false or null to disable it.
       
  1224      * @return void
       
  1225      */
       
  1226     public function useObjectMapping($value)
       
  1227     {
       
  1228         if ($value === True) {
       
  1229             $this->_useObjectMapping = true;
       
  1230         } else {
       
  1231             $this->_useObjectMapping = false;
       
  1232         }
       
  1233     }
       
  1234 
       
  1235 }