1<?php
2/**
3 * Copyright 2017 Facebook, Inc.
4 *
5 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6 * use, copy, modify, and distribute this software in source code or binary
7 * form for use in connection with the web services and APIs provided by
8 * Facebook.
9 *
10 * As with any software that integrates with the Facebook platform, your use
11 * of this software is subject to the Facebook Developer Principles and
12 * Policies [http://developers.facebook.com/policy/]. This copyright notice
13 * shall be included in all copies or substantial portions of the software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 */
24namespace Facebook\Http;
25
26/**
27 * Class GraphRawResponse
28 *
29 * @package Facebook
30 */
31class GraphRawResponse
32{
33    /**
34     * @var array The response headers in the form of an associative array.
35     */
36    protected $headers;
37
38    /**
39     * @var string The raw response body.
40     */
41    protected $body;
42
43    /**
44     * @var int The HTTP status response code.
45     */
46    protected $httpResponseCode;
47
48    /**
49     * Creates a new GraphRawResponse entity.
50     *
51     * @param string|array $headers        The headers as a raw string or array.
52     * @param string       $body           The raw response body.
53     * @param int          $httpStatusCode The HTTP response code (if sending headers as parsed array).
54     */
55    public function __construct($headers, $body, $httpStatusCode = null)
56    {
57        if (is_numeric($httpStatusCode)) {
58            $this->httpResponseCode = (int)$httpStatusCode;
59        }
60
61        if (is_array($headers)) {
62            $this->headers = $headers;
63        } else {
64            $this->setHeadersFromString($headers);
65        }
66
67        $this->body = $body;
68    }
69
70    /**
71     * Return the response headers.
72     *
73     * @return array
74     */
75    public function getHeaders()
76    {
77        return $this->headers;
78    }
79
80    /**
81     * Return the body of the response.
82     *
83     * @return string
84     */
85    public function getBody()
86    {
87        return $this->body;
88    }
89
90    /**
91     * Return the HTTP response code.
92     *
93     * @return int
94     */
95    public function getHttpResponseCode()
96    {
97        return $this->httpResponseCode;
98    }
99
100    /**
101     * Sets the HTTP response code from a raw header.
102     *
103     * @param string $rawResponseHeader
104     */
105    public function setHttpResponseCodeFromHeader($rawResponseHeader)
106    {
107        preg_match('|HTTP/\d\.\d\s+(\d+)\s+.*|', $rawResponseHeader, $match);
108        $this->httpResponseCode = (int)$match[1];
109    }
110
111    /**
112     * Parse the raw headers and set as an array.
113     *
114     * @param string $rawHeaders The raw headers from the response.
115     */
116    protected function setHeadersFromString($rawHeaders)
117    {
118        // Normalize line breaks
119        $rawHeaders = str_replace("\r\n", "\n", $rawHeaders);
120
121        // There will be multiple headers if a 301 was followed
122        // or a proxy was followed, etc
123        $headerCollection = explode("\n\n", trim($rawHeaders));
124        // We just want the last response (at the end)
125        $rawHeader = array_pop($headerCollection);
126
127        $headerComponents = explode("\n", $rawHeader);
128        foreach ($headerComponents as $line) {
129            if (strpos($line, ': ') === false) {
130                $this->setHttpResponseCodeFromHeader($line);
131            } else {
132                list($key, $value) = explode(': ', $line, 2);
133                $this->headers[$key] = $value;
134            }
135        }
136    }
137}
138