1 <?php
2
3 4 5 6 7 8
9
10 namespace frankmayer\ArangoDbPhpCore\Protocols\Http;
11
12 use frankmayer\ArangoDbPhpCore\ServerException;
13
14
15 16 17 18 19
20 class HttpResponse implements HttpResponseInterface
21 {
22 23 24 25 26
27 public $enabledHttpServerExceptions;
28
29
30 31 32
33 public $request;
34 35 36
37 public $headers = [];
38 39 40
41 public $body;
42 43 44
45 public $batch;
46 47 48
49 public $protocol;
50 51 52
53 public $status;
54 55 56
57 public $statusPhrase;
58 59 60
61 public $verboseExtractStatusLine = false;
62 63 64
65 public $batchContentId;
66
67
68 69 70
71 public function __construct()
72 {
73
74 $this->enabledHttpServerExceptions = [400, 401, 403, 405, 412, 500, 600, 601];
75 }
76
77
78 79 80 81 82 83 84
85 public function build($request)
86 {
87 if ($request instanceof AbstractHttpRequest) {
88 $response = $request->response;
89 $this->request = $request;
90
91 if ($request->batch === true) {
92 $boundary = $request->batchBoundary;
93 $this->batch = $this->deconstructBatchResponseBody($response, $boundary);
94 }
95 } else {
96 $response = $request;
97 }
98 $this->splitResponseToHeadersArrayAndBody($response);
99 $statusLineArray = explode(" ", trim($this->headers['status'][0]));
100
101 $this->status = (int) $statusLineArray[1];
102
103 if ($this->verboseExtractStatusLine === true) {
104 $this->protocol = $statusLineArray[0];
105
106 $this->statusPhrase = $this->decodeGetStatusPhrase($statusLineArray);
107 }
108
109 if (in_array(intval($this->status), $this->enabledHttpServerExceptions)) {
110
111
112 $this->protocol = $statusLineArray[0];
113 $this->statusPhrase = $this->decodeGetStatusPhrase($statusLineArray);
114 throw new ServerException($this->statusPhrase, $this->status);
115
116 }
117
118 return $this;
119 }
120
121
122 123 124 125 126
127 protected function decodeGetStatusPhrase($statusLineArray)
128 {
129 $phrase = '';
130 foreach ($statusLineArray as $key => $part) {
131 if ($key > 1) {
132 $phrase .= $part . ' ';
133 }
134 }
135 $phrase = trim($phrase, " ");
136
137 return $phrase;
138 }
139
140
141 142 143 144 145 146 147 148 149
150 protected function splitResponseToHeadersArrayAndBody($response)
151 {
152
153
154 list($headers, $this->body) = explode("\r\n\r\n", $response, 2);
155
156 $this->headers = $this->getHeaderArray($headers);
157 }
158
159
160 161 162 163 164 165 166
167 public function deconstructBatchResponseBody($batchResponseBody, $boundary)
168 {
169 $connector = $this->request->client->connector;
170 $batchObjects = [];
171 $batchResponseBody = rtrim($batchResponseBody, '--' . $boundary . '--');
172
173 $batchParts = explode('--' . $boundary . $connector::HTTP_EOL, $batchResponseBody);
174 array_shift($batchParts);
175 $i = 0;
176 foreach ($batchParts as &$batchPart) {
177
178 $batchPartHeaders = static::splitBatchPart($batchPart);
179
180 $batchObject = new static();
181 $batchObject->build($batchPartHeaders[1]);
182
183 $batchArangoHeaderArray = $this->getHeaderArray($batchPartHeaders[0]);
184 if (array_key_exists('Content-Id', $batchArangoHeaderArray)) {
185 $batchObject->batchContentId = $batchArangoHeaderArray['Content-Id'][0];
186 }
187 $batchObjects[] = $batchObject;
188 $i++;
189 }
190
191 return $batchObjects;
192 }
193
194
195 196 197 198 199
200 public static function splitBatchPart($batchPart)
201 {
202 $parts = explode("\r\n\r\n", trim($batchPart), 2);
203
204 return $parts;
205 }
206
207
208 209 210
211 public function setBatch($batch)
212 {
213 $this->batch = $batch;
214 }
215
216 217 218
219 public function getBatch()
220 {
221 return $this->batch;
222 }
223
224 225 226
227 public function setBody($body)
228 {
229 $this->body = $body;
230 }
231
232 233 234
235 public function getBody()
236 {
237 return $this->body;
238 }
239
240 241 242
243 public function setHeaders($headers)
244 {
245 $this->headers = $headers;
246 }
247
248 249 250
251 public function getHeaders()
252 {
253 return $this->headers;
254 }
255
256 257 258
259 public function setRequest($request)
260 {
261 $this->request = $request;
262 }
263
264 265 266
267 public function getRequest()
268 {
269 return $this->request;
270 }
271
272 273 274
275 public function setStatus($status)
276 {
277 $this->status = $status;
278 }
279
280 281 282
283 public function getStatus()
284 {
285 return $this->status;
286 }
287
288 289 290
291 public function getProtocol()
292 {
293 return $this->protocol;
294 }
295
296 297 298
299 public function getStatusPhrase()
300 {
301 return $this->statusPhrase;
302 }
303
304 305 306
307 public function setVerboseExtractStatusLine($verboseStatusLine)
308 {
309 $this->verboseExtractStatusLine = $verboseStatusLine;
310 }
311
312 313 314
315 public function getVerboseExtractStatusLine()
316 {
317 return $this->verboseExtractStatusLine;
318 }
319
320 321 322 323 324
325 protected function getHeaderArray($headers)
326 {
327 $headerArray = [];
328 $headersArray = explode("\r\n", trim($headers));
329 foreach ($headersArray as $line => $header) {
330 if ($line > 0) {
331 $pair = explode(": ", $header);
332 $headerArray[$pair[0]][] = $pair[1];
333 } else {
334 $headerArray['status'][] = $header;
335 }
336 }
337
338 return $headerArray;
339 }
340 }
341