Completed
Push — master ( f2d7cc...c90f48 )
by Robert
04:06
created

ResponseTransformer::isDebug()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace MediaMonks\RestApiBundle\Response;
4
5
use JMS\Serializer\SerializationContext;
6
use JMS\Serializer\Serializer;
7
use MediaMonks\RestApiBundle\Model\ResponseModel;
8
use MediaMonks\RestApiBundle\Model\ResponseModelFactory;
9
use MediaMonks\RestApiBundle\Request\Format;
10
use Symfony\Component\HttpFoundation\Request;
11
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
12
use Symfony\Component\HttpFoundation\JsonResponse as SymfonyJsonResponse;
13
14
class ResponseTransformer implements ResponseTransformerInterface
15
{
16
    const WRAPPER_PADDING = 'padding';
17
    const WRAPPER_POST_MESSAGE = 'postMessage';
18
19
    const PARAMETER_CALLBACK = 'callback';
20
    const PARAMETER_WRAPPER = '_wrapper';
21
22
    /**
23
     * @var Serializer
24
     */
25
    protected $serializer;
26
27
    /**
28
     * @var \Twig_Environment
29
     */
30
    protected $twig;
31
32
    /**
33
     * @var bool
34
     */
35
    protected $debug = false;
36
37
    /**
38
     * @var string
39
     */
40
    protected $postMessageOrigin;
41
42
    /**
43
     * @var ResponseModelFactory
44
     */
45
    protected $responseModelFactory;
46
47
    /**
48
     * ResponseTransformer constructor.
49
     * @param Serializer $serializer
50
     * @param \Twig_Environment $twig
51
     * @param array $options
52
     */
53 32
    public function __construct(Serializer $serializer, \Twig_Environment $twig, $options = [])
54
    {
55 32
        $this->serializer = $serializer;
56 32
        $this->twig       = $twig;
57 32
        $this->setOptions($options);
58 32
    }
59
60
    /**
61
     * @param array $options
62
     */
63 32
    public function setOptions(array $options)
64
    {
65 32
        if (isset($options['debug'])) {
66 19
            $this->setDebug($options['debug']);
67 19
        }
68 32
        if (isset($options['post_message_origin'])) {
69 2
            $this->setPostMessageOrigin($options['post_message_origin']);
70 2
        }
71 32
    }
72
73
    /**
74
     * @return boolean
75
     */
76 23
    public function isDebug()
77
    {
78 23
        return $this->debug;
79
    }
80
81
    /**
82
     * @param boolean $debug
83
     * @return ResponseTransformer
84
     */
85 19
    public function setDebug($debug)
86 1
    {
87 19
        $this->debug = $debug;
88 19
        return $this;
89
    }
90
91
    /**
92
     * @return string
93
     */
94 5
    public function getPostMessageOrigin()
95
    {
96 5
        return $this->postMessageOrigin;
97
    }
98
99
    /**
100
     * @param string $postMessageOrigin
101
     * @return ResponseTransformer
102
     */
103 3
    public function setPostMessageOrigin($postMessageOrigin)
104
    {
105 3
        $this->postMessageOrigin = $postMessageOrigin;
106 3
        return $this;
107
    }
108
109
    /**
110
     * @param Request $request
111
     * @param SymfonyResponse $response
112
     * @return SymfonyResponse
113
     */
114 23
    public function transformEarly(Request $request, SymfonyResponse $response)
115
    {
116 23
        $responseModel = $response->getContent();
117
118 23
        if (!$responseModel instanceof ResponseModel) {
119 4
            $responseModel = $this->getResponseModelFactory()->createFromContent($response);
120 4
        }
121
122 23
        $responseModel->setReturnStackTrace($this->isDebug());
123 23
        $response->setStatusCode($responseModel->getStatusCode());
124 23
        $this->forceStatusCodeHttpOK($request, $response, $responseModel);
125 23
        $response = $this->createSerializedResponse($request, $response, $responseModel);
126
127 23
        return $response;
128
    }
129
130
    /**
131
     * @param ResponseModelFactory $factory
132
     */
133 2
    public function setResponseModelFactory($factory)
134
    {
135 2
        $this->responseModelFactory = $factory;
136 2
    }
137
138
    /**
139
     * @return ResponseModelFactory
140
     */
141 6
    public function getResponseModelFactory()
142
    {
143 6
        if (!isset($this->responseModelFactory)) {
144 4
            $this->responseModelFactory = ResponseModelFactory::createFactory();
145 4
        }
146
147 6
        return $this->responseModelFactory;
148
    }
149
150
    /**
151
     * @param Request $request
152
     * @param SymfonyResponse $response
153
     */
154 22
    public function transformLate(Request $request, SymfonyResponse $response)
155
    {
156 22
        if ($request->getRequestFormat() === Format::FORMAT_JSON
157 22
            && $request->query->has(self::PARAMETER_CALLBACK)
158 22
            && $response instanceof JsonResponse
159 22
        ) {
160 2
            $this->wrapResponse($request, $response);
161 2
        }
162 22
    }
163
164
    /**
165
     * Check if we should put the status code in the output and force a 200 OK in the header
166
     *
167
     * @param Request $request
168
     * @param SymfonyResponse $response
169
     * @param ResponseModel $responseModel
170
     */
171 23
    protected function forceStatusCodeHttpOK(
172
        Request $request,
173
        SymfonyResponse $response,
174
        ResponseModel $responseModel
175
    ) {
176 23
        if ($request->headers->has('X-Force-Status-Code-200')
177 20
            || ($request->getRequestFormat() == Format::FORMAT_JSON && $request->query->has(self::PARAMETER_CALLBACK))
178 23
        ) {
179 3
            $responseModel->setReturnStatusCode(true);
180 3
            $response->setStatusCode(Response::HTTP_OK);
181 3
            $response->headers->set('X-Status-Code', Response::HTTP_OK);
182 3
        }
183 23
    }
184
185
    /**
186
     * @param Request $request
187
     * @param SymfonyResponse $response
188
     * @param ResponseModel $responseModel
189
     * @return SymfonyResponse
190
     */
191 23
    protected function createSerializedResponse(
192
        Request $request,
193
        SymfonyResponse $response,
194
        ResponseModel $responseModel
195
    ) {
196
        try {
197 23
            $response = $this->serialize($request, $response, $responseModel);
198 23
        } catch (\Exception $e) {
199 1
            $response = new SymfonyJsonResponse([
200
                'error' => [
201 1
                    'code'    => Error::CODE_SERIALIZE,
202 1
                    'message' => $e->getMessage()
203 1
                ]
204 1
            ]);
205
        }
206
207 23
        return $response;
208
    }
209
210
    /**
211
     * @param Request $request
212
     * @param SymfonyResponse $response
213
     * @param ResponseModel $responseModel
214
     * @return JsonResponse|SymfonyResponse
215
     */
216 23
    protected function serialize(Request $request, SymfonyResponse $response, ResponseModel $responseModel)
217
    {
218 23
        switch ($request->getRequestFormat()) {
219 23
            case Format::FORMAT_XML:
220 2
                $response->setContent($this->getSerializedContent($request, $responseModel));
221 2
                break;
222 21
            default:
223 21
                $headers           = $response->headers;
224 21
                $response          = new JsonResponse(
225 21
                    $this->getSerializedContent($request, $responseModel),
226 20
                    $response->getStatusCode()
227 20
                );
228 20
                $response->headers = $headers; // some headers might mess up if we pass it to the JsonResponse
229 20
                break;
230 23
        }
231
232 22
        return $response;
233
    }
234
235
    /**
236
     * @param Request $request
237
     * @param ResponseModel $responseModel
238
     * @return mixed|string
239
     */
240 23
    protected function getSerializedContent(Request $request, ResponseModel $responseModel)
241
    {
242 23
        return $this->serializer->serialize(
243 23
            $responseModel->toArray(),
244 22
            $request->getRequestFormat(),
245 22
            $this->getSerializerContext()
246 22
        );
247
    }
248
249
    /**
250
     * @return SerializationContext
251
     */
252 22
    protected function getSerializerContext()
253
    {
254 22
        $context = new SerializationContext();
255 22
        $context->setSerializeNull(true);
256 22
        return $context;
257
    }
258
259
    /**
260
     * @param Request $request
261
     * @param JsonResponse $response
262
     */
263 2
    protected function wrapResponse(Request $request, JsonResponse $response)
264
    {
265 2
        switch ($request->query->get(self::PARAMETER_WRAPPER)) {
266 2
            case self::WRAPPER_POST_MESSAGE:
267 1
                $response->setContent(
268 1
                    $this->twig->render(
269 1
                        'MediaMonksRestApiBundle::post_message.html.twig',
270
                        [
271 1
                            'request'  => $request,
272 1
                            'response' => $response,
273 1
                            'callback' => $request->query->get(self::PARAMETER_CALLBACK),
274 1
                            'origin'   => $this->getPostMessageOrigin()
275 1
                        ]
276 1
                    )
277 1
                )->headers->set('Content-Type', 'text/html');
278 1
                break;
279 1
            default:
280 1
                $response->setCallback($request->query->get(self::PARAMETER_CALLBACK));
281 1
                break;
282 2
        }
283 2
    }
284
}
285