Completed
Pull Request — master (#13)
by Steven
04:02
created

TNTSearchEngine::filters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
3
namespace TeamTNT\Scout\Engines;
4
5
use Illuminate\Database\Eloquent\Collection;
6
use Laravel\Scout\Builder;
7
use Laravel\Scout\Engines\Engine;
8
use TeamTNT\TNTSearch\TNTSearch;
9
10
class TNTSearchEngine extends Engine
11
{
12
    /**
13
     * Create a new engine instance.
14
     *
15
     * @param TNTSearch $tnt
16
     */
17
    public function __construct(TNTSearch $tnt)
18
    {
19
        $this->tnt = $tnt;
0 ignored issues
show
Bug introduced by
The property tnt does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
20
    }
21
22
    /**
23
     * Update the given model in the index.
24
     *
25
     * @param Collection $models
26
     *
27
     * @return void
28
     */
29
    public function update($models)
30
    {
31
        $this->initIndex($models->first());
32
33
        $models->each(function ($model) {
34
            $searchableFields = $model->toSearchableArray();
35
36
            $this->tnt->selectIndex("{$this->getIndexName($model)}.index");
37
            $index = $this->tnt->getIndex();
38
            $index->setPrimaryKey($model->getKeyName());
39
40
            if ($model->getKey()) {
41
                $index->update($model->getKey(), $searchableFields);
42
            } else {
43
                $index->insert($searchableFields);
44
            }
45
        });
46
    }
47
48
    /**
49
     * Remove the given model from the index.
50
     *
51
     * @param Collection $models
52
     *
53
     * @return void
54
     */
55
    public function delete($models)
56
    {
57
        $this->initIndex($models->first());
58
        $models->each(function ($model) {
59
            $this->tnt->selectIndex("{$this->getIndexName($model)}.index");
60
            $index = $this->tnt->getIndex();
61
            $index->setPrimaryKey($model->getKeyName());
62
            $index->delete($model->id);
63
        });
64
    }
65
66
    /**
67
     * Perform the given search on the engine.
68
     *
69
     * @param Builder $builder
70
     *
71
     * @return mixed
72
     */
73
    public function search(Builder $builder)
74
    {
75
        return $this->performSearch($builder);
76
    }
77
78
    /**
79
     * Perform the given search on the engine.
80
     *
81
     * @param Builder $builder
82
     * @param int     $perPage
83
     * @param int     $page
84
     *
85
     * @return mixed
86
     */
87
    public function paginate(Builder $builder, $perPage, $page)
88
    {
89
        $builder->limit = 500;
90
        $results = $this->performSearch($builder);
91
        $chunks = array_chunk($results['ids'], $perPage);
92
        if (array_key_exists($page - 1, $chunks)) {
93
            $results['ids'] = $chunks[$page - 1];
94
        } else {
95
            $results['ids'] = end($chunks);
96
        }
97
98
        return $results;
99
    }
100
101
    /**
102
     * Perform the given search on the engine.
103
     *
104
     * @param Builder $builder
105
     * @param array   $options
106
     *
107
     * @return mixed
108
     */
109
    protected function performSearch(Builder $builder, array $options = [])
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
110
    {
111
        $model = $builder->model;
112
        $index = $builder->index ?: $this->getIndexName($model);
113
        $limit = $builder->limit ?: 10;
114
        $this->tnt->selectIndex("{$index}.index");
115
116
        return $this->tnt->search($builder->query, $limit);
117
    }
118
119
    /**
120
     * Get the filter array for the query.
121
     *
122
     * @param Builder $builder
123
     *
124
     * @return array
125
     */
126
    protected function filters(Builder $builder)
127
    {
128
        return collect($builder->wheres)->map(function ($value, $key) {
129
            return $key.'='.$value;
130
        })->values()->all();
131
    }
132
133
    /**
134
     * Map the given results to instances of the given model.
135
     *
136
     * @param mixed                               $results
137
     * @param \Illuminate\Database\Eloquent\Model $model
138
     *
139
     * @return Collection
140
     */
141
    public function map($results, $model)
142
    {
143
        if (count($results['ids']) === 0) {
144
            return Collection::make();
145
        }
146
        $keys = collect($results['ids']);
147
        $models = $model->whereIn(
148
            $model->getKeyName(), $keys
149
        )->get()->keyBy($model->getKeyName());
150
151
        return collect($results['ids'])->map(function ($hit) use ($models) {
152
            return $models[$hit];
153
        });
154
    }
155
156
    public function initIndex($model)
157
    {
158
        $indexName = $this->getIndexName($model);
159
160
        if (!file_exists($this->tnt->config['storage']."/{$indexName}.index")) {
161
            $indexer = $this->tnt->createIndex("$indexName.index");
162
            $indexer->setDatabaseHandle($model->getConnection()->getPdo());
163
            $indexer->disableOutput = true;
164
            $indexer->setPrimaryKey($model->getKeyName());
165
            $fields = implode(', ', array_keys($model->toSearchableArray()));
166
            $indexer->query("SELECT {$model->getKeyName()}, $fields FROM $indexName WHERE {$model->getKeyName()} = {$model->getKey()}");
167
            $indexer->run();
168
        }
169
    }
170
171
    /**
172
     * @param $model
173
     * @return mixed
174
     */
175
    private function getIndexName($model)
176
    {
177
        if (property_exists($model, 'searchable_index')) {
178
            return $model->searchable_index;
179
        }
180
181
        return $model->searchableAs();
182
    }
183
}
184