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;
25
26use ArrayIterator;
27use IteratorAggregate;
28use ArrayAccess;
29
30/**
31 * Class FacebookBatchResponse
32 *
33 * @package Facebook
34 */
35class FacebookBatchResponse extends FacebookResponse implements IteratorAggregate, ArrayAccess
36{
37    /**
38     * @var FacebookBatchRequest The original entity that made the batch request.
39     */
40    protected $batchRequest;
41
42    /**
43     * @var array An array of FacebookResponse entities.
44     */
45    protected $responses = [];
46
47    /**
48     * Creates a new Response entity.
49     *
50     * @param FacebookBatchRequest $batchRequest
51     * @param FacebookResponse     $response
52     */
53    public function __construct(FacebookBatchRequest $batchRequest, FacebookResponse $response)
54    {
55        $this->batchRequest = $batchRequest;
56
57        $request = $response->getRequest();
58        $body = $response->getBody();
59        $httpStatusCode = $response->getHttpStatusCode();
60        $headers = $response->getHeaders();
61        parent::__construct($request, $body, $httpStatusCode, $headers);
62
63        $responses = $response->getDecodedBody();
64        $this->setResponses($responses);
65    }
66
67    /**
68     * Returns an array of FacebookResponse entities.
69     *
70     * @return array
71     */
72    public function getResponses()
73    {
74        return $this->responses;
75    }
76
77    /**
78     * The main batch response will be an array of requests so
79     * we need to iterate over all the responses.
80     *
81     * @param array $responses
82     */
83    public function setResponses(array $responses)
84    {
85        $this->responses = [];
86
87        foreach ($responses as $key => $graphResponse) {
88            $this->addResponse($key, $graphResponse);
89        }
90    }
91
92    /**
93     * Add a response to the list.
94     *
95     * @param int        $key
96     * @param array|null $response
97     */
98    public function addResponse($key, $response)
99    {
100        $originalRequestName = isset($this->batchRequest[$key]['name']) ? $this->batchRequest[$key]['name'] : $key;
101        $originalRequest = isset($this->batchRequest[$key]['request']) ? $this->batchRequest[$key]['request'] : null;
102
103        $httpResponseBody = isset($response['body']) ? $response['body'] : null;
104        $httpResponseCode = isset($response['code']) ? $response['code'] : null;
105        // @TODO With PHP 5.5 support, this becomes array_column($response['headers'], 'value', 'name')
106        $httpResponseHeaders = isset($response['headers']) ? $this->normalizeBatchHeaders($response['headers']) : [];
107
108        $this->responses[$originalRequestName] = new FacebookResponse(
109            $originalRequest,
110            $httpResponseBody,
111            $httpResponseCode,
112            $httpResponseHeaders
113        );
114    }
115
116    /**
117     * @inheritdoc
118     */
119    public function getIterator()
120    {
121        return new ArrayIterator($this->responses);
122    }
123
124    /**
125     * @inheritdoc
126     */
127    public function offsetSet($offset, $value)
128    {
129        $this->addResponse($offset, $value);
130    }
131
132    /**
133     * @inheritdoc
134     */
135    public function offsetExists($offset)
136    {
137        return isset($this->responses[$offset]);
138    }
139
140    /**
141     * @inheritdoc
142     */
143    public function offsetUnset($offset)
144    {
145        unset($this->responses[$offset]);
146    }
147
148    /**
149     * @inheritdoc
150     */
151    public function offsetGet($offset)
152    {
153        return isset($this->responses[$offset]) ? $this->responses[$offset] : null;
154    }
155
156    /**
157     * Converts the batch header array into a standard format.
158     * @TODO replace with array_column() when PHP 5.5 is supported.
159     *
160     * @param array $batchHeaders
161     *
162     * @return array
163     */
164    private function normalizeBatchHeaders(array $batchHeaders)
165    {
166        $headers = [];
167
168        foreach ($batchHeaders as $header) {
169            $headers[$header['name']] = $header['value'];
170        }
171
172        return $headers;
173    }
174}
175