Completed
Branch master (726023)
by
unknown
02:44
created

Encoder::getRelationshipLink()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 11
ccs 7
cts 7
cp 1
rs 9.4285
cc 1
eloc 6
nc 1
nop 6
crap 1
1
<?php namespace Neomerx\JsonApi\Encoder;
2
3
/**
4
 * Copyright 2015 [email protected] (www.neomerx.com)
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\Http\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
    protected $container;
43
44
    /**
45
     * @var FactoryInterface
46
     */
47
    protected $factory;
48
49
    /**
50
     * @var EncoderOptions|null
51
     */
52
    protected $encoderOptions;
53
54
    /**
55
     * Links in array<string,LinkInterface> format.
56
     *
57
     * @var array|null
58
     */
59
    protected $links;
60
61
    /**
62
     * @var array|object|null
63
     */
64
    protected $meta;
65
66
    /**
67
     * @var bool
68
     */
69
    protected $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 64
    public function __construct(
82
        FactoryInterface $factory,
83
        ContainerInterface $container,
84
        EncoderOptions $encoderOptions = null
85
    ) {
86 64
        $this->factory        = $factory;
87 64
        $this->container      = $container;
88 64
        $this->encoderOptions = $encoderOptions;
89
90 64
        $this->resetEncodeParameters();
91 64
    }
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 57 View Code Duplication
    public function withRelationshipSelfLink($resource, $relationshipName, $meta = null, $treatAsHref = false)
1 ignored issue
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...
129
    {
130 1
        $link = $this->container->getSchema($resource)
131 57
            ->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)
