Passed
Pull Request — master (#33)
by Serhii
04:22
created

DefaultImportSource::chunked()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 30
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 4

Importance

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