Completed
Pull Request — master (#15)
by Michal
28:17
created

ResponseModel::dataToArray()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4.0092

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 16
ccs 11
cts 12
cp 0.9167
rs 9.2
cc 4
eloc 10
nc 5
nop 1
crap 4.0092
1
<?php
2
3
namespace MediaMonks\RestApiBundle\Model;
4
5
use MediaMonks\RestApiBundle\Exception\AbstractValidationException;
6
use MediaMonks\RestApiBundle\Exception\ExceptionInterface;
7
use MediaMonks\RestApiBundle\Response\Error;
8
use MediaMonks\RestApiBundle\Response\PaginatedResponseInterface;
9
use MediaMonks\RestApiBundle\Util\StringUtil;
10
use Symfony\Component\HttpFoundation\RedirectResponse;
11
use Symfony\Component\HttpFoundation\Response;
12
use Symfony\Component\HttpKernel\Exception\HttpException;
13
14
class ResponseModel
15
{
16
    const EXCEPTION_GENERAL = 'Exception';
17
    const EXCEPTION_HTTP = 'HttpException';
18
19
    /**
20
     * @var int
21
     */
22
    protected $statusCode = Response::HTTP_OK;
23
24
    /**
25
     * @var bool
26
     */
27
    protected $returnStatusCode = false;
28
29
    /**
30
     * @var bool
31
     */
32
    protected $returnStackTrace = false;
33
34
    /**
35
     * @var mixed
36
     */
37
    protected $data;
38
39
    /**
40
     * @var Response
41
     */
42
    protected $response;
43
44
    /**
45
     * @var \Exception
46
     */
47
    protected $exception;
48
49
    /**
50
     * @var PaginatedResponseInterface
51
     */
52
    protected $pagination;
53
54
    /**
55
     * @return boolean
56
     */
57 14
    public function isReturnStackTrace()
58
    {
59 14
        return $this->returnStackTrace;
60
    }
61
62
    /**
63
     * @param boolean $returnStackTrace
64
     * @return $this
65
     */
66 22
    public function setReturnStackTrace($returnStackTrace)
67
    {
68 22
        $this->returnStackTrace = $returnStackTrace;
69
70 22
        return $this;
71
    }
72
73
    /**
74
     * @return int
75
     */
76 33
    public function getStatusCode()
77
    {
78 33
        if (isset($this->exception)) {
79 13
            return $this->getExceptionStatusCode();
80
        }
81 20
        if ($this->isEmpty()) {
82 3
            return Response::HTTP_NO_CONTENT;
83
        }
84
85 18
        return $this->statusCode;
86
    }
87
88
    /**
89
     * @return int
90
     */
91 13
    protected function getExceptionStatusCode()
92
    {
93 13
        if ($this->exception instanceof HttpException) {
94 4
            return $this->exception->getStatusCode();
95
        }
96 9
        if ($this->exception instanceof AbstractValidationException) {
97 4
            return Response::HTTP_BAD_REQUEST;
98
        }
99 5
        if ($this->isValidHttpStatusCode($this->exception->getCode())) {
100 2
            return $this->exception->getCode();
101
        }
102
103 3
        return Response::HTTP_INTERNAL_SERVER_ERROR;
104
    }
105
106
    /**
107
     * @param int $code
108
     * @return bool
109
     */
110 5
    protected function isValidHttpStatusCode($code)
111
    {
112 5
        return array_key_exists($code, Response::$statusTexts) && $code >= Response::HTTP_BAD_REQUEST;
113
    }
114
115
    /**
116
     * @param int $statusCode
117
     * @return $this
118
     */
119 10
    public function setStatusCode($statusCode)
120
    {
121 10
        $this->statusCode = $statusCode;
122
123 10
        return $this;
124
    }
125
126
    /**
127
     * @return bool
128
     */
129 29
    public function getReturnStatusCode()
130
    {
131 29
        return $this->returnStatusCode;
132
    }
133
134
    /**
135
     * @param bool $returnStatusCode
136
     * @return $this
137
     */
138 3
    public function setReturnStatusCode($returnStatusCode)
139
    {
140 3
        $this->returnStatusCode = $returnStatusCode;
141
142 3
        return $this;
143
    }
144
145
    /**
146
     * @return mixed
147
     */
148 10
    public function getData()
149
    {
150 10
        return $this->data;
151
    }
152
153
    /**
154
     * @param mixed $data
155
     * @return $this
156
     */
157 25
    public function setData($data)
158
    {
159 25
        $this->data = $data;
160
161 25
        return $this;
162
    }
163
164
    /**
165
     * @return \Exception
166
     */
167 11
    public function getException()
168
    {
169 11
        return $this->exception;
170
    }
171
172
    /**
173
     * @param \Exception $exception
174
     * @return $this
175
     */
176 17
    public function setException(\Exception $exception)
177
    {
178 17
        $this->exception = $exception;
179
180 17
        return $this;
181
    }
182
183
    /**
184
     * @return PaginatedResponseInterface
185
     */
186 11
    public function getPagination()
187
    {
188 11
        return $this->pagination;
189
    }
190
191
    /**
192
     * @param PaginatedResponseInterface $pagination
193
     * @return $this
194
     */
195 4
    public function setPagination(PaginatedResponseInterface $pagination)
196
    {
197 4
        $this->pagination = $pagination;
198 4
        $this->setData($pagination->getData());
199
200 4
        return $this;
201
    }
202
203
    /**
204
     * @return Response
205
     */
206 11
    public function getResponse()
207
    {
208 11
        return $this->response;
209
    }
210
211
    /**
212
     * @param Response $response
213
     * @return ResponseModel
214
     */
215 8
    public function setResponse(Response $response)
216
    {
217 8
        $this->response = $response;
218 8
        $this->setStatusCode($response->getStatusCode());
219 8
        $this->setData($response->getContent());
220
221 8
        return $this;
222
    }
223
224
    /**
225
     * @param bool $wrapResponse
226
     * @return array|string
227
     */
228 28
    public function toArray($wrapResponse = true)
229
    {
230 28
        $return = [];
231 28
        if ($wrapResponse && $this->getReturnStatusCode()) {
232 2
            $return['statusCode'] = $this->getStatusCode();
233 2
        }
234 28
        if (isset($this->exception)) {
235 14
            if ($wrapResponse) {
236 14
                $return['error'] = $this->exceptionToArray();
237 14
            } else {
238
                return $this->exceptionToArray();
239
            }
240 28
        } elseif (isset($this->response) && $this->response instanceof RedirectResponse) {
241 2
            if ($wrapResponse) {
242 2
                $return['location'] = $this->response->headers->get('Location');
243 2
            } else {
244
                return $this->response->headers->get('Location');
245
            }
246 2
        } else {
247 12
            if ($wrapResponse) {
248 12
                $return += $this->dataToArray();
249 12
            } else {
250
                return $this->dataToArray($wrapResponse);
251
            }
252
        }
253
254 28
        return $return;
255
    }
256
257
    /**
258
     * @param bool $wrapResponse
259
     * @return array|mixed
260
     */
261 12
    protected function dataToArray($wrapResponse = true)
262
    {
263 12
        $return = [];
264 12
        if (isset($this->data)) {
265 11
            if ($wrapResponse) {
266 11
                $return['data'] = $this->data;
267 11
            } else {
268
                $return = $this->data;
269
            }
270 11
            if (isset($this->pagination)) {
271 3
                $return['pagination'] = $this->pagination->toArray();
272 3
            }
273 11
        }
274
275 12
        return $return;
276
    }
277
278
    /**
279
     * @return array
280
     */
281 14
    protected function exceptionToArray()
282
    {
283 14
        if ($this->exception instanceof ExceptionInterface) {
284 4
            $error = $this->exception->toArray();
285 14
        } elseif ($this->exception instanceof HttpException) {
286 4
            $error = $this->httpExceptionToArray();
287 4
        } else {
288 6
            $error = $this->generalExceptionToArray();
289
        }
290 14
        if ($this->isReturnStackTrace()) {
291 10
            $error['stack_trace'] = $this->getExceptionStackTrace();
292 10
        }
293
294 14
        return $error;
295
    }
296
297
    /**
298
     * @return string
299
     */
300 10
    protected function getExceptionStackTrace()
301
    {
302 10
        $traces = [];
303 10
        foreach ($this->exception->getTrace() as $trace) {
304 10
            $trace['args'] = json_decode(json_encode($trace['args']), true);
305 10
            $traces[] = $trace;
306 10
        }
307
308 10
        return $traces;
309
    }
310
311
    /**
312
     * @return array
313
     */
314 4
    protected function httpExceptionToArray()
315
    {
316
        return [
317 4
            'code'    => $this->getExceptionErrorCode(Error::CODE_HTTP, self::EXCEPTION_HTTP),
318 4
            'message' => $this->exception->getMessage(),
319 4
        ];
320
    }
321
322
    /**
323
     * @return array
324
     */
325 6
    protected function generalExceptionToArray()
326
    {
327
        return [
328 6
            'code'    => trim($this->getExceptionErrorCode(Error::CODE_GENERAL, self::EXCEPTION_GENERAL), '.'),
329 6
            'message' => $this->exception->getMessage(),
330 6
        ];
331
    }
332
333
    /**
334
     * @param string $errorCode
335
     * @param string $trim
336
     * @return string
337
     */
338 10
    protected function getExceptionErrorCode($errorCode, $trim = null)
339
    {
340 10
        return sprintf($errorCode, StringUtil::classToSnakeCase($this->exception, $trim));
341
    }
342
343
    /**
344
     * @return bool
345
     */
346 23
    public function isEmpty()
347
    {
348
        return (
349 23
            !isset($this->exception)
350 23
            && is_null($this->data)
351 23
            && !isset($this->pagination)
352 23
            && $this->isEmptyResponse()
353 23
        );
354
    }
355
356
    /**
357
     * @return bool
358
     */
359 3
    protected function isEmptyResponse()
360
    {
361 3
        return !isset($this->response) || $this->response->isEmpty();
362
    }
363
364
    // @codeCoverageIgnoreStart
365
    /**
366
     * This is called when an exception is thrown during the response transformation
367
     *
368
     * @return string
369
     */
370
    public function __toString()
371
    {
372
        $data = $this->toArray();
373
        $data['error']['code'] = Error::CODE_REST_API_BUNDLE;
374
375
        return json_encode($data);
376
    }
377
    // @codeCoverageIgnoreEnd
378
}
379