Passed
Push — master ( 18a4d8...e0d339 )
by Marcin
02:40 queued 11s
created

RequestParser::getQueryHash()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 10
dl 0
loc 17
ccs 0
cts 10
cp 0
rs 9.9332
c 1
b 0
f 0
cc 4
nc 5
nop 0
crap 20
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 \Mrcnpdlk\Lib\UrlSearchParser\Exception\DuplicateParamException
70
     * @throws \Mrcnpdlk\Lib\UrlSearchParser\Exception\EmptyParamException
71
     * @throws \Mrcnpdlk\Lib\UrlSearchParser\Exception\InvalidParamException
72
     */
73 22
    public function __construct(string $query)
74
    {
75 22
        $this->query = $query;
76 22
        $this->parse($query);
77 12
    }
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
     * @throws \Mrcnpdlk\Lib\UrlSearchParser\Exception
135
     *
136
     * @return string
137
     */
138
    public function getQueryHash(): string
139
    {
140
        try {
141
            $resJson = json_encode($this->queryParams);
142
            if (false === $resJson) {
143
                throw new RuntimeException('Cannot generate json_encode');
144
            }
145
            /** @var string|false $res */
146
            $res = md5($resJson);
147
            if (false === $res) {
148
                throw new RuntimeException('Cannot generate md5 hash');
149
            }
150
        } catch (RuntimeException $e) {
151
            throw new Exception(sprintf('Cannot query hash. %s', $e->getMessage()));
152
        }
153
154
        return $res;
155
    }
156
157
    /**
158
     * @param string      $param
159
     * @param string|null $type    If NULL return value AS IS
160
     * @param mixed|null  $default
161
     *
162
     * @return mixed|null
163
     */
164 22
    public function getQueryParam(string $param, string $type = null, $default = null)
165
    {
166 22
        if (isset($this->queryParams[$param])) {
167 22
            if (null !== $type) {
168 21
                $type = strtolower($type);
169 21
                if (!in_array($type, ['boolean', 'bool', 'integer', 'int', 'float', 'double', 'string', 'array'])) {
170 1
                    throw new InvalidArgumentException(sprintf('Unsupported type [%s]', $type));
171
                }
172
173 20
                $var = $this->queryParams[$param];
174
175 20
                if ('array' === $type && is_string($var)) {
176 2
                    $var = explode(',', $var);
177 19
                } elseif ('string' === $type && is_array($var)) {
178 1
                    $var = implode(',', $var);
179 19
                } elseif (in_array($type, ['boolean', 'bool']) && in_array(strtolower($var), ['true', 'false'])) {
180 2
                    $var = ('true' === strtolower($var));
181 19
                } elseif (!settype($var, $type)) {
182
                    throw new RuntimeException(sprintf('Cannot set type [%s]', $type));
183
                }
184
185 20
                return $var;
186
            }
187
188 1
            return $this->queryParams[$param];
189
        }
190
191 19
        return $default ?? null;
192
    }
193
194
    /**
195
     * @return \Mrcnpdlk\Lib\UrlSearchParser\Criteria\Sort
196
     */
197 3
    public function getSort(): Sort
198
    {
199 3
        return $this->sort;
200
    }
201
202
    /**
203
     * @param string $param
204
     *
205
     * @return $this
206
     */
207 1
    public function removeQueryParam(string $param): self
208
    {
209 1
        unset($this->queryParams[$param]);
210
211 1
        return $this;
212
    }
213
214
    /**
215
     * @param \Mrcnpdlk\Lib\UrlSearchParser\Criteria\Filter $filter
216
     *
217
     * @return $this
218
     */
219 15
    public function setFilter(Filter $filter): self
220
    {
221 15
        $this->filter = $filter;
222
223 15
        return $this;
224
    }
225
226
    /**
227
     * @param int|null $limit
228
     *
229
     * @throws \Mrcnpdlk\Lib\UrlSearchParser\Exception\InvalidParamException
230
     *
231
     * @return $this
232
     */
233 15
    public function setLimit(?int $limit): self
234
    {
235 15
        $this->limit = $limit;
236 15
        if (null !== $this->limit && $this->limit < 0) {
237 1
            throw new InvalidParamException('Limit value cannot be lower than 0');
238
        }
239
240 14
        return $this;
241
    }
242
243
    /**
244
     * @param int|null $offset
245
     *
246
     * @throws \Mrcnpdlk\Lib\UrlSearchParser\Exception\InvalidParamException
247
     *
248
     * @return $this
249
     */
250 14
    public function setOffset(?int $offset): self
251
    {
252 14
        $this->offset = $offset;
253 14
        if (null !== $this->offset && $this->offset < 0) {
254 1
            throw new InvalidParamException('Offset value cannot be lower than 0');
255
        }
256
257 13
        return $this;
258
    }
259
260
    /**
261
     * @param int|null $page
262
     *
263
     * @throws \Mrcnpdlk\Lib\UrlSearchParser\Exception\InvalidParamException
264
     *
265
     * @return $this
266
     */
267 13
    public function setPage(?int $page): self
268
    {
269 13
        $this->page = $page;
270 13
        if (null !== $this->page && $this->page < 0) {
271 1
            throw new InvalidParamException('Page value cannot be lower than 0');
272
        }
273
274 12
        return $this;
275
    }
276
277
    /**
278
     * @param string|null $phrase
279
     *
280
     * @return $this
281
     */
282 12
    public function setPhrase(?string $phrase): self
283
    {
284 12
        $this->phrase = $phrase;
285
286 12
        return $this;
287
    }
288
289
    /**
290
     * @param \Mrcnpdlk\Lib\UrlSearchParser\Criteria\Sort $sort
291
     *
292
     * @return $this
293
     */
294 19
    public function setSort(Sort $sort): self
295
    {
296 19
        $this->sort = $sort;
297
298 19
        return $this;
299
    }
300
301
    /**
302
     * @param string $query
303
     *
304
     * @throws \Mrcnpdlk\Lib\UrlSearchParser\Exception\DuplicateParamException
305
     * @throws \Mrcnpdlk\Lib\UrlSearchParser\Exception\EmptyParamException
306
     * @throws \Mrcnpdlk\Lib\UrlSearchParser\Exception\InvalidParamException
307
     */
308 22
    private function parse(string $query): void
309
    {
310 22
        parse_str($query, $this->queryParams);
311
312 22
        $this->setSort(new Sort($this->getQueryParam(self::SORT_IDENTIFIER, 'string')));
313 19
        $this->setFilter(new Filter($this->getQueryParam(self::FILTER_IDENTIFIER, 'array', [])));
314 15
        $this->setLimit($this->getQueryParam(self::LIMIT_IDENTIFIER, 'int'));
315 14
        $this->setOffset($this->getQueryParam(self::OFFSET_IDENTIFIER, 'int'));
316 13
        $this->setPage($this->getQueryParam(self::PAGE_IDENTIFIER, 'int'));
317 12
        $this->setPhrase($this->getQueryParam(self::PHRASE_IDENTIFIER, 'string'));
318 12
    }
319
}
320