Passed
Push — master ( 6562a2...099732 )
by Christopher
04:59
created

AbstractQuery::sort()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 3
dl 0
loc 9
ccs 6
cts 6
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
namespace Triadev\Leopard\Business\Dsl;
3
4
use Illuminate\Database\Eloquent\Model;
5
use ONGR\ElasticsearchDSL\BuilderInterface;
6
use ONGR\ElasticsearchDSL\Query\Compound\BoolQuery;
7
use ONGR\ElasticsearchDSL\Search as OngrSearch;
8
use ONGR\ElasticsearchDSL\Sort\FieldSort;
9
use Triadev\Leopard\Busines\Dsl\Query\Specialized;
10
use Triadev\Leopard\Business\Dsl\Query\Compound;
11
use Triadev\Leopard\Business\Dsl\Query\TermLevel;
12
use Triadev\Leopard\Business\Dsl\Query\Fulltext;
13
use Triadev\Leopard\Business\Dsl\Query\Geo;
14
use Triadev\Leopard\Business\Dsl\Query\Joining;
15
use Triadev\Leopard\Business\Dsl\Query\InnerHit;
16
use Triadev\Leopard\Business\Dsl\Search as SearchDsl;
17
use Triadev\Leopard\Business\Filler\EloquentFiller;
18
use Triadev\Leopard\Business\Helper\IsModelSearchable;
19
use Triadev\Leopard\Contract\ElasticsearchManagerContract;
20
use Triadev\Leopard\Contract\FillerContract;
21
use Triadev\Leopard\Facade\Leopard;
22
use Triadev\Leopard\Model\SearchResult;
23
use Triadev\Leopard\Searchable;
24
25
/**
26
 * Class AbstractQuery
27
 * @package Triadev\Leopard\Business\Dsl
28
 *
29
 * @method TermLevel termLevel()
30
 * @method Fulltext fulltext()
31
 * @method Geo geo()
32
 * @method Compound compound()
33
 * @method Joining joining()
34
 * @method Specialized specialized()
35
 * @method InnerHit innerHit()
36
 */
