Passed
Push — main ( 72a80e...5c8241 )
by Mohammad
13:39
created

Criteriable::scopeAppendSortables()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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

106
        return array_diff($this->getFillable(), $this->/** @scrutinizer ignore-call */ getHidden());
Loading history...
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

106
        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...
107
    }
108
109
    /**
110
     * By default, all fillables and not hidden are sortables, if you want to override that explicitly set an array of sortables.
111
     */
112
    public function getSortables(): array
113
    {
114
        if (null !== $this->sortables) {
115
            return $this->sortables;
116
        }
117
118
        return array_diff($this->getFillable(), $this->getHidden());
119
    }
120
121
    public function setSearchables($searchables): self
122
    {
123
        $this->searchables = $searchables;
124
125
        return $this;
126
    }
127
128
    /**
129
     * By default, all fillables and not hidden are filterables, if you want to override that explicitly set an array of searchables.
130
     * For a relation this is the syntax [ relationName => [columns in the relation] ].
131
     */
132
    public function getFilterables(): array
133
    {
134
        if (null !== $this->filterable) {
135
            return $this->filterable;
136
        }
137
138
        return array_diff($this->getFillable(), $this->getHidden());
139
    }
140
141
    public function setFilterables($searchables): self
142
    {
143
        $this->searchables = $searchables;
144
145
        return $this;
146
    }
147
}
148