Completed
Branch master (9acd60)
by
unknown
09:48
created

Encoder::encodeData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 7
Ratio 100 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 7
loc 7
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 2
crap 1
1
<?php namespace Neomerx\JsonApi\Encoder;
2
3
/**
4
 * Copyright 2015-2017 [email protected]
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use \Iterator;
20
use \InvalidArgumentException;
21
use \Psr\Log\LoggerAwareTrait;
22
use \Psr\Log\LoggerAwareInterface;
23
use \Neomerx\JsonApi\Factories\Factory;
24
use \Neomerx\JsonApi\Contracts\Document\ErrorInterface;
25
use \Neomerx\JsonApi\Contracts\Encoder\EncoderInterface;
26
use \Neomerx\JsonApi\Contracts\Schema\ContainerInterface;
27
use \Neomerx\JsonApi\Contracts\Document\DocumentInterface;
28
use \Neomerx\JsonApi\Contracts\Factories\FactoryInterface;
29
use \Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface;
30
use \Neomerx\JsonApi\Contracts\Encoder\Parameters\ParametersAnalyzerInterface;
31
32
/**
33
 * @package Neomerx\JsonApi
34
 */
35
class Encoder implements EncoderInterface, LoggerAwareInterface
36
{
37
    use LoggerAwareTrait;
38
39
    /**
40
     * @var ContainerInterface
41
     */
42
    private $container;
43
44
    /**
45
     * @var FactoryInterface
46
     */
47
    private $factory;
48
49
    /**
50
     * @var EncoderOptions|null
51
     */
52
    private $encoderOptions;
53
54
    /**
55
     * Links in array<string,LinkInterface> format.
56
     *
57
     * @var array|null
58
     */
59
    private $links;
60
61
    /**
62
     * @var array|object|null
63
     */
64
    private $meta;
65
66
    /**
67
     * @var bool
68
     */
69
    private $isAddJsonApiVersion;
70
71
    /**
72
     * @var mixed|null
73
     */
74
    protected $jsonApiVersionMeta;
75
76
    /**
77
     * @param FactoryInterface    $factory
78
     * @param ContainerInterface  $container
79
     * @param EncoderOptions|null $encoderOptions
80
     */
81 75
    public function __construct(
82
        FactoryInterface $factory,
83
        ContainerInterface $container,
84
        EncoderOptions $encoderOptions = null
85
    ) {
86 75
        $this->factory        = $factory;
87 75
        $this->container      = $container;
88 75
        $this->encoderOptions = $encoderOptions;
89
90 75
        $this->resetEncodeParameters();
91 75
    }
92
93
    /**
94
     * @inheritdoc
95
     */
96 5
    public function withLinks(array $links)
97
    {
98 5
        $this->links = array_merge($this->links, $links);
99
100 5
        return $this;
101
    }
102
103
    /**
104
     * @inheritdoc
105
     */
106 3
    public function withMeta($meta)
107
    {
108 3
        $this->meta = $meta;
109
110 3
        return $this;
111
    }
112
113
    /**
114
     * @inheritdoc
115
     */
116 1
    public function withJsonApiVersion($meta = null)
117
    {
118 1
        $this->isAddJsonApiVersion = true;
119 1
        $this->jsonApiVersionMeta  = $meta;
120
121 1
        return $this;
122
    }
123
124
125
    /**
126
     * @inheritdoc
127
     */
128 1 View Code Duplication
    public function withRelationshipSelfLink($resource, $relationshipName, $meta = null, $treatAsHref = false)
129
    {
130 1
        $link = $this->getContainer()->getSchema($resource)
131 1
            ->getRelationshipSelfLink($resource, $relationshipName, $meta, $treatAsHref);
132
133 1
        return $this->withLinks([
134 1
            DocumentInterface::KEYWORD_SELF => $link,
135 1
        ]);
136
    }
137
138
    /**
139
     * @inheritdoc
140
     */
141 1 View Code Duplication
    public function withRelationshipRelatedLink($resource, $relationshipName, $meta = null, $treatAsHref = false)
142
    {
143 1
        $link = $this->getContainer()->getSchema($resource)
144 1
            ->getRelationshipRelatedLink($resource, $relationshipName, $meta, $treatAsHref);
145
146 1
        return $this->withLinks([
147 1
            DocumentInterface::KEYWORD_RELATED => $link,
148 1
        ]);
149
    }
150
151
    /**
152
     * @inheritdoc
153
     */
154 62 View Code Duplication
    public function encodeData($data, EncodingParametersInterface $parameters = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
155 1
    {
156 62
        $array  = $this->encodeDataToArray($this->getContainer(), $data, $parameters);
157 60
        $result = $this->encodeToJson($array);
158
159 60
        return $result;
160
    }
161
162
    /**
163
     * @inheritdoc
164
     */
165 3 View Code Duplication
    public function encodeIdentifiers($data, EncodingParametersInterface $parameters = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
166
    {
167 3
        $array  = $this->encodeIdentifiersToArray($data, $parameters);
168 2
        $result = $this->encodeToJson($array);
169
170 2
        return $result;
171
    }
172
173
    /**
174
     * @inheritdoc
175
     */
176 2
    public function encodeError(ErrorInterface $error)
177
    {
178 2
        return $this->encodeToJson($this->encodeErrorToArray($error));
179
    }
180
181
    /**
182
     * @inheritdoc
183
     */
184 3
    public function encodeErrors($errors)
185
    {
186 3
        return $this->encodeToJson($this->encodeErrorsToArray($errors));
187
    }
188
189
    /**
190
     * @inheritdoc
191
     */
192 1
    public function encodeMeta($meta)
193
    {
194 1
        return $this->encodeToJson($this->encodeMetaToArray($meta));
195 1
    }
196
197
    /**
198
     * @param ContainerInterface               $container
199
     * @param object|array|Iterator|null       $data
200
     * @param EncodingParametersInterface|null $parameters
201
     *
202
     * @return array
203
     */
204 66
    protected function encodeDataToArray(
205
        ContainerInterface $container,
206
        $data,
207 1
        EncodingParametersInterface $parameters = null
208
    ) {
209 66
        $this->checkInputData($data);
210
211 65
        $docWriter     = $this->getFactory()->createDocument();
212 65
        $paramAnalyzer = $this->createParametersAnalyzer($container, $parameters);
213 65
        $parserManager = $this->getFactory()->createManager($paramAnalyzer);
214 65
        $interpreter   = $this->getFactory()->createReplyInterpreter($docWriter, $paramAnalyzer);
215 65
        $parser        = $this->getFactory()->createParser($container, $parserManager);
216
217 65
        $this->configureUrlPrefix($docWriter);
218
219 65
        foreach ($parser->parse($data) as $reply) {
220 65
            $interpreter->handle($reply);
221 65
        }
222
223 64
        if ($this->getMeta() !== null) {
224 3
            $docWriter->setMetaToDocument($this->getMeta());
225 3
        }
226
227 64
        if (empty($this->getLinks()) === false) {
228 5
            $docWriter->setDocumentLinks($this->getLinks());
229 5
        }
230
231 64
        if ($this->isWithJsonApiVersion() === true) {
232 1
            $docWriter->addJsonApiVersion(self::JSON_API_VERSION, $this->getJsonApiVersionMeta());
233 2
        }
234
235 64
        $result = $docWriter->getDocument();
236 64
        $this->resetEncodeParameters();
237
238 64
        return $result;
239
    }
240
241
    /**
242
     * Encode array to JSON.
243
     *
244
     * @param array $document
245
     *
246
     * @return string
247
     */
248 68
    protected function encodeToJson(array $document)
249
    {
250 68
        return $this->getEncoderOptions() === null ?
251 68
            json_encode($document) :
252 68
            json_encode($document, $this->getEncoderOptions()->getOptions(), $this->getEncoderOptions()->getDepth());
253
    }
254
255
    /**
256
     * Create encoder instance.
257
     *
258
     * @param array               $schemas       Schema providers.
259
     * @param EncoderOptions|null $encodeOptions
260
     *
261
     * @return EncoderInterface
262
     */
263 73
    public static function instance(array $schemas = [], EncoderOptions $encodeOptions = null)
264
    {
265 73
        $factory   = static::createFactory();
266 73
        $container = $factory->createContainer($schemas);
267 73
        $encoder   = $factory->createEncoder($container, $encodeOptions);
268
269 73
        return $encoder;
270
    }
271
272
    /**
273
     * @return FactoryInterface
274
     */
275 65
    protected static function createFactory()
276
    {
277 65
        return new Factory();
278
    }
279
280
    /**
281
     * @param mixed $data
282
     */
283 66
    protected function checkInputData($data)
284
    {
285 66
        if (is_array($data) === false && is_object($data) === false && $data !== null && !($data instanceof Iterator)) {
286 1
            throw new InvalidArgumentException('data');
287
        }
288 65
    }
289
290
    /**
291
     * @param object|array|Iterator|null       $data
292
     * @param EncodingParametersInterface|null $parameters
293
     *
294
     * @return array
295
     */
296 3
    protected function encodeIdentifiersToArray($data, EncodingParametersInterface $parameters = null)
297
    {
298 3
        $container = $this->getFactory()->createResourceIdentifierContainerAdapter($this->getContainer());
299 3
        $result    = $this->encodeDataToArray($container, $data, $parameters);
300
301 3
        return $result;
302
    }
303
304
    /**
305
     * @param ErrorInterface $error
306
     *
307
     * @return array
308
     */
309 3
    protected function encodeErrorToArray(ErrorInterface $error)
310
    {
311 3
        $docWriter = $this->getFactory()->createDocument();
312 3
        $docWriter->addError($error);
313 3
        $array = $docWriter->getDocument();
314
315 3
        return $array;
316
    }
317
318
    /**
319
     * @param $errors
320
     *
321
     * @return array
322
     */
323 4
    protected function encodeErrorsToArray($errors)
324
    {
325 4
        $docWriter = $this->getFactory()->createDocument();
326 4
        $docWriter->addErrors($errors);
327 4
        $array = $docWriter->getDocument();
328
329 4
        return $array;
330
    }
331
332
    /**
333
     * @param $meta
334
     *
335
     * @return array
336
     */
337 2
    protected function encodeMetaToArray($meta)
338
    {
339 2
        $docWriter = $this->getFactory()->createDocument();
340
341 2
        $docWriter->setMetaToDocument($meta);
342 2
        $docWriter->unsetData();
343 2
        $array = $docWriter->getDocument();
344
345 2
        return $array;
346
    }
347
348
    /**
349
     * @return ContainerInterface
350
     */
351 66
    protected function getContainer()
352
    {
353 66
        return $this->container;
354
    }
355
356
    /**
357
     * @return FactoryInterface
358
     */
359 73
    protected function getFactory()
360
    {
361 73
        return $this->factory;
362
    }
363
364
    /**
365
     * @return EncoderOptions|null
366
     */
367 71
    protected function getEncoderOptions()
368
    {
369 71
        return $this->encoderOptions;
370
    }
371
372
    /**
373
     * @return array|null
374
     */
375 64
    protected function getLinks()
376
    {
377 64
        return $this->links;
378
    }
379
380
    /**
381
     * @return array|null|object
382
     */
383 64
    public function getMeta()
384
    {
385 64
        return $this->meta;
386
    }
387
388
    /**
389
     * @return boolean
390
     */
391 64
    protected function isWithJsonApiVersion()
392
    {
393 64
        return $this->isAddJsonApiVersion;
394
    }
395
396
    /**
397
     * @return mixed|null
398
     */
399 1
    protected function getJsonApiVersionMeta()
400
    {
401 1
        return $this->jsonApiVersionMeta;
402
    }
403
404
    /**
405
     * @param ContainerInterface               $container
406
     * @param EncodingParametersInterface|null $parameters
407
     *
408
     * @return ParametersAnalyzerInterface
409
     */
410 65
    private function createParametersAnalyzer(
411
        ContainerInterface $container,
412
        EncodingParametersInterface $parameters = null
413
    ) {
414 65
        return $this->getFactory()->createParametersAnalyzer(
415 65
            $parameters === null ? $this->getFactory()->createQueryParameters() : $parameters,
416
            $container
417 65
        );
418
    }
419
420
    /**
421
     * Reset encode parameters.
422
     */
423 75
    private function resetEncodeParameters()
424
    {
425 75
        $this->meta                = null;
426 75
        $this->links               = [];
427 75
        $this->isAddJsonApiVersion = false;
428 75
        $this->jsonApiVersionMeta  = null;
429 75
    }
430
431
    /**
432
     * @param DocumentInterface $docWriter
433
     */
434 65
    private function configureUrlPrefix(DocumentInterface $docWriter)
435
    {
436 65
        $this->getEncoderOptions() !== null && $this->getEncoderOptions()->getUrlPrefix() !== null ?
437 65
            $docWriter->setUrlPrefix($this->getEncoderOptions()->getUrlPrefix()) : null;
438 65
    }
439
}
440