Passed
Push — main ( 8d6dc9...a090f0 )
by Mohammad
11:35
created

Criteriable::getSortables()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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

95
        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

95
        return array_diff($this->getFillable(), $this->/** @scrutinizer ignore-call */ getHidden());
Loading history...
96
    }
97
98
    /**
99
     * By default, all fillables and not hidden are sortables, if you want to override that explicitly set an array of sortables.
100
     */
101
    public function getSortables(): array
102
    {
103
        if (null !== $this->sortables) {
104
            return $this->sortables;
105
        }
106
107
        return array_diff($this->getFillable(), $this->getHidden());
108
    }
109
110
    public function setSearchables($searchables): self
111
    {
112
        $this->searchables = $searchables;
113
114
        return $this;
115
    }
116
117
    /**
118
     * By default, all fillables and not hidden are filterables, if you want to override that explicitly set an array of searchables.
119
     * For a relation this is the syntax [ relationName => [columns in the relation] ].
120
     */
121
    public function getFilterables(): array
122
    {
123
        if (null !== $this->filterable) {
124
            return $this->filterable;
125
        }
126
127
        return array_diff($this->getFillable(), $this->getHidden());
128
    }
129
130
    public function setFilterables($searchables): self
131
    {
132
        $this->searchables = $searchables;
133
134
        return $this;
135
    }
136
}
137