Passed
Push — master ( 65bc60...4839bb )
by noitran
05:19
created

RequestParser   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 199
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 23
eloc 50
dl 0
loc 199
ccs 0
cts 61
cp 0
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A parseColumn() 0 9 2
A __construct() 0 5 1
A getQueryParameter() 0 3 1
A parseExpression() 0 7 2
A isValidDataType() 0 11 3
A extractValue() 0 7 2
A parse() 0 11 1
A getAttributes() 0 3 1
A init() 0 5 1
A parseDataType() 0 17 3
A parseRelation() 0 9 2
A parseValue() 0 11 3
A setQueryParameterName() 0 5 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Noitran\RQL\Parsers\Request\Illuminate;
6
7
use Illuminate\Http\Request;
8
use Illuminate\Support\Str;
9
use Noitran\RQL\Exceptions\RuntimeException;
10
use Noitran\RQL\Parsers\AbstractParser;
11
use Noitran\RQL\Parsers\Model;
12
13
/**
14
 * Class RequestParser.
15
 */
16
class RequestParser extends AbstractParser
17
{
18
    /**
19
     * @var string
20
     */
21
    protected $queryParameterName;
22
23
    /**
24
     * @var Request
25
     */
26
    protected $request;
27
28
    /**
29
     * RequestParser constructor.
30
     *
31
     * @param Request $request
32
     */
33
    public function __construct(Request $request)
34
    {
35
        $this->request = $request;
36
37
        $this->init();
38
    }
39
40
    /**
41
     * @return RequestParser
42
     */
43
    public function init(): self
44
    {
45
        $this->setQueryParameterName();
46
47
        return $this;
48
    }
49
50
    /**
51
     * @return array
52
     */
53
    public function getAttributes(): array
54
    {
55
        return $this->request->toArray();
56
    }
57
58
    /**
59
     * @return RequestParser
60
     */
61
    public function setQueryParameterName(): self
62
    {
63
        $this->queryParameterName = config('rql.parsers.default_query_parameter', 'filter');
64
65
        return $this;
66
    }
67
68
    /**
69
     * @return string|array|null
70
     */
71
    public function getQueryParameter()
72
    {
73
        return $this->request->input($this->queryParameterName);
74
    }
75
76
    /**
77
     * @return mixed
78
     */
79
    public function parse(): Model
80
    {
81
        $model = new Model();
82
83
        $model->setRelation($this->parseRelation($this->filterParameter));
0 ignored issues
show
Bug introduced by
It seems like $this->parseRelation($this->filterParameter) can also be of type null; however, parameter $relation of Noitran\RQL\Parsers\Model::setRelation() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

83
        $model->setRelation(/** @scrutinizer ignore-type */ $this->parseRelation($this->filterParameter));
Loading history...
Bug Best Practice introduced by
The property filterParameter does not exist on Noitran\RQL\Parsers\Requ...lluminate\RequestParser. Did you maybe forget to declare it?
Loading history...
84
        $model->setField($this->parseColumn($this->filterParameter));
85
        $model->setExpression($this->parseExpression($this->filterValue));
0 ignored issues
show
Bug Best Practice introduced by
The property filterValue does not exist on Noitran\RQL\Parsers\Requ...lluminate\RequestParser. Did you maybe forget to declare it?
Loading history...
86
        $model->setDataType($this->parseDataType($this->filterValue));
87
        $model->setValue($this->parseValue($this->filterValue));
88
89
        return $model;
90
    }
91
92
    /**
93
     * @param $filterParameter
94
     *
95
     * @return string|null
96
     */
97
    protected function parseRelation($filterParameter): ?string
98
    {
99
        if (false !== strpos($filterParameter, '.')) {
100
            $lastDotPosition = strrpos($filterParameter, '.');
101
102
            return substr($filterParameter, 0, $lastDotPosition);
103
        }
104
105
        return null;
106
    }
107
108
    /**
109
     * @param $filterParameter
110
     *
111
     * @return string
112
     */
113
    protected function parseColumn($filterParameter): string
114
    {
115
        if (false !== strpos($filterParameter, '.')) {
116
            $lastDotPosition = strrpos($filterParameter, '.');
117
118
            return substr($filterParameter, $lastDotPosition + 1);
119
        }
120
121
        return $filterParameter;
122
    }
123
124
    /**
125
     * @param $filterValue
126
     *
127
     * @return string
128
     */
129
    protected function parseExpression($filterValue): string
130
    {
131
        if (! \is_array($filterValue)) {
132
            return config('repositories.filtering.default_expression', '$eq');
133
        }
134
135
        return key($filterValue);
0 ignored issues
show
Bug Best Practice introduced by
The expression return key($filterValue) could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
136
    }
137
138
    /**
139
     * @param $filterValue
140
     *
141
     * @throws RuntimeException
142
     *
143
     * @return string
144
     */
145
    protected function parseDataType($filterValue): string
146
    {
147
        $value = $this->extractValue($filterValue);
148
149
        if (false !== strpos($value, ':')) {
150
            $lastColonPosition = strpos($value, ':');
151
152
            $parsedDataType = substr($value, 0, $lastColonPosition);
153
154
            if (! $this->isValidDataType($parsedDataType)) {
155
                return config('repositories.filtering.default_data_type', '$string');
156
            }
157
158
            return $parsedDataType;
159
        }
160
161
        return config('repositories.filtering.default_data_type', '$string');
162
    }
163
164
    /**
165
     * @param $filterValue
166
     *
167
     * @return string
168
     */
169
    protected function parseValue($filterValue): string
170
    {
171
        $value = $this->extractValue($filterValue);
172
173
        if (Str::startsWith($value, ['$']) && false !== strpos($value, ':')) {
174
            $lastColonPosition = strpos($value, ':');
175
176
            return substr($value, $lastColonPosition + 1);
177
        }
178
179
        return $value;
180
    }
181
182
    /**
183
     * @param $filterValue
184
     *
185
     * @return string
186
     */
187
    private function extractValue($filterValue): string
188
    {
189
        if (! \is_array($filterValue)) {
190
            return $filterValue;
191
        }
192
193
        return array_shift($filterValue);
194
    }
195
196
    /**
197
     * @param $dataType
198
     * @param bool $strict
199
     *
200
     * @throws RuntimeException
201
     *
202
     * @return bool
203
     */
204
    private function isValidDataType($dataType, $strict = false): bool
205
    {
206
        if (! \in_array($dataType, config('repositories.filtering.allowed_data_types', '$string'), true)) {
207
            if ($strict) {
208
                throw new RuntimeException('Invalid/Unallowed data type passed.');
209
            }
210
211
            return false;
212
        }
213
214
        return true;
215
    }
216
}
217