Passed
Pull Request — master (#14)
by Christopher
04:19
created

Searchable::syncRelationships()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 21
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5.0187

Importance

Changes 0
Metric Value
cc 5
eloc 10
nc 4
nop 0
dl 0
loc 21
ccs 10
cts 11
cp 0.9091
crap 5.0187
rs 9.6111
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
13
/**
14
 * Trait Searchable
15
 * @package Triadev\Leopard
16
 *
17
 * @property string $documentIndex
18
 * @property string $documentType
19
 * @property bool $syncDocument
20
 * @property array $searchable
21
 * @property array $syncRelationships
22
 *
23
 * @method static ElasticsearchManagerContract search()
24
 * @methdo static ElasticsearchManagerContract suggest()
25
 * @method array buildDocument()
26
 * @method array toArray()
27
 * @method string getTable()
28
 */
29
trait Searchable
30
{
31
    use IsModelSearchable;
32
    
33
    /** @var bool */
34
    public $isDocument = false;
35
    
36
    /** @var float|null */
37
    public $documentScore;
38
    
39
    /** @var int|null */
40
    public $documentVersion;
41
    
42
    /**
43
     * Searchable boot model.
44
     */
45 135
    public static function bootSearchable()
46
    {
47
        static::saved(function (Model $model) {
48
            /** @var Model|Searchable $model */
49 1
            if ($model->shouldSyncDocument()) {
50 1
                $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

50
                $model->repository()->save(/** @scrutinizer ignore-type */ $model);
Loading history...
51
            }
52
    
53 1
            $model->syncRelationships();
54 135
        });
55
        
56
        static::deleted(function (Model $model) {
57
            /** @var Model|Searchable $model */
58
            if ($model->shouldSyncDocument()) {
59
                $model->repository()->delete($model);
0 ignored issues
show
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

59
                $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...
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

59
                $model->repository()->delete(/** @scrutinizer ignore-type */ $model);
Loading history...
60
            }
61
    
62
            $model->syncRelationships();
63 135
        });
64 135
    }
65
    
66
    /**
67
     * Repository
68
     *
69
     * @return ElasticsearchRepositoryContract
70
     */
71 1
    public function repository(): ElasticsearchRepositoryContract
72
    {
73 1
        return app(ElasticsearchRepositoryContract::class);
74
    }
75
    
76
    /**
77
     * Get document index
78
     *
79
     * @return string|null
80
     */
81 17
    public function getDocumentIndex(): ?string
82
    {
83 17
        if (property_exists($this, 'documentIndex')) {
84 16
            return $this->documentIndex;
85
        }
86
        
87 1
        return null;
88
    }
89
    
90
    /**
91
     * Get document type
92
     *
93
     * @return string
94
     */
95 14
    public function getDocumentType(): string
96
    {
97 14
        if (property_exists($this, 'documentType')) {
98 13
            return (string)$this->documentType;
99
        }
100
        
101 1
        return (string)$this->getTable();
102
    }
103
    
104
    /**
105
     * Should sync document
106
     *
107
     * @return bool
108
     */
109 2
    public function shouldSyncDocument(): bool
110
    {
111 2
        if (property_exists($this, 'syncDocument')) {
112 2
            return (bool)$this->syncDocument;
113
        }
114
        
115 1
        return true;
116
    }
117
    
118
    /**
119
     * Sync relationships
120
     */
121 1
    public function syncRelationships()
122
    {
123 1
        if (property_exists($this, 'syncRelationships')) {
124 1
            foreach ($this->syncRelationships as $syncRelationshipClass) {
125
                /** @var Model $syncRelationship */
126 1
                $syncRelationship = new $syncRelationshipClass();
127
                
128
                /** @var BelongsTo $relation */
129 1
                $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

129
                /** @scrutinizer ignore-call */ 
130
                $relation = $this->belongsTo(
Loading history...
130 1
                    $syncRelationshipClass,
131 1
                    $syncRelationship->getForeignKey()
132
                );
133
                
134
                /** @var Model|Searchable $parent */
135 1
                $parent = $relation->first();
136
                
137 1
                if (!$parent || !$this->isModelSearchable($parent)) {
0 ignored issues
show
Bug introduced by
It seems like $parent 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

137
                if (!$parent || !$this->isModelSearchable(/** @scrutinizer ignore-type */ $parent)) {
Loading history...
138
                    continue;
139
                }
140
                
141 1
                $parent->repository()->save($parent);
142
            }
143
        }
144 1
    }
145
    
146
    /**
147
     * Get document data
148
     *
149
     * @return array
150
     */
151 9
    public function getDocumentData() : array
152
    {
153 9
        if (method_exists($this, 'buildDocument')) {
154 7
            return $this->buildDocument();
155
        }
156
        
157 2
        if (property_exists($this, 'searchable') && is_array($this->searchable)) {
158 1
            return $this->buildDocumentFromArray($this->searchable);
159
        }
160
        
161 1
        return $this->toArray();
162
    }
163
    
164 1
    private function buildDocumentFromArray(array $searchable)
165
    {
166 1
        $document = [];
167
        
168 1
        foreach ($searchable as $value) {
169 1
            $result = $this->$value;
170
            
171 1
            if ($result instanceof Collection) {
172
                $result = $result->toArray();
173 1
            } elseif ($result instanceof Carbon) {
174
                $result = $result->toDateTimeString();
175
            } else {
176 1
                $result = $this->$value;
177
            }
178
            
179 1
            $document[$value] = $result;
180
        }
181
        
182 1
        return $document;
183
    }
184
    
185
    /**
186
     * @param $name
187
     * @param $arguments
188
     * @return mixed
189
     */
190 7
    public function __call($name, $arguments)
191
    {
192 7
        if ($name == 'search') {
193
            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

193
            return Leopard::search()->model(/** @scrutinizer ignore-type */ $this);
Loading history...
194
        }
195
        
196 7
        if ($name == 'suggest') {
197
            return Leopard::suggest();
198
        }
199
        
200 7
        return parent::__call($name, $arguments);
201
    }
202
}
203