Searchable::buildDocumentFromArray()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4.0961

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 4
nop 1
dl 0
loc 19
ccs 9
cts 11
cp 0.8182
crap 4.0961
rs 9.9
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
 * @method BelongsTo belongsTo($related, $foreignKey = null, $ownerKey = null, $relation = null)
31
 */
32
trait Searchable
33
{
34
    use IsModelSearchable;
35
    
36
    /** @var bool */
37
    public $isDocument = false;
38
    
39
    /** @var float|null */
40
    public $documentScore;
41
    
42
    /** @var int|null */
43
    public $documentVersion;
44
    
45
    /**
46
     * Searchable boot model.
47
     */
48 34
    public static function bootSearchable()
49
    {
50
        static::saved(function (Model $model) {
51
            /** @var Model|Searchable $model */
52 2
            if ($model->shouldSyncDocument()) {
53 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

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

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

62
                $model->repository()->delete(/** @scrutinizer ignore-type */ $model);
Loading history...
63
            }
64
    
65
            $model->syncRelationships();
66 34
        });
67 34
    }
68
    
69
    /**
70
     * Repository
71
     *
72
     * @return ElasticsearchRepositoryContract
73
     */
74 2
    public function repository(): ElasticsearchRepositoryContract
75
    {
76 2
        return app(ElasticsearchRepositoryContract::class);
77
    }
78
    
79
    /**
80
     * Get document index
81
     *
82
     * @return string|null
83
     */
84 20
    public function getDocumentIndex(): ?string
85
    {
86 20
        if (property_exists($this, 'documentIndex')) {
87 19
            return $this->documentIndex;
88
        }
89
        
90 1
        return null;
91
    }
92
    
93
    /**
94
     * Get document type
95
     *
96
     * @return string
97
     */
98 14
    public function getDocumentType(): string
99
    {
100 14
        if (property_exists($this, 'documentType')) {
101 13
            return (string)$this->documentType;
102
        }
103
        
104 1
        return (string)$this->getTable();
105
    }
106
    
107
    /**
108
     * Should sync document
109
     *
110
     * @return bool
111
     */
112 3
    public function shouldSyncDocument(): bool
113
    {
114 3
        if (property_exists($this, 'syncDocument')) {
115 3
            return (bool)$this->syncDocument;
116
        }
117
        
118 1
        return true;
119
    }
120
    
121
    /**
122
     * Sync relationships
123
     */
124 2
    public function syncRelationships()
125
    {
126 2
        if (method_exists($this, 'buildSyncRelationships')) {
127 2
            foreach ($this->buildSyncRelationships() as $syncRelationship) {
128 2
                if (!$syncRelationship instanceof SyncRelationship) {
129
                    continue;
130
                }
131
                
132
                /** @var BelongsTo $relation */
133 2
                $relation = $this->belongsTo(
134 2
                    $syncRelationship->getRelatedClass(),
135 2
                    $syncRelationship->getForeignKey(),
136 2
                    $syncRelationship->getOwnerKey(),
137 2
                    $syncRelationship->getRelation()
138
                );
139
    
140 2
                foreach ($relation->get() as $r) {
141
                    /** @var Model|Searchable $r */
142 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

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

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

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