Test Failed
Push — develop ( aee2c5...af4094 )
by Nuno
04:06
created

UpdateJob   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 151
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 22
eloc 59
dl 0
loc 151
ccs 0
cts 62
cp 0
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A usesSoftDelete() 0 3 2
B splitSearchable() 0 27 6
A __construct() 0 3 1
B handle() 0 42 9
A shouldBeSplitted() 0 18 4
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\Jobs;
15
16
use function is_array;
17
use function in_array;
18
use function is_string;
19
use function is_object;
20
use function get_class;
21
use Illuminate\Support\Str;
22
use Illuminate\Support\Collection;
23
use Illuminate\Database\Eloquent\SoftDeletes;
24
use Algolia\AlgoliaSearch\Interfaces\ClientInterface;
0 ignored issues
show
Bug introduced by
The type Algolia\AlgoliaSearch\Interfaces\ClientInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
use Algolia\ScoutExtended\Searchable\ObjectIdEncrypter;
26
27
/**
28
 * @internal
29
 */
30
final class UpdateJob
31
{
32
    /**
33
     * Contains a list of splittables searchables.
34
     *
35
     * Example: [
36
     *      '\App\Thread' => true,
37
     *      '\App\User' => false,
38
     * ];
39
     *
40
     * @var array
41
     */
42
    private $splittables = [];
43
44
    /**
45
     * @var \Illuminate\Support\Collection
46
     */
47
    private $searchables;
48
49
    /**
50
     * UpdateJob constructor.
51
     *
52
     * @param \Illuminate\Support\Collection $searchables
53
     *
54
     * @return void
55
     */
56
    public function __construct(Collection $searchables)
57
    {
58
        $this->searchables = $searchables;
59
    }
60
61
    /**
62
     * @param \Algolia\AlgoliaSearch\Interfaces\ClientInterface $client
63
     *
64
     * @return void
65
     */
66
    public function handle(ClientInterface $client): void
67
    {
68
        if ($this->searchables->isEmpty()) {
69
            return;
70
        }
71
72
        if (config('scout.soft_delete', false) && $this->usesSoftDelete($this->searchables->first())) {
73
            $this->searchables->each->pushSoftDeleteMetadata();
74
        }
75
76
        $index = $client->initIndex($this->searchables->first()->searchableAs());
77
78
        $objectsToSave = [];
79
        $searchablesToDelete = [];
80
81
        foreach ($this->searchables as $key => $searchable) {
82
            if (empty($array = array_merge($searchable->toSearchableArray(), $searchable->scoutMetadata()))) {
83
                continue;
84
            }
85
86
            $array['_tags'] = ObjectIdEncrypter::encrypt($searchable);
87
88
            if ($this->shouldBeSplitted($searchable)) {
89
                [$pieces, $splittedBy] = $this->splitSearchable($searchable, $array);
90
91
                foreach ($pieces as $number => $piece) {
92
                    $array['objectID'] = ObjectIdEncrypter::encrypt($searchable, $number);
93
                    $array[$splittedBy] = $piece;
94
                    $objectsToSave[] = $array;
95
                }
96
                $searchablesToDelete[] = $searchable;
97
            } else {
98
                $array['objectID'] = ObjectIdEncrypter::encrypt($searchable);
99
                $objectsToSave[] = $array;
100
            }
101
        }
102
103
        dispatch_now(new DeleteJob(collect($searchablesToDelete)));
104
105
        $result = $index->saveObjects($objectsToSave);
106
        if (config('scout.synchronous', false)) {
107
            $result->wait();
108
        }
109
    }
110
111
    /**
112
     * @param  object $searchable
113
     *
114
     * @return bool
115
     */
116
    private function shouldBeSplitted($searchable): bool
117
    {
118
        $class = get_class($searchable->getModel());
119
120
        if (! array_key_exists($class, $this->splittables)) {
121
            $this->splittables[$class] = false;
122
123
            foreach ($searchable->toSearchableArray() as $key => $value) {
124
                $method = 'split'.Str::camel($key);
125
                $model = $searchable->getModel();
126
                if (method_exists($model, $method)) {
127
                    $this->splittables[$class] = true;
128
                    break;
129
                }
130
            }
131
        }
132
133
        return $this->splittables[$class];
134
    }
135
136
    /**
137
     * @param  object $searchable
138
     * @param  array $array
139
     *
140
     * @return array
141
     */
142
    private function splitSearchable($searchable, array $array): array
143
    {
144
        $splittedBy = null;
145
        $pieces = [];
146
        foreach ($array as $key => $value) {
147
            $method = 'split'.Str::camel((string) $key);
148
            $model = $searchable->getModel();
149
            if (method_exists($model, $method)) {
150
                $result = $model->{$method}($value);
151
152
                switch (true) {
153
                    case is_array($result):
154
                        $pieces = $result;
155
                        break;
156
                    case is_string($result):
157
                        $pieces = (new $result)($model, $value);
158
                        break;
159
                    case is_object($result):
160
                        $pieces = $result->__invoke($model, $value);
161
                        break;
162
                }
163
                $splittedBy = $key;
164
                break;
165
            }
166
        }
167
168
        return [$pieces, $splittedBy];
169
    }
170
171
    /**
172
     * Determine if the given searchable uses soft deletes.
173
     *
174
     * @param  object $searchable
175
     *
176
     * @return bool
177
     */
178
    private function usesSoftDelete($searchable): bool
179
    {
180
        return $searchable instanceof Model && in_array(SoftDeletes::class, class_uses_recursive($searchable), true);
0 ignored issues
show
Bug introduced by
The type Algolia\ScoutExtended\Jobs\Model was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
181
    }
182
}
183