Completed
Push — master ( 6b5beb...afd247 )
by Freek
01:16
created

ModelSearchAspect::addExactSearchableAttribute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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