Completed
Branch next (d66390)
by Neomerx
02:32
created

EncoderPropertiesTrait::withIncludedPaths()   A

Complexity

Conditions 4
Paths 1

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
nc 1
nop 1
dl 0
loc 20
ccs 11
cts 11
cp 1
crap 4
rs 9.6
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Neomerx\JsonApi\Encoder;
4
5
/**
6
 * Copyright 2015-2019 [email protected]
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 * http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
use Neomerx\JsonApi\Contracts\Encoder\EncoderInterface;
22
use Neomerx\JsonApi\Contracts\Factories\FactoryInterface;
23
use Neomerx\JsonApi\Contracts\Schema\LinkInterface;
24
use Neomerx\JsonApi\Contracts\Schema\SchemaContainerInterface;
25
26
/**
27
 * @package Neomerx\JsonApi
28
 */
29
trait EncoderPropertiesTrait
30
{
31
    /**
32
     * @var SchemaContainerInterface
33
     */
34
    private $container;
35
36
    /**
37
     * @var FactoryInterface
38
     */
39
    private $factory;
40
41
    /**
42
     * @var string
43
     */
44
    private $urlPrefix;
45
46
    /**
47
     * @var array
48
     */
49
    private $includePaths;
50
51
    /**
52
     * @var array
53
     */
54
    private $fieldSets;
55
56
    /**
57
     * @var int
58
     */
59
    private $encodeOptions;
60
61
    /**
62
     * @var int
63
     */
64
    private $encodeDepth;
65
66
    /**
67
     * @var iterable
68
     */
69
    private $links;
70
71
    /**
72
     * @var iterable
73
     */
74
    private $profile;
75
76
    /**
77
     * @var bool
78
     */
79
    private $hasMeta;
80
81
    /**
82
     * @var mixed
83
     */
84
    private $meta;
85
86
    /**
87
     * @var string|null
88
     */
89
    private $jsonApiVersion;
90
91
    /**
92
     * @var mixed
93
     */
94
    private $jsonApiMeta;
95
96
    /**
97
     * @var bool
98
     */
99
    private $hasJsonApiMeta;
100
101
    /**
102
     * Reset to initial state.
103
     *
104
     * @param string   $urlPrefix
105
     * @param iterable $includePaths
106
     * @param array    $fieldSets
107
     * @param int      $encodeOptions
108
     * @param int      $encodeDepth
109
     *
110
     * @return EncoderPropertiesTrait
0 ignored issues
show
Comprehensibility Bug introduced by
The return type EncoderPropertiesTrait is a trait, and thus cannot be used for type-hinting in PHP. Maybe consider adding an interface and use that for type-hinting?

In PHP traits cannot be used for type-hinting as they do not define a well-defined structure. This is because any class that uses a trait can rename that trait’s methods.

If you would like to return an object that has a guaranteed set of methods, you could create a companion interface that lists these methods explicitly.

Loading history...
111
     */
112 81
    protected function reset(
113
        string $urlPrefix,
114
        iterable $includePaths,
115
        array $fieldSets,
116
        int $encodeOptions,
117
        int $encodeDepth
118
    ): self {
119 81
        $this->links          = null;
120 81
        $this->profile        = null;
121 81
        $this->hasMeta        = false;
122 81
        $this->meta           = null;
123 81
        $this->jsonApiVersion = null;
124 81
        $this->jsonApiMeta    = null;
125 81
        $this->hasJsonApiMeta = false;
126
127
        $this
128 81
            ->withUrlPrefix($urlPrefix)
129 81
            ->withIncludedPaths($includePaths)
130 81
            ->withFieldSets($fieldSets)
131 81
            ->withEncodeOptions($encodeOptions)
132 81
            ->withEncodeDepth($encodeDepth);
133
134 81
        return $this;
135
    }
136
137
    /**
138
     * @return SchemaContainerInterface
139
     */
140 70
    protected function getSchemaContainer(): SchemaContainerInterface
141
    {
142 70
        return $this->container;
143
    }
144
145
    /**
146
     * @param SchemaContainerInterface $container
147
     *
148
     * @return self
149
     */
150 81
    public function setContainer(SchemaContainerInterface $container): self
151
    {
152 81
        $this->container = $container;
153
154 81
        return $this;
155
    }
156
157
    /**
158
     * @return FactoryInterface
159
     */
160 79
    protected function getFactory(): FactoryInterface
161
    {
162 79
        return $this->factory;
163
    }
164
165
    /**
166
     * @param FactoryInterface $factory
167
     *
168
     * @return self
169
     */
170 81
    public function setFactory(FactoryInterface $factory): self
171
    {
172 81
        $this->factory = $factory;
173
174 81
        return $this;
175
    }
176
177
    /**
178
     * @param string $prefix
179
     *
180
     * @return self|EncoderInterface
181
     */
182 81
    public function withUrlPrefix(string $prefix): EncoderInterface
183
    {
184 81
        $this->urlPrefix = $prefix;
185
186 81
        return $this;
187
    }
188
    /**
189
     * @return string
190
     */
191 79
    protected function getUrlPrefix(): string
192
    {
193 79
        return $this->urlPrefix;
194
    }
195
196
    /**
197
     * @param iterable $paths
198
     *
199
     * @return self|EncoderInterface
200
     */
201 81
    public function withIncludedPaths(iterable $paths): EncoderInterface
202
    {
203 81
        assert(
204 81
            call_user_func(
205
                function (array $paths): bool {
206 81
                    $pathsOk = true;
207 81
                    foreach ($paths as $path) {
208 22
                        $pathsOk = $pathsOk === true && is_string($path) === true && empty($path) === false;
209
                    }
210
211 81
                    return $pathsOk;
212 81
                },
213 81
                $paths
214
            )
215
        );
216
217 81
        $this->includePaths = $paths;
218
219 81
        return $this;
220
    }
221
222
    /**
223
     * @return array
224
     */
225 70
    protected function getIncludePaths(): array
226
    {
227 70
        return $this->includePaths;
228
    }
229
230
    /**
231
     * @param array $fieldSets
232
     *
233
     * @return self|EncoderInterface
234
     */
235 81
    public function withFieldSets(array $fieldSets): EncoderInterface
236
    {
237 81
        $this->fieldSets = $fieldSets;
238
239 81
        return $this;
240
    }
241
242
243
    /**
244
     * @return array
245
     */
246 70
    protected function getFieldSets(): array
247
    {
248 70
        return $this->fieldSets;
249
    }
250
251
    /**
252
     * @param int $options
253
     *
254
     * @return self|EncoderInterface
255
     */
256 81
    public function withEncodeOptions(int $options): EncoderInterface
257
    {
258 81
        $this->encodeOptions = $options;
259
260 81
        return $this;
261
    }
262
263
    /**
264
     * @return int
265
     */
266 73
    protected function getEncodeOptions(): int
267
    {
268 73
        return $this->encodeOptions;
269
    }
270
271
    /**
272
     * @param int $depth
273
     *
274
     * @return self|EncoderInterface
275
     */
276 81
    public function withEncodeDepth(int $depth): EncoderInterface
277
    {
278 81
        assert($depth > 0);
279
280 81
        $this->encodeDepth = $depth;
281
282 81
        return $this;
283
    }
284
285
    /**
286
     * @return int
287
     */
288 73
    protected function getEncodeDepth(): int
289
    {
290 73
        return $this->encodeDepth;
291
    }
292
293
    /**
294
     * @param iterable $links
295
     *
296
     * @return self|EncoderInterface
297
     */
298 5
    public function withLinks(iterable $links): EncoderInterface
299
    {
300 5
        $this->links = $this->hasLinks() === true ? $this->mergeIterables($this->links, $links) : $links;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->hasLinks() === tr...links, $links) : $links can also be of type object<Generator>. However, the property $links is declared as type object<Neomerx\JsonApi\Encoder\iterable>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
301
302 5
        return $this;
303
    }
