Passed
Pull Request — master (#33)
by Serhii
10:43
created

DefaultImportSource::chunked()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 31
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 24
c 1
b 0
f 0
dl 0
loc 31
ccs 23
cts 23
cp 1
rs 9.536
cc 4
nc 4
nop 0
crap 4
1
<?php
2
3
namespace Matchish\ScoutElasticSearch\Console\Commands;
4
5
class DefaultImportSource implements ImportSource
6
{
7
    const DEFAULT_CHUNK_SIZE = 500;
8
9
    private $className;
10
    private $scopes;
11
12
    /**
13
     * DefaultImportSource constructor.
14
     * @param string $className
15
     * @param array $scopes
16
     */
17 25
    public function __construct(string $className, array $scopes = [])
18
    {
19 25
        $this->className = $className;
20 25
        $this->scopes = $scopes;
21 25
    }
22
23 11
    public function syncWithSearchUsingQueue()
24
    {
25 11
        return $this->model()->syncWithSearchUsingQueue();
26
    }
27
28 11
    public function syncWithSearchUsing()
29
    {
30 11
        return $this->model()->syncWithSearchUsing();
31
    }
32
33 18
    public function searchableAs(): string
34
    {
35 18
        return $this->model()->searchableAs();
36
    }
37
38 17
    public function chunked()
39
    {
40 17
        $query = $this->newQuery();
41 17
        $searchable = $this->model();
42 17
        $totalSearchables = $query->count();
43 17
        if ($totalSearchables) {
44 12
            $chunkSize = (int) config('scout.chunk.searchable', self::DEFAULT_CHUNK_SIZE);
45 12
            $cloneQuery = clone $query;
46 12
            $cloneQuery->joinSub('SELECT @row :=0, 1 as temp', 'r', 'r.temp', 'r.temp')
47 12
                ->selectRaw("@row := @row +1 AS rownum, {$searchable->getKeyName()}");
48 12
            $ids = \DB::query()->fromSub($cloneQuery, 'ranked')->whereRaw("rownum %{$chunkSize} =0")->pluck('id');
49 12
            $pairs = [];
50 12
            $lastId = null;
51 12
            foreach ($ids as $id) {
52 10
                if ($lastId) {
53 6
                    $pairs[] = [$lastId, $id];
54
                } else {
55 10
                    $pairs[] = [null, $id];
56
                }
57 10
                $lastId = $id;
58
            }
59 12
            $pairs[] = [$lastId, null];
60
61
            return collect($pairs)->map(function ($pair) {
62 12
                [$start, $end] = $pair;
63 12
                $chunkScope = new ChunkScope($start, $end);
64
65 12
                return new static($this->className, [$chunkScope]);
66 12
            });
67
        } else {
68 12
            return collect();
69
        }
70
    }
71
72
    /**
73
     * @return mixed
74
     */
75 25
    private function model()
76
    {
77 25
        return new $this->className;
78
    }
79
80 21
    private function newQuery()
81
    {
82 21
        $query = $this->model()->newQuery();
83 21
        $softDelete = config('scout.soft_delete', false);
84
        $query
85
            ->when($softDelete, function ($query) {
86 2
                return $query->withTrashed();
87 21
            })
88 21
            ->orderBy($this->model()->getKeyName());
89 21
        $scopes = $this->scopes;
90
91
        return collect($scopes)->reduce(function ($instance, $scope) {
92 11
            $instance->withGlobalScope($scope->key(), $scope);
93
94 11
            return $instance;
95 21
        }, $query);
96
    }
97
98 15
    public function get()
99
    {
100 15
        return $this->newQuery()->get();
101
    }
102
}
103