Test Failed
Pull Request — master (#16)
by Christopher
07:42
created

src/Searchable.php (1 issue)

Labels
Severity
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 63
    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);
52
            }
53
    
54 2
            $model->syncRelationships();
55 63
        });
56
        
57
        static::deleted(function (Model $model) {
58
            /** @var Model|Searchable $model */
59
            if ($model->shouldSyncDocument()) {
60
                $model->repository()->delete($model);
61
            }
62
    
63
            $model->syncRelationships();
64 63
        });
65 63
    }
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 20
    public function getDocumentIndex(): ?string
83
    {
84 20
        if (property_exists($this, 'documentIndex')) {
85 19
            return $this->documentIndex;
86
        }
87
        
88 1
        return null;
89
    }
90
    
91
    /**
92
     * Get document type
93
     *
94
     * @return string
95
     */
96 14
    public function getDocumentType(): string
97
    {
98 14
        if (property_exists($this, 'documentType')) {
99 13
            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
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)) {
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);
198
        }
199
        
200 8
        if ($name == 'suggest') {
201
            return Leopard::suggest();
202
        }
203
        
204 8
        return parent::__call($name, $arguments);
205
    }
206
}
207