Completed
Branch master (84355a)
by
unknown
06:22
created

Encoder::addTopLevelMeta()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 1
crap 2
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 76
    public function __construct(
82
        FactoryInterface $factory,
83
        ContainerInterface $container,
84
        EncoderOptions $encoderOptions = null
85
    ) {
86 76
        $this->factory        = $factory;
87 76
        $this->container      = $container;
88 76
        $this->encoderOptions = $encoderOptions;
89
90 76
        $this->resetEncodeParameters();
91 76
    }
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 4
    public function withMeta($meta)
107
    {
108 4
        $this->meta = $meta;
109
110 4
        return $this;
111
    }
112
113
    /**
114
     * @inheritdoc
115
     */
116 2
    public function withJsonApiVersion($meta = null)
117
    {
118 2
        $this->isAddJsonApiVersion = true;
119 2
        $this->jsonApiVersionMeta  = $meta;
120
121 2
        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 3
    public function encodeError(ErrorInterface $error)
177
    {
178 3
        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
        $this->addTopLevelMeta($docWriter);
224 64
        $this->addTopLevelLinks($docWriter);
225 64
        $this->addTopLevelJsonApiVersion($docWriter);
226
227 64
        $result = $docWriter->getDocument();
228 64
        $this->resetEncodeParameters();
229
230 64
        return $result;
231
    }
232
233
    /**
234
     * Encode array to JSON.
235
     *
236
     * @param array $document
237
     *
238
     * @return string
239
     */
240 69
    protected function encodeToJson(array $document)
241
    {
242 69
        return $this->getEncoderOptions() === null ?
243 69
            json_encode($document) :
244 69
            json_encode($document, $this->getEncoderOptions()->getOptions(), $this->getEncoderOptions()->getDepth());
245
    }
246
247
    /**
248
     * Create encoder instance.
249
     *
250
     * @param array               $schemas       Schema providers.
251
     * @param EncoderOptions|null $encodeOptions
252
     *
253
     * @return EncoderInterface
254
     */
255 74
    public static function instance(array $schemas = [], EncoderOptions $encodeOptions = null)
256
    {
257 74
        $factory   = static::createFactory();
258 74
        $container = $factory->createContainer($schemas);
259 74
        $encoder   = $factory->createEncoder($container, $encodeOptions);
260
261 74
        return $encoder;
262
    }
263
264
    /**
265
     * @return FactoryInterface
266
     */
267 66
    protected static function createFactory()
268
    {
269 66
        return new Factory();
270
    }
271
272
    /**
273
     * @param mixed $data
274
     */
275 66
    protected function checkInputData($data)
276
    {
277 66
        if (is_array($data) === false && is_object($data) === false && $data !== null && !($data instanceof Iterator)) {
278 1
            throw new InvalidArgumentException('data');
279
        }
280 65
    }
281
282
    /**
283
     * @param object|array|Iterator|null       $data
284
     * @param EncodingParametersInterface|null $parameters
285
     *
286
     * @return array
287
     */
288 3
    protected function encodeIdentifiersToArray($data, EncodingParametersInterface $parameters = null)
289
    {
290 3
        $container = $this->getFactory()->createResourceIdentifierContainerAdapter($this->getContainer());
291 3
        $result    = $this->encodeDataToArray($container, $data, $parameters);
292
293 3
        return $result;
294
    }
295
296
    /**
297
     * @param ErrorInterface $error
298
     *
299
     * @return array
300
     */
301 4
    protected function encodeErrorToArray(ErrorInterface $error)
302
    {
303 4
        $docWriter = $this->getFactory()->createDocument();
304 4
        $docWriter->addError($error);
305
306 4
        $this->addTopLevelMeta($docWriter);
307 4
        $this->addTopLevelJsonApiVersion($docWriter);
308
309 4
        $array = $docWriter->getDocument();
310
311 4
        return $array;
312
    }
313
314
    /**
315
     * @param $errors
316
     *
317
     * @return array
318
     */
319 4
    protected function encodeErrorsToArray($errors)
320
    {
321 4
        $docWriter = $this->getFactory()->createDocument();
322 4
        $docWriter->addErrors($errors);
323
324 4
        $this->addTopLevelMeta($docWriter);
325 4
        $this->addTopLevelJsonApiVersion($docWriter);
326
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
     * @param DocumentInterface $docWriter
350
     */
351 71
    protected function addTopLevelMeta(DocumentInterface $docWriter)
352
    {
353 71
        if ($this->getMeta() !== null) {
354 4
            $docWriter->setMetaToDocument($this->getMeta());
355 4
        }
356 71
    }
357
358
    /**
359
     * @param DocumentInterface $docWriter
360
     */
361 64
    protected function addTopLevelLinks(DocumentInterface $docWriter)
362
    {
363 64
        if (empty($this->getLinks()) === false) {
364 5
            $docWriter->setDocumentLinks($this->getLinks());
365 5
        }
366 64
    }
367
368
    /**
369
     * @param DocumentInterface $docWriter
370
     */
371 71
    protected function addTopLevelJsonApiVersion(DocumentInterface $docWriter)
372
    {
373 71
        if ($this->isWithJsonApiVersion() === true) {
374 2
            $docWriter->addJsonApiVersion(self::JSON_API_VERSION, $this->getJsonApiVersionMeta());
375 2
        }
376 71
    }
377
378
    /**
379
     * @return ContainerInterface
380
     */
381 66
    protected function getContainer()
382
    {
383 66
        return $this->container;
384
    }
385
386
    /**
387
     * @return FactoryInterface
388
     */
389 74
    protected function getFactory()
390
    {
391 74
        return $this->factory;
392
    }
393
394
    /**
395
     * @return EncoderOptions|null
396
     */
397 72
    protected function getEncoderOptions()
398
    {
399 72
        return $this->encoderOptions;
400
    }
401
402
    /**
403
     * @return array|null
404
     */
405 64
    protected function getLinks()
406
    {
407 64
        return $this->links;
408
    }
409
410
    /**
411
     * @return array|null|object
412
     */
413 71
    public function getMeta()
414
    {
415 71
        return $this->meta;
416
    }
417
418
    /**
419
     * @return boolean
420
     */
421 71
    protected function isWithJsonApiVersion()
422
    {
423 71
        return $this->isAddJsonApiVersion;
424
    }
425
426
    /**
427
     * @return mixed|null
428
     */
429 2
    protected function getJsonApiVersionMeta()
430
    {
431 2
        return $this->jsonApiVersionMeta;
432
    }
433
434
    /**
435
     * @param ContainerInterface               $container
436
     * @param EncodingParametersInterface|null $parameters
437
     *
438
     * @return ParametersAnalyzerInterface
439
     */
440 65
    private function createParametersAnalyzer(
441
        ContainerInterface $container,
442
        EncodingParametersInterface $parameters = null
443
    ) {
444 65
        return $this->getFactory()->createParametersAnalyzer(
445 65
            $parameters === null ? $this->getFactory()->createQueryParameters() : $parameters,
446
            $container
447 65
        );
448
    }
449
450
    /**
451
     * Reset encode parameters.
452
     */
453 76
    private function resetEncodeParameters()
454
    {
455 76
        $this->meta                = null;
456 76
        $this->links               = [];
457 76
        $this->isAddJsonApiVersion = false;
458 76
        $this->jsonApiVersionMeta  = null;
459 76
    }
460
461
    /**
462
     * @param DocumentInterface $docWriter
463
     */
464 65
    private function configureUrlPrefix(DocumentInterface $docWriter)
465
    {
466 65
        $this->getEncoderOptions() !== null && $this->getEncoderOptions()->getUrlPrefix() !== null ?
467 65
            $docWriter->setUrlPrefix($this->getEncoderOptions()->getUrlPrefix()) : null;
468 65
    }
469
}
470