Passed
Push — main ( e14a5f...bd5a48 )
by Simon
01:26
created

ElasticIndex::deleteIndex()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 2
nop 1
dl 0
loc 12
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * class ElasticIndex|Firesphere\ElasticSearch\Indexes\ElasticIndex is the base for indexing items
4
 *
5
 * @package Firesphere\Elastic\Search
6
 * @author Simon `Firesphere` Erkelens; Marco `Sheepy` Hermo
7
 * @copyright Copyright (c) 2018 - now() Firesphere & Sheepy
8
 */
9
10
namespace Firesphere\ElasticSearch\Indexes;
11
12
use Elastic\Elasticsearch\Exception\ClientResponseException;
13
use Elastic\Elasticsearch\Exception\MissingParameterException;
14
use Elastic\Elasticsearch\Exception\ServerResponseException;
15
use Firesphere\ElasticSearch\Queries\Builders\QueryBuilder;
16
use Firesphere\ElasticSearch\Queries\ElasticQuery;
17
use Firesphere\ElasticSearch\Results\SearchResult;
18
use Firesphere\ElasticSearch\Services\ElasticCoreService;
19
use Firesphere\ElasticSearch\Traits\IndexTraits\BaseIndexTrait;
20
use Firesphere\SearchBackend\Indexes\CoreIndex;
21
use Firesphere\SearchBackend\Traits\LoggerTrait;
22
use Firesphere\SearchBackend\Traits\QueryTraits\QueryFilterTrait;
23
use LogicException;
24
use Psr\Container\NotFoundExceptionInterface;
25
use SilverStripe\Control\HTTPRequest;
26
use SilverStripe\Core\Config\Configurable;
27
use SilverStripe\Core\Extensible;
28
use SilverStripe\Core\Injector\Injectable;
29
use SilverStripe\Core\Injector\Injector;
30
use SilverStripe\Dev\Deprecation;
31
32
/**
33
 * Base for managing a Elastic core.
34
 *
35
 * Base index settings and methods. Should be extended with at least a name for the index.
36
 * This is an abstract class that can not be instantiated on it's own
37
 *
38
 * @package Firesphere\Elastic\Search
39
 */
