Completed
Push — master ( b6a026...05da76 )
by
unknown
01:27
created

ModelSearchAspect::__construct()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 32
rs 8.7857
c 0
b 0
f 0
cc 6
nc 6
nop 2
1
<?php
2
3
namespace Spatie\Searchable;
4
5
use Illuminate\Support\Collection;
6
use Illuminate\Foundation\Auth\User;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Database\Eloquent\Builder;
9
use Spatie\Searchable\Exceptions\InvalidSearchableModel;
10
use Spatie\Searchable\Exceptions\InvalidModelSearchAspect;
11
12
class ModelSearchAspect extends SearchAspect
13
{
14
    /** @var \Illuminate\Database\Eloquent\Model */
15
    protected $model;
16
17
    /** @var array */
18
    protected $attributes = [];
19
20
    public static function forModel(string $model, ...$attributes): self
21
    {
22
        return new self($model, $attributes);
23
    }
24
25
    /**
26
     * @param string $model
27
     * @param array|\Closure $attributes
28
     *
29
     * @throws \Spatie\Searchable\Exceptions\InvalidSearchableModel
30
     */
31
    public function __construct(string $model, $attributes = [])
32
    {
33
        if (! is_subclass_of($model, Model::class)) {
34
            throw InvalidSearchableModel::notAModel($model);
35
        }
36
37
        if (! is_subclass_of($model, Searchable::class)) {
38
            throw InvalidSearchableModel::modelDoesNotImplementSearchable($model);
39
        }
40
41
        $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...
42
43
        if (is_array($attributes)) {
44
            $this->attributes = SearchableAttribute::createMany($attributes);
45
46
            return;
47
        }
48
49
        if (is_string($attributes)) {
50
            $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...
51
52
            return;
53
        }
54
55
        if (is_callable($attributes)) {
56
            $callable = $attributes;
57
58
            $callable($this);
59
60
            return;
61
        }
62
    }
63
64
    public function addSearchableAttribute(string $attribute, bool $partial = true): self
65
    {
66
        $this->attributes[] = SearchableAttribute::create($attribute, $partial);
67
68
        return $this;
69
    }
70
71
    public function addExactSearchableAttribute(string $attribute): self
72
    {
73
        $this->attributes[] = SearchableAttribute::createExact($attribute);
74
75
        return $this;
76
    }
77
78
    public function getType(): string
79
    {
80
        $model = new $this->model();
81
82
        if (property_exists($model, 'searchableType')) {
83
            return $model->searchableType;
84
        }
85
86
        return $model->getTable();
87
    }
88
89
    public function getResults(string $term, User $user = null): Collection
90
    {
91
        if (empty($this->attributes)) {
92
            throw InvalidModelSearchAspect::noSearchableAttributes($this->model);
93
        }
94
95
        $query = ($this->model)::query();
96
97
        $this->addSearchConditions($query, $term);
98
99
        return $query->get();
100
    }
101
102
    protected function addSearchConditions(Builder $query, string $term)
103
    {
104
        $attributes = $this->attributes;
105
        $searchTerms = explode(' ', $term);
106
107
        $query->where(function (Builder $query) use ($attributes, $term, $searchTerms) {
108
            foreach (array_wrap($attributes) as $attribute) {
109
                foreach ($searchTerms as $searchTerm) {
110
                    $sql = "LOWER({$attribute->getAttribute()}) LIKE ?";
111
                    $searchTerm = mb_strtolower($searchTerm, 'UTF8');
112
113
                    $attribute->isPartial()
114
                        ? $query->orWhereRaw($sql, ["%{$searchTerm}%"])
115
                        : $query->orWhere($attribute->getAttribute(), $searchTerm);
116
                }
117
            }
118
        });
119
    }
120
}
121