ModelsResolver   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 77
Duplicated Lines 0 %

Test Coverage

Coverage 96.97%

Importance

Changes 11
Bugs 1 Features 0
Metric Value
wmc 15
eloc 37
c 11
b 1
f 0
dl 0
loc 77
ccs 32
cts 33
cp 0.9697
rs 10

1 Method

Rating   Name   Duplication   Size   Complexity  
D from() 0 57 15
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 call_user_func;
17
use Illuminate\Database\Eloquent\Collection;
18
use Illuminate\Database\Eloquent\SoftDeletes;
19
use Illuminate\Support\Arr;
20
use function in_array;
21
use Laravel\Scout\Builder;
22
use Laravel\Scout\Searchable;
23
24
/**
25
 * @internal
26
 */
27
final class ModelsResolver
28
{
29
    /**
30
     * @var string[]
31
     */
32
    public static $metadata = [
33
        '_snippetResult',
34
        '_highlightResult',
35
        '_rankingInfo',
36
    ];
37
38
    /**
39
     * Get a set of models from the provided results.
40
     *
41
     * @param \Laravel\Scout\Builder $builder
42
     * @param  object $searchable
43
     * @param  array $results
44
     *
45
     * @return \Illuminate\Database\Eloquent\Collection
46
     */
47 6
    public function from(Builder $builder, $searchable, array $results): Collection
48
    {
49 6
        $instances = collect();
50 6
        $hits = collect($results['hits'])->keyBy('objectID');
51
52 6
        $models = [];
53 6
        foreach ($hits->keys() as $id) {
54 6
            $modelClass = ObjectIdEncrypter::decryptSearchable((string) $id);
55 5
            $modelKey = ObjectIdEncrypter::decryptSearchableKey((string) $id);
56 5
            if (! array_key_exists($modelClass, $models)) {
57 5
                $models[$modelClass] = [];
58
            }
59
60 5
            $models[$modelClass][] = $modelKey;
61
        }
62
63 5
        foreach ($models as $modelClass => $modelKeys) {
64 5
            $model = new $modelClass;
65
66 5
            if (in_array(Searchable::class, class_uses_recursive($model), true)) {
67 5
                if (! empty($models = $model->getScoutModelsByIds($builder, $modelKeys))) {
68 5
                    $instances = $instances->merge($models->load($searchable->getRelations($modelClass)));
69
                }
70
            } else {
71 1
                $query = in_array(SoftDeletes::class, class_uses_recursive($model),
72 1
                    true) ? $model->withTrashed() : $model->newQuery();
73
74 1
                if ($builder->queryCallback) {
75
                    call_user_func($builder->queryCallback, $query);
76
                }
77
78 1
                $scoutKey = method_exists($model,
79 1
                    'getScoutKeyName') ? $model->getScoutKeyName() : $model->getQualifiedKeyName();
80 1
                if ($models = $query->whereIn($scoutKey, $modelKeys)->get()) {
81 5
                    $instances = $instances->merge($models->load($searchable->getRelations($modelClass)));
82
                }
83
            }
84
        }
85
86 5
        $result = $searchable->newCollection();
87
88 5
        foreach ($hits as $id => $hit) {
89 5
            foreach ($instances as $instance) {
90 5
                if (ObjectIdEncrypter::encrypt($instance) === ObjectIdEncrypter::withoutPart((string) $id)) {
91 5
                    if (method_exists($instance, 'withScoutMetadata')) {
92 5
                        foreach (Arr::only($hit, self::$metadata) as $metadataKey => $metadataValue) {
93 1
                            $instance->withScoutMetadata($metadataKey, $metadataValue);
94
                        }
95
                    }
96
97 5
                    $result->push($instance);
98 5
                    break;
99
                }
100
            }
101
        }
102
103 5
        return $result;
104
    }
105
}
106