40
abstract class ElasticIndex extends CoreIndex
41
{
42
    use Extensible;
43
    use Configurable;
44
    use Injectable;
45
    use QueryFilterTrait;
46
    use BaseIndexTrait;
47
    use LoggerTrait;
48
49
    /**
50
     * @var array
51
     */
52
    protected $clientQuery;
53
54
    /**
55
     * @var array Classes to index
56
     */
57
    protected $class = [];
58
59
    public function __construct()
60
    {
61
        $this->client = Injector::inst()->get(ElasticCoreService::class)->getClient();
62
63
        $this->extend('onBeforeInit');
64
        $this->init();
65
        $this->extend('onAfterInit');
66
    }
67
68
69
    /**
70
     * Required to initialise the fields.
71
     * It's loaded in to the non-static properties for backward compatibility with FTS
72
     * Also, it's a tad easier to use this way, loading the other way around would be very
73
     * memory intensive, as updating the config for each item is not efficient
74
     */
75
    public function init()
76
    {
77
        $config = self::config()->get($this->getIndexName());
78
        if (!$config) {
79
            Deprecation::notice('5', 'Please set an index name and use a config yml');
80
        }
81
82
        if (!empty($this->getClasses())) {
83
            if (!$this->usedAllFields) {
84
                Deprecation::notice('5', 'It is advised to use a config YML for most cases');
85
            }
86
87
            return;
88
        }
89
90
        $this->initFromConfig($config);
91
    }
92
93
94
    /**
95
     * @param HTTPRequest|null $request
96
     * @return bool
97
     * @throws ClientResponseException
98
     * @throws MissingParameterException
99
     * @throws NotFoundExceptionInterface
100
     * @throws ServerResponseException
101
     */
102
    public function deleteIndex(HTTPRequest $request): bool
103
    {
104
        $deleteResult = false;
105
        if ($this->shouldClear($request) && $this->indexExists()) {
106
            $this->getLogger()->info(sprintf('Clearing index %s', $this->getIndexName()));
107
            $deleteResult = $this->client
108
                ->indices()
109
                ->delete(['index' => $this->getIndexName()])
110
                ->asBool();
0 ignored issues
show
Bug introduced by
The method asBool() does not exist on Http\Promise\Promise. ( Ignorable by Annotation )

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

110
                ->/** @scrutinizer ignore-call */ asBool();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
111
        }
112
113
        return $deleteResult;
114
    }
115
116
    /**
117
     * @param HTTPRequest $request
118
     * @return bool
119
     */
120
    private function shouldClear(HTTPRequest $request): bool
121
    {
122
        $var = $request->getVar('clear');
123
124
        return !empty($var);
125
    }
126
127
128
    /**
129
     * @return bool
130
     * @throws ClientResponseException
131
     * @throws MissingParameterException
132
     * @throws ServerResponseException
133
     */
134
    public function indexExists(): bool
135
    {
136
        return $this->getClient()
137
            ->indices()
138
            ->exists(['index' => $this->getIndexName()])
139
            ->asBool();
140
    }
141
142
    abstract public function getIndexName();
143
144
    /**
145
     * Get classes
146
     *
147
     * @return array
148
     */
149
    public function getClasses(): array
150
    {
151
        return $this->class;
152
    }
153
154
    /**
155
     * Generate the config from yml if possible
156
     * @param array|null $config
157
     */
158
    protected function initFromConfig($config): void
159
    {
160
        if (!$config || !array_key_exists('Classes', $config)) {
161
            throw new LogicException('No classes or config to index found!');
162
        }
163
164
        $this->setClasses($config['Classes']);
165
166
        // For backward compatibility, copy the config to the protected values
167
        // Saves doubling up further down the line
168
        foreach (parent::$fieldTypes as $type) {
169
            if (array_key_exists($type, $config)) {
170
                $method = 'set' . $type;
171
                if (method_exists($this, $method)) {
172
                    $this->$method($config[$type]);
173
                }
174
            }
175
        }
176
    }
177
178
    /**
179
     * Set the classes
180
     *
181
     * @param array $class
182
     * @return $this
183
     */
184
    public function setClasses($class): self
185
    {
186
        $this->class = $class;
187
188
        return $this;
189
    }
190
191
    /**
192
     * @param ElasticQuery $query
193
     * @return SearchResult
194
     * @throws ClientResponseException
195
     * @throws ServerResponseException
196
     */
197
    public function doSearch(ElasticQuery $query)
198
    {
199
        $this->clientQuery = QueryBuilder::buildQuery($query, $this);
200
201
        $result = $this->client->search($this->clientQuery);
202
203
        $result = new SearchResult($result, $query, $this);
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type Http\Promise\Promise; however, parameter $result of Firesphere\ElasticSearch...chResult::__construct() does only seem to accept Elastic\Elasticsearch\Response\Elasticsearch, 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

203
        $result = new SearchResult(/** @scrutinizer ignore-type */ $result, $query, $this);
Loading history...
204
205
        return $result;
206
    }
207
208
    /**
209
     * Add a class to index or query
210
     * $options is not used anymore, added for backward compatibility
211
     *
212
     * @param $class
213
     * @param array $options unused
214
     * @return $this
215
     */
216
    public function addClass($class, $options = []): self
217
    {
218
        $this->class[] = $class;
219
220
        return $this;
221
    }
222
223
    public function getClientQuery(): array
224
    {
225
        return $this->clientQuery;
226
    }
227
228
    public function setClientQuery(array $clientQuery): void
229
    {
230
        $this->clientQuery = $clientQuery;
231
    }
232
}
233