Completed
Push — master ( 80b847...ba65ab )
by Zing
10:58
created

FiltersExact   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 57
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 26
dl 0
loc 57
ccs 26
cts 26
cp 1
rs 10
c 1
b 0
f 0
wmc 9

4 Methods

Rating   Name   Duplication   Size   Complexity  
A isRelationProperty() 0 11 3
A withRelationConstraint() 0 18 1
A apply() 0 11 3
A withPropertyConstraint() 0 7 2
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\Collection;
10
use Illuminate\Support\Str;
11
use Zing\QueryBuilder\Contracts\Filter;
12
13
class FiltersExact implements Filter
14
{
15
    protected $relationConstraints = [];
16
17 13
    public function apply(Builder $query, $value, $property): Builder
18
    {
19 13
        if ($property instanceof Expression) {
20 1
            return $this->withPropertyConstraint($query, $value, $property);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->withProper...ery, $value, $property) 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...
21
        }
22
23 12
        if ($this->isRelationProperty($query, $property)) {
24 2
            return $this->withRelationConstraint($query, $value, $property);
25
        }
26
27 12
        return $this->withPropertyConstraint($query, $value, $property);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->withProper...ery, $value, $property) 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...
28
    }
29
30 8
    protected function withPropertyConstraint(Builder $query, $value, $property)
31
    {
32 8
        if (is_array($value)) {
33 2
            return $query->whereIn($property, $value);
34
        }
35
36 6
        return $query->where($property, '=', $value);
37
    }
38
39 12
    protected function isRelationProperty(Builder $query, string $property): bool
40
    {
41 12
        if (! Str::contains($property, '.')) {
42 9
            return false;
43
        }
44
45 3
        if (in_array($property, $this->relationConstraints, true)) {
46 2
            return false;
47
        }
48
49 3
        return ! Str::startsWith($property, $query->getModel()->getTable() . '.');
50
    }
51
52 2
    protected function withRelationConstraint($query, $value, string $property)
53
    {
54 2
        [$relation, $property] = collect(explode('.', $property))
55 2
            ->pipe(
56
                function (Collection $parts) {
57
                    return [
58 2
                        $parts->except(count($parts) - 1)->map([Str::class, 'camel'])->implode('.'),
59 2
                        $parts->last(),
60
                    ];
61 2
                }
62
            );
63
64 2
        return $query->whereHas(
65 2
            $relation,
66
            function ($query) use ($value, $property): void {
67 2
                $this->relationConstraints[] = $property = $query->getModel()->getTable() . '.' . $property;
68
69 2
                $this->apply($query, $value, $property);
70 2
            }
71
        );
72
    }
73
}
74