Passed
Push — master ( 099732...be2242 )
by Christopher
02:03
created

Searchable::syncRelationships()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 7.1429

Importance

Changes 0
Metric Value
cc 7
eloc 13
nc 6
nop 0
dl 0
loc 23
ccs 12
cts 14
cp 0.8571
crap 7.1429
rs 8.8333
c 0
b 0
f 0
1
<?php
2
namespace Triadev\Leopard;
3
4
use Carbon\Carbon;
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Database\Eloquent\Relations\BelongsTo;
7
use Illuminate\Support\Collection;
8
use Triadev\Leopard\Business\Helper\IsModelSearchable;
9
use Triadev\Leopard\Contract\ElasticsearchManagerContract;
10
use Triadev\Leopard\Contract\Repository\ElasticsearchRepositoryContract;
11
use Triadev\Leopard\Facade\Leopard;
12
use Triadev\Leopard\Model\SyncRelationship;
13
14
/**
15
 * Trait Searchable
16
 * @package Triadev\Leopard
17
 *
18
 * @property string $documentIndex
19
 * @property string $documentType
20
 * @property bool $syncDocument
21
 * @property array $searchable
22
 *
23
 * @method static ElasticsearchManagerContract search()
24
 * @methdo static ElasticsearchManagerContract suggest()
25
 * @method array buildDocument()
26
 * @method SyncRelationship[] buildSyncRelationships()
27
 * @method array toArray()
28
 * @method string getTable()
29
 */
