Encoder::getOriginalUri()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php declare (strict_types = 1);
2
3
namespace Limoncello\Flute\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 Closure;
22
use Limoncello\Flute\Contracts\Encoder\EncoderInterface;
23
use Limoncello\Flute\Contracts\Models\PaginatedDataInterface;
24
use Limoncello\Flute\Contracts\Validation\JsonApiQueryParserInterface;
25
use Neomerx\JsonApi\Contracts\Http\Query\BaseQueryParserInterface;
26
use Neomerx\JsonApi\Contracts\Schema\DocumentInterface;
27
use Psr\Http\Message\UriInterface;
28
use function array_merge;
29
use function assert;
30
use function http_build_query;
31
use function parse_str;
32
33
/**
34
 * @package Limoncello\Flute
35
 */
36
class Encoder extends \Neomerx\JsonApi\Encoder\Encoder implements EncoderInterface
37
{
38
    /**
39
     * @var UriInterface
40
     */
41
    private $originalUri;
42 21
43
    /**
44 21
     * @inheritdoc
45
     */
46 21
    public function forOriginalUri(UriInterface $uri): EncoderInterface
47
    {
48
        $this->originalUri = $uri;
49
50
        return $this;
51
    }
52 16
53
    /**
54 16
     * @inheritdoc
55
     */
56 16
    public function encodeData($data): string
57
    {
58
        $data = $this->handleRelationshipStorageAndPagingData($data);
59
60
        return parent::encodeData($data);
61
    }
62 1
63
    /**
64 1
     * @inheritdoc
65
     */
66 1
    public function encodeIdentifiers($data): string
67
    {
68
        $data = $this->handleRelationshipStorageAndPagingData($data);
69
70
        return parent::encodeIdentifiers($data);
71
    }
72 2
73
    /**
74 2
     * @return UriInterface
75
     */
76
    protected function getOriginalUri(): UriInterface
77
    {
78
        return $this->originalUri;
79
    }
80
81
    /**
82 17
     * @param mixed $data
83
     *
84 17
     * @return mixed
85
     */
86 12
    private function handleRelationshipStorageAndPagingData($data)
87 12
    {
88
        if ($data instanceof PaginatedDataInterface) {
89
            /** @var PaginatedDataInterface $data */
90
            $this->addPagingLinksIfNeeded($data);
91
            $data = $data->getData();
92 17
        }
93
94
        /** @var mixed $data */
95
96
        return $data;
97
    }
98
99
    /**
100 12
     * @param PaginatedDataInterface $data
101
     *
102 12
     * @return void
103 12
     */
104 12
    private function addPagingLinksIfNeeded(PaginatedDataInterface $data): void
105
    {
106 2
        if ($data->isCollection() === true &&
107 2
            (0 < $data->getOffset() || $data->hasMoreItems() === true) &&
108
            $this->getOriginalUri() !== null
109 2
        ) {
110 2
            $links       = [];
111 2
            $linkClosure = $this->createLinkClosure($data->getLimit());
112 2
113
            $prev = DocumentInterface::KEYWORD_PREV;
114 2
            $next = DocumentInterface::KEYWORD_NEXT;
115
            $data->getOffset() <= 0 ?: $links[$prev] = $linkClosure(max(0, $data->getOffset() - $data->getLimit()));
116
            $data->hasMoreItems() === false ?: $links[$next] = $linkClosure($data->getOffset() + $data->getLimit());
117
118
            $this->withLinks($links);
0 ignored issues
show
Documentation introduced by
$links is of type array, 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...
119
        }
120
    }
121
122
    /**
123 2
     * @param int $pageSize
124
     *
125 2
     * @return Closure
126
     */
127 2
    private function createLinkClosure(int $pageSize): Closure
128
    {
129
        assert($pageSize > 0);
130 2
131
        parse_str($this->getOriginalUri()->getQuery(), $queryParams);
132 2
133 2
        return function ($offset) use ($pageSize, $queryParams) {
134
            $paramsWithPaging = array_merge($queryParams, [
135
                BaseQueryParserInterface::PARAM_PAGE => [
136 2
                    JsonApiQueryParserInterface::PARAM_PAGING_OFFSET => $offset,
137 2
                    JsonApiQueryParserInterface::PARAM_PAGING_LIMIT  => $pageSize,
138 2
                ],
139
            ]);
140 2
            $newUri  = $this->getOriginalUri()->withQuery(http_build_query($paramsWithPaging));
141 2
            $fullUrl = (string)$newUri;
142
            $link    = $this->getFactory()->createLink(false, $fullUrl, false);
143
144
            return $link;
145
        };
146
    }
147
}
148