Passed
Push — main ( 81954b...0c0fd2 )
by Mohammad
03:01
created

Criteriable::scopeSetSearchables()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 5
rs 10
1
<?php
2
3
namespace Shamaseen\Repository\Utility\Models;
4
5
use Illuminate\Database\Eloquent\Builder;
6
7
/**
8
 * @method static Builder filterByCriteria(array $criteria)
9
 * @method static Builder searchByCriteria(array $criteria)
10
 * @method static Builder orderByCriteria(array $criteria)
11
 * @method static Builder setSearchables(array $searchables)
12
 * @method static Builder appendSearchables(array $searchables)
13
 * @method static Builder setFilterables(array $filterables)
14
 * @method static Builder appendFilterables(array $filterables)
15
 * @method static Builder setSortables(array $sortables)
16
 * @method static Builder appendSortables(array $sortables)
17
 */
18
trait Criteriable
19
{
20
    protected ?array $searchables = null;
21
    protected ?array $filterables = null;
22
    protected ?array $sortables = null;
23
24
    /**
25
     * @var array<array<string>>
26
     */
27
    protected ?array $fulltextSearch = [];
28
29
    public function scopeFilterByCriteria($query, array $criteria): Builder
30
    {
31
        foreach ($this->getFilterables() as $method => $columns) {
32
            // if this is associative then it is a relation
33
            if ('string' === gettype($method)) {
34
                if (method_exists($this, $method) && array_key_exists($method, $criteria)) {
35
                    $query->whereHas($method, function ($query) use ($criteria, $columns, $method) {
36
                        /* @var $query Builder */
37
                        $query->where(function ($query2) use ($criteria, $columns, $method) {
38
                            /* @var $query2 Builder */
39
                            foreach ((array) $columns as $column) {
40
                                $query2->where($column, $criteria[$method]);
41
                            }
42
                        });
43
                    });
44
                }
45
            } elseif (array_key_exists($columns, $criteria)) {
46
                $query->where($columns, $criteria[$columns]);
47
            }
48
        }
49
50
        return $query;
51
    }
52
53
    public function scopeSearchByCriteria($query, array $criteria): Builder
54
    {
55
        if (isset($criteria['search'])) {
56
            $query->where(function ($q) use ($criteria) {
57
                foreach ((array) $this->fulltextSearch as $pair) {
58
                    $q->orWhereRaw(sprintf("match(%s) against('%s')",
59
                        implode(',', $pair), $criteria['search']));
60
                }
61
62
                /*
63
                 * @var Builder $q
64
                 */
65
                foreach ($this->getSearchables() as $method => $columns) {
66
                    if (method_exists($this, $method)) {
67
                        $q->orWhereHas($method, function ($query) use ($criteria, $columns) {
68
                            /* @var $query Builder */
69
                            $query->where(function ($query2) use ($criteria, $columns) {
70
                                /* @var $query2 Builder */
71
                                foreach ((array) $columns as $column) {
72
                                    $query2->orWhere($column, 'like', $criteria['search'].'%');
73
                                }
74
                            });
75
                        });
76
                    } else {
77
                        $q->orWhere($columns, 'like', $criteria['search'].'%');
78
                    }
79
                }
80
            });
81
        }
82
83
        return $query;
84
    }
85
86
    public function scopeOrderByCriteria($query, array $criteria): Builder
87
    {
88
        if (isset($criteria['order']) && in_array($criteria['order'], $this->getSortables())) {
89
            $query->orderBy($criteria['order'], $criteria['direction'] ?? 'desc');
90
        }
91
92
        return $query;
93
    }
94
95
    /**
96
     * By default, all fillables and not hidden are searchables, if you want to override that explicitly set an array of searchables.
97
     * For a relation this is the syntax [ relationName => [columns in the relation] ].
98
     */
99
    public function getSearchables(): array
100
    {
101
        if (null !== $this->searchables) {
102
            return $this->searchables;
103
        }
104
105
        return array_diff($this->getFillable(), $this->getHidden());
0 ignored issues
show
Bug introduced by
The method getFillable() does not exist on Shamaseen\Repository\Utility\Models\Criteriable. Did you maybe mean getFilterables()? ( Ignorable by Annotation )

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

105
        return array_diff($this->/** @scrutinizer ignore-call */ getFillable(), $this->getHidden());

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...
Bug introduced by
It seems like getHidden() 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

105
        return array_diff($this->getFillable(), $this->/** @scrutinizer ignore-call */ getHidden());
Loading history...
106
    }
107
108
    public function scopeAppendSearchables($query, array $searchables): Builder
109
    {
110
        $this->searchables = collect($this->searchables)->merge($searchables)->unique()->toArray();
111
112
        return $query;
113
    }
114
115
    public function scopeSetSearchables($query, array $searchables): Builder
116
    {
117
        $this->searchables = $searchables;
118
119
        return $query;
120
    }
121
122
    /**
123
     * By default, all fillables and not hidden are sortables, if you want to override that explicitly set an array of sortables.
124
     */
125
    public function getSortables(): array
126
    {
127
        if (null !== $this->sortables) {
128
            return $this->sortables;
129
        }
130
131
        return array_diff($this->getFillable(), $this->getHidden());
132
    }
133
134
    public function scopeAppendSortables($query, array $sortables): Builder
135
    {
136
        $this->sortables = collect($this->sortables)->merge($sortables)->unique()->toArray();
137
138
        return $query;
139
    }
140
141
    public function scopeSetSortables($query, array $sortables): Builder
142
    {
143
        $this->sortables = $sortables;
144
145
        return $query;
146
    }
147
148
    /**
149
     * By default, all fillables and not hidden are filterables, if you want to override that explicitly set an array of searchables.
150
     * For a relation this is the syntax [ relationName => [columns in the relation] ].
151
     */
152
    public function getFilterables(): array
153
    {
154
        if (null !== $this->filterables) {
155
            return $this->filterables;
156
        }
157
158
        return array_diff($this->getFillable(), $this->getHidden());
159
    }
160
161
    public function scopeAppendFilterables($query, array $filterables): Builder
162
    {
163
        $this->filterables = collect($this->filterables)->merge($filterables)->unique()->toArray();
164
165
        return $query;
166
    }
167
168
    public function scopeSetFilterables($query, array $filterables): Builder
169
    {
170
        $this->filterables = $filterables;
171
172
        return $query;
173
    }
174
}
175