Passed
Pull Request — master (#38)
by Zing
10:07 queued 06:18
created

WithSearchable::searchable()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 6
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 11
ccs 7
cts 7
cp 1
crap 5
rs 9.6111
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 3
    public function searchable($searchable)
15
    {
16 3
        $searchable = is_array($searchable) ? $searchable : func_get_args();
17 3
        $search = $this->request->input('search');
18 3
        if ($search === null || (is_string($search) && trim($search) === '')) {
19 1
            return $this;
20
        }
21
22 2
        $searchable = $this->resolveNestedSearchable($searchable);
23
24 2
        return $this->applySearchable($search, $searchable);
25
    }
26
27 2
    protected function applySearchable($search, array $searchable = [])
28
    {
29 2
        return $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

29
        return $this->/** @scrutinizer ignore-call */ where(
Loading history...
30
            function (Builder $query) use ($search, $searchable): void {
31 2
                collect($searchable)->each(
32
                    function ($value, $key) use ($query, $search) {
33 2
                        if (is_numeric($key)) {
34 1
                            return $query->orWhere($value, 'like', "%{$search}%");
35
                        }
36
37 1
                        return $this->applyRelationSearchable($query, $key, $value, $search);
38 2
                    }
39
                );
40 2
            }
41
        );
42
    }
43
44 1
    protected function applyRelationSearchable($query, $relation, $fields, $search)
45
    {
46 1
        return $query->orWhereHas(
47 1
            $relation,
48
            function (Builder $query) use ($fields, $search): void {
49 1
                $query->where(
50
                    function (Builder $query) use ($fields, $search): void {
51 1
                        foreach ($fields as $field) {
52 1
                            $query->orWhere($field, 'like', "%{$search}%");
53
                        }
54 1
                    }
55
                );
56 1
            }
57
        );
58
    }
59
60
    /**
61
     * @param string $field
62
     * @param array $results
63
     *
64
     * @return array
65
     */
66 1
    private function addNestedRelation($field, array $results)
67
    {
68 1
        [$relation, $property] = $this->resolveNestedRelation($field);
69
70 1
        $results[$relation][] = $property;
71
72 1
        return $results;
73
    }
74
75 2
    private function resolveNestedSearchable(array $searchable)
76
    {
77 2
        $results = [];
78 2
        foreach ($searchable as $field) {
79 2
            if (Str::contains($field, '.')) {
80 1
                $results = $this->addNestedRelation($field, $results);
81
            } else {
82 2
                $results[] = $field;
83
            }
84
        }
85
86 2
        return $results;
87
    }
88
}
89