ModelSearchAspect   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
wmc 19
lcom 1
cbo 6
dl 0
loc 125
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A forModel() 0 4 1
B __construct() 0 32 6
A addSearchableAttribute() 0 6 1
A addExactSearchableAttribute() 0 6 1
A getType() 0 10 2
A getResults() 0 16 3
A addSearchConditions() 0 18 4
A __call() 0 6 1
1
<?php
2
3
namespace Spatie\Searchable;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Foundation\Auth\User;
8
use Illuminate\Support\Arr;
9
use Illuminate\Support\Collection;
10
use Illuminate\Support\Traits\ForwardsCalls;
11
use Spatie\Searchable\Exceptions\InvalidModelSearchAspect;
12
use Spatie\Searchable\Exceptions\InvalidSearchableModel;
13
14
class ModelSearchAspect extends SearchAspect
15
{
16
    use ForwardsCalls;
17
18
    /** @var \Illuminate\Database\Eloquent\Model */
19
    protected $model;
20
21
    /** @var array */
22
    protected $attributes = [];
23
24
    /** @var array */
25
    protected $callsToForward = [];
26
27
    public static function forModel(string $model, ...$attributes): self
28
    {
29
        return new self($model, $attributes);
30
    }
31
32
    /**
33
     * @param string $model
34
     * @param array|\Closure $attributes
35
     *
36
     * @throws \Spatie\Searchable\Exceptions\InvalidSearchableModel
37
     */
38
    public function __construct(string $model, $attributes = [])
39
    {
40
        if (! is_subclass_of($model, Model::class)) {
41
            throw InvalidSearchableModel::notAModel($model);
42
        }
43
44
        if (! is_subclass_of($model, Searchable::class)) {
45
            throw InvalidSearchableModel::modelDoesNotImplementSearchable($model);
46
        }
47
48
        $this->model = $model;
0 ignored issues
show
Documentation Bug introduced by
It seems like $model of type string is incompatible with the declared type object<Illuminate\Database\Eloquent\Model> of property $model.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
49
50
        if (is_array($attributes)) {
51
            $this->attributes = SearchableAttribute::createMany($attributes);
52
53
            return;
54
        }
55
56
        if (is_string($attributes)) {
57
            $this->attributes = SearchableAttribute::create($attributes);
0 ignored issues
show
Documentation Bug introduced by
It seems like \Spatie\Searchable\Searc...te::create($attributes) of type object<self> is incompatible with the declared type array of property $attributes.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
58
59
            return;
60
        }
61
62
        if (is_callable($attributes)) {
63
            $callable = $attributes;
64
65
            $callable($this);
66
67
            return;
68
        }
69
    }
70
71
    public function addSearchableAttribute(string $attribute, bool $partial = true): self
72
    {
73
        $this->attributes[] = SearchableAttribute::create($attribute, $partial);
74
75
        return $this;
76
    }
77
78
    public function addExactSearchableAttribute(string $attribute): self
79
    {
80
        $this->attributes[] = SearchableAttribute::createExact($attribute);
81
82
        return $this;
83
    }
84
85
    public function getType(): string
86
    {
87
        $model = new $this->model();
88
89
        if (property_exists($model, 'searchableType')) {
90
            return $model->searchableType;
91
        }
92
93
        return $model->getTable();
94
    }
95
96
    public function getResults(string $term, User $user = null): Collection
97
    {
98
        if (empty($this->attributes)) {
99
            throw InvalidModelSearchAspect::noSearchableAttributes($this->model);
100
        }
101
102
        $query = ($this->model)::query();
103
104
        foreach ($this->callsToForward as $method => $parameters) {
105
            $this->forwardCallTo($query, $method, $parameters);
106
        }
107
108
        $this->addSearchConditions($query, $term);
109
110
        return $query->get();
111
    }
112
113
    protected function addSearchConditions(Builder $query, string $term)
114
    {
115
        $attributes = $this->attributes;
116
        $searchTerms = explode(' ', $term);
117
118
        $query->where(function (Builder $query) use ($attributes, $term, $searchTerms) {
119
            foreach (Arr::wrap($attributes) as $attribute) {
120
                foreach ($searchTerms as $searchTerm) {
121
                    $sql = "LOWER(`{$attribute->getAttribute()}`) LIKE ?";
122
                    $searchTerm = mb_strtolower($searchTerm, 'UTF8');
123
124
                    $attribute->isPartial()
125
                        ? $query->orWhereRaw($sql, ["%{$searchTerm}%"])
126
                        : $query->orWhere($attribute->getAttribute(), $searchTerm);
127
                }
128
            }
129
        });
130
    }
131
132
    public function __call($method, $parameters)
133
    {
134
        $this->callsToForward[$method] = $parameters;
135
136
        return $this;
137
    }
138
}
139