Completed
Push — master ( dfa8b0...b3dd5a )
by
unknown
08:57
created

forceEmptyResponseOnHttpNoContent()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
crap 2
1
<?php
2
3
namespace MediaMonks\RestApi\Response;
4
5
use MediaMonks\RestApi\Model\ResponseModelFactory;
6
use MediaMonks\RestApi\Model\ResponseModelInterface;
7
use MediaMonks\RestApi\Request\Format;
8
use MediaMonks\RestApi\Serializer\SerializerInterface;
9
use Symfony\Component\HttpFoundation\Request;
10
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
11
use Symfony\Component\HttpFoundation\JsonResponse as SymfonyJsonResponse;
12
13
class ResponseTransformer implements ResponseTransformerInterface
14
{
15
16
    const WRAPPER_PADDING = 'padding';
17
18
    const WRAPPER_POST_MESSAGE = 'postMessage';
19
20
    const PARAMETER_CALLBACK = 'callback';
21
22
    const PARAMETER_WRAPPER = '_wrapper';
23
24
    /**
25
     * @var SerializerInterface
26
     */
27
    protected $serializer;
28
29
    /**
30
     * @var bool
31
     */
32
    protected $debug = false;
33
34
    /**
35
     * @var string
36
     */
37
    protected $postMessageOrigin;
38
39
    /**
40
     * @var ResponseModelFactory
41
     */
42
    protected $responseModelFactory;
43
44
    /**
45
     * @param SerializerInterface $serializer
46
     * @param ResponseModelFactory $responseModelFactory
47
     * @param array $options
48
     */
49 16
    public function __construct(
50
        SerializerInterface $serializer,
51
        ResponseModelFactory $responseModelFactory,
52
        $options = []
53
    ) {
54 16
        $this->serializer = $serializer;
55 16
        $this->responseModelFactory = $responseModelFactory;
56
57 16
        $this->setOptions($options);
58 16
    }
59
60
    /**
61
     * @param array $options
62
     */
63 16
    public function setOptions(array $options)
64
    {
65 16
        if (isset($options['debug'])) {
66 2
            $this->setDebug($options['debug']);
67 2
        }
68 16
        if (isset($options['post_message_origin'])) {
69 3
            $this->setPostMessageOrigin($options['post_message_origin']);
70 3
        }
71 16
    }
72
73
    /**
74
     * @return boolean
75
     */
76 5
    public function isDebug()
77
    {
78 5
        return $this->debug;
79
    }
80
81
    /**
82
     * @param boolean $debug
83
     *
84
     * @return ResponseTransformer
85
     */
86 2
    public function setDebug($debug)
87
    {
88 2
        $this->debug = $debug;
89
90 2
        return $this;
91
    }
92
93
    /**
94
     * @return string
95
     */
96 5
    public function getPostMessageOrigin()
97
    {
98 5
        return $this->postMessageOrigin;
99
    }
100
101
    /**
102
     * @param string $postMessageOrigin
103
     *
104
     * @return ResponseTransformer
105
     */
106 4
    public function setPostMessageOrigin($postMessageOrigin)
107
    {
108 4
        $this->postMessageOrigin = $postMessageOrigin;
109
110 4
        return $this;
111
    }
112
113
    /**
114
     * @param Request $request
115
     * @param SymfonyResponse $response
116
     *
117
     * @return SymfonyResponse
118
     */
119 4
    public function transformEarly(Request $request, SymfonyResponse $response)
120
    {
121 4
        $responseModel = $response->getContent();
122
123 4
        if (!$responseModel instanceof ResponseModelInterface) {
124 1
            $responseModel = $this->responseModelFactory->createFromContent(
125
                $response
126 1
            );
127 1
        }
128
129 4
        $responseModel->setReturnStackTrace($this->isDebug());
130 4
        $response->setStatusCode($responseModel->getStatusCode());
131 4
        $this->forceStatusCodeHttpOK($request, $response, $responseModel);
132 4
        $response = $this->createSerializedResponse(
133 4
            $request,
134 4
            $response,
135
            $responseModel
136 4
        );
137
138 4
        return $response;
139
    }
140
141
    /**
142
     * @param Request $request
143
     * @param SymfonyResponse $response
144
     */
145 4
    public function transformLate(Request $request, SymfonyResponse $response)
146
    {
147 4
        if ($request->getRequestFormat() === Format::FORMAT_JSON
148 4
            && $request->query->has(self::PARAMETER_CALLBACK)
149 4
            && $response instanceof JsonResponse
150 4
        ) {
151 2
            $this->wrapResponse($request, $response);
152 2
        }
153
154 4
        $this->forceEmptyResponseOnHttpNoContent($response);
155 4
    }
156
157
    /**
158
     * @param $data
159
     *
160
     * @return Response
161
     */
162 1
    public function createResponseFromContent($data)
163
    {
164 1
        return new Response(
165 1
            $this->responseModelFactory->createFromContent($data)
0 ignored issues
show
Documentation introduced by
$this->responseModelFact...reateFromContent($data) is of type object<MediaMonks\RestAp...ResponseModelInterface>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
166 1
        );
167
    }
168
169
    /**
170
     * Check if we should put the status code in the output and force a 200 OK
171
     * in the header
172
     *
173
     * @param Request $request
174
     * @param SymfonyResponse $response
175
     * @param ResponseModelInterface $responseModel
176
     */
177 4
    protected function forceStatusCodeHttpOK(
178
        Request $request,
179
        SymfonyResponse $response,
180
        ResponseModelInterface $responseModel
181
    ) {
182 4
        if ($request->headers->has('X-Force-Status-Code-200')
183 1
            || ($request->getRequestFormat(
184 1
                ) == Format::FORMAT_JSON && $request->query->has(
185
                    self::PARAMETER_CALLBACK
186 1
                ))
187 4
        ) {
188 3
            $responseModel->setReturnStatusCode(true);
189 3
            $response->setStatusCode(Response::HTTP_OK);
190 3
            $response->headers->set('X-Status-Code', Response::HTTP_OK);
191 3
        }
192 4
    }
193
194
    /**
195
     * Make sure content is empty when the status code is "204 NoContent"
196
     *
197
     * @param SymfonyResponse $response
198
     */
199 4
    protected function forceEmptyResponseOnHttpNoContent(
200
        SymfonyResponse $response
201
    ) {
202 4
        if ($response->getStatusCode() === Response::HTTP_NO_CONTENT) {
203 1
            $response->setContent(null);
204 1
            $response->headers->remove('Content-Type');
205 1
        }
206 4
    }
207
208
    /**
209
     * @param Request $request
210
     * @param SymfonyResponse $response
211
     * @param ResponseModelInterface $responseModel
212
     *
213
     * @return SymfonyResponse
214
     */
215 4
    protected function createSerializedResponse(
216
        Request $request,
217
        SymfonyResponse $response,
218
        ResponseModelInterface $responseModel
219
    ) {
220
        try {
221 4
            $response = $this->serialize($request, $response, $responseModel);
222 4
        } catch (\Exception $e) {
223 1
            $response = new SymfonyJsonResponse(
224
                [
225
                    'error' => [
226 1
                        'code' => Error::CODE_SERIALIZE,
227 1
                        'message' => $e->getMessage(),
228 1
                    ],
229
                ]
230 1
            );
231
        }
232
233 4
        return $response;
234
    }
235
236
    /**
237
     * @param Request $request
238
     * @param SymfonyResponse $response
239
     * @param ResponseModelInterface $responseModel
240
     *
241
     * @return JsonResponse|SymfonyResponse
242
     */
243 4
    protected function serialize(
244
        Request $request,
245
        SymfonyResponse $response,
246
        ResponseModelInterface $responseModel
247
    ) {
248 4
        switch ($request->getRequestFormat()) {
249 4
            case Format::FORMAT_XML:
250 2
                $response->setContent(
251 2
                    $this->getSerializedContent($request, $responseModel)
252 2
                );
253 2
                break;
254 2
            default:
255 2
                $headers = $response->headers;
256 2
                $response = new JsonResponse(
257 2
                    $this->getSerializedContent($request, $responseModel),
258 1
                    $response->getStatusCode()
259 1
                );
260 1
                $response->headers = $headers; // some headers might mess up if we pass it to the JsonResponse
261 1
                break;
262 4
        }
263
264 3
        return $response;
265
    }
266
267
    /**
268
     * @param Request $request
269
     * @param ResponseModelInterface $responseModel
270
     *
271
     * @return mixed|string
272
     */
273 4
    protected function getSerializedContent(
274
        Request $request,
275
        ResponseModelInterface $responseModel
276
    ) {
277 4
        return $this->serializer->serialize(
278 4
            $responseModel->toArray(),
279 3
            $request->getRequestFormat()
280 3
        );
281
    }
282
283
    /**
284
     * @param Request $request
285
     * @param JsonResponse $response
286
     *
287
     * @throws \Exception
288
     */
289 2
    protected function wrapResponse(Request $request, JsonResponse $response)
290
    {
291 2
        switch ($request->query->get(self::PARAMETER_WRAPPER)) {
292 2
            case self::WRAPPER_POST_MESSAGE:
293 1
                $response->setContent(
294 1
                    sprintf(
295 1
                        $this->getPostMessageTemplate(),
296 1
                        $response->getContent(),
297 1
                        $this->getCallbackFromRequest($request),
298 1
                        $this->getPostMessageOrigin()
299 1
                    )
300 1
                )->headers->set('Content-Type', 'text/html');
301 1
                break;
302 1
            default:
303 1
                $response->setCallback(
304 1
                    $request->query->get(self::PARAMETER_CALLBACK)
305 1
                );
306 1
                break;
307 2
        }
308 2
    }
309
310
    /**
311
     * @param Request $request
312
     *
313
     * @return string
314
     */
315 1
    protected function getCallbackFromRequest(Request $request)
316
    {
317 1
        $response = new JsonResponse('');
318 1
        $response->setCallback($request->query->get(self::PARAMETER_CALLBACK));
319
320 1
        return $response->getCallback();
321
    }
322
323
    /**
324
     * @return string
325
     */
326 1
    protected function getPostMessageTemplate()
327
    {
328
        return <<<EOD
329
<html>
330
<body>
331
<script>
332
    try {
333
        var data = %s;
334
    }
335
    catch (error) {
336
        var data = {"error": {"code": "error.parse.post_message", "message": "Post message parse error"}};
337
    }
338
339
    top.postMessage(JSON.stringify({
340
        name: '%s',
341
        result: data
342
    }), '%s');
343
</script>
344
</body>
345
</html>
346 1
EOD;
347
    }
348
}
349