Completed
Pull Request — master (#47)
by Jasper
11:54
created

Parser::buildDataDocument()   A

Complexity

Conditions 5
Paths 9

Size

Total Lines 40
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

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