Failed Conditions
Push — 186-self-joins-fail-in-relatio... ( ba3e0e...5bcaaa )
by Bas
08:01 queued 40s
created

CompilesFilters::filterYear()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 6
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 11
ccs 4
cts 4
cp 1
crap 1
rs 10
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Query\Concerns;
4
5
use Illuminate\Database\Query\Builder as IlluminateQueryBuilder;
6
use Illuminate\Database\Query\Expression;
7
use Illuminate\Database\Query\JoinClause;
8
use LaravelFreelancerNL\Aranguent\Query\Builder;
9
10
trait CompilesFilters
11
{
12
    /**
13
     * Compile the "having" portions of the query.
14
     *
15
     * @param  \Illuminate\Database\Query\Builder  $query
16
     * @return string
17
     */
18 8
    protected function compileHavings(IlluminateQueryBuilder $query)
19
    {
20 8
        return 'FILTER ' . $this->removeLeadingBoolean(collect($query->havings)->map(function ($having) use ($query) {
0 ignored issues
show
Bug introduced by
It seems like removeLeadingBoolean() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

20
        return 'FILTER ' . $this->/** @scrutinizer ignore-call */ removeLeadingBoolean(collect($query->havings)->map(function ($having) use ($query) {
Loading history...
Bug introduced by
It seems like $query->havings can also be of type array; however, parameter $value of collect() does only seem to accept Illuminate\Contracts\Support\Arrayable, 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

20
        return 'FILTER ' . $this->removeLeadingBoolean(collect(/** @scrutinizer ignore-type */ $query->havings)->map(function ($having) use ($query) {
Loading history...
21 8
            return $having['boolean'] . ' ' . $this->filter($query, $having);
22 8
        })->implode(' '));
23
    }
24
25
    /**
26
     * Get an array of all the where clauses for the query.
27
     *
28
     * @param  \Illuminate\Database\Query\Builder  $query
29
     * @return array<string>
30
     */
31 389
    protected function compileWheresToArray($query)
32
    {
33 389
        return collect($query->wheres)->map(function ($where) use ($query) {
0 ignored issues
show
Bug introduced by
$query->wheres of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

33
        return collect(/** @scrutinizer ignore-type */ $query->wheres)->map(function ($where) use ($query) {
Loading history...
34 274
            $type = ucfirst($where['type']);
35 389
            return $where['boolean'] . ' ' . $this->{"filter{$type}"}($query, $where);
36
        })->all();
37
    }
38
39
    /**
40
     * Format the where clause statements into one string.
41
     *
42
     * @param IlluminateQueryBuilder $query
43
     * @param  array<mixed>  $aql
44
     * @return string
45
     *
46
     * @SuppressWarnings("PHPMD.UnusedFormalParameter")
47 274
     */
48
    protected function concatenateWhereClauses($query, $aql)
49 274
    {
50
        return 'FILTER ' . $this->removeLeadingBoolean(implode(' ', $aql));
51
    }
52
53
    /**
54
     * @param string $type
55
     * @return string
56 4
     */
57
    protected function getOperatorByWhereType($type)
58 4
    {
59
        if (isset($this->whereTypeOperators[$type])) {
60
            return $this->whereTypeOperators[$type];
61
        }
62 4
63
        return '==';
64
    }
65
66
67
    /**
68
     * Compile a single having clause.
69
     *
70
     * @param IlluminateQueryBuilder $query
71
     * @param array<mixed> $filter
72
     * @return string
73
     * @throws \Exception
74 8
     */
75
    protected function filter(IlluminateQueryBuilder $query, array $filter)
76
    {
77
        // If the having clause is "raw", we can just return the clause straight away
78
        // without doing any more processing on it. Otherwise, we will compile the
79 8
        // clause into SQL based on the components that make it up from builder.
80 1
        return match ($filter['type']) {
81 1
            'Raw' => $filter['sql'],
82 1
            'between' => $this->filterBetween($query, $filter),
83 2
            'Null' => $this->filterNull($query, $filter),
84
            'NotNull' => $this->filterNotNull($query, $filter),
85
            'bit' => $this->filterBit($query, $filter),
86 1
            'Expression' => $this->filterExpression($query, $filter),
87 8
            'Nested' => $this->compileNestedHavings($filter),
0 ignored issues
show
Bug introduced by
It seems like compileNestedHavings() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

87
            'Nested' => $this->/** @scrutinizer ignore-call */ compileNestedHavings($filter),
Loading history...
88 8
            default => $this->filterBasic($query, $filter),
89
        };
90
    }
91
92
    /**
93
     * Compile a basic having|filter clause.
94
     *
95
     * @param IlluminateQueryBuilder $query
96
     * @param array<mixed> $filter
97
     * @return string
98
     * @throws \Exception
99 241
     */
100
    protected function filterBasic(IlluminateQueryBuilder $query, $filter)
101 241
    {
102
        $predicate = [];
103 241
104
        $filter = $this->normalizeOperator($filter);
105 241
106 239
        if (!$filter['column'] instanceof expression) {
107
            $column = $this->normalizeColumn($query, $filter['column']);
0 ignored issues
show
Bug introduced by
It seems like normalizeColumn() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

107
            /** @scrutinizer ignore-call */ 
108
            $column = $this->normalizeColumn($query, $filter['column']);
Loading history...
108 241
        }
109 2
        if ($filter['column'] instanceof expression) {
110
            $column = $filter['column']->getValue($this);
0 ignored issues
show
Bug introduced by
$this of type LaravelFreelancerNL\Aran...oncerns\CompilesFilters is incompatible with the type Illuminate\Database\Grammar expected by parameter $grammar of Illuminate\Database\Query\Expression::getValue(). ( Ignorable by Annotation )

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

110
            $column = $filter['column']->getValue(/** @scrutinizer ignore-type */ $this);
Loading history...
111
        }
112 241
113 241
        $predicate[0] = $column;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $column does not seem to be defined for all execution paths leading up to this point.
Loading history...
114 241
        $predicate[1] = $filter['operator'];
115
        $predicate[2] = $this->parameter($filter['value']);
0 ignored issues
show
Bug introduced by
It seems like parameter() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

115
        /** @scrutinizer ignore-call */ 
116
        $predicate[2] = $this->parameter($filter['value']);
Loading history...
116 241
117
        return implode(" ", $predicate);
118
    }
119
120
121
    /**
122
     * Compile a "between" filter clause.
123
     *
124
     * @param IlluminateQueryBuilder $query
125
     * @param array<mixed> $filter
126
     * @return string
127
     * @throws \Exception
128 3
     */
129
    protected function filterBetween(IlluminateQueryBuilder $query, $filter): string
130 3
    {
131
        $predicate = [];
132 3
133
        [$minOperator, $maxOperator, $boolean] = $this->getBetweenOperators($filter['not']);
134 3
135 3
        $min = $this->parameter(reset($filter['values']));
136
        $max = $this->parameter(end($filter['values']));
137 3
138
        $normalizedColumn = $this->normalizeColumn($query, $filter['column']);
139 3
140 3
        $predicate[0][0] = $normalizedColumn;
141 3
        $predicate[0][1] = $minOperator;
142
        $predicate[0][2] = $min;
143 3
144 3
        $predicate[1][0] = $normalizedColumn;
145 3
        $predicate[1][1] = $maxOperator;
146
        $predicate[1][2] = $max;
147 3
148
        return implode(" ", $predicate[0]) . " " . $boolean . " " . implode(" ", $predicate[1]);
149
    }
150
151
    /**
152
     * Compile a "between columns" filter clause.
153
     *
154
     * @param IlluminateQueryBuilder $query
155
     * @param array<mixed> $filter
156
     * @return string
157
     * @throws \Exception
158 1
     */
159
    protected function filterBetweenColumns(IlluminateQueryBuilder $query, $filter)
160 1
    {
161
        $predicate = [];
162 1
163
        [$minOperator, $maxOperator, $boolean] = $this->getBetweenOperators($filter['not']);
164 1
165
        $column = $this->normalizeColumn($query, $filter['column']);
166 1
167 1
        $predicate[0][0] = $column;
168 1
        $predicate[0][1] = $minOperator;
169
        $predicate[0][2] = $this->normalizeColumn($query, reset($filter['values']));
170 1
171 1
        $predicate[1][0] = $column;
172 1
        $predicate[1][1] = $maxOperator;
173
        $predicate[1][2] = $this->normalizeColumn($query, end($filter['values']));
174 1
175
        return implode(" ", $predicate[0]) . " " . $boolean . " " . implode(" ", $predicate[1]);
176
    }
177
178
    /**
179
     * Compile a filter clause comparing two columns..
180
     *
181
     * @param IlluminateQueryBuilder $query
182
     * @param array<mixed> $filter
183
     * @return string
184
     * @throws \Exception
185 56
     */
186
    protected function filterColumn(IlluminateQueryBuilder $query, $filter)
187 56
    {
188
        $predicate = [];
189 56
190 56
        $filter = $this->normalizeOperator($filter);
191 56
        $predicate[0] = $this->normalizeColumn($query, $filter['first']);
192 56
        $predicate[1] = $filter['operator'];
193
        $predicate[2] = $this->normalizeColumn($query, $filter['second']);
194 56
195
        return implode(" ", $predicate);
196
    }
197
198
    /**
199
     * Compile a "filter null" clause.
200
     *
201
     * @param IlluminateQueryBuilder $query
202
     * @param array<mixed> $filter
203
     * @return string
204
     * @throws \Exception
205 25
     */
206
    protected function filterNull(IlluminateQueryBuilder $query, $filter)
207 25
    {
208
        $predicate = [];
209 25
210 25
        $predicate[0] = $this->normalizeColumn($query, $filter['column']);
211 25
        $predicate[1] = '==';
212
        $predicate[2] = "null";
213 25
214
        return implode(" ", $predicate);
215
    }
216
217
    /**
218
     * Compile a "filter not null" clause.
219
     *
220
     * @param IlluminateQueryBuilder $query
221
     * @param array<mixed> $filter
222
     * @return string
223
     * @throws \Exception
224 20
     */
225
    protected function filterNotNull(IlluminateQueryBuilder $query, $filter)
226 20
    {
227
        $predicate = [];
228 20
229 20
        $predicate[0] = $this->normalizeColumn($query, $filter['column']);
230 20
        $predicate[1] = '!=';
231
        $predicate[2] = "null";
232 20
233
        return implode(" ", $predicate);
234
    }
235
236
    /**
237
     * Compile a "filter in" clause.
238
     *
239
     * @param  IlluminateQueryBuilder  $query
240
     * @param  array<mixed>  $filter
241
     * @return string
242 19
     */
243
    protected function filterIn(IlluminateQueryBuilder $query, $filter)
244 19
    {
245
        $predicate = [];
246 19
247 19
        $predicate[0] = $this->normalizeColumn($query, $filter['column']);
248 19
        $predicate[1] = 'IN';
249
        $predicate[2] = $this->parameter($filter['values']);
250 19
251
        return implode(" ", $predicate);
252
    }
253
254
    /**
255
     * Compile a "filter in raw" clause.
256
     *
257
     * For safety, filterIntegerInRaw ensures this method is only used with integer values.
258
     *
259
     * @param IlluminateQueryBuilder $query
260
     * @param array<mixed> $filter
261
     * @return string
262
     * @throws \Exception
263 1
     */
264
    protected function filterRaw(IlluminateQueryBuilder $query, array $filter): string
265 1
    {
266
        return $filter['sql'] instanceof \Illuminate\Contracts\Database\Query\Expression ? $filter['sql']->getValue($this) : $filter['sql'];
0 ignored issues
show
Bug introduced by
$this of type LaravelFreelancerNL\Aran...oncerns\CompilesFilters is incompatible with the type Illuminate\Database\Grammar expected by parameter $grammar of Illuminate\Database\Query\Expression::getValue(). ( Ignorable by Annotation )

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

266
        return $filter['sql'] instanceof \Illuminate\Contracts\Database\Query\Expression ? $filter['sql']->getValue(/** @scrutinizer ignore-type */ $this) : $filter['sql'];
Loading history...
267 1
    }
268 1
269 1
270
    /**
271 1
     * Compile a "filter in raw" clause.
272
     *
273
     * For safety, filterIntegerInRaw ensures this method is only used with integer values.
274
     *
275
     * @param IlluminateQueryBuilder $query
276
     * @param array<mixed> $filter
277
     * @return string
278
     * @throws \Exception
279
     */
280
    protected function filterInRaw(IlluminateQueryBuilder $query, array $filter): string
281
    {
282 1
        $predicate = [];
283
284 1
        $predicate[0] = $this->normalizeColumn($query, $filter['column']);
285
        $predicate[1] = 'IN';
286 1
        $predicate[2] = '[' . implode(', ', $filter['values']) . ']';
287 1
288 1
        return implode(" ", $predicate);
289
    }
290 1
291
    /**
292
     * Compile a "filter not in" clause.
293
     *
294
     * @param IlluminateQueryBuilder $query
295
     * @param array<mixed> $filter
296
     * @return string
297
     * @throws \Exception
298
     */
299
    protected function filterNotIn(IlluminateQueryBuilder $query, array $filter): string
300
    {
301
        $predicate = [];
302 1
303
        $predicate[0] = $this->normalizeColumn($query, $filter['column']);
304 1
        $predicate[1] = 'NOT IN';
305
        $predicate[2] = $this->parameter($filter['values']);
306 1
307 1
        return implode(" ", $predicate);
308 1
    }
309
310 1
    /**
311
     * Compile a "filter not in raw" clause.
312
     *
313
     * For safety, filterIntegerInRaw ensures this method is only used with integer values.
314
     *
315
     * @param  IlluminateQueryBuilder  $query
316
     * @param  array<mixed>  $filter
317
     * @return string
318
     */
319
    protected function filterNotInRaw(IlluminateQueryBuilder $query, array $filter): string
320
    {
321 1
        $predicate = [];
322
323 1
        $predicate[0] = $this->normalizeColumn($query, $filter['column']);
324
        $predicate[1] = 'NOT IN';
325 1
        $predicate[2] = '[' . implode(', ', $filter['values']) . ']';
326
327 1
        return implode(" ", $predicate);
328 1
    }
329 1
330
    /**
331 1
     * Compile a "filter JSON contains" clause.
332
     *
333
     * @param IlluminateQueryBuilder $query
334
     * @param array<mixed> $filter
335
     * @return string
336
     * @throws \Exception
337
     */
338
    protected function filterJsonContains(IlluminateQueryBuilder $query, $filter)
339
    {
340
        $predicate = [];
341 1
342
        $operator = $filter['not'] ? 'NOT IN' : 'IN';
343 1
344
        $predicate[0] = $this->parameter($filter['value']);
345 1
        $predicate[1] = $operator;
346
        $predicate[2] = $this->normalizeColumn($query, $filter['column']);
347 1
348
        return implode(" ", $predicate);
349 1
    }
350 1
351 1
    /**
352
     * Compile a "filterJsonLength" clause.
353 1
     *
354
     * @param  IlluminateQueryBuilder  $query
355
     * @param  array<mixed>  $filter
356
     * @return string
357
     */
358
    protected function filterJsonLength(IlluminateQueryBuilder $query, array $filter): string
359
    {
360
        $predicate = [];
361
362
        $filter = $this->normalizeOperator($filter);
363
364
        $column = $this->normalizeColumn($query, $filter['column']);
365
366
        $predicate[0] = "LENGTH($column)";
367
        $predicate[1] = $filter['operator'];
368
        $predicate[2] = $this->parameter($filter['value']);
369
370
        return implode(" ", $predicate);
371
    }
372
373
    /**
374
     * @param array<mixed> $filter
375 1
     * @return mixed
376
     *
377 1
     * @SuppressWarnings("PHPMD.UnusedFormalParameter")
378
     */
379 1
    protected function filterExpression(IlluminateQueryBuilder $query, $filter)
380 1
    {
381 1
        return $filter['column']->getValue($this);
382 1
    }
383
384 1
    /**
385
     * Compile a filter date clause.
386
     *
387
     * @param IlluminateQueryBuilder $query
388
     * @param array<mixed> $filter
389
     * @return string
390
     * @throws \Exception
391
     */
392
    protected function filterDate(IlluminateQueryBuilder $query, $filter)
393
    {
394
        $predicate = [];
395 1
396
        $filter = $this->normalizeOperator($filter);
397 1
        $predicate[0] = 'DATE_FORMAT(' . $this->normalizeColumn($query, $filter['column']) . ', "%yyyy-%mm-%dd")';
398
        $predicate[1] = $filter['operator'];
399 1
        $predicate[2] = $this->parameter($filter['value']);
400
401 1
        return implode(' ', $predicate);
402 1
    }
403 1
404
    /**
405 1
     * Compile a filter year clause.
406
     *
407
     * @param IlluminateQueryBuilder $query
408
     * @param array<mixed> $filter
409
     * @return string
410
     * @throws \Exception
411
     */
412
    protected function filterYear(IlluminateQueryBuilder $query, $filter)
413
    {
414
        $predicate = [];
415
416 4
        $filter = $this->normalizeOperator($filter);
417
418 4
        $predicate[0] = 'DATE_YEAR(' . $this->normalizeColumn($query, $filter['column']) . ')';
419 4
        $predicate[1] = $filter['operator'];
420
        $predicate[2] = $this->parameter($filter['value']);
421 4
422
        return implode(' ', $predicate);
423 4
    }
424
425 4
    /**
426 4
     * Compile a filter month clause.
427 4
     *
428
     * @param IlluminateQueryBuilder $query
429 4
     * @param array<mixed> $filter
430
     * @return string
431 4
     * @throws \Exception
432 2
     */
433
    protected function filterLike(IlluminateQueryBuilder $query, $filter)
434
    {
435 4
        $column =  $this->normalizeColumn($query, $filter['column']);
436
        $value = $this->parameter($filter['value']);
437
438
        $predicate = [];
439
440
        $filter = $this->normalizeOperator($filter);
441
442
        $predicate[0] = ($filter['caseSensitive']) ? $column : 'LOWER(' . $column . ')';
443
        $predicate[1] = 'LIKE';
444
        $predicate[2] = ($filter['caseSensitive']) ? $value : 'LOWER(' . $value . ')';
445
446 1
        $result = implode(' ', $predicate);
447
448 1
        if ($filter['not']) {
449
            $result = 'NOT (' . $result . ')';
450 1
        }
451
452 1
        return $result;
453 1
    }
454 1
455
    /**
456 1
     * Compile a filter month clause.
457
     *
458
     * @param IlluminateQueryBuilder $query
459
     * @param array<mixed> $filter
460
     * @return string
461
     * @throws \Exception
462
     */
463
    protected function filterMonth(IlluminateQueryBuilder $query, $filter)
464
    {
465
        $predicate = [];
466
467
        $filter = $this->normalizeOperator($filter);
468 1
469
        $predicate[0] =  'DATE_MONTH(' . $this->normalizeColumn($query, $filter['column']) . ')';
470 1
        $predicate[1] = $filter['operator'];
471
        $predicate[2] = $this->parameter($filter['value']);
472 1
473
        return implode(' ', $predicate);
474 1
    }
475 1
476 1
477
    /**
478 1
     * Compile a filter day clause.
479
     *
480
     * @param IlluminateQueryBuilder $query
481
     * @param array<mixed> $filter
482
     * @return string
483
     * @throws \Exception
484
     */
485
    protected function filterDay(IlluminateQueryBuilder $query, $filter)
486
    {
487
        $predicate = [];
488 1
489
        $filter = $this->normalizeOperator($filter);
490 1
491
        $predicate[0] = 'DATE_DAY(' . $this->normalizeColumn($query, $filter['column']) . ')';
492 1
        $predicate[1] = $filter['operator'];
493
        $predicate[2] = $this->parameter($filter['value']);
494 1
495 1
        return implode(' ', $predicate);
496 1
    }
497
498 1
    /**
499
     * Compile a filter time clause.
500
     *
501
     * @param  IlluminateQueryBuilder  $query
502
     * @param  array<mixed>  $filter
503
     * @return string
504
     */
505
    protected function filterTime(IlluminateQueryBuilder $query, $filter)
506
    {
507
        $predicate = [];
508
509 1
        $filter = $this->normalizeOperator($filter);
510
511 1
        $predicate[0] = 'DATE_FORMAT(' . $this->normalizeColumn($query, $filter['column']) . ", '%hh:%ii:%ss')";
512
        $predicate[1] = $filter['operator'];
513 1
        $predicate[2] = $this->parameter($filter['value']);
514
515 1
        return implode(' ', $predicate);
516 1
    }
517 1
518
    /**
519 1
     * Compile a filter condition with a sub-select.
520
     *
521
     * @param IlluminateQueryBuilder $query
522
     * @param array<mixed> $filter
523
     * @return string
524
     * @throws \Exception
525
     */
526
    protected function filterSub(IlluminateQueryBuilder $query, $filter)
527
    {
528
        $predicate = [];
529
530
        $filter = $this->normalizeOperator($filter);
531 14
532
        $predicate[0] = $this->normalizeColumn($query, $filter['column']);
533 14
        $predicate[1] = $filter['operator'];
534
        $predicate[2] = $filter['subquery'];
535
536
        return implode(' ', $predicate);
537
    }
538
539
    /**
540
     * Compile a filter exists clause.
541
     *
542
     * @param  \Illuminate\Database\Query\Builder  $query
543
     * @param  array<mixed>  $filter
544
     * @return string
545 12
     *
546
     * @SuppressWarnings("PHPMD.UnusedFormalParameter")
547 12
     */
548
    protected function filterExists(IlluminateQueryBuilder $query, $filter)
549
    {
550
        return 'LENGTH(' . $filter['subquery'] . ') > 0';
551
    }
552
553
    /**
554
     * Compile a filter exists clause.
555
     *
556
     * @param  \Illuminate\Database\Query\Builder  $query
557
     * @param  array<mixed>  $filter
558
     * @return string
559 52
     *
560
     * @SuppressWarnings("PHPMD.UnusedFormalParameter")
561
     */
562
    protected function filterNotExists(IlluminateQueryBuilder $query, $filter)
563
    {
564 52
        return 'LENGTH(' . $filter['subquery'] . ') == 0';
565
    }
566 52
567
    /**
568
     * Compile a nested where clause.
569
     *
570
     * @param  \Illuminate\Database\Query\Builder  $query
571
     * @param  array<mixed>  $filter
572
     * @return string
573
     *
574
     * @SuppressWarnings("PHPMD.UnusedFormalParameter")
575
     */
576
    protected function filterNested(IlluminateQueryBuilder $query, $filter)
577
    {
578
        // Here we will calculate what portion of the string we need to remove. If this
579
        // is a join clause query, we need to remove the "on" portion of the SQL and
580
        // if it is a normal query we need to take the leading "where" of queries.
581
        $offset = $filter['query'] instanceof JoinClause ? 3 : 6;
582
583
        return '(' . substr($this->compileWheres($filter['query']), $offset) . ')';
0 ignored issues
show
Bug introduced by
The method compileWheres() does not exist on LaravelFreelancerNL\Aran...oncerns\CompilesFilters. Did you maybe mean compileWheresToArray()? ( Ignorable by Annotation )

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

583
        return '(' . substr($this->/** @scrutinizer ignore-call */ compileWheres($filter['query']), $offset) . ')';

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
584
    }
585
586
587
    /**
588
     * Compile a having clause involving a bit operator.
589
     *
590
     * @param IlluminateQueryBuilder $query
591
     * @param array<mixed> $filter
592
     * @return string
593
     * @throws \Exception
594
     */
595
    protected function filterBit(IlluminateQueryBuilder $query, $filter)
596
    {
597
        $column = $this->normalizeColumn($query, $filter['column']);
598
        $value = $this->parameter($filter['value']);
599
600
        $bitExpression = match ($filter['operator']) {
601
            '|' => $this->bitExpressionOr($column, $value),
602
            '^' => $this->bitExpressionXor($column, $value),
603
            '~' => $this->bitExpressionNegate($column),
604
            '&~' => $this->bitExpressionNegatedAnd($column, $value),
605
            '<<' => $this->bitExpressionLeftShift($column, $value),
606
            '>>' => $this->bitExpressionRightShift($column, $value),
607
            default =>  $this->bitExpressionAnd($column, $value),
608
        };
609
610
        return '(' . $bitExpression . ') != 0';
611
    }
612
613
    protected function bitExpressionAnd(string $column, int|string $value): string
614
    {
615
        return 'BIT_AND(' . $column . ', ' . $value . ')';
616
    }
617
618
    protected function bitExpressionOr(string $column, int|string $value): string
619
    {
620
        return 'BIT_AND(' . $column . ', ' . $value . ')';
621
    }
622
623
    protected function bitExpressionXor(string $column, int|string $value): string
624
    {
625
        return 'BIT_XOR(' . $column . ', ' . $value . ')';
626
    }
627
628
    protected function bitExpressionNegate(string $column): string
629
    {
630
        return 'BIT_NEGATE(' . $column . ', BIT_POPCOUNT(' . $column . '))';
631
    }
632
633
    protected function bitExpressionNegatedAnd(string $column, int|string $value): string
634
    {
635
        return 'BIT_AND(' . $column . ', BIT_NEGATE(' . $value . ', BIT_POPCOUNT(' . $value . '))';
636 4
    }
637
638 4
    protected function bitExpressionLeftShift(string $column, int|string $value): string
639 4
    {
640 4
        return 'BIT_SHIFT_LEFT(' . $column . ',  ' . $value . ', BIT_POPCOUNT(' . $column . '))';
641
    }
642 4
643 1
    protected function bitExpressionRightShift(string $column, int|string $value): string
644 1
    {
645 1
        return 'BIT_SHIFT_RIGHT(' . $column . ',  ' . $value . ', BIT_POPCOUNT(' . $column . '))';
646
    }
647
648 4
    /**
649
     * Generate operators for between and 'not between'
650
     * @param  bool  $notBetween
651
     * @return string[]
652
     */
653
    protected function getBetweenOperators(bool $notBetween)
654
    {
655 262
        $minOperator = '>=';
656
        $maxOperator = '<=';
657 262
        $boolean = 'AND';
658 260
659
        if ($notBetween) {
660 262
            $minOperator = '<';
661 4
            $maxOperator = '>';
662
            $boolean = 'OR';
663
        }
664 262
665
        return [$minOperator, $maxOperator, $boolean];
666
    }
667
668
    /**
669
     * @param array<mixed> $filter
670
     * @return array<mixed>
671
     */
672
    protected function normalizeOperator($filter)
673
    {
674
        if (isset($filter['operator'])) {
675
            $filter['operator'] = $this->translateOperator($filter['operator']);
0 ignored issues
show
Bug introduced by
It seems like translateOperator() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

675
            /** @scrutinizer ignore-call */ 
676
            $filter['operator'] = $this->translateOperator($filter['operator']);
Loading history...
676
        }
677
        if (!isset($filter['operator'])) {
678
            $filter['operator'] = $this->getOperatorByWhereType($filter['type']);
679
        }
680
681
        return $filter;
682
    }
683
}
684