304
305
    /**
306
     * @return bool
307
     */
308 79
    protected function hasLinks(): bool
309
    {
310 79
        return $this->links !== null;
311
    }
312
313
    /**
314
     * @return iterable
315
     */
316 5
    protected function getLinks(): iterable
317
    {
318 5
        return $this->links;
319
    }
320
321
    /**
322
     * @param iterable $links
323
     *
324
     * @return self|EncoderInterface
325
     */
326 1
    public function withProfile(iterable $links): EncoderInterface
327
    {
328 1
        $this->profile = $links;
329
330 1
        return $this;
331
    }
332
333
    /**
334
     * @return bool
335
     */
336 79
    protected function hasProfile(): bool
337
    {
338 79
        return $this->profile !== null;
339
    }
340
341
    /**
342
     * @return iterable
343
     */
344 1
    protected function getProfile(): iterable
345
    {
346 1
        return $this->profile;
347
    }
348
349
    /**
350
     * @param mixed $meta
351
     *
352
     * @return self|EncoderInterface
353
     */
354 6
    public function withMeta($meta): EncoderInterface
355
    {
356 6
        $this->meta    = $meta;
357 6
        $this->hasMeta = true;
358
359 6
        return $this;
360
    }
361
362
    /**
363
     * @return bool
364
     */