30
trait Searchable
31
{
32
    use IsModelSearchable;
33
    
34
    /** @var bool */
35
    public $isDocument = false;
36
    
37
    /** @var float|null */
38
    public $documentScore;
39
    
40
    /** @var int|null */
41
    public $documentVersion;
42
    
43
    /**
44
     * Searchable boot model.
45
     */
46 136
    public static function bootSearchable()
47
    {
48
        static::saved(function (Model $model) {
49
            /** @var Model|Searchable $model */
50 2
            if ($model->shouldSyncDocument()) {
51 2
                $model->repository()->save($model);
0 ignored issues
show
Bug introduced by
It seems like $model can also be of type Triadev\Leopard\Searchable; however, parameter $model of Triadev\Leopard\Contract...ositoryContract::save() does only seem to accept Illuminate\Database\Eloquent\Model, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

51
                $model->repository()->save(/** @scrutinizer ignore-type */ $model);
Loading history...
52
            }
53
    
54 2
            $model->syncRelationships();
55 136
        });
56
        
57
        static::deleted(function (Model $model) {
58
            /** @var Model|Searchable $model */
59
            if ($model->shouldSyncDocument()) {
60
                $model->repository()->delete($model);
0 ignored issues
show
Bug introduced by
It seems like $model can also be of type Triadev\Leopard\Searchable; however, parameter $model of Triadev\Leopard\Contract...itoryContract::delete() does only seem to accept Illuminate\Database\Eloquent\Model, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

60
                $model->repository()->delete(/** @scrutinizer ignore-type */ $model);
Loading history...
Unused Code introduced by
The call to Illuminate\Database\Eloquent\Builder::delete() has too many arguments starting with $model. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

60
                $model->repository()->/** @scrutinizer ignore-call */ delete($model);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
61
            }
62
    
63
            $model->syncRelationships();
64 136
        });
65 136
    }
66
    
67
    /**
68
     * Repository
69
     *
70
     * @return ElasticsearchRepositoryContract
71
     */
72 2
    public function repository(): ElasticsearchRepositoryContract
73
    {
74 2
        return app(ElasticsearchRepositoryContract::class);
75
    }
76
    
77
    /**
78
     * Get document index
79
     *
80
     * @return string|null
81
     */
82 18
    public function getDocumentIndex(): ?string
83
    {
84 18
        if (property_exists($this, 'documentIndex')) {
85 17
            return $this->documentIndex;
86
        }
87
        
88 1
        return null;
89
    }
90
    
91
    /**
92
     * Get document type
93
     *
94
     * @return string
95
     */
96 15
    public function getDocumentType(): string
97
    {
98 15
        if (property_exists($this, 'documentType')) {
99 14
            return (string)$this->documentType;
100
        }
101
        
102 1
        return (string)$this->getTable();
103
    }
104
    
105
    /**
106
     * Should sync document
107
     *
108
     * @return bool
109
     */
110 3
    public function shouldSyncDocument(): bool
111
    {
112 3
        if (property_exists($this, 'syncDocument')) {
113 3
            return (bool)$this->syncDocument;
114
        }
115
        
116 1
        return true;
117
    }
118
    
119
    /**
120
     * Sync relationships
121
     */
122 2
    public function syncRelationships()
123
    {
124 2
        if (method_exists($this, 'buildSyncRelationships')) {
125 2
            foreach ($this->buildSyncRelationships() as $syncRelationship) {
126 2
                if (!$syncRelationship instanceof SyncRelationship) {
127
                    continue;
128
                }
129
                
130
                /** @var BelongsTo $relation */
131 2
                $relation = $this->belongsTo(
0 ignored issues
show
Bug introduced by
The method belongsTo() does not exist on Triadev\Leopard\Searchable. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

131
                /** @scrutinizer ignore-call */ 
132
                $relation = $this->belongsTo(
Loading history...
132 2
                    $syncRelationship->getRelatedClass(),
133 2
                    $syncRelationship->getForeignKey(),
134 2
                    $syncRelationship->getOwnerKey(),
135 2
                    $syncRelationship->getRelation()
136
                );
137
    
138 2
                foreach ($relation->get() as $r) {
139
                    /** @var Model|Searchable $r */
140 2
                    if (!$r || !$this->isModelSearchable($r)) {
0 ignored issues
show
Bug introduced by
It seems like $r can also be of type Triadev\Leopard\Searchable; however, parameter $model of Triadev\Leopard\Searchable::isModelSearchable() does only seem to accept Illuminate\Database\Eloquent\Model, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

140
                    if (!$r || !$this->isModelSearchable(/** @scrutinizer ignore-type */ $r)) {
Loading history...
141
                        continue;
142
                    }
143
        
144 2
                    $r->repository()->save($r);
145
                }
146
            }
147
        }
148 2
    }
149
    
150
    /**
151
     * Get document data
152
     *
153
     * @return array
154
     */
155 10
    public function getDocumentData() : array
156
    {
157 10
        if (method_exists($this, 'buildDocument')) {
158 8
            return $this->buildDocument();
159
        }
160
        
161 2
        if (property_exists($this, 'searchable') && is_array($this->searchable)) {
162 1
            return $this->buildDocumentFromArray($this->searchable);
163
        }
164
        
165 1
        return $this->toArray();
166
    }
167
    
168 1
    private function buildDocumentFromArray(array $searchable)
169
    {
170 1
        $document = [];
171
        
172 1
        foreach ($searchable as $value) {
173 1
            $result = $this->$value;
174
            
175 1
            if ($result instanceof Collection) {
176
                $result = $result->toArray();
177 1
            } elseif ($result instanceof Carbon) {
178
                $result = $result->toDateTimeString();
179
            } else {
180 1
                $result = $this->$value;
181
            }
182
            
183 1
            $document[$value] = $result;
184
        }
185
        
186 1
        return $document;
187
    }
188
    
189
    /**
190
     * @param $name
191
     * @param $arguments
192
     * @return mixed
193
     */
194 8
    public function __call($name, $arguments)
195
    {
196 8
        if ($name == 'search') {
197
            return Leopard::search()->model($this);
0 ignored issues
show
Bug introduced by
$this of type Triadev\Leopard\Searchable is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $model of Triadev\Leopard\Business...\AbstractQuery::model(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

197
            return Leopard::search()->model(/** @scrutinizer ignore-type */ $this);
Loading history...
198
        }
199
        
200 8
        if ($name == 'suggest') {
201
            return Leopard::suggest();
202
        }
203
        
204 8
        return parent::__call($name, $arguments);
205
    }
206
}
207