ExactFilter   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 77
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 26
dl 0
loc 77
ccs 26
cts 26
cp 1
rs 10
c 0
b 0
f 0
wmc 11

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A apply() 0 11 4
A withPropertyConstraint() 0 7 2
A isRelationProperty() 0 11 3
A withRelationConstraint() 0 12 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Zing\QueryBuilder\Filters;
6
7
use Illuminate\Database\Eloquent\Builder;
8
use Illuminate\Database\Query\Expression;
9
use Illuminate\Support\Str;
10
use Zing\QueryBuilder\Concerns\NestedRelation;
11
use Zing\QueryBuilder\Contracts\Filter;
12
13
class ExactFilter implements Filter
14
{
15
    use NestedRelation;
16
17
    /**
18
     * @var string[]
19
     */
20
    protected $relationConstraints = [];
21
22
    /**
23
     * @var bool
24
     */
25
    protected $autoRelationConstraints = true;
26
27 43
    public function __construct(bool $autoRelationConstraints = true)
28
    {
29 43
        $this->autoRelationConstraints = $autoRelationConstraints;
30
    }
31
32
    /**
33
     * @param mixed $value
34
     * @param string|\Illuminate\Database\Query\Expression $property
35
     */
36 38
    public function apply(Builder $query, $value, $property): Builder
37
    {
38 38
        if ($property instanceof Expression) {
39 1
            return $this->withPropertyConstraint($query, $value, $property);
40
        }
41
42 37
        if ($this->autoRelationConstraints && $this->isRelationProperty($query, $property)) {
43 4
            return $this->withRelationConstraint($query, $value, $property);
44
        }
45
46 37
        return $this->withPropertyConstraint($query, $value, $property);
47
    }
48
49
    /**
50
     * @param mixed $value
51
     * @param \Illuminate\Database\Query\Expression|string $property
52
     */
53 18
    protected function withPropertyConstraint(Builder $query, $value, $property): Builder
54
    {
55 18
        if (\is_array($value)) {
56 7
            return $query->whereIn($property, $value);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->whereIn($property, $value) could return the type Illuminate\Database\Query\Builder which is incompatible with the type-hinted return Illuminate\Database\Eloquent\Builder. Consider adding an additional type-check to rule them out.
Loading history...
57
        }
58
59 12
        return $query->where($property, '=', $value);
60
    }
61
62 37
    protected function isRelationProperty(Builder $query, string $property): bool
63
    {
64 37
        if (! Str::contains($property, '.')) {
65 33
            return false;
66
        }
67
68 5
        if (\in_array($property, $this->relationConstraints, true)) {
69 4
            return false;
70
        }
71
72 5
        return ! Str::startsWith($property, $query->getModel()->getTable() . '.');
73
    }
74
75
    /**
76
     * @param mixed $value
77
     */
78 4
    protected function withRelationConstraint(Builder $query, $value, string $property): Builder
79
    {
80 4
        [$relation, $property] = $this->resolveNestedRelation($property);
81
82 4
        return $query->whereHas(
83
            $relation,
84 4
            function ($query) use ($value, $property): void {
85 4
                $property = $query->getModel()
86 4
                    ->getTable() . '.' . $property;
87 4
                $this->relationConstraints[] = $property;
88
89 4
                $this->apply($query, $value, $property);
90
            }
91
        );
92
    }
93
}
94