365 79
    protected function hasMeta(): bool
366
    {
367 79
        return $this->hasMeta;
368
    }
369
370
    /**
371
     * @return mixed
372
     */
373 6
    public function getMeta()
374
    {
375 6
        return $this->meta;
376
    }
377
378
    /**
379
     * @param string $version
380
     *
381
     * @return self|EncoderInterface
382
     */
383 2
    public function withJsonApiVersion(string $version): EncoderInterface
384
    {
385 2
        $this->jsonApiVersion = $version;
386
387 2
        return $this;
388
    }
389
390
    /**
391
     * @return bool
392
     */
393 79
    protected function hasJsonApiVersion(): bool
394
    {
395 79
        return $this->jsonApiVersion !== null;
396
    }
397
398
    /**
399
     * @return string
400
     */
401 2
    protected function getJsonApiVersion(): string
402
    {
403 2
        return $this->jsonApiVersion;
404
    }
405
406
    /**
407
     * @param mixed $meta
408
     *
409
     * @return self|EncoderInterface
410
     */
411 2
    public function withJsonApiMeta($meta): EncoderInterface
412
    {
413 2
        $this->jsonApiMeta    = $meta;
414 2
        $this->hasJsonApiMeta = true;
415
416 2
        return $this;
417
    }
418
419
    /**
420
     * @return bool
421
     */
422 79
    protected function hasJsonApiMeta(): bool
423
    {
424 79
        return $this->hasJsonApiMeta;
425
    }
426
427
    /**
428
     * @return mixed
429
     */
430 2
    protected function getJsonApiMeta()
431
    {
432 2
        return $this->jsonApiMeta;
433
    }
434
435
    /**
436
     * @param mixed  $resource
437
     * @param string $relationshipName
438
     *
439
     * @return self|EncoderInterface
440
     */
441 1 View Code Duplication
    public function withRelationshipSelfLink($resource, string $relationshipName): EncoderInterface
442
    {
443
        $link = $this
444 1
            ->getSchemaContainer()->getSchema($resource)
445 1
            ->getRelationshipSelfLink($resource, $relationshipName);
446
447 1
        return $this->withLinks([
0 ignored issues
show
Documentation introduced by
array(\Neomerx\JsonApi\C...terface::SELF => $link) is of type array<string|integer,obj...\Schema\LinkInterface>>, but the function expects a object<Neomerx\JsonApi\Encoder\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
448 1
            LinkInterface::SELF => $link,
449
        ]);
450
    }
451
452
    /**
453
     * @param mixed  $resource
454
     * @param string $relationshipName
455
     *
456
     * @return self|EncoderInterface
457
     */
458 1 View Code Duplication
    public function withRelationshipRelatedLink($resource, string $relationshipName): EncoderInterface
459
    {
460
        $link = $this
461 1
            ->getSchemaContainer()->getSchema($resource)
462 1
            ->getRelationshipRelatedLink($resource, $relationshipName);
463
464 1
        return $this->withLinks([
0 ignored issues
show
Documentation introduced by
array(\Neomerx\JsonApi\C...face::RELATED => $link) is of type array<string|integer,obj...\Schema\LinkInterface>>, but the function expects a object<Neomerx\JsonApi\Encoder\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
465 1
            LinkInterface::RELATED => $link,
466
        ]);
467
    }
468
469
    /**
470
     * @param iterable $iterable1
471
     * @param iterable $iterable2
472
     *
473
     * @return iterable
474
     */
475 1
    private function mergeIterables(iterable $iterable1, iterable $iterable2): iterable
476
    {
477 1
        yield from $iterable1;
478 1
        yield from $iterable2;
479 1
    }
480
}
481