37
abstract class AbstractQuery
38
{
39
    use IsModelSearchable;
40
    
41
    /** @var OngrSearch */
42
    public $search;
43
    
44
    /** @var string */
45
    public $boolState = BoolQuery::MUST;
46
    
47
    /** @var string|null */
48
    private $index;
49
    
50
    /** @var string|null */
51
    private $type;
52
    
53
    /** @var Model|null */
54
    public $model;
55
    
56
    /** @var ElasticsearchManagerContract */
57
    private $manager;
58
    
59
    /**
60
     * BoolQuery constructor.
61
     * @param OngrSearch|null $search
62
     * @param Model|null $model
63
     */
64 36
    public function __construct(?OngrSearch $search = null, ?Model $model = null)
65
    {
66 36
        $this->search = $search ?: new OngrSearch();
67 36
        $this->model = $model;
68
    
69 36
        $this->manager = app()->make(ElasticsearchManagerContract::class);
70 36
    }
71
    
72
    /**
73
     * Overwrite default index
74
     *
75
     * @param string $index
76
     * @return AbstractQuery|Search
77
     */
78 3
    public function overwriteIndex(string $index) : AbstractQuery
79
    {
80 3
        $this->index = $index;
81 3
        return $this;
82
    }
83
    
84
    /**
85
     * Get index
86
     *
87
     * @return string
88
     */
89 1
    public function getIndex() : string
90
    {
91 1
        return $this->index ?: config('leopard.index');
92
    }
93
    
94
    /**
95
     * Overwrite default type
96
     *
97
     * @param string $type
98
     * @return AbstractQuery|Search
99
     */
100 3
    public function overwriteType(string $type) : AbstractQuery
101
    {
102 3
        $this->type = $type;
103 3
        return $this;
104
    }
105
    
106
    /**
107
     * Get type
108
     *
109
     * @return string|null
110
     */
111 1
    public function getType() : ?string
112
    {
113 1
        return $this->type;
114
    }
115
    
116
    /**
117
     * Add model
118
     *
119
     * @param Model|Searchable $model
120
     * @return AbstractQuery|Search
121
     *
122
     * @throws \InvalidArgumentException
123
     */
124 3
    public function model(Model $model) : AbstractQuery
125
    {
126 3
        $this->isModelSearchable($model);
127
        
128 2
        $this->model = $model;
129
        
130 2
        if (is_string($index = $model->getDocumentIndex())) {
131 2
            $this->overwriteIndex($index);
132
        }
133
        
134 2
        $this->overwriteType($model->getDocumentType());
0 ignored issues
show
Bug introduced by
It seems like $model->getDocumentType() can also be of type Illuminate\Database\Eloquent\Builder; however, parameter $type of Triadev\Leopard\Business...tQuery::overwriteType() does only seem to accept string, 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

134
        $this->overwriteType(/** @scrutinizer ignore-type */ $model->getDocumentType());
Loading history...
135
        
136 2
        return $this;
137
    }
138
    
139
    /**
140
     * To dsl
141
     *
142
     * @return array
143
     */
144 33
    public function toDsl() : array
145
    {
146 33
        return $this->search->toArray();
147
    }
148
    
149
    /**
150
     * Get search
151
     *
152
     * @return OngrSearch
153
     */
154 4
    public function getSearch() : OngrSearch
155
    {
156 4
        return $this->search;
157
    }
158
    
159
    /**
160
     * Get query
161
     *
162
     * @return BuilderInterface
163
     */
164 12
    public function getQuery() : BuilderInterface
165
    {
166 12
        return $this->search->getQueries();
167
    }
168
    
169
    /**
170
     * Get
171
     *
172
     * @param FillerContract|null $filler
173
     * @return SearchResult
174
     */
175 2
    public function get(?FillerContract $filler = null) : SearchResult
176
    {
177 2
        $searchResult = new SearchResult($this->getRaw());
178
        
179 2
        if ($this->model) {
180 1
            $filler = $filler ?: new EloquentFiller();
181 1
            $filler->fill($this->model, $searchResult);
182
        }
183
        
184 2
        return $searchResult;
185
    }
186
    
187
    /**
188
     * Get raw search result
189
     *
190
     * @return array
191
     */
192 2
    public function getRaw() : array
193
    {
194
        $params = [
195 2
            'index' => $this->index,
196 2
            'body' => $this->toDsl()
197
        ];
198
        
199 2
        if ($this->type) {
200
            $params['type'] = $this->type;
201
        }
202
        
203 2
        return $this->manager->searchStatement($params);
204
    }
205
    
206
    /**
207
     * Append
208
     *
209
     * @param BuilderInterface $query
210
     * @return AbstractQuery|TermLevel|Fulltext|Geo|SearchDsl|Joining|Specialized|InnerHit|Search
211
     */
212 32
    public function append(BuilderInterface $query) : AbstractQuery
213
    {
214 32
        $this->search->addQuery($query, $this->boolState);
215 32
        return $this;
216
    }
217
    
218
    /**
219
     * Bool state: must
220
     *
221
     * @return AbstractQuery|TermLevel|Fulltext|Geo|SearchDsl|Joining|Specialized|InnerHit|Search
222
     */
223 2
    public function must(): AbstractQuery
224
    {
225 2
        $this->boolState = BoolQuery::MUST;
226 2
        return $this;
227
    }
228
    
229
    /**
230
     * Bool state: must not
231
     *
232
     * @return AbstractQuery|TermLevel|Fulltext|Geo|SearchDsl|Joining|Specialized|InnerHit|Search
233
     */
234 1
    public function mustNot(): AbstractQuery
235
    {
236 1
        $this->boolState = BoolQuery::MUST_NOT;
237 1
        return $this;
238
    }
239
    
240
    /**
241
     * Bool state: should
242
     *
243
     * @return AbstractQuery|TermLevel|Fulltext|Geo|SearchDsl|Joining|Specialized|InnerHit|Search
244
     */
245 1
    public function should(): AbstractQuery
246
    {
247 1
        $this->boolState = BoolQuery::SHOULD;
248 1
        return $this;
249
    }
250
    
251
    /**
252
     * Bool state: filter
253
     *
254
     * @return AbstractQuery|TermLevel|Fulltext|Geo|SearchDsl|Joining|Specialized|InnerHit|Search
255
     */
256 8
    public function filter(): AbstractQuery
257
    {
258 8
        $this->boolState = BoolQuery::FILTER;
259 8
        return $this;
260
    }
261
    
262
    /**
263
     * Paginate
264
     *
265
     * @param int $page
266
     * @param int $limit
267
     * @return AbstractQuery|TermLevel|Fulltext|Geo|Compound|Joining|Specialized|InnerHit|Search
268
     */
269 1
    public function paginate(int $page, int $limit = 25) : AbstractQuery
270
    {
271 1
        $this->search->setFrom($limit * ($page - 1))->setSize($limit);
272 1
        return $this;
273
    }
274
    
275
    /**
276
     * Min score
277
     *
278
     * @param int $minScore
279
     * @return AbstractQuery|TermLevel|Fulltext|Geo|Compound|Joining|Specialized|InnerHit|Search
280
     */
281 1
    public function minScore(int $minScore) : AbstractQuery
282
    {
283 1
        $this->search->setMinScore($minScore);
284 1
        return $this;
285
    }
286
    
287
    /**
288
     * Sort
289
     *
290
     * @param string $field
291
     * @param string $order
292
     * @param array $params
293
     * @return AbstractQuery|TermLevel|Fulltext|Geo|Compound|Joining|Specialized|InnerHit|Search
294
     */
295 1
    public function sort(string $field, string $order = FieldSort::DESC, array $params = []) : AbstractQuery
296
    {
297 1
        $this->search->addSort(new FieldSort(
298 1
            $field,
299 1
            $order,
300 1
            $params
301
        ));
302
        
303 1
        return $this;
304
    }
305
    
306
    /**
307
     * Search
308
     *
309
     * @param \Closure $search
310
     * @return AbstractQuery|TermLevel|Fulltext|Geo|Compound|Joining|Specialized|InnerHit|Search
311
     */
312 1
    public function bool(\Closure $search) : AbstractQuery
313
    {
314 1
        $searchBuilder = new Search();
315 1
        $search($searchBuilder);
316
        
317 1
        $this->append($searchBuilder->getQuery());
318
        
319 1
        return $this;
320
    }
321
    
322
    /**
323
     * Call
324
     *
325
     * @param string $name
326
     * @param array $arguments
327
     *
328
     * @return AbstractQuery|null
329
     */
330
    public function __call(string $name, array $arguments)
331
    {
332
        $validFunctions = [
333
            'termLevel',
334
            'fulltext',
335
            'geo',
336
            'compound',
337
            'joining',
338
            'specialized',
339
            'innerHit'
340
        ];
341
        
342
        if (in_array($name, $validFunctions)) {
343
            return Leopard::search($this->search, $this->model)->$name();
344
        }
345
        
346
        return null;
347
    }
348
}
349