Completed
Branch devel (4fc3ef)
by Marcin
05:51
created

RequestParser::parse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 10
c 0
b 0
f 0
ccs 8
cts 8
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * Created by Marcin.
4
 * Date: 16.06.2018
5
 * Time: 13:45
6
 */
7
declare(strict_types=1);
8
9
namespace Mrcnpdlk\Lib\UrlSearchParser;
10
11
use function in_array;
12
use InvalidArgumentException;
13
use function is_array;
14
use function is_string;
15
use Mrcnpdlk\Lib\UrlSearchParser\Criteria\Filter;
16
use Mrcnpdlk\Lib\UrlSearchParser\Criteria\Sort;
17
use Mrcnpdlk\Lib\UrlSearchParser\Exception\EmptyParamException;
18
use Mrcnpdlk\Lib\UrlSearchParser\Exception\InvalidParamException;
19
use RuntimeException;
20
21
class RequestParser
22
{
23
    public const SORT_IDENTIFIER   = 'sort';
24
    public const FILTER_IDENTIFIER = 'filter';
25
26
    public const LIMIT_IDENTIFIER  = 'limit';
27
    public const OFFSET_IDENTIFIER = 'offset';
28
    public const PAGE_IDENTIFIER   = 'page';
29
    public const PHRASE_IDENTIFIER = 'phrase';
30
31
    /**
32
     * @var string
33
     */
34
    private $query;
35
    /**
36
     * @var array
37
     */
38
    private $queryParams = [];
39
    /**
40
     * @var \Mrcnpdlk\Lib\UrlSearchParser\Criteria\Sort
41
     */
42
    private $sort;
43
    /**
44
     * @var \Mrcnpdlk\Lib\UrlSearchParser\Criteria\Filter
45
     */
46
    private $filter;
47
    /**
48
     * @var int|null
49
     */
50
    private $limit;
51
    /**
52
     * @var int|null
53
     */
54
    private $page;
55
    /**
56
     * @var int|null
57
     */
58
    private $offset;
59
    /**
60
     * @var string|null
61
     */
62
    private $phrase;
63
64
    /**
65
     * RequestParser constructor.
66
     *
67
     * @param string $query
68
     *
69
     * @throws Exception
70
     * @throws EmptyParamException
71
     * @throws InvalidParamException
72
     */
73 20
    public function __construct(string $query)
74
    {
75 20
        $this->query = $query;
76 20
        $this->parse($query);
77 11
    }
78
79
    /**
80
     * @return \Mrcnpdlk\Lib\UrlSearchParser\Criteria\Filter
81
     */
82 4
    public function getFilter(): Filter
83
    {
84 4
        return $this->filter;
85
    }
86
87
    /**
88
     * @param int|null $default
89
     *
90
     * @return int|null
91
     */
92 2
    public function getLimit(int $default = null): ?int
93
    {
94 2
        return $this->limit ?? $default;
95
    }
96
97
    /**
98
     * @param int|null $default
99
     *
100
     * @return int|null
101
     */
102 2
    public function getOffset(int $default = null): ?int
103
    {
104 2
        return $this->offset ?? $default;
105
    }
106
107
    /**
108
     * @param int|null $default
109
     *
110
     * @return int|null
111
     */
112 2
    public function getPage(int $default = null): ?int
113
    {
114 2
        return $this->page ?? $default;
115
    }
116
117
    /**
118
     * @return string|null
119
     */
120 2
    public function getPhrase(): ?string
121
    {
122 2
        return $this->phrase;
123
    }
124
125
    /**
126
     * @return string
127
     */
128 1
    public function getQuery(): string
129
    {
130 1
        return $this->query;
131
    }
132
133
    /**
134
     * @return string
135
     */
136
    public function getQueryHash(): string
137
    {
138
        return md5(json_encode($this->queryParams));
139
    }
140
141
    /**
142
     * @param string      $param
143
     * @param string|null $type    If NULL return value AS IS
144
     * @param mixed|null  $default
145
     *
146
     * @return mixed|null
147
     */
148 20
    public function getQueryParam(string $param, string $type = null, $default = null)
149
    {
150 20
        if (isset($this->queryParams[$param])) {
151 20
            if (null !== $type) {
152 19
                $type = strtolower($type);
153 19
                if (!in_array($type, ['boolean', 'bool', 'integer', 'int', 'float', 'double', 'string', 'array'])) {
154 1
                    throw new InvalidArgumentException(sprintf('Unsupported type [%s]', $type));
155
                }
156
157 18
                $var = $this->queryParams[$param];
158
159 18
                if ('array' === $type && is_string($var)) {
160 2
                    $var = explode(',', $var);
161 17
                } elseif ('string' === $type && is_array($var)) {
162 1
                    $var = implode(',', $var);
163 17
                } elseif (in_array($type, ['boolean', 'bool']) && in_array(strtolower($var), ['true', 'false'])) {
164 2
                    $var = ('true' === strtolower($var));
165 17
                } elseif (!settype($var, $type)) {
166
                    throw new RuntimeException(sprintf('Cannot set type [%s]', $type));
167
                }
168
169 18
                return $var;
170
            }
171
172 1
            return $this->queryParams[$param];
173
        }
174
175 18
        return $default ?? null;
176
    }
177
178
    /**
179
     * @return \Mrcnpdlk\Lib\UrlSearchParser\Criteria\Sort
180
     */
181 2
    public function getSort(): Sort
182
    {
183 2
        return $this->sort;
184
    }
185
186
    /**
187
     * @param string $param
188
     *
189
     * @return $this
190
     */
191 1
    public function removeQueryParam(string $param): self
192
    {
193 1
        unset($this->queryParams[$param]);
194
195 1
        return $this;
196
    }
197
198
    /**
199
     * @param \Mrcnpdlk\Lib\UrlSearchParser\Criteria\Filter $filter
200
     *
201
     * @return $this
202
     */
203 14
    public function setFilter(Filter $filter): self
204
    {
205 14
        $this->filter = $filter;
206
207 14
        return $this;
208
    }
209
210
    /**
211
     * @param int|null $limit
212
     *
213
     * @throws \Mrcnpdlk\Lib\UrlSearchParser\Exception\InvalidParamException
214
     *
215
     * @return $this
216
     */
217 14
    public function setLimit(?int $limit): self
218
    {
219 14
        $this->limit = $limit;
220 14
        if (null !== $this->limit && $this->limit < 0) {
221 1
            throw new InvalidParamException('Limit value cannot be lower than 0');
222
        }
223
224 13
        return $this;
225
    }
226
227
    /**
228
     * @param int|null $offset
229
     *
230
     * @throws \Mrcnpdlk\Lib\UrlSearchParser\Exception\InvalidParamException
231
     *
232
     * @return $this
233
     */
234 13
    public function setOffset(?int $offset): self
235
    {
236 13
        $this->offset = $offset;
237 13
        if (null !== $this->offset && $this->offset < 0) {
238 1
            throw new InvalidParamException('Offset value cannot be lower than 0');
239
        }
240
241 12
        return $this;
242
    }
243
244
    /**
245
     * @param int|null $page
246
     *
247
     * @throws \Mrcnpdlk\Lib\UrlSearchParser\Exception\InvalidParamException
248
     *
249
     * @return $this
250
     */
251 12
    public function setPage(?int $page): self
252
    {
253 12
        $this->page = $page;
254 12
        if (null !== $this->page && $this->page < 0) {
255 1
            throw new InvalidParamException('Page value cannot be lower than 0');
256
        }
257
258 11
        return $this;
259
    }
260
261
    /**
262
     * @param string|null $phrase
263
     *
264
     * @return $this
265
     */
266 11
    public function setPhrase(?string $phrase): self
267
    {
268 11
        $this->phrase = $phrase;
269
270 11
        return $this;
271
    }
272
273
    /**
274
     * @param \Mrcnpdlk\Lib\UrlSearchParser\Criteria\Sort $sort
275
     *
276
     * @return $this
277
     */
278 18
    public function setSort(Sort $sort): self
279
    {
280 18
        $this->sort = $sort;
281
282 18
        return $this;
283
    }
284
285
    /**
286
     * @param string $query
287
     *
288
     * @throws \Mrcnpdlk\Lib\UrlSearchParser\Exception\EmptyParamException
289
     * @throws \Mrcnpdlk\Lib\UrlSearchParser\Exception\InvalidParamException
290
     */
291 20
    private function parse(string $query): void
292
    {
293 20
        parse_str($query, $this->queryParams);
294
295 20
        $this->setSort(new Sort($this->getQueryParam(self::SORT_IDENTIFIER, 'string')));
296 18
        $this->setFilter(new Filter($this->getQueryParam(self::FILTER_IDENTIFIER, 'array', [])));
297 14
        $this->setLimit($this->getQueryParam(self::LIMIT_IDENTIFIER, 'int'));
298 13
        $this->setOffset($this->getQueryParam(self::OFFSET_IDENTIFIER, 'int'));
299 12
        $this->setPage($this->getQueryParam(self::PAGE_IDENTIFIER, 'int'));
300 11
        $this->setPhrase($this->getQueryParam(self::PHRASE_IDENTIFIER, 'string'));
301 11
    }
302
}
303