Test Failed
Pull Request — master (#116)
by Zing
04:20
created

WithSearchable::addNestedRelation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Zing\QueryBuilder\Concerns;
6
7
use Illuminate\Database\Eloquent\Builder;
8
use Illuminate\Support\Str;
9
10
trait WithSearchable
11
{
12
    use NestedRelation;
13
14 4
    /**
15
     * @param string|array<string> $searchable
16 4
     *
17 4
     * @return $this
18 4
     */
19 1
    public function searchable($searchable)
20
    {
21
        $searchable = is_array($searchable) ? $searchable : func_get_args();
22 3
        $search = $this->request->input('search');
23 1
        if ($search === null) {
24
            return $this;
25
        }
26 2
27
        if (is_string($search) && trim($search) === '') {
28 2
            return $this;
29
        }
30
31 2
        $searchable = $this->resolveNestedSearchable($searchable);
32
33 2
        return $this->applySearchable($search, $searchable);
34 2
    }
35 2
36 2
    /**
37 2
     * @param mixed $search
38 1
     * @param array<array<string>|string> $searchable
39
     *
40
     * @return $this
41 1
     */
42 2
    protected function applySearchable($search, array $searchable = [])
43
    {
44 2
        $this->where(
0 ignored issues
show
Bug introduced by
It seems like where() 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

44
        $this->/** @scrutinizer ignore-call */ 
45
               where(
Loading history...
45
            function (Builder $query) use ($search, $searchable): void {
46
                collect($searchable)->each(
47
                    function ($value, $key) use ($query, $search): void {
48 1
                        if (is_numeric($key)) {
49
                            $query->orWhere($value, 'like', sprintf('%%%s%%', $search));
50 1
51 1
                            return;
52 1
                        }
53 1
54 1
                        $this->applyRelationSearchable($query, $key, (array) $value, $search);
55 1
                    }
56 1
                );
57
            }
58 1
        );
59
60 1
        return $this;
61
    }
62
63
    /**
64
     * @param array<string> $fields
65
     * @param mixed $search
66
     */
67 1
    protected function applyRelationSearchable(Builder $query, string $relation, array $fields, $search): Builder
68
    {
69 1
        return $query->orWhereHas(
70
            $relation,
71 1
            function (Builder $query) use ($fields, $search): void {
72
                $query->where(
73 1
                    function (Builder $query) use ($fields, $search): void {
74
                        foreach ($fields as $field) {
75
                            $query->orWhere($field, 'like', sprintf('%%%s%%', $search));
76 2
                        }
77
                    }
78 2
                );
79 2
            }
80 2
        );
81 1
    }
82
83 1
    /**
84
     * @param array<string> $searchable
85
     *
86
     * @return array<array<string>|string>
87 2
     */
88
    private function resolveNestedSearchable(array $searchable)
89
    {
90
        $results = [];
91
        foreach ($searchable as $singleSearchable) {
92
            if (Str::contains($singleSearchable, '.')) {
93
                [$relation, $property] = $this->resolveNestedRelation($singleSearchable);
94
95
                $results[$relation][] = $property;
96
            } else {
97
                $results[] = $singleSearchable;
98
            }
99
        }
100
101
        return $results;
102
    }
103
}
104