1<?php 2 3namespace Guzzle\Http\Message; 4 5use Guzzle\Common\Version; 6use Guzzle\Common\ToArrayInterface; 7use Guzzle\Common\Exception\RuntimeException; 8use Guzzle\Http\EntityBodyInterface; 9use Guzzle\Http\EntityBody; 10use Guzzle\Http\Exception\BadResponseException; 11use Guzzle\Http\RedirectPlugin; 12use Guzzle\Parser\ParserRegistry; 13 14/** 15 * Guzzle HTTP response object 16 */ 17class Response extends AbstractMessage implements \Serializable 18{ 19 /** 20 * @var array Array of reason phrases and their corresponding status codes 21 */ 22 private static $statusTexts = array( 23 100 => 'Continue', 24 101 => 'Switching Protocols', 25 102 => 'Processing', 26 200 => 'OK', 27 201 => 'Created', 28 202 => 'Accepted', 29 203 => 'Non-Authoritative Information', 30 204 => 'No Content', 31 205 => 'Reset Content', 32 206 => 'Partial Content', 33 207 => 'Multi-Status', 34 208 => 'Already Reported', 35 226 => 'IM Used', 36 300 => 'Multiple Choices', 37 301 => 'Moved Permanently', 38 302 => 'Found', 39 303 => 'See Other', 40 304 => 'Not Modified', 41 305 => 'Use Proxy', 42 307 => 'Temporary Redirect', 43 308 => 'Permanent Redirect', 44 400 => 'Bad Request', 45 401 => 'Unauthorized', 46 402 => 'Payment Required', 47 403 => 'Forbidden', 48 404 => 'Not Found', 49 405 => 'Method Not Allowed', 50 406 => 'Not Acceptable', 51 407 => 'Proxy Authentication Required', 52 408 => 'Request Timeout', 53 409 => 'Conflict', 54 410 => 'Gone', 55 411 => 'Length Required', 56 412 => 'Precondition Failed', 57 413 => 'Request Entity Too Large', 58 414 => 'Request-URI Too Long', 59 415 => 'Unsupported Media Type', 60 416 => 'Requested Range Not Satisfiable', 61 417 => 'Expectation Failed', 62 422 => 'Unprocessable Entity', 63 423 => 'Locked', 64 424 => 'Failed Dependency', 65 425 => 'Reserved for WebDAV advanced collections expired proposal', 66 426 => 'Upgrade required', 67 428 => 'Precondition Required', 68 429 => 'Too Many Requests', 69 431 => 'Request Header Fields Too Large', 70 500 => 'Internal Server Error', 71 501 => 'Not Implemented', 72 502 => 'Bad Gateway', 73 503 => 'Service Unavailable', 74 504 => 'Gateway Timeout', 75 505 => 'HTTP Version Not Supported', 76 506 => 'Variant Also Negotiates (Experimental)', 77 507 => 'Insufficient Storage', 78 508 => 'Loop Detected', 79 510 => 'Not Extended', 80 511 => 'Network Authentication Required', 81 ); 82 83 /** @var EntityBodyInterface The response body */ 84 protected $body; 85 86 /** @var string The reason phrase of the response (human readable code) */ 87 protected $reasonPhrase; 88 89 /** @var string The status code of the response */ 90 protected $statusCode; 91 92 /** @var array Information about the request */ 93 protected $info = array(); 94 95 /** @var string The effective URL that returned this response */ 96 protected $effectiveUrl; 97 98 /** @var array Cacheable response codes (see RFC 2616:13.4) */ 99 protected static $cacheResponseCodes = array(200, 203, 206, 300, 301, 410); 100 101 /** 102 * Create a new Response based on a raw response message 103 * 104 * @param string $message Response message 105 * 106 * @return self|bool Returns false on error 107 */ 108 public static function fromMessage($message) 109 { 110 $data = ParserRegistry::getInstance()->getParser('message')->parseResponse($message); 111 if (!$data) { 112 return false; 113 } 114 115 $response = new static($data['code'], $data['headers'], $data['body']); 116 $response->setProtocol($data['protocol'], $data['version']) 117 ->setStatus($data['code'], $data['reason_phrase']); 118 119 // Set the appropriate Content-Length if the one set is inaccurate (e.g. setting to X) 120 $contentLength = (string) $response->getHeader('Content-Length'); 121 $actualLength = strlen($data['body']); 122 if (strlen($data['body']) > 0 && $contentLength != $actualLength) { 123 $response->setHeader('Content-Length', $actualLength); 124 } 125 126 return $response; 127 } 128 129 /** 130 * Construct the response 131 * 132 * @param string $statusCode The response status code (e.g. 200, 404, etc) 133 * @param ToArrayInterface|array $headers The response headers 134 * @param string|resource|EntityBodyInterface $body The body of the response 135 * 136 * @throws BadResponseException if an invalid response code is given 137 */ 138 public function __construct($statusCode, $headers = null, $body = null) 139 { 140 parent::__construct(); 141 $this->setStatus($statusCode); 142 $this->body = EntityBody::factory($body !== null ? $body : ''); 143 144 if ($headers) { 145 if (is_array($headers)) { 146 $this->setHeaders($headers); 147 } elseif ($headers instanceof ToArrayInterface) { 148 $this->setHeaders($headers->toArray()); 149 } else { 150 throw new BadResponseException('Invalid headers argument received'); 151 } 152 } 153 } 154 155 /** 156 * @return string 157 */ 158 public function __toString() 159 { 160 return $this->getMessage(); 161 } 162 163 public function serialize() 164 { 165 return json_encode(array( 166 'status' => $this->statusCode, 167 'body' => (string) $this->body, 168 'headers' => $this->headers->toArray() 169 )); 170 } 171 172 public function unserialize($serialize) 173 { 174 $data = json_decode($serialize, true); 175 $this->__construct($data['status'], $data['headers'], $data['body']); 176 } 177 178 /** 179 * Get the response entity body 180 * 181 * @param bool $asString Set to TRUE to return a string of the body rather than a full body object 182 * 183 * @return EntityBodyInterface|string 184 */ 185 public function getBody($asString = false) 186 { 187 return $asString ? (string) $this->body : $this->body; 188 } 189 190 /** 191 * Set the response entity body 192 * 193 * @param EntityBodyInterface|string $body Body to set 194 * 195 * @return self 196 */ 197 public function setBody($body) 198 { 199 $this->body = EntityBody::factory($body); 200 201 return $this; 202 } 203 204 /** 205 * Set the protocol and protocol version of the response 206 * 207 * @param string $protocol Response protocol 208 * @param string $version Protocol version 209 * 210 * @return self 211 */ 212 public function setProtocol($protocol, $version) 213 { 214 $this->protocol = $protocol; 215 $this->protocolVersion = $version; 216 217 return $this; 218 } 219 220 /** 221 * Get the protocol used for the response (e.g. HTTP) 222 * 223 * @return string 224 */ 225 public function getProtocol() 226 { 227 return $this->protocol; 228 } 229 230 /** 231 * Get the HTTP protocol version 232 * 233 * @return string 234 */ 235 public function getProtocolVersion() 236 { 237 return $this->protocolVersion; 238 } 239 240 /** 241 * Get a cURL transfer information 242 * 243 * @param string $key A single statistic to check 244 * 245 * @return array|string|null Returns all stats if no key is set, a single stat if a key is set, or null if a key 246 * is set and not found 247 * @link http://www.php.net/manual/en/function.curl-getinfo.php 248 */ 249 public function getInfo($key = null) 250 { 251 if ($key === null) { 252 return $this->info; 253 } elseif (array_key_exists($key, $this->info)) { 254 return $this->info[$key]; 255 } else { 256 return null; 257 } 258 } 259 260 /** 261 * Set the transfer information 262 * 263 * @param array $info Array of cURL transfer stats 264 * 265 * @return self 266 */ 267 public function setInfo(array $info) 268 { 269 $this->info = $info; 270 271 return $this; 272 } 273 274 /** 275 * Set the response status 276 * 277 * @param int $statusCode Response status code to set 278 * @param string $reasonPhrase Response reason phrase 279 * 280 * @return self 281 * @throws BadResponseException when an invalid response code is received 282 */ 283 public function setStatus($statusCode, $reasonPhrase = '') 284 { 285 $this->statusCode = (int) $statusCode; 286 287 if (!$reasonPhrase && isset(self::$statusTexts[$this->statusCode])) { 288 $this->reasonPhrase = self::$statusTexts[$this->statusCode]; 289 } else { 290 $this->reasonPhrase = $reasonPhrase; 291 } 292 293 return $this; 294 } 295 296 /** 297 * Get the response status code 298 * 299 * @return integer 300 */ 301 public function getStatusCode() 302 { 303 return $this->statusCode; 304 } 305 306 /** 307 * Get the entire response as a string 308 * 309 * @return string 310 */ 311 public function getMessage() 312 { 313 $message = $this->getRawHeaders(); 314 315 // Only include the body in the message if the size is < 2MB 316 $size = $this->body->getSize(); 317 if ($size < 2097152) { 318 $message .= (string) $this->body; 319 } 320 321 return $message; 322 } 323 324 /** 325 * Get the the raw message headers as a string 326 * 327 * @return string 328 */ 329 public function getRawHeaders() 330 { 331 $headers = 'HTTP/1.1 ' . $this->statusCode . ' ' . $this->reasonPhrase . "\r\n"; 332 $lines = $this->getHeaderLines(); 333 if (!empty($lines)) { 334 $headers .= implode("\r\n", $lines) . "\r\n"; 335 } 336 337 return $headers . "\r\n"; 338 } 339 340 /** 341 * Get the response reason phrase- a human readable version of the numeric 342 * status code 343 * 344 * @return string 345 */ 346 public function getReasonPhrase() 347 { 348 return $this->reasonPhrase; 349 } 350 351 /** 352 * Get the Accept-Ranges HTTP header 353 * 354 * @return string Returns what partial content range types this server supports. 355 */ 356 public function getAcceptRanges() 357 { 358 return (string) $this->getHeader('Accept-Ranges'); 359 } 360 361 /** 362 * Calculate the age of the response 363 * 364 * @return integer 365 */ 366 public function calculateAge() 367 { 368 $age = $this->getHeader('Age'); 369 370 if ($age === null && $this->getDate()) { 371 $age = time() - strtotime($this->getDate()); 372 } 373 374 return $age === null ? null : (int) (string) $age; 375 } 376 377 /** 378 * Get the Age HTTP header 379 * 380 * @return integer|null Returns the age the object has been in a proxy cache in seconds. 381 */ 382 public function getAge() 383 { 384 return (string) $this->getHeader('Age'); 385 } 386 387 /** 388 * Get the Allow HTTP header 389 * 390 * @return string|null Returns valid actions for a specified resource. To be used for a 405 Method not allowed. 391 */ 392 public function getAllow() 393 { 394 return (string) $this->getHeader('Allow'); 395 } 396 397 /** 398 * Check if an HTTP method is allowed by checking the Allow response header 399 * 400 * @param string $method Method to check 401 * 402 * @return bool 403 */ 404 public function isMethodAllowed($method) 405 { 406 $allow = $this->getHeader('Allow'); 407 if ($allow) { 408 foreach (explode(',', $allow) as $allowable) { 409 if (!strcasecmp(trim($allowable), $method)) { 410 return true; 411 } 412 } 413 } 414 415 return false; 416 } 417 418 /** 419 * Get the Cache-Control HTTP header 420 * 421 * @return string 422 */ 423 public function getCacheControl() 424 { 425 return (string) $this->getHeader('Cache-Control'); 426 } 427 428 /** 429 * Get the Connection HTTP header 430 * 431 * @return string 432 */ 433 public function getConnection() 434 { 435 return (string) $this->getHeader('Connection'); 436 } 437 438 /** 439 * Get the Content-Encoding HTTP header 440 * 441 * @return string|null 442 */ 443 public function getContentEncoding() 444 { 445 return (string) $this->getHeader('Content-Encoding'); 446 } 447 448 /** 449 * Get the Content-Language HTTP header 450 * 451 * @return string|null Returns the language the content is in. 452 */ 453 public function getContentLanguage() 454 { 455 return (string) $this->getHeader('Content-Language'); 456 } 457 458 /** 459 * Get the Content-Length HTTP header 460 * 461 * @return integer Returns the length of the response body in bytes 462 */ 463 public function getContentLength() 464 { 465 return (int) (string) $this->getHeader('Content-Length'); 466 } 467 468 /** 469 * Get the Content-Location HTTP header 470 * 471 * @return string|null Returns an alternate location for the returned data (e.g /index.htm) 472 */ 473 public function getContentLocation() 474 { 475 return (string) $this->getHeader('Content-Location'); 476 } 477 478 /** 479 * Get the Content-Disposition HTTP header 480 * 481 * @return string|null Returns the Content-Disposition header 482 */ 483 public function getContentDisposition() 484 { 485 return (string) $this->getHeader('Content-Disposition'); 486 } 487 488 /** 489 * Get the Content-MD5 HTTP header 490 * 491 * @return string|null Returns a Base64-encoded binary MD5 sum of the content of the response. 492 */ 493 public function getContentMd5() 494 { 495 return (string) $this->getHeader('Content-MD5'); 496 } 497 498 /** 499 * Get the Content-Range HTTP header 500 * 501 * @return string Returns where in a full body message this partial message belongs (e.g. bytes 21010-47021/47022). 502 */ 503 public function getContentRange() 504 { 505 return (string) $this->getHeader('Content-Range'); 506 } 507 508 /** 509 * Get the Content-Type HTTP header 510 * 511 * @return string Returns the mime type of this content. 512 */ 513 public function getContentType() 514 { 515 return (string) $this->getHeader('Content-Type'); 516 } 517 518 /** 519 * Checks if the Content-Type is of a certain type. This is useful if the 520 * Content-Type header contains charset information and you need to know if 521 * the Content-Type matches a particular type. 522 * 523 * @param string $type Content type to check against 524 * 525 * @return bool 526 */ 527 public function isContentType($type) 528 { 529 return stripos($this->getHeader('Content-Type'), $type) !== false; 530 } 531 532 /** 533 * Get the Date HTTP header 534 * 535 * @return string|null Returns the date and time that the message was sent. 536 */ 537 public function getDate() 538 { 539 return (string) $this->getHeader('Date'); 540 } 541 542 /** 543 * Get the ETag HTTP header 544 * 545 * @return string|null Returns an identifier for a specific version of a resource, often a Message digest. 546 */ 547 public function getEtag() 548 { 549 return (string) $this->getHeader('ETag'); 550 } 551 552 /** 553 * Get the Expires HTTP header 554 * 555 * @return string|null Returns the date/time after which the response is considered stale. 556 */ 557 public function getExpires() 558 { 559 return (string) $this->getHeader('Expires'); 560 } 561 562 /** 563 * Get the Last-Modified HTTP header 564 * 565 * @return string|null Returns the last modified date for the requested object, in RFC 2822 format 566 * (e.g. Tue, 15 Nov 1994 12:45:26 GMT) 567 */ 568 public function getLastModified() 569 { 570 return (string) $this->getHeader('Last-Modified'); 571 } 572 573 /** 574 * Get the Location HTTP header 575 * 576 * @return string|null Used in redirection, or when a new resource has been created. 577 */ 578 public function getLocation() 579 { 580 return (string) $this->getHeader('Location'); 581 } 582 583 /** 584 * Get the Pragma HTTP header 585 * 586 * @return Header|null Returns the implementation-specific headers that may have various effects anywhere along 587 * the request-response chain. 588 */ 589 public function getPragma() 590 { 591 return (string) $this->getHeader('Pragma'); 592 } 593 594 /** 595 * Get the Proxy-Authenticate HTTP header 596 * 597 * @return string|null Authentication to access the proxy (e.g. Basic) 598 */ 599 public function getProxyAuthenticate() 600 { 601 return (string) $this->getHeader('Proxy-Authenticate'); 602 } 603 604 /** 605 * Get the Retry-After HTTP header 606 * 607 * @return int|null If an entity is temporarily unavailable, this instructs the client to try again after a 608 * specified period of time. 609 */ 610 public function getRetryAfter() 611 { 612 return (string) $this->getHeader('Retry-After'); 613 } 614 615 /** 616 * Get the Server HTTP header 617 * 618 * @return string|null A name for the server 619 */ 620 public function getServer() 621 { 622 return (string) $this->getHeader('Server'); 623 } 624 625 /** 626 * Get the Set-Cookie HTTP header 627 * 628 * @return string|null An HTTP cookie. 629 */ 630 public function getSetCookie() 631 { 632 return (string) $this->getHeader('Set-Cookie'); 633 } 634 635 /** 636 * Get the Trailer HTTP header 637 * 638 * @return string|null The Trailer general field value indicates that the given set of header fields is present in 639 * the trailer of a message encoded with chunked transfer-coding. 640 */ 641 public function getTrailer() 642 { 643 return (string) $this->getHeader('Trailer'); 644 } 645 646 /** 647 * Get the Transfer-Encoding HTTP header 648 * 649 * @return string|null The form of encoding used to safely transfer the entity to the user 650 */ 651 public function getTransferEncoding() 652 { 653 return (string) $this->getHeader('Transfer-Encoding'); 654 } 655 656 /** 657 * Get the Vary HTTP header 658 * 659 * @return string|null Tells downstream proxies how to match future request headers to decide whether the cached 660 * response can be used rather than requesting a fresh one from the origin server. 661 */ 662 public function getVary() 663 { 664 return (string) $this->getHeader('Vary'); 665 } 666 667 /** 668 * Get the Via HTTP header 669 * 670 * @return string|null Informs the client of proxies through which the response was sent. 671 */ 672 public function getVia() 673 { 674 return (string) $this->getHeader('Via'); 675 } 676 677 /** 678 * Get the Warning HTTP header 679 * 680 * @return string|null A general warning about possible problems with the entity body 681 */ 682 public function getWarning() 683 { 684 return (string) $this->getHeader('Warning'); 685 } 686 687 /** 688 * Get the WWW-Authenticate HTTP header 689 * 690 * @return string|null Indicates the authentication scheme that should be used to access the requested entity 691 */ 692 public function getWwwAuthenticate() 693 { 694 return (string) $this->getHeader('WWW-Authenticate'); 695 } 696 697 /** 698 * Checks if HTTP Status code is a Client Error (4xx) 699 * 700 * @return bool 701 */ 702 public function isClientError() 703 { 704 return $this->statusCode >= 400 && $this->statusCode < 500; 705 } 706 707 /** 708 * Checks if HTTP Status code is Server OR Client Error (4xx or 5xx) 709 * 710 * @return boolean 711 */ 712 public function isError() 713 { 714 return $this->isClientError() || $this->isServerError(); 715 } 716 717 /** 718 * Checks if HTTP Status code is Information (1xx) 719 * 720 * @return bool 721 */ 722 public function isInformational() 723 { 724 return $this->statusCode < 200; 725 } 726 727 /** 728 * Checks if HTTP Status code is a Redirect (3xx) 729 * 730 * @return bool 731 */ 732 public function isRedirect() 733 { 734 return $this->statusCode >= 300 && $this->statusCode < 400; 735 } 736 737 /** 738 * Checks if HTTP Status code is Server Error (5xx) 739 * 740 * @return bool 741 */ 742 public function isServerError() 743 { 744 return $this->statusCode >= 500 && $this->statusCode < 600; 745 } 746 747 /** 748 * Checks if HTTP Status code is Successful (2xx | 304) 749 * 750 * @return bool 751 */ 752 public function isSuccessful() 753 { 754 return ($this->statusCode >= 200 && $this->statusCode < 300) || $this->statusCode == 304; 755 } 756 757 /** 758 * Check if the response can be cached based on the response headers 759 * 760 * @return bool Returns TRUE if the response can be cached or false if not 761 */ 762 public function canCache() 763 { 764 // Check if the response is cacheable based on the code 765 if (!in_array((int) $this->getStatusCode(), self::$cacheResponseCodes)) { 766 return false; 767 } 768 769 // Make sure a valid body was returned and can be cached 770 if ((!$this->getBody()->isReadable() || !$this->getBody()->isSeekable()) 771 && ($this->getContentLength() > 0 || $this->getTransferEncoding() == 'chunked')) { 772 return false; 773 } 774 775 // Never cache no-store resources (this is a private cache, so private 776 // can be cached) 777 if ($this->getHeader('Cache-Control') && $this->getHeader('Cache-Control')->hasDirective('no-store')) { 778 return false; 779 } 780 781 return $this->isFresh() || $this->getFreshness() === null || $this->canValidate(); 782 } 783 784 /** 785 * Gets the number of seconds from the current time in which this response is still considered fresh 786 * 787 * @return int|null Returns the number of seconds 788 */ 789 public function getMaxAge() 790 { 791 if ($header = $this->getHeader('Cache-Control')) { 792 // s-max-age, then max-age, then Expires 793 if ($age = $header->getDirective('s-maxage')) { 794 return $age; 795 } 796 if ($age = $header->getDirective('max-age')) { 797 return $age; 798 } 799 } 800 801 if ($this->getHeader('Expires')) { 802 return strtotime($this->getExpires()) - time(); 803 } 804 805 return null; 806 } 807 808 /** 809 * Check if the response is considered fresh. 810 * 811 * A response is considered fresh when its age is less than or equal to the freshness lifetime (maximum age) of the 812 * response. 813 * 814 * @return bool|null 815 */ 816 public function isFresh() 817 { 818 $fresh = $this->getFreshness(); 819 820 return $fresh === null ? null : $fresh >= 0; 821 } 822 823 /** 824 * Check if the response can be validated against the origin server using a conditional GET request. 825 * 826 * @return bool 827 */ 828 public function canValidate() 829 { 830 return $this->getEtag() || $this->getLastModified(); 831 } 832 833 /** 834 * Get the freshness of the response by returning the difference of the maximum lifetime of the response and the 835 * age of the response (max-age - age). 836 * 837 * Freshness values less than 0 mean that the response is no longer fresh and is ABS(freshness) seconds expired. 838 * Freshness values of greater than zero is the number of seconds until the response is no longer fresh. A NULL 839 * result means that no freshness information is available. 840 * 841 * @return int 842 */ 843 public function getFreshness() 844 { 845 $maxAge = $this->getMaxAge(); 846 $age = $this->calculateAge(); 847 848 return $maxAge && $age ? ($maxAge - $age) : null; 849 } 850 851 /** 852 * Parse the JSON response body and return an array 853 * 854 * @return array|string|int|bool|float 855 * @throws RuntimeException if the response body is not in JSON format 856 */ 857 public function json() 858 { 859 $data = json_decode((string) $this->body, true); 860 if (JSON_ERROR_NONE !== json_last_error()) { 861 throw new RuntimeException('Unable to parse response body into JSON: ' . json_last_error()); 862 } 863 864 return $data === null ? array() : $data; 865 } 866 867 /** 868 * Parse the XML response body and return a \SimpleXMLElement. 869 * 870 * In order to prevent XXE attacks, this method disables loading external 871 * entities. If you rely on external entities, then you must parse the 872 * XML response manually by accessing the response body directly. 873 * 874 * @return \SimpleXMLElement 875 * @throws RuntimeException if the response body is not in XML format 876 * @link http://websec.io/2012/08/27/Preventing-XXE-in-PHP.html 877 */ 878 public function xml() 879 { 880 $errorMessage = null; 881 $internalErrors = libxml_use_internal_errors(true); 882 $disableEntities = libxml_disable_entity_loader(true); 883 libxml_clear_errors(); 884 885 try { 886 $xml = new \SimpleXMLElement((string) $this->body ?: '<root />', LIBXML_NONET); 887 if ($error = libxml_get_last_error()) { 888 $errorMessage = $error->message; 889 } 890 } catch (\Exception $e) { 891 $errorMessage = $e->getMessage(); 892 } 893 894 libxml_clear_errors(); 895 libxml_use_internal_errors($internalErrors); 896 libxml_disable_entity_loader($disableEntities); 897 898 if ($errorMessage) { 899 throw new RuntimeException('Unable to parse response body into XML: ' . $errorMessage); 900 } 901 902 return $xml; 903 } 904 905 /** 906 * Get the redirect count of this response 907 * 908 * @return int 909 */ 910 public function getRedirectCount() 911 { 912 return (int) $this->params->get(RedirectPlugin::REDIRECT_COUNT); 913 } 914 915 /** 916 * Set the effective URL that resulted in this response (e.g. the last redirect URL) 917 * 918 * @param string $url The effective URL 919 * 920 * @return self 921 */ 922 public function setEffectiveUrl($url) 923 { 924 $this->effectiveUrl = $url; 925 926 return $this; 927 } 928 929 /** 930 * Get the effective URL that resulted in this response (e.g. the last redirect URL) 931 * 932 * @return string 933 */ 934 public function getEffectiveUrl() 935 { 936 return $this->effectiveUrl; 937 } 938 939 /** 940 * @deprecated 941 * @codeCoverageIgnore 942 */ 943 public function getPreviousResponse() 944 { 945 Version::warn(__METHOD__ . ' is deprecated. Use the HistoryPlugin.'); 946 return null; 947 } 948 949 /** 950 * @deprecated 951 * @codeCoverageIgnore 952 */ 953 public function setRequest($request) 954 { 955 Version::warn(__METHOD__ . ' is deprecated'); 956 return $this; 957 } 958 959 /** 960 * @deprecated 961 * @codeCoverageIgnore 962 */ 963 public function getRequest() 964 { 965 Version::warn(__METHOD__ . ' is deprecated'); 966 return null; 967 } 968} 969