[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/zend/Zend/Gdata/ -> App.php (source)

   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 [email protected] 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$
  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          $this->_httpClient->setUri($url);
 644          $this->_httpClient->setConfig(array('maxredirects' => 0));
 645  
 646          // Set the proper adapter if we are handling a streaming upload
 647          $usingMimeStream = false;
 648          $oldHttpAdapter = null;
 649  
 650          if ($body instanceof Zend_Gdata_MediaMimeStream) {
 651              $usingMimeStream = true;
 652              $this->_httpClient->setRawDataStream($body, $contentType);
 653              $oldHttpAdapter = $this->_httpClient->getAdapter();
 654  
 655              if ($oldHttpAdapter instanceof Zend_Http_Client_Adapter_Proxy) {
 656                  require_once 'Zend/Gdata/HttpAdapterStreamingProxy.php';
 657                  $newAdapter = new Zend_Gdata_HttpAdapterStreamingProxy();
 658              } else {
 659                  require_once 'Zend/Gdata/HttpAdapterStreamingSocket.php';
 660                  $newAdapter = new Zend_Gdata_HttpAdapterStreamingSocket();
 661              }
 662              $this->_httpClient->setAdapter($newAdapter);
 663          } else {
 664              $this->_httpClient->setRawData($body, $contentType);
 665          }
 666  
 667          try {
 668              $response = $this->_httpClient->request($method);
 669              // reset adapter
 670              if ($usingMimeStream) {
 671                  $this->_httpClient->setAdapter($oldHttpAdapter);
 672              }
 673          } catch (Zend_Http_Client_Exception $e) {
 674              // reset adapter
 675              if ($usingMimeStream) {
 676                  $this->_httpClient->setAdapter($oldHttpAdapter);
 677              }
 678              require_once 'Zend/Gdata/App/HttpException.php';
 679              throw new Zend_Gdata_App_HttpException($e->getMessage(), $e);
 680          }
 681          if ($response->isRedirect() && $response->getStatus() != '304') {
 682              if ($remainingRedirects > 0) {
 683                  $newUrl = $response->getHeader('Location');
 684                  $response = $this->performHttpRequest(
 685                      $method, $newUrl, $headers, $body,
 686                      $contentType, $remainingRedirects);
 687              } else {
 688                  require_once 'Zend/Gdata/App/HttpException.php';
 689                  throw new Zend_Gdata_App_HttpException(
 690                          'Number of redirects exceeds maximum', null, $response);
 691              }
 692          }
 693          if (!$response->isSuccessful()) {
 694              require_once 'Zend/Gdata/App/HttpException.php';
 695              $exceptionMessage = 'Expected response code 200, got ' .
 696                  $response->getStatus();
 697              if (self::getVerboseExceptionMessages()) {
 698                  $exceptionMessage .= "\n" . $response->getBody();
 699              }
 700              $exception = new Zend_Gdata_App_HttpException($exceptionMessage);
 701              $exception->setResponse($response);
 702              throw $exception;
 703          }
 704          return $response;
 705      }
 706  
 707      /**
 708       * Imports a feed located at $uri.
 709       *
 710       * @param  string $uri
 711       * @param  Zend_Http_Client $client The client used for communication
 712       * @param  string $className The class which is used as the return type
 713       * @throws Zend_Gdata_App_Exception
 714       * @return string|Zend_Gdata_App_Feed Returns string only if the object
 715       *                                    mapping has been disabled explicitly
 716       *                                    by passing false to the
 717       *                                    useObjectMapping() function.
 718       */
 719      public static function import($uri, $client = null,
 720          $className='Zend_Gdata_App_Feed')
 721      {
 722          $app = new Zend_Gdata_App($client);
 723          $requestData = $app->prepareRequest('GET', $uri);
 724          $response = $app->performHttpRequest(
 725              $requestData['method'], $requestData['url']);
 726  
 727          $feedContent = $response->getBody();
 728          if (!$this->_useObjectMapping) {
 729              return $feedContent;
 730          }
 731          $feed = self::importString($feedContent, $className);
 732          if ($client != null) {
 733              $feed->setHttpClient($client);
 734          }
 735          return $feed;
 736      }
 737  
 738      /**
 739       * Imports the specified URL (non-statically).
 740       *
 741       * @param  string $url The URL to import
 742       * @param  string $className The class which is used as the return type
 743       * @param array $extraHeaders Extra headers to add to the request, as an
 744       *        array of string-based key/value pairs.
 745       * @throws Zend_Gdata_App_Exception
 746       * @return string|Zend_Gdata_App_Feed Returns string only if the object
 747       *                                    mapping has been disabled explicitly
 748       *                                    by passing false to the
 749       *                                    useObjectMapping() function.
 750       */
 751      public function importUrl($url, $className='Zend_Gdata_App_Feed',
 752          $extraHeaders = array())
 753      {
 754          $response = $this->get($url, $extraHeaders);
 755  
 756          $feedContent = $response->getBody();
 757          if (!$this->_useObjectMapping) {
 758              return $feedContent;
 759          }
 760  
 761          $protocolVersionStr = $response->getHeader('GData-Version');
 762          $majorProtocolVersion = null;
 763          $minorProtocolVersion = null;
 764          if ($protocolVersionStr !== null) {
 765              // Extract protocol major and minor version from header
 766              $delimiterPos = strpos($protocolVersionStr, '.');
 767              $length = strlen($protocolVersionStr);
 768              $major = substr($protocolVersionStr, 0, $delimiterPos);
 769              $minor = substr($protocolVersionStr, $delimiterPos + 1, $length);
 770              $majorProtocolVersion = $major;
 771              $minorProtocolVersion = $minor;
 772          }
 773  
 774          $feed = self::importString($feedContent, $className,
 775              $majorProtocolVersion, $minorProtocolVersion);
 776          if ($this->getHttpClient() != null) {
 777              $feed->setHttpClient($this->getHttpClient());
 778          }
 779          $etag = $response->getHeader('ETag');
 780          if ($etag !== null) {
 781              $feed->setEtag($etag);
 782          }
 783          return $feed;
 784      }
 785  
 786  
 787      /**
 788       * Imports a feed represented by $string.
 789       *
 790       * @param string $string
 791       * @param string $className The class which is used as the return type
 792       * @param integer $majorProcolVersion (optional) The major protocol version
 793       *        of the data model object that is to be created.
 794       * @param integer $minorProcolVersion (optional) The minor protocol version
 795       *        of the data model object that is to be created.
 796       * @throws Zend_Gdata_App_Exception
 797       * @return Zend_Gdata_App_Feed
 798       */
 799      public static function importString($string,
 800          $className='Zend_Gdata_App_Feed', $majorProtocolVersion = null,
 801          $minorProtocolVersion = null)
 802      {
 803          // Load the feed as an XML DOMDocument object
 804          @ini_set('track_errors', 1);
 805          $doc = new DOMDocument();
 806          $success = @$doc->loadXML($string);
 807          @ini_restore('track_errors');
 808  
 809          if (!$success) {
 810              require_once 'Zend/Gdata/App/Exception.php';
 811              throw new Zend_Gdata_App_Exception(
 812                  "DOMDocument cannot parse XML: $php_errormsg");
 813          }
 814  
 815          $feed = new $className();
 816          $feed->setMajorProtocolVersion($majorProtocolVersion);
 817          $feed->setMinorProtocolVersion($minorProtocolVersion);
 818          $feed->transferFromXML($string);
 819          $feed->setHttpClient(self::getstaticHttpClient());
 820          return $feed;
 821      }
 822  
 823  
 824      /**
 825       * Imports a feed from a file located at $filename.
 826       *
 827       * @param  string $filename
 828       * @param  string $className The class which is used as the return type
 829       * @param  string $useIncludePath Whether the include_path should be searched
 830       * @throws Zend_Gdata_App_Exception
 831       * @return Zend_Gdata_App_Feed
 832       */
 833      public static function importFile($filename,
 834              $className='Zend_Gdata_App_Feed', $useIncludePath = false)
 835      {
 836          @ini_set('track_errors', 1);
 837          $feed = @file_get_contents($filename, $useIncludePath);
 838          @ini_restore('track_errors');
 839          if ($feed === false) {
 840              require_once 'Zend/Gdata/App/Exception.php';
 841              throw new Zend_Gdata_App_Exception(
 842                  "File could not be loaded: $php_errormsg");
 843          }
 844          return self::importString($feed, $className);
 845      }
 846  
 847      /**
 848       * GET a URI using client object.
 849       *
 850       * @param string $uri GET URI
 851       * @param array $extraHeaders Extra headers to add to the request, as an
 852       *        array of string-based key/value pairs.
 853       * @throws Zend_Gdata_App_HttpException
 854       * @return Zend_Http_Response
 855       */
 856      public function get($uri, $extraHeaders = array())
 857      {
 858          $requestData = $this->prepareRequest('GET', $uri, $extraHeaders);
 859          return $this->performHttpRequest(
 860              $requestData['method'], $requestData['url'],
 861              $requestData['headers']);
 862      }
 863  
 864      /**
 865       * POST data with client object
 866       *
 867       * @param mixed $data The Zend_Gdata_App_Entry or XML to post
 868       * @param string $uri POST URI
 869       * @param array $headers Additional HTTP headers to insert.
 870       * @param string $contentType Content-type of the data
 871       * @param array $extraHeaders Extra headers to add to the request, as an
 872       *        array of string-based key/value pairs.
 873       * @return Zend_Http_Response
 874       * @throws Zend_Gdata_App_Exception
 875       * @throws Zend_Gdata_App_HttpException
 876       * @throws Zend_Gdata_App_InvalidArgumentException
 877       */
 878      public function post($data, $uri = null, $remainingRedirects = null,
 879              $contentType = null, $extraHeaders = null)
 880      {
 881          $requestData = $this->prepareRequest(
 882              'POST', $uri, $extraHeaders, $data, $contentType);
 883          return $this->performHttpRequest(
 884                  $requestData['method'], $requestData['url'],
 885                  $requestData['headers'], $requestData['data'],
 886                  $requestData['contentType']);
 887      }
 888  
 889      /**
 890       * PUT data with client object
 891       *
 892       * @param mixed $data The Zend_Gdata_App_Entry or XML to post
 893       * @param string $uri PUT URI
 894       * @param array $headers Additional HTTP headers to insert.
 895       * @param string $contentType Content-type of the data
 896       * @param array $extraHeaders Extra headers to add to the request, as an
 897       *        array of string-based key/value pairs.
 898       * @return Zend_Http_Response
 899       * @throws Zend_Gdata_App_Exception
 900       * @throws Zend_Gdata_App_HttpException
 901       * @throws Zend_Gdata_App_InvalidArgumentException
 902       */
 903      public function put($data, $uri = null, $remainingRedirects = null,
 904              $contentType = null, $extraHeaders = null)
 905      {
 906          $requestData = $this->prepareRequest(
 907              'PUT', $uri, $extraHeaders, $data, $contentType);
 908          return $this->performHttpRequest(
 909                  $requestData['method'], $requestData['url'],
 910                  $requestData['headers'], $requestData['data'],
 911                  $requestData['contentType']);
 912      }
 913  
 914      /**
 915       * DELETE entry with client object
 916       *
 917       * @param mixed $data The Zend_Gdata_App_Entry or URL to delete
 918       * @return void
 919       * @throws Zend_Gdata_App_Exception
 920       * @throws Zend_Gdata_App_HttpException
 921       * @throws Zend_Gdata_App_InvalidArgumentException
 922       */
 923      public function delete($data, $remainingRedirects = null)
 924      {
 925          if (is_string($data)) {
 926              $requestData = $this->prepareRequest('DELETE', $data);
 927          } else {
 928              $headers = array();
 929  
 930              $requestData = $this->prepareRequest(
 931                  'DELETE', null, $headers, $data);
 932          }
 933          return $this->performHttpRequest($requestData['method'],
 934                                           $requestData['url'],
 935                                           $requestData['headers'],
 936                                           '',
 937                                           $requestData['contentType'],
 938                                           $remainingRedirects);
 939      }
 940  
 941      /**
 942       * Inserts an entry to a given URI and returns the response as a
 943       * fully formed Entry.
 944       *
 945       * @param mixed  $data The Zend_Gdata_App_Entry or XML to post
 946       * @param string $uri POST URI
 947       * @param string $className The class of entry to be returned.
 948       * @param array $extraHeaders Extra headers to add to the request, as an
 949       *        array of string-based key/value pairs.
 950       * @return Zend_Gdata_App_Entry The entry returned by the service after
 951       *         insertion.
 952       */
 953      public function insertEntry($data, $uri, $className='Zend_Gdata_App_Entry',
 954          $extraHeaders = array())
 955      {
 956          $response = $this->post($data, $uri, null, null, $extraHeaders);
 957  
 958          $returnEntry = new $className($response->getBody());
 959          $returnEntry->setHttpClient(self::getstaticHttpClient());
 960  
 961          $etag = $response->getHeader('ETag');
 962          if ($etag !== null) {
 963              $returnEntry->setEtag($etag);
 964          }
 965  
 966          return $returnEntry;
 967      }
 968  
 969      /**
 970       * Update an entry
 971       *
 972       * @param mixed $data Zend_Gdata_App_Entry or XML (w/ID and link rel='edit')
 973       * @param string|null The URI to send requests to, or null if $data
 974       *        contains the URI.
 975       * @param string|null The name of the class that should be deserialized
 976       *        from the server response. If null, then 'Zend_Gdata_App_Entry'
 977       *        will be used.
 978       * @param array $extraHeaders Extra headers to add to the request, as an
 979       *        array of string-based key/value pairs.
 980       * @return Zend_Gdata_App_Entry The entry returned from the server
 981       * @throws Zend_Gdata_App_Exception
 982       */
 983      public function updateEntry($data, $uri = null, $className = null,
 984          $extraHeaders = array())
 985      {
 986          if ($className === null && $data instanceof Zend_Gdata_App_Entry) {
 987              $className = get_class($data);
 988          } elseif ($className === null) {
 989              $className = 'Zend_Gdata_App_Entry';
 990          }
 991  
 992          $response = $this->put($data, $uri, null, null, $extraHeaders);
 993          $returnEntry = new $className($response->getBody());
 994          $returnEntry->setHttpClient(self::getstaticHttpClient());
 995  
 996          $etag = $response->getHeader('ETag');
 997          if ($etag !== null) {
 998              $returnEntry->setEtag($etag);
 999          }
1000  
1001          return $returnEntry;
1002      }
1003  
1004      /**
1005       * Provides a magic factory method to instantiate new objects with
1006       * shorter syntax than would otherwise be required by the Zend Framework
1007       * naming conventions.  For instance, to construct a new
1008       * Zend_Gdata_Calendar_Extension_Color, a developer simply needs to do
1009       * $gCal->newColor().  For this magic constructor, packages are searched
1010       * in the same order as which they appear in the $_registeredPackages
1011       * array
1012       *
1013       * @param string $method The method name being called
1014       * @param array $args The arguments passed to the call
1015       * @throws Zend_Gdata_App_Exception
1016       */
1017      public function __call($method, $args)
1018      {
1019          if (preg_match('/^new(\w+)/', $method, $matches)) {
1020              $class = $matches[1];
1021              $foundClassName = null;
1022              foreach ($this->_registeredPackages as $name) {
1023                   try {
1024                       // Autoloading disabled on next line for compatibility
1025                       // with magic factories. See ZF-6660.
1026                       if (!class_exists($name . '_' . $class, false)) {
1027                          require_once 'Zend/Loader.php';
1028                          @Zend_Loader::loadClass($name . '_' . $class);
1029                       }
1030                       $foundClassName = $name . '_' . $class;
1031                       break;
1032                   } catch (Zend_Exception $e) {
1033                       // package wasn't here- continue searching
1034                   }
1035              }
1036              if ($foundClassName != null) {
1037                  $reflectionObj = new ReflectionClass($foundClassName);
1038                  $instance = $reflectionObj->newInstanceArgs($args);
1039                  if ($instance instanceof Zend_Gdata_App_FeedEntryParent) {
1040                      $instance->setHttpClient($this->_httpClient);
1041  
1042                      // Propogate version data
1043                      $instance->setMajorProtocolVersion(
1044                              $this->_majorProtocolVersion);
1045                      $instance->setMinorProtocolVersion(
1046                              $this->_minorProtocolVersion);
1047                  }
1048                  return $instance;
1049              } else {
1050                  require_once 'Zend/Gdata/App/Exception.php';
1051                  throw new Zend_Gdata_App_Exception(
1052                          "Unable to find '$class}' in registered packages");
1053              }
1054          } else {
1055              require_once 'Zend/Gdata/App/Exception.php';
1056              throw new Zend_Gdata_App_Exception("No such method $method}");
1057          }
1058      }
1059  
1060      /**
1061       * Retrieve all entries for a feed, iterating through pages as necessary.
1062       * Be aware that calling this function on a large dataset will take a
1063       * significant amount of time to complete. In some cases this may cause
1064       * execution to timeout without proper precautions in place.
1065       *
1066       * @param $feed The feed to iterate through.
1067       * @return mixed A new feed of the same type as the one originally
1068       *          passed in, containing all relevent entries.
1069       */
1070      public function retrieveAllEntriesForFeed($feed) {
1071          $feedClass = get_class($feed);
1072          $reflectionObj = new ReflectionClass($feedClass);
1073          $result = $reflectionObj->newInstance();
1074          do {
1075              foreach ($feed as $entry) {
1076                  $result->addEntry($entry);
1077              }
1078  
1079              $next = $feed->getLink('next');
1080              if ($next !== null) {
1081                  $feed = $this->getFeed($next->href, $feedClass);
1082              } else {
1083                  $feed = null;
1084              }
1085          }
1086          while ($feed != null);
1087          return $result;
1088      }
1089  
1090      /**
1091       * This method enables logging of requests by changing the
1092       * Zend_Http_Client_Adapter used for performing the requests.
1093       * NOTE: This will not work if you have customized the adapter
1094       * already to use a proxy server or other interface.
1095       *
1096       * @param $logfile The logfile to use when logging the requests
1097       */
1098      public function enableRequestDebugLogging($logfile)
1099      {
1100          $this->_httpClient->setConfig(array(
1101              'adapter' => 'Zend_Gdata_App_LoggingHttpClientAdapterSocket',
1102              'logfile' => $logfile
1103              ));
1104      }
1105  
1106      /**
1107       * Retrieve next set of results based on a given feed.
1108       *
1109       * @param Zend_Gdata_App_Feed $feed The feed from which to
1110       *          retreive the next set of results.
1111       * @param string $className (optional) The class of feed to be returned.
1112       *          If null, the next feed (if found) will be the same class as
1113       *          the feed that was given as the first argument.
1114       * @return Zend_Gdata_App_Feed|null Returns a
1115       *          Zend_Gdata_App_Feed or null if no next set of results
1116       *          exists.
1117       */
1118      public function getNextFeed($feed, $className = null)
1119      {
1120          $nextLink = $feed->getNextLink();
1121          if (!$nextLink) {
1122              return null;
1123          }
1124          $nextLinkHref = $nextLink->getHref();
1125  
1126          if ($className === null) {
1127              $className = get_class($feed);
1128          }
1129  
1130          return $this->getFeed($nextLinkHref, $className);
1131      }
1132  
1133      /**
1134       * Retrieve previous set of results based on a given feed.
1135       *
1136       * @param Zend_Gdata_App_Feed $feed The feed from which to
1137       *          retreive the previous set of results.
1138       * @param string $className (optional) The class of feed to be returned.
1139       *          If null, the previous feed (if found) will be the same class as
1140       *          the feed that was given as the first argument.
1141       * @return Zend_Gdata_App_Feed|null Returns a
1142       *          Zend_Gdata_App_Feed or null if no previous set of results
1143       *          exists.
1144       */
1145      public function getPreviousFeed($feed, $className = null)
1146      {
1147          $previousLink = $feed->getPreviousLink();
1148          if (!$previousLink) {
1149              return null;
1150          }
1151          $previousLinkHref = $previousLink->getHref();
1152  
1153          if ($className === null) {
1154              $className = get_class($feed);
1155          }
1156  
1157          return $this->getFeed($previousLinkHref, $className);
1158      }
1159  
1160      /**
1161       * Returns the data for an If-Match header based on the current Etag
1162       * property. If Etags are not supported by the server or cannot be
1163       * extracted from the data, then null will be returned.
1164       *
1165       * @param boolean $allowWeak If false, then if a weak Etag is detected,
1166       *        then return null rather than the Etag.
1167       * @return string|null $data
1168       */
1169      public function generateIfMatchHeaderData($data, $allowWeek)
1170      {
1171          $result = '';
1172          // Set an If-Match header if an ETag has been set (version >= 2 only)
1173          if ($this->_majorProtocolVersion >= 2 &&
1174                  $data instanceof Zend_Gdata_App_Entry) {
1175              $etag = $data->getEtag();
1176              if (($etag !== null) &&
1177                      ($allowWeek || substr($etag, 0, 2) != 'W/')) {
1178                  $result = $data->getEtag();
1179              }
1180          }
1181          return $result;
1182      }
1183  
1184      /**
1185       * Determine whether service object is using XML to object mapping.
1186       *
1187       * @return boolean True if service object is using XML to object mapping,
1188       *                 false otherwise.
1189       */
1190      public function usingObjectMapping()
1191      {
1192          return $this->_useObjectMapping;
1193      }
1194  
1195      /**
1196       * Enable/disable the use of XML to object mapping.
1197       *
1198       * @param boolean $value Pass in true to use the XML to object mapping.
1199       *                       Pass in false or null to disable it.
1200       * @return void
1201       */
1202      public function useObjectMapping($value)
1203      {
1204          if ($value === True) {
1205              $this->_useObjectMapping = true;
1206          } else {
1207              $this->_useObjectMapping = false;
1208          }
1209      }
1210  
1211  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1