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