Test Failed
Push — develop ( 013d90...7b3751 )
by Nuno
03:38
created

Aggregator::bootSearchable()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * This file is part of Scout Extended.
7
 *
8
 * (c) Algolia Team <[email protected]>
9
 *
10
 *  For the full copyright and license information, please view the LICENSE
11
 *  file that was distributed with this source code.
12
 */
13
14
namespace Algolia\ScoutExtended\Searchable;
15
16
use function in_array;
17
use Laravel\Scout\Searchable;
18
use Illuminate\Database\Eloquent\Model;
19
use Illuminate\Database\Eloquent\SoftDeletes;
20
use Algolia\ScoutExtended\Contracts\SearchableCountableContract;
21
use Algolia\ScoutExtended\Exceptions\ModelNotDefinedInAggregatorException;
22
23
abstract class Aggregator implements SearchableCountableContract
24
{
25
    use Searchable;
0 ignored issues
show
Bug introduced by
The trait Laravel\Scout\Searchable requires the property $queryCallback which is not provided by Algolia\ScoutExtended\Searchable\Aggregator.
Loading history...
26
27
    /**
28
     * The names of the models that should be aggregated.
29
     *
30
     * @var string[]
31
     */
32
    protected $models = [];
33
34
    /**
35
     * The model being queried, if any.
36
     *
37
     * @var \Illuminate\Database\Eloquent\Model|null
38
     */
39
    protected $model;
40
41
    /**
42
     * Returns the index name.
43
     *
44
     * @var string
45
     */
46
    protected $indexName;
47
48
    /**
49
     * Boot the aggregator.
50
     *
51
     * @return void
52
     */
53 6
    public static function bootSearchable(): void
54
    {
55 6
        ($self = new static)->registerSearchableMacros();
56
57 6
        $observer = tap(resolve(AggregatorObserver::class))->setAggregator(static::class, $models = $self->getModels());
58
59 6
        foreach ($models as $model) {
60 6
            $model::observe($observer);
61
        }
62 6
    }
63
64
    /**
65
     * Creates an instance of the aggregator.
66
     *
67
     * @param \Illuminate\Database\Eloquent\Model $model
68
     *
69
     * @return \Algolia\ScoutExtended\Searchable\Aggregator
70
     */
71 1
    public static function create(Model $model): Aggregator
72
    {
73 1
        return (new static)->setModel($model);
74
    }
75
76
    /**
77
     * Get the names of the models that should be aggregated.
78
     *
79
     * @return string[]
80
     */
81 6
    public function getModels(): array
82
    {
83 6
        return $this->models;
84
    }
85
86
    /**
87
     * Get the model instance being queried.
88
     *
89
     * @return \Illuminate\Database\Eloquent\Model
90
     *
91
     * @throws \Algolia\ScoutExtended\Exceptions\ModelNotDefinedInAggregatorException
92
     */
93
    public function getModel(): Model
94
    {
95
        if ($this->model === null) {
96
            throw new ModelNotDefinedInAggregatorException();
97
        }
98
99
        return $this->model;
100
    }
101
102
    /**
103
     * Set a model instance for the model being queried.
104
     *
105
     * @param \Illuminate\Database\Eloquent\Model $model
106
     *
107
     * @return \Algolia\ScoutExtended\Searchable\Aggregator
108
     */
109 1
    public function setModel(Model $model): Aggregator
110
    {
111 1
        $this->model = $model;
112
113 1
        return $this;
114
    }
115
116
    /**
117
     * Get the value used to index the model.
118
     *
119
     * @return mixed
120
     */
121
    public function getScoutKey()
122
    {
123
        if ($this->model === null) {
124
            throw new ModelNotDefinedInAggregatorException();
125
        }
126
127
        return method_exists($this->model, 'getScoutKey') ? $this->model->getScoutKey() : $this->model->getKey();
128
    }
129
130
    /**
131
     * Get the index name for the searchable.
132
     *
133
     * @return string
134
     */
135
    public function searchableAs(): string
136
    {
137
        return config('scout.prefix').UuidGenerator::getUuid(static::class);
138
    }
139
140
    /**
141
     * Get the searchable array of the searchable.
142
     *
143
     * @return array
144
     */
145
    public function toSearchableArray(): array
146
    {
147
        if ($this->model === null) {
148
            throw new ModelNotDefinedInAggregatorException();
149
        }
150
151
        return method_exists($this->model, 'toSearchableArray') ? $this->model->toSearchableArray() :
0 ignored issues
show
Bug Best Practice introduced by
The expression return method_exists($th...$this->model->toArray() could return the type Illuminate\Database\Eloquent\Builder which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
152
            $this->model->toArray();
153
    }
154
155
    /**
156
     * Make all instances of the model searchable.
157
     *
158
     * @return void
159
     */
160
    public static function makeAllSearchable()
161
    {
162
        foreach ((new static)->getModels() as $model) {
163
            $instance = new $model;
164
165
            $softDeletes =
166
                in_array(SoftDeletes::class, class_uses_recursive($model)) && config('scout.soft_delete', false);
167
168
            $instance->newQuery()->when($softDeletes, function ($query) {
169
                $query->withTrashed();
170
            })->orderBy($instance->getKeyName())->get()->map(function ($model) {
171
                return static::create($model);
172
            })->searchable();
173
        }
174
    }
175
176
    /**
177
     * Remove all instances of the model from the search index.
178
     *
179
     * @return void
180
     */
181
    public static function removeAllFromSearch(): void
182
    {
183
        foreach ((new static)->getModels() as $model) {
184
            $instance = new $model;
185
186
            $instance->newQuery()->orderBy($instance->getKeyName())->get()->map(function ($model) {
187
                return static::create($model);
188
            })->unsearchable();
189
        }
190
    }
191
192
    /**
193
     * {@inheritdoc}
194
     */
195
    public function getSearchableCount(): int
196
    {
197
        $count = 0;
198
199
        foreach ($this->getModels() as $model) {
200
            $softDeletes =
201
                in_array(SoftDeletes::class, class_uses_recursive($model), true) && config('scout.soft_delete', false);
202
203
            $count += $model::query()->when($softDeletes, function ($query) {
204
                $query->withTrashed();
205
            })->count();
206
        }
207
208
        return (int) $count;
209
    }
210
}
211