Passed
Push — feature-FRAM-91-custom-criteri... ( 7e2102 )
by Vincent
15:55
created

Criteria::getIterator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Bdf\Prime\Entity;
4
5
use ArrayAccess;
6
use Bdf\Prime\Query\Contract\Orderable;
7
use Exception;
8
use IteratorAggregate;
9
use Traversable;
10
11
/**
12
 * Builder for entity criteria
13
 */
14
class Criteria implements ArrayAccess, IteratorAggregate
15
{
16
    /**
17
     * Critères injectés vers le dépot d'entity
18
     *
19
     * @var array<string, mixed>
20
     */
21
    protected array $criteria = [];
22
23
    /**
24
     * Map attribute name to filters (i.e. attribute with operator)
25
     *
26
     * <pre>
27
     * ex:
28
     *   ['weight >' => 10, 'weight <' => 20]
29
     * Will generates inputs:
30
     *   ['weight' => ['weight >', 'weight <']]
31
     * </pre>
32
     *
33
     * @var array<string, list<string>>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string, list<string>> at position 4 could not be parsed: Expected '>' at position 4, but found 'list'.
Loading history...
34
     */
35
    protected array $inputs = [];
36
37
    /**
38
     * Commandes spéciales du query builder (ex: ':limit')
39
     *
40
     * @var array<string, mixed>
41
     */
42
    protected array $specials = [];
43
44
    /**
45
     * Constructor
46
     *
47
     * @param array $filters
48
     * @psalm-consistent-constructor
49
     */
50 21
    public function __construct(array $filters = [])
51
    {
52 21
        $this->import($filters);
53
    }
54
55
    /**
56
     * Import criteria
57
     *
58
     * @param array $filters
59
     *
60
     * @return self
61
     */
62 21
    public function import($filters)
63
    {
64 21
        foreach ($filters as $filter => $value) {
65 3
            $this->add($filter, $value);
66
        }
67
68 21
        return $this;
69
    }
70
71
    /**
72
     * Add a criterion
73
     *
74
     * @param string $filter
75
     * @param mixed  $value
76
     * @param bool   $replace
77
     *
78
     * @return self
79
     */
80 13
    public function add($filter, $value, $replace = false)
81
    {
82 13
        if ($filter[0] === ':') {
83 5
            $this->specials[$filter] = $value;
84
        } else {
85 12
            list($attribute) = explode(' ', trim($filter));
86
87 12
            if ($replace && isset($this->inputs[$attribute])) {
88 1
                $this->remove($attribute);
89
            }
90
91 12
            $this->criteria[$filter]  = $value;
92 12
            $this->inputs[$attribute][] = $filter;
93
        }
94
95 13
        return $this;
96
    }
97
98
    /**
99
     * Remove criterion
100
     *
101
     * @param string $filter   criterion to remove. Could be a alias
102
     * @return self
103
     */
104 4
    public function remove($filter)
105
    {
106 4
        list($attribute) = explode(' ', trim($filter));
107
108 4
        if (isset($this->inputs[$attribute])) {
109 3
            foreach ($this->inputs[$attribute] as $key) {
110 3
                unset($this->criteria[$key]);
111
            }
112
        }
113
114 4
        unset($this->criteria[$filter]);
115 4
        unset($this->inputs[$attribute]);
116 4
        unset($this->specials[$filter]);
117
118 4
        return $this;
119
    }
120
121
    /**
122
     * Does criterion exist
123
     *
124
     * @param string $filter    criterion exists. Could be a alias
125
     * @return bool
126
     */
127 2
    public function exists($filter)
128
    {
129 2
        return isset($this->criteria[$filter]) || isset($this->inputs[$filter]);
130
    }
131
132
    /**
133
     * Get a criterion value
134
     *
135
     * @param string $filter    criterion to get. Could be a alias
136
     * @param mixed  $default
137
     *
138
     * @return mixed
139
     */
140 6
    public function get($filter, $default = null)
141
    {
142 6
        if (isset($this->criteria[$filter])) {
143 3
            return $this->criteria[$filter];
144
        }
145
146 4
        if (isset($this->inputs[$filter])) {
147 2
            return $this->criteria[$this->inputs[$filter][0]];
148
        }
149
150 3
        return $default;
151
    }
152
153
    /**
154
     * Get special criterion
155
     *
156
     * @param string $filter   Could be a alias
157
     * @param mixed  $default
158
     *
159
     * @return mixed
160
     */
161 1
    public function special($filter, $default = null)
162
    {
163 1
        return isset($this->specials[$filter])
164 1
            ? $this->specials[$filter]
165 1
            : $default;
166
    }
167
168
    /**
169
     * Get all criteria including specials
170
     *
171
     * @return array
172
     */
173 4
    public function all()
174
    {
175 4
        return $this->criteria + $this->specials;
176
    }
177
178
    /**
179
     * Get criteria only
180
     *
181
     * @todo trigger "Using deprecated language feature PHP4 constructor"
182
     *
183
     * @return array
184
     */
185 2
    public function criteria()
186
    {
187 2
        return $this->criteria;
188
    }
189
190
    /**
191
     * Get all special criteria
192
     *
193
     * @return array
194
     */
195 1
    public function specials()
196
    {
197 1
        return $this->specials;
198
    }
199
200
    /**
201
     * Set attribute order
202
     *
203
     * @param string $attribute
204
     * @param Orderable::ORDER_* $type
205
     *
206
     * @return void
207
     */
208 1
    public function order(string $attribute, string $type = Orderable::ORDER_ASC): void
209
    {
210 1
        $this->specials[':order'][$attribute] = $type;
211
    }
212
213
    /**
214
     * Get attribute order type
215
     *
216
     * @param string $attribute
217
     * @return string|null  Returns attribute order type. Null if not found
218
     */
219 1
    public function orderType($attribute)
220
    {
221 1
        return isset($this->specials[':order'][$attribute])
222 1
            ? $this->specials[':order'][$attribute]
223 1
            : null;
224
    }
225
226
    /**
227
     * Set/Get page number
228
     *
229
     * @param int $page
230
     * @return int|null
231
     */
232 1
    public function page($page = null)
233
    {
234 1
        if ($page === null) {
235 1
            return isset($this->specials[':limitPage'][0])
236 1
                ? $this->specials[':limitPage'][0]
237 1
                : 0;
238
        }
239
240 1
        $this->specials[':limitPage'][0] = $page;
241
    }
242
243
    /**
244
     * Set/Get the max number of rows in a page
245
     *
246
     * @param int $maxRows
247
     * @return int|null
248
     */
249 1
    public function pageMaxRows($maxRows = null)
250
    {
251 1
        if ($maxRows === null) {
252 1
            return isset($this->specials[':limitPage'][1])
253 1
                ? $this->specials[':limitPage'][1]
254 1
                : 0;
255
        }
256
257 1
        $this->specials[':limitPage'][1] = $maxRows;
258
    }
259
260
    /**
261
     * Set/Get SQL max results
262
     *
263
     * @param int $maxResults
264
     * @return int|null
265
     */
266 1
    public function maxResults($maxResults = null)
267
    {
268 1
        if ($maxResults === null) {
269 1
            return isset($this->specials[':limit'])
270 1
                ? $this->specials[':limit']
271 1
                : 0;
272
        }
273
274 1
        $this->specials[':limit'] = $maxResults;
275
    }
276
277
    /**
278
     * Set/Get SQL offset
279
     *
280
     * @param int $firstResult
281
     * @return int|null
282
     */
283 1
    public function firstResult($firstResult = null)
284
    {
285 1
        if ($firstResult === null) {
286 1
            return isset($this->specials[':offset'])
287 1
                ? $this->specials[':offset']
288 1
                : 0;
289
        }
290
291 1
        $this->specials[':offset'] = $firstResult;
292
    }
293
294
    /**
295
     * {@inheritdoc}
296
     */
297 1
    public function offsetSet($offset, $value): void
298
    {
299 1
        $this->add($offset, $value);
300
    }
301
302
    /**
303
     * {@inheritdoc}
304
     */
305
    #[\ReturnTypeWillChange]
306 1
    public function offsetGet($offset)
307
    {
308 1
        return $this->get($offset);
309
    }
310
311
    /**
312
     * {@inheritdoc}
313
     */
314 1
    public function offsetExists($offset): bool
315
    {
316 1
        return $this->exists($offset);
317
    }
318
319
    /**
320
     * {@inheritdoc}
321
     */
322 1
    public function offsetUnset($offset): void
323
    {
324 1
        $this->remove($offset);
325
    }
326
327
    /**
328
     * {@inheritdoc}
329
     */
330 3
    public function getIterator(): iterable
331
    {
332 3
        yield from $this->all();
333
    }
334
}
335