Completed
Pull Request — master (#119)
by Toby
65:37 queued 63:37
created

Parameters::getSort()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 32
Code Lines 19

Duplication

Lines 8
Ratio 25 %

Code Coverage

Tests 21
CRAP Score 5

Importance

Changes 0
Metric Value
dl 8
loc 32
ccs 21
cts 21
cp 1
rs 8.439
c 0
b 0
f 0
cc 5
eloc 19
nc 3
nop 1
crap 5
1
<?php
2
3
/*
4
 * This file is part of JSON-API.
5
 *
6
 * (c) Toby Zerner <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Tobscure\JsonApi;
13
14
use Tobscure\JsonApi\Exception\InvalidParameterException;
15
16
class Parameters
17
{
18
    /**
19
     * @var array
20
     */
21
    protected $input;
22
23
    /**
24
     * @param array $input
25
     */
26 42
    public function __construct(array $input)
27
    {
28 42
        $this->input = $input;
29 42
    }
30
31
    /**
32
     * Get the includes.
33
     *
34
     * @param array $available
35
     *
36
     * @throws \Tobscure\JsonApi\Exception\InvalidParameterException
37
     *
38
     * @return array
39
     */
40 9
    public function getInclude(array $available = [])
41
    {
42 9
        if ($include = $this->getInput('include')) {
43 6
            $relationships = explode(',', $include);
44
45 6
            $invalid = array_diff($relationships, $available);
46
47 6 View Code Duplication
            if (count($invalid)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
48 3
                throw new InvalidParameterException(
49 3
                    'Invalid includes ['.implode(',', $invalid).']',
50 3
                    1,
51 3
                    null,
52
                    'include'
53 3
                );
54
            }
55
56 3
            return $relationships;
57
        }
58
59 3
        return [];
60
    }
61
62
    /**
63
     * Get number of offset.
64
     *
65
     * @param int|null $perPage
66
     *
67
     * @throws \Tobscure\JsonApi\Exception\InvalidParameterException
68
     *
69
     * @return int
70
     */
71 9
    public function getOffset($perPage = null)
72
    {
73 9
        if ($perPage && ($offset = $this->getOffsetFromNumber($perPage))) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $perPage of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
74 3
            return $offset;
75
        }
76
77 6
        $offset = (int) $this->getPage('offset');
78
79 6
        if ($offset < 0) {
80 3
            throw new InvalidParameterException(
81 3
                'page[offset] must be >=0',
82 3
                2,
83 3
                null,
84
                'page[offset]'
85 3
            );
86
        }
87
88 3
        return $offset;
89
    }
90
91
    /**
92
     * Calculate the offset based on the page[number] parameter.
93
     *
94
     * @param int $perPage
95
     *
96
     * @throws \Tobscure\JsonApi\Exception\InvalidParameterException
97
     *
98
     * @return int
99
     */
100 3
    private function getOffsetFromNumber($perPage)
101
    {
102 3
        $page = (int) $this->getPage('number');
103
104 3
        if ($page <= 1) {
105
            return 0;
106
        }
107
108 3
        return ($page - 1) * $perPage;
109
    }
110
111
    /**
112
     * Get the limit.
113
     *
114
     * @param int|null $max
115
     *
116
     * @return int|null
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
117
     */
118 6
    public function getLimit($max = null)
119
    {
120 6
        $limit = $this->getPage('limit') ?: $this->getPage('size') ?: null;
121
122 6
        if ($limit && $max) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $limit of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $max of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
123
            $limit = min($max, $limit);
124
        }
125
126 6
        return $limit;
127
    }
128
129
    /**
130
     * Get the sort.
131
     *
132
     * @param array $available
133
     *
134
     * @throws \Tobscure\JsonApi\Exception\InvalidParameterException
135
     *
136
     * @return array
137
     */
138 12
    public function getSort(array $available = [])
139
    {
140 12
        $sort = [];
141
142 12
        if ($input = $this->getInput('sort')) {
143 9
            $fields = explode(',', $input);
144
145 9
            foreach ($fields as $field) {
146 9
                if (substr($field, 0, 1) === '-') {
147 3
                    $field = substr($field, 1);
148 3
                    $order = 'desc';
149 3
                } else {
150 9
                    $order = 'asc';
151
                }
152
153 9
                $sort[$field] = $order;
154 9
            }
155
156 9
            $invalid = array_diff(array_keys($sort), $available);
157
158 9 View Code Duplication
            if (count($invalid)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
159 3
                throw new InvalidParameterException(
160 3
                    'Invalid sort fields ['.implode(',', $invalid).']',
161 3
                    3,
162 3
                    null,
163
                    'sort'
164 3
                );
165
            }
166 6
        }
167
168 9
        return $sort;
169
    }
170
171
    /**
172
     * Get the fields requested for inclusion.
173
     *
174
     * @return array
175
     */
176 6
    public function getFields()
177
    {
178 6
        $fields = $this->getInput('fields');
179
180 6
        if (! is_array($fields)) {
181 3
            return [];
182
        }
183
184 3
        return array_map(function ($fields) {
185 3
            return explode(',', $fields);
186 3
        }, $fields);
187
    }
188
189
    /**
190
     * Get a filter item.
191
     *
192
     * @return mixed
193
     */
194
    public function getFilter()
195
    {
196
        return $this->getInput('filter');
197
    }
198
199
    /**
200
     * Get an input item.
201
     *
202
     * @param string $key
203
     * @param null $default
204
     *
205
     * @return mixed
206
     */
207 42
    private function getInput($key, $default = null)
208
    {
209 42
        return isset($this->input[$key]) ? $this->input[$key] : $default;
210
    }
211
212
    /**
213
     * Get the page.
214
     *
215
     * @param string $key
216
     *
217
     * @return string
218
     */
219 15
    private function getPage($key)
220
    {
221 15
        $page = $this->getInput('page');
222
223 15
        return isset($page[$key]) ? $page[$key] : '';
224
    }
225
}
226