Passed
Push — master ( 20fa94...bcb279 )
by Michael
02:03
created

JsonApiViewListener::handleView()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 1
crap 1
1
<?php
2
declare(strict_types = 1);
3
4
namespace Mikemirten\Bundle\JsonApiBundle\EventListener;
5
6
use Mikemirten\Bundle\JsonApiBundle\Builder\DocumentBuilder;
7
use Mikemirten\Bundle\JsonApiBundle\Response\AbstractJsonApiView;
8
use Mikemirten\Bundle\JsonApiBundle\Response\Behaviour\HttpAttributesAwareInterface;
9
use Mikemirten\Bundle\JsonApiBundle\Response\JsonApiDocumentView;
10
use Symfony\Component\HttpFoundation\Response;
11
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
12
use Mikemirten\Component\JsonApi\Document\{
13
    AbstractDocument,
14
    NoDataDocument,
15
    SingleResourceDocument,
16
    ErrorObject,
17
    JsonApiObject,
18
    ResourceObject
19
};
20
21
/**
22
 * JsonApi view listener
23
 * Handles a JsonApi-document or its part responded by controller
24
 *
25
 * @package Mikemirten\Bundle\JsonApiBundle\EventListener
26
 */
27
class JsonApiViewListener
28
{
29
    /**
30
     * Document builder
31
     *
32
     * @var DocumentBuilder
33
     */
34
    protected $documentBuilder;
35
36
    /**
37
     * JsonApiViewListener constructor.
38
     *
39
     * @param DocumentBuilder $builder
40
     */
41 8
    public function __construct(DocumentBuilder $builder)
42
    {
43 8
        $this->documentBuilder = $builder;
44 8
    }
45
46
    /**
47
     * On Kernel View event handler
48
     *
49
     * @param GetResponseForControllerResultEvent $event
50
     */
51 7
    public function onKernelView(GetResponseForControllerResultEvent $event)
52
    {
53 7
        $result = $event->getControllerResult();
54
55 7
        if (! is_object($result)) {
56 1
            return;
57
        }
58
59 6
        $response = $this->handleResult($result);
60
61 6
        if ($response !== null) {
62 6
            $event->setResponse($response);
63
        }
64 6
    }
65
66
    /**
67
     * Handle result
68
     *
69
     * @param  mixed $result
70
     * @return Response | null
71
     */
72 6
    protected function handleResult($result)
73
    {
74
        // Json API document
75 6
        if ($result instanceof AbstractDocument) {
76 1
            return $this->createResponse($result);
77
        }
78
79
        // Json API document wrapped into view
80 5
        if ($result instanceof JsonApiDocumentView) {
81 1
            return $this->handleDocumentView($result);
82
        }
83
84
        // An object or an iterator of objects for serialization wrapped into view
85 4
        if ($result instanceof AbstractJsonApiView) {
86 2
            return $this->handleView($result);
87
        }
88
89
        // A resource-object of Json API document
90 2
        if ($result instanceof ResourceObject) {
91 1
            return $this->handleResource($result);
92
        }
93
94
        // An error-object of Json API document
95 1
        if ($result instanceof ErrorObject) {
96 1
            return $this->handleError($result);
97
        }
98
    }
99
100
    /**
101
     * Handle document Json API view
102
     *
103
     * @param  JsonApiDocumentView $view
104
     * @return Response
105
     */
106 1
    protected function handleDocumentView(JsonApiDocumentView $view)
107
    {
108 1
        $document = $view->getDocument();
109 1
        $response = $this->createResponse($document);
110
111 1
        $this->handleHttpAttributes($response, $view);
112 1
        return $response;
113
    }
114
115
    /**
116
     * Handle a JSON-API view contains an object(s) for serialization
117
     *
118
     * @param  AbstractJsonApiView $view
119
     * @return Response
120
     */
121 2
    protected function handleView(AbstractJsonApiView $view)
122
    {
123 2
        $document = $this->documentBuilder->build($view);
124 2
        $response = $this->createResponse($document);
125
126 2
        $this->handleHttpAttributes($response, $view);
127 2
        return $response;
128
    }
129
130
    /**
131
     * Handle response data besides of the document itself
132
     * 
133
     * @param Response                     $response
134
     * @param HttpAttributesAwareInterface $view
135
     */
136 3
    protected function handleHttpAttributes(Response $response, HttpAttributesAwareInterface $view)
137
    {
138 3
        $response->setStatusCode($view->getStatusCode());
139 3
        $response->headers->add($view->getHeaders());
140 3
    }
141
142
    /**
143
     * Handle single resource object
144
     *
145
     * @param  ResourceObject $resource
146
     * @return Response
147
     */
148 1
    protected function handleResource(ResourceObject $resource): Response
149
    {
150 1
        $document = new SingleResourceDocument($resource);
151 1
        $document->setJsonApi(new JsonApiObject());
152
153 1
        return $this->createResponse($document);
154
    }
155
156
    /**
157
     * Handle error
158
     *
159
     * @param  ErrorObject $error
160
     * @return Response
161
     */
162 1
    protected function handleError(ErrorObject $error): Response
163
    {
164 1
        $document = new NoDataDocument();
165 1
        $document->setJsonApi(new JsonApiObject());
166 1
        $document->addError($error);
167
168 1
        return $this->createResponse($document);
169
    }
170
171
    /**
172
     * Create response
173
     *
174
     * @param  AbstractDocument $document
175
     * @return Response
176
     */
177 6
    protected function createResponse(AbstractDocument $document): Response
178
    {
179 6
        $encoded  = $this->encode($document->toArray());
180 6
        $response = new Response($encoded);
181
182 6
        $response->headers->set('Content-Type', 'application/vnd.api+json');
183
184 6
        return $response;
185
    }
186
187
    /**
188
     * Encode object into a json-string
189
     *
190
     * @param  mixed $object
191
     * @return string
192
     * @throws \LogicException
193
     */
194 6
    protected function encode($object): string
195
    {
196 6
        $encoded = json_encode($object);
197
198 6
        if (json_last_error() === JSON_ERROR_NONE) {
199 6
            return $encoded;
200
        }
201
202
        throw new \LogicException('Encoding error: ' . json_last_error_msg());
203
    }
204
}