1 ignored issue
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...
142
    {
143 1
        $link = $this->container->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 56
    public function encodeData($data, EncodingParametersInterface $parameters = null)
155 1
    {
156 56
        $container = $this->container;
157 56
        $result    = $this->encodeDataInternal($container, $data, $parameters);
158
159 54
        return $result;
160
    }
161
162
    /**
163
     * @inheritdoc
164
     */
165 3
    public function encodeIdentifiers($data, EncodingParametersInterface $parameters = null)
166
    {
167 3
        $container = $this->factory->createResourceIdentifierContainerAdapter($this->container);
168 2
        $result    = $this->encodeDataInternal($container, $data, $parameters);
169
170 2
        return $result;
171
    }
172
173
    /**
174
     * @inheritdoc
175
     */
176 2
    public function encodeError(ErrorInterface $error)
177
    {
178 2
        $docWriter = $this->factory->createDocument();
179
180 2
        $docWriter->addError($error);
181
182 2
        return $this->encodeToJson($docWriter->getDocument());
183
    }
184
185
    /**
186
     * @inheritdoc
187
     */
188 3
    public function encodeErrors($errors)
189
    {
190 2
        $docWriter = $this->factory->createDocument();
191 2
        foreach ($errors as $error) {
192 2
            $docWriter->addError($error);
193 2
        }
194
195 3
        return $this->encodeToJson($docWriter->getDocument());
196
    }
197
198
    /**
199
     * @inheritdoc
200
     */
201 1
    public function encodeMeta($meta)
202
    {
203 1
        $docWriter = $this->factory->createDocument();
204
205 1
        $docWriter->setMetaToDocument($meta);
206 1
        $docWriter->unsetData();
207
208 1
        return $this->encodeToJson($docWriter->getDocument());
209
    }
210
211
    /**
212
     * @param ContainerInterface               $container
213
     * @param object|array|Iterator|null       $data
214
     * @param EncodingParametersInterface|null $parameters
215
     *
216
     * @return string
217
     */
218 58
    protected function encodeDataInternal(
219
        ContainerInterface $container,
220
        $data,
221
        EncodingParametersInterface $parameters = null
222
    ) {
223 58
        $this->checkInputData($data);
224
225 57
        $docWriter     = $this->factory->createDocument();
226 57
        $paramAnalyzer = $this->createParametersAnalyzer($container, $parameters);
227 57
        $parserManager = $this->factory->createManager($paramAnalyzer);
228 57
        $interpreter   = $this->factory->createReplyInterpreter($docWriter, $paramAnalyzer);
229 57
        $parser        = $this->factory->createParser($container, $parserManager);
230
231 57
        $this->configureUrlPrefix($docWriter);
232
233 57
        foreach ($parser->parse($data) as $reply) {
234 57
            $interpreter->handle($reply);
235 57
        }
236
237 56
        if ($this->meta !== null) {
238 3
            $docWriter->setMetaToDocument($this->meta);
239 3
        }
240
241 56
        if (empty($this->links) === false) {
242 5
            $docWriter->setDocumentLinks($this->links);
243 5
        }
244
245 56
        if ($this->isAddJsonApiVersion === true) {
246 1
            $docWriter->addJsonApiVersion(self::JSON_API_VERSION, $this->jsonApiVersionMeta);
247 1
        }
248
249 56
        $result = $this->encodeToJson($docWriter->getDocument());
250 56
        $this->resetEncodeParameters();
251
252 56
        return $result;
253
    }
254
255
    /**
256
     * Encode array to JSON.
257
     *
258
     * @param array $document
259
     *
260
     * @return string
261
     */
262 61
    protected function encodeToJson(array $document)
263
    {
264 61
        return $this->encoderOptions === null ?
265 61
            json_encode($document) :
266 61
            json_encode($document, $this->encoderOptions->getOptions(), $this->encoderOptions->getDepth());
267
    }
268
269
    /**
270
     * Create encoder instance.
271
     *
272
     * @param array               $schemas       Schema providers.
273
     * @param EncoderOptions|null $encodeOptions
274
     *
275
     * @return EncoderInterface
1 ignored issue
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use Encoder.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
276
     */
277 63
    public static function instance(array $schemas = [], EncoderOptions $encodeOptions = null)
278
    {
279 63
        $factory   = static::getFactory();
280 63
        $container = $factory->createContainer($schemas);
281 63
        $encoder   = $factory->createEncoder($container, $encodeOptions);
282
283 63
        return $encoder;
284
    }
285
286
    /**
287
     * @return FactoryInterface
288
     */
289 60
    protected static function getFactory()
290
    {
291 60
        return new Factory();
292
    }
293
294
    /**
295
     * @param mixed $data
296
     */
297 58
    protected function checkInputData($data)
298
    {
299 58
        if (is_array($data) === false && is_object($data) === false && $data !== null && !($data instanceof Iterator)) {
300 1
            throw new InvalidArgumentException('data');
301
        }
302 57
    }
303
304
    /**
305
     * @param ContainerInterface               $container
306
     * @param EncodingParametersInterface|null $parameters
307
     *
308
     * @return ParametersAnalyzerInterface
309
     */
310 57
    private function createParametersAnalyzer(
311
        ContainerInterface $container,
312
        EncodingParametersInterface $parameters = null
313
    ) {
314 57
        return $this->factory->createParametersAnalyzer(
315 57
            $parameters === null ? $this->factory->createEncodingParameters() : $parameters,
316
            $container
317 57
        );
318
    }
319
320
    /**
321
     * Reset encode parameters.
322
     */
323 64
    private function resetEncodeParameters()
324
    {
325 64
        $this->meta                = null;
326 64
        $this->links               = [];
327 64
        $this->isAddJsonApiVersion = false;
328 64
        $this->jsonApiVersionMeta  = null;
329 64
    }
330
331
    /**
332
     * @param DocumentInterface $docWriter
333
     */
334 57
    private function configureUrlPrefix(DocumentInterface $docWriter)
335
    {
336 57
        $this->encoderOptions !== null && $this->encoderOptions->getUrlPrefix() !== null ?
337 57
            $docWriter->setUrlPrefix($this->encoderOptions->getUrlPrefix()) : null;
338 57
    }
339
}
340