[ Index ] |
PHP Cross Reference of moodle-2.8 |
[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-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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |