Completed
Pull Request — master (#48)
by Jasper
12:30
created

Parser::responseHasBody()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Swis\JsonApi\Client\JsonApi;
4
5
use Art4\JsonApiClient\DocumentInterface as Art4JsonApiDocumentInterface;
6
use Art4\JsonApiClient\ResourceCollectionInterface;
7
use Art4\JsonApiClient\ResourceItemInterface;
8
use Art4\JsonApiClient\Utils\Manager as Art4JsonApiClientManager;
9
use Psr\Http\Message\ResponseInterface;
10
use Swis\JsonApi\Client\Collection;
11
use Swis\JsonApi\Client\CollectionDocument;
12
use Swis\JsonApi\Client\Document;
13
use Swis\JsonApi\Client\Errors\ErrorCollection;
14
use Swis\JsonApi\Client\Interfaces\DocumentInterface;
15
use Swis\JsonApi\Client\Interfaces\ParserInterface;
16
use Swis\JsonApi\Client\InvalidResponseDocument;
17
use Swis\JsonApi\Client\ItemDocument;
18
use Swis\JsonApi\Client\Jsonapi;
19
use Swis\JsonApi\Client\Meta;
20
21
class Parser implements ParserInterface
22
{
23
    /**
24
     * @var \Art4\JsonApiClient\Utils\Manager
25
     */
26
    protected $manager;
27
28
    /**
29
     * @var \Swis\JsonApi\Client\JsonApi\Hydrator
30
     */
31
    private $hydrator;
32
33
    /**
34
     * @var \Swis\JsonApi\Client\JsonApi\ErrorsParser
35
     */
36
    private $errorsParser;
37
38
    /**
39
     * @var \Swis\JsonApi\Client\JsonApi\LinksParser
40
     */
41
    private $linksParser;
42
43
    /**
44
     * @param \Art4\JsonApiClient\Utils\Manager         $manager
45
     * @param \Swis\JsonApi\Client\JsonApi\Hydrator     $hydrator
46
     * @param \Swis\JsonApi\Client\JsonApi\ErrorsParser $errorsParser
47
     * @param \Swis\JsonApi\Client\JsonApi\LinksParser  $linksParser
48
     */
49
    public function __construct(
50
        Art4JsonApiClientManager $manager,
51
        Hydrator $hydrator,
52
        ErrorsParser $errorsParser,
53
        LinksParser $linksParser
54
    ) {
55
        $this->manager = $manager;
56
        $this->hydrator = $hydrator;
57
        $this->errorsParser = $errorsParser;
58
        $this->linksParser = $linksParser;
59
    }
60
61
    /**
62
     * @return \Swis\JsonApi\Client\JsonApi\Hydrator
63
     */
64
    public function getHydrator(): Hydrator
65
    {
66
        return $this->hydrator;
67
    }
68
69
    /**
70
     * @param \Psr\Http\Message\ResponseInterface $response
71
     *
72
     * @return \Swis\JsonApi\Client\Interfaces\DocumentInterface
73
     */
74
    public function deserializeResponse(ResponseInterface $response): DocumentInterface
75
    {
76
        $document = new InvalidResponseDocument();
77
78
        if ($this->responseHasBody($response)) {
79
            $document = $this->deserialize((string)$response->getBody());
80
        } elseif ($this->responseHasSuccessfulStatusCode($response)) {
81
            $document = new Document();
82
        }
83
84
        $document->setResponse($response);
85
86
        return $document;
87
    }
88
89
    /**
90
     * @param \Psr\Http\Message\ResponseInterface $response
91
     *
92
     * @return bool
93
     */
94
    private function responseHasBody(ResponseInterface $response): bool
95
    {
96
        return (bool)$response->getBody()->getSize();
97
    }
98
99
    /**
100
     * @param \Psr\Http\Message\ResponseInterface $response
101
     *
102
     * @return bool
103
     */
104
    private function responseHasSuccessfulStatusCode(ResponseInterface $response): bool
105
    {
106
        return $response->getStatusCode() >= 200 && $response->getStatusCode() < 300;
107
    }
108
109
    /**
110
     * @param string $json
111
     *
112
     * @throws \DomainException
113
     *
114
     * @return \Swis\JsonApi\Client\Interfaces\DocumentInterface
115
     */
116
    public function deserialize(string $json): DocumentInterface
117
    {
118
        $jsonApiDocument = $this->getJsonApiDocument($json);
119
120
        if ($jsonApiDocument->has('data')) {
121
            $document = $this->buildDataDocument($jsonApiDocument);
122
        } else {
123
            $document = new Document();
124
        }
125
126
        $document->setLinks($this->parseLinks($jsonApiDocument));
127
        $document->setErrors($this->parseErrors($jsonApiDocument));
128
        $document->setMeta($this->parseMeta($jsonApiDocument));
129
        $document->setJsonapi($this->parseJsonapi($jsonApiDocument));
130
131
        return $document;
132
    }
133
134
    /**
135
     * @param string $json
136
     *
137
     * @throws \DomainException
138
     *
139
     * @return \Art4\JsonApiClient\DocumentInterface
140
     */
141
    private function getJsonApiDocument(string $json): Art4JsonApiDocumentInterface
142
    {
143
        $jsonApiDocument = $this->manager->parse($json);
144
145
        if (!$jsonApiDocument instanceof Art4JsonApiDocumentInterface) {
146
            throw new \DomainException('Result is not a JSON API Document');
147
        }
148
149
        return $jsonApiDocument;
150
    }
151
152
    /**
153
     * @param \Art4\JsonApiClient\DocumentInterface $jsonApiDocument
154
     *
155
     * @throws \DomainException
156
     *
157
     * @return \Swis\JsonApi\Client\Interfaces\DocumentInterface
158
     */
159
    protected function buildDataDocument(Art4JsonApiDocumentInterface $jsonApiDocument): DocumentInterface
160
    {
161
        $data = $this->getJsonApiDocumentData($jsonApiDocument);
162
        $includedInDocument = $this->getJsonApiDocumentIncluded($jsonApiDocument);
163
164
        $allHydratedItems = new Collection();
165
        $allJsonApiItems = new Collection();
166
167
        if ($data instanceof ResourceItemInterface) {
168
            $item = $this->hydrator->hydrateItem($data);
169
            $allHydratedItems->push($item);
170
            $allJsonApiItems->push($data);
171
172
            $document = new ItemDocument();
173
            $document->setData($item);
174
        } elseif ($data instanceof ResourceCollectionInterface) {
175
            $collection = $this->hydrator->hydrateCollection($data);
176
            $allHydratedItems = $allHydratedItems->concat($collection);
177
            $allJsonApiItems = $allJsonApiItems->concat(new Collection($data->asArray()));
178
179
            $document = new CollectionDocument();
180
            $document->setData($collection);
181
        } else {
182
            throw new \DomainException('Data is not Collection or Item');
183
        }
184
185
        $included = null;
186
        if ($includedInDocument) {
187
            $included = $this->hydrator->hydrateCollection($includedInDocument);
188
            $allHydratedItems = $allHydratedItems->concat($included);
189
            $allJsonApiItems = $allJsonApiItems->concat(new Collection($includedInDocument->asArray()));
190
        }
191
192
        $this->hydrator->hydrateRelationships($allJsonApiItems, $allHydratedItems);
193
194
        if ($included) {
195
            $document->setIncluded($included);
196
        }
197
198
        return $document;
199
    }
200
201
    /**
202
     * @param \Art4\JsonApiClient\DocumentInterface $document
203
     *
204
     * @throws \DomainException
205
     *
206
     * @return \Art4\JsonApiClient\ResourceItemInterface|\Art4\JsonApiClient\ResourceCollectionInterface
207
     */
208
    private function getJsonApiDocumentData(Art4JsonApiDocumentInterface $document)
209
    {
210
        $resource = $document->get('data');
211
212
        if (!$resource instanceof ResourceItemInterface && !$resource instanceof ResourceCollectionInterface) {
213
            throw new \DomainException('Result is not a Json API Resource');
214
        }
215
216
        return $resource;
217
    }
218
219
    /**
220
     * @param \Art4\JsonApiClient\DocumentInterface $document
221
     *
222
     * @return \Art4\JsonApiClient\ResourceCollection|null
223
     */
224
    private function getJsonApiDocumentIncluded(Art4JsonApiDocumentInterface $document)
225
    {
226
        if ($document->has('included')) {
227
            return $document->get('included');
228
        }
229
230
        return null;
231
    }
232
233
    /**
234
     * @param \Art4\JsonApiClient\DocumentInterface $document
235
     *
236
     * @return \Swis\JsonApi\Client\Links|null
237
     */
238
    private function parseLinks(Art4JsonApiDocumentInterface $document)
239
    {
240
        if (!$document->has('links')) {
241
            return null;
242
        }
243
244
        return $this->linksParser->parse($document->get('links')->asArray(false));
245
    }
246
247
    /**
248
     * @param \Art4\JsonApiClient\DocumentInterface $document
249
     *
250
     * @return \Swis\JsonApi\Client\Errors\ErrorCollection
251
     */
252
    private function parseErrors(Art4JsonApiDocumentInterface $document): ErrorCollection
253
    {
254
        if (!$document->has('errors')) {
255
            return new ErrorCollection();
256
        }
257
258
        return $this->errorsParser->parse($document->get('errors'));
259
    }
260
261
    /**
262
     * @param \Art4\JsonApiClient\DocumentInterface $document
263
     *
264
     * @return \Swis\JsonApi\Client\Meta|null
265
     */
266
    private function parseMeta(Art4JsonApiDocumentInterface $document)
267
    {
268
        if (!$document->has('meta')) {
269
            return null;
270
        }
271
272
        return new Meta($document->get('meta')->asArray(true));
273
    }
274
275
    /**
276
     * @param \Art4\JsonApiClient\DocumentInterface $document
277
     *
278
     * @return \Swis\JsonApi\Client\Jsonapi|null
279
     */
280
    private function parseJsonapi(Art4JsonApiDocumentInterface $document)
281
    {
282
        if (!$document->has('jsonapi')) {
283
            return null;
284
        }
285
286
        $jsonApi = $document->get('jsonapi');
287
288
        return new Jsonapi(
289
            $jsonApi->has('version') ? $jsonApi->get('version') : null,
290
            $jsonApi->has('meta') ? new Meta($jsonApi->get('meta')->asArray(true)) : null
291
        );
292
    }
293
294
    /**
295
     * @param \Swis\JsonApi\Client\Interfaces\DocumentInterface $document
296
     *
297
     * @return string
298
     */
299
    public function serialize(DocumentInterface $document): string
300
    {
301
    }
302
}
303