Passed
Pull Request — master (#14)
by Christopher
03:51
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 Illuminate\Support\Facades\DB;
9
use Tests\Integration\Model\Entity\TestRelationshipModel;
10
use Triadev\Leopard\Business\Helper\IsModelSearchable;
11
use Triadev\Leopard\Contract\ElasticsearchManagerContract;
12
use Triadev\Leopard\Contract\Repository\ElasticsearchRepositoryContract;
13
use Triadev\Leopard\Facade\Leopard;
14
15
/**
16
 * Trait Searchable
17
 * @package Triadev\Leopard
18
 *
19
 * @property string $documentIndex
20
 * @property string $documentType
21
 * @property bool $syncDocument
22
 * @property array $searchable
23
 * @property array $syncRelationships
24
 *
25
 * @method static ElasticsearchManagerContract search()
26
 * @methdo static ElasticsearchManagerContract suggest()
27
 * @method array buildDocument()
28
 * @method array toArray()
29
 * @method string getTable()
30
 */
31
trait Searchable
32
{
33
    use IsModelSearchable;
34
    
35
    /** @var bool */
36
    public $isDocument = false;
37
    
38
    /** @var float|null */
39
    public $documentScore;
40
    
41
    /** @var int|null */
42
    public $documentVersion;
43
    
44
    /**
45
     * Searchable boot model.
46
     */
47 135
    public static function bootSearchable()
48
    {
49
        static::saved(function (Model $model) {
50
            /** @var Model|Searchable $model */
51 1
            if ($model->shouldSyncDocument()) {
52 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

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

61
                $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

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

131
                /** @scrutinizer ignore-call */ 
132
                $relation = $this->belongsTo(
Loading history...
132 1
                    $syncRelationshipClass,
133 1
                    $syncRelationship->getForeignKey()
134
                );
135
                
136
                /** @var Model|Searchable $parent */
137 1
                $parent = $relation->first();
138
                
139 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

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

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