Test Failed
Pull Request — master (#170)
by Serhii
13:10
created

DefaultImportSource::count()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 2
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 4
rs 10
ccs 0
cts 0
cp 0
crap 6
1
<?php
2
declare(strict_types=1);
3
4
namespace Matchish\ScoutElasticSearch\Searchable;
5
6
use Illuminate\Database\Eloquent\Builder;
7
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
8
use Illuminate\Database\Eloquent\Model;
9
use Illuminate\Support\LazyCollection;
10
use Matchish\ScoutElasticSearch\Database\Scopes\FromScope;
11
use Matchish\ScoutElasticSearch\Database\Scopes\PageScope;
12
13
final class DefaultImportSource implements ImportSource
14
{
15
    const DEFAULT_CHUNK_SIZE = 500;
16
    const DEFAULT_WORKERS = 1;
17
18
    /**
19
     * @var string
20
     */
21
    private $className;
22
    /**
23
     * @var array
24
     */
25
    private $scopes;
26
    /**
27
     * @var ?object
28 28
     */
29
    private $last;
30 28
    /**
31 28
     * @var int
32 28
     */
33
    private $count;
34 12
35
    /**
36 12
     * DefaultImportSource constructor.
37
     * @param string $className
38
     * @param array $scopes
39 12
     */
40
    public function __construct(string $className, array $scopes = [])
41 12
    {
42
        $this->className = $className;
43
        $this->scopes = $scopes;
44 20
    }
45
46 20
    public function syncWithSearchUsingQueue(): ?string
47
    {
48
        return $this->model()->syncWithSearchUsingQueue();
49 18
    }
50
51 18
    public function syncWithSearchUsing(): ?string
52 18
    {
53 18
        return $this->model()->syncWithSearchUsing();
54 13
    }
55 13
56
    public function searchableAs(): string
57 13
    {
58 13
        return $this->model()->searchableAs();
59
    }
60 13
61 13
    public function chunked(): LazyCollection
62
    {
63 13
        return LazyCollection::make(function () {
64
            $chunkSize = (int) config('scout.chunk.searchable', self::DEFAULT_CHUNK_SIZE);
65
            $workers = (int) config('scout.parallel.workers', self::DEFAULT_WORKERS);
66
67
            $lastChunk = null;
68
            while (true) {
69
                $chunks = [];
70 28
                for ($page = 1; $page <= $workers; $page++) {
71
                    $chunkScopes = [];
72 28
                    $chunkScopes[] = new PageScope($page, $chunkSize);
73
                    if ($lastChunk instanceof ImportSource && $lastChunk->last() instanceof Model) {
74
                        $chunkScopes[] = new FromScope($lastChunk->last()->getKey());
75 23
                    }
76
                    $chunk = new static($this->className, array_merge($this->scopes, $chunkScopes));
77 23
                    $chunks[] = $chunk;
78 23
                }
79
                yield collect($chunks);
80 23
                if (!isset($chunk) || !$chunk->count()) break;
81 2
                $lastChunk = $chunk;
82 23
            }
83 23
        });
84 23
    }
85
86 23
    /**
87 13
     * @return mixed
88
     */
89 13
    private function model()
90 23
    {
91
        return new $this->className;
92
    }
93 17
94
    private function newQuery(): Builder
95
    {
96 17
        $query = $this->model()->newQuery();
97
        $softDelete = $this->className::usesSoftDelete() && config('scout.soft_delete', false);
98 17
        $query
99
            ->when($softDelete, function ($query) {
100
                return $query->withTrashed();
101
            })
102
            ->orderBy($this->model()->getKeyName());
103
        $scopes = $this->scopes;
104
105
        return collect($scopes)->reduce(function ($instance, $scope) {
106
            $instance->withGlobalScope(get_class($scope), $scope);
107
108
            return $instance;
109
        }, $query);
110
    }
111
112
    public function get(): EloquentCollection
113
    {
114
        /** @var EloquentCollection $models */
115
        $models = $this->newQuery()->get();
116
        $this->last = $models->last();
117
        $this->count = $models->count();
118
        return $models;
119
    }
120
121
    public function count(): int
122
    {
123
        if (isset($this->count)) return $this->count;
124
        return $this->newQuery()->count();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->newQuery()->count() could return the type Illuminate\Database\Eloquent\Builder which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
125
    }
126
127
    public function last(): ?object
128
    {
129
        if ($this->last) return $this->last;
130
        return $this->get()->last();
131
    }
132
}
133