Completed
Push — master ( 6a987b...aa82ab )
by Nuno
23:32 queued 20:14
created

Aggregator::getScoutKey()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3.1406

Importance

Changes 0
Metric Value
cc 3
eloc 3
nc 3
nop 0
dl 0
loc 7
ccs 3
cts 4
cp 0.75
crap 3.1406
rs 10
c 0
b 0
f 0
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 Illuminate\Support\Str;
18
use Laravel\Scout\Searchable;
19
use Illuminate\Database\Eloquent\Model;
20
use Illuminate\Database\Eloquent\SoftDeletes;
21
use Algolia\ScoutExtended\Contracts\SearchableCountableContract;
22
use Algolia\ScoutExtended\Exceptions\ModelNotDefinedInAggregatorException;
23
24
abstract class Aggregator implements SearchableCountableContract
25
{
26
    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...
27
28
    /**
29
     * The names of the models that should be aggregated.
30
     *
31
     * @var string[]
32
     */
33
    protected $models = [];
34
35
    /**
36
     * The model being queried, if any.
37
     *
38
     * @var \Illuminate\Database\Eloquent\Model|null
39
     */
40
    protected $model;
41
42
    /**
43
     * Returns the index name.
44
     *
45
     * @var string
46
     */
47
    protected $indexName;
48
49
    /**
50
     * Boot the aggregator.
51
     *
52
     * @return void
53
     */
54 6
    public static function bootSearchable(): void
55
    {
56 6
        ($self = new static)->registerSearchableMacros();
57
58 6
        $observer = tap(resolve(AggregatorObserver::class))->setAggregator(static::class, $models = $self->getModels());
59
60 6
        foreach ($models as $model) {
61 6
            $model::observe($observer);
62
        }
63 6
    }
64
65
    /**
66
     * Creates an instance of the aggregator.
67
     *
68
     * @param \Illuminate\Database\Eloquent\Model $model
69
     *
70
     * @return \Algolia\ScoutExtended\Searchable\Aggregator
71
     */
72 6
    public static function create(Model $model): Aggregator
73
    {
74 6
        return (new static)->setModel($model);
75
    }
76
77
    /**
78
     * Get the names of the models that should be aggregated.
79
     *
80
     * @return string[]
81
     */
82 6
    public function getModels(): array
83
    {
84 6
        return $this->models;
85
    }
86
87
    /**
88
     * Get the model instance being queried.
89
     *
90
     * @return \Illuminate\Database\Eloquent\Model
91
     *
92
     * @throws \Algolia\ScoutExtended\Exceptions\ModelNotDefinedInAggregatorException
93
     */
94 6
    public function getModel(): Model
95
    {
96 6
        if ($this->model === null) {
97
            throw new ModelNotDefinedInAggregatorException();
98
        }
99
100 6
        return $this->model;
101
    }
102
103
    /**
104
     * Set a model instance for the model being queried.
105
     *
106
     * @param \Illuminate\Database\Eloquent\Model $model
107
     *
108
     * @return \Algolia\ScoutExtended\Searchable\Aggregator
109
     */
110 6
    public function setModel(Model $model): Aggregator
111
    {
112 6
        $this->model = $model;
113
114 6
        return $this;
115
    }
116
117
    /**
118
     * Get the value used to index the model.
119
     *
120
     * @return mixed
121
     */
122 6
    public function getScoutKey()
123
    {
124 6
        if ($this->model === null) {
125
            throw new ModelNotDefinedInAggregatorException();
126
        }
127
128 6
        return method_exists($this->model, 'getScoutKey') ? $this->model->getScoutKey() : $this->model->getKey();
129
    }
130
131
    /**
132
     * Get the index name for the searchable.
133
     *
134
     * @return string
135
     */
136 8
    public function searchableAs(): string
137
    {
138 8
        return config('scout.prefix').str_replace('\\', '', Str::snake(class_basename(static::class)));
139
    }
140
141
    /**
142
     * Get the searchable array of the searchable.
143
     *
144
     * @return array
145
     */
146 6
    public function toSearchableArray(): array
147
    {
148 6
        if ($this->model === null) {
149
            throw new ModelNotDefinedInAggregatorException();
150
        }
151
152 6
        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...
153 6
            $this->model->toArray();
154
    }
155
156
    /**
157
     * Make all instances of the model searchable.
158
     *
159
     * @return void
160
     */
161 1
    public static function makeAllSearchable()
162
    {
163 1
        foreach ((new static)->getModels() as $model) {
164 1
            $instance = new $model;
165
166
            $softDeletes =
167 1
                in_array(SoftDeletes::class, class_uses_recursive($model)) && config('scout.soft_delete', false);
168
169
            $instance->newQuery()->when($softDeletes, function ($query) {
170
                $query->withTrashed();
171
            })->orderBy($instance->getKeyName())->get()->map(function ($model) {
172 1
                return static::create($model);
173 1
            })->searchable();
174
        }
175 1
    }
176
177
    /**
178
     * {@inheritdoc}
179
     */
180
    public function getSearchableCount(): int
181
    {
182
        $count = 0;
183
184
        foreach ($this->getModels() as $model) {
185
            $softDeletes =
186
                in_array(SoftDeletes::class, class_uses_recursive($model), true) && config('scout.soft_delete', false);
187
188
            $count += $model::query()->when($softDeletes, function ($query) {
189
                $query->withTrashed();
190
            })->count();
191
        }
192
193
        return (int) $count;
194
    }
195
196
    /**
197
     * Handle dynamic method calls into the model.
198
     *
199
     * @param  string  $method
200
     * @param  array  $parameters
201
     * @return mixed
202
     */
203
    public function __call($method, $parameters)
204
    {
205
        $model = $this->model ?? new class extends Model {
206
        };
207
208
        return $model->$method(...$parameters);
209
    }
210
}
211