Completed
Push — master ( 8a6a3b...86b2ed )
by Nicolas
03:28
created

Settings::get()   B

Complexity

Conditions 8
Paths 7

Size

Total Lines 36

Duplication

Lines 19
Ratio 52.78 %

Importance

Changes 0
Metric Value
dl 19
loc 36
rs 8.0995
c 0
b 0
f 0
cc 8
nc 7
nop 1
1
<?php
2
namespace Elastica\Index;
3
4
use Elastica\Exception\NotFoundException;
5
use Elastica\Exception\ResponseException;
6
use Elastica\Index as BaseIndex;
7
use Elastica\Request;
8
9
/**
10
 * Elastica index settings object.
11
 *
12
 * All settings listed in the update settings API (https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html)
13
 * can be changed on a running indices. To make changes like the merge policy (https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-merge.html)
14
 * the index has to be closed first and reopened after the call
15
 *
16
 * @author Nicolas Ruflin <[email protected]>
17
 *
18
 * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html
19
 * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-merge.html
20
 */
21
class Settings
22
{
23
    const DEFAULT_REFRESH_INTERVAL = '1s';
24
25
    const DEFAULT_NUMBER_OF_REPLICAS = 1;
26
27
    const DEFAULT_NUMBER_OF_SHARDS = 5;
28
29
    /**
30
     * Response.
31
     *
32
     * @var \Elastica\Response Response object
33
     */
34
    protected $_response;
35
36
    /**
37
     * Stats info.
38
     *
39
     * @var array Stats info
40
     */
41
    protected $_data = [];
42
43
    /**
44
     * Index.
45
     *
46
     * @var \Elastica\Index Index object
47
     */
48
    protected $_index;
49
50
    /**
51
     * Construct.
52
     *
53
     * @param \Elastica\Index $index Index object
54
     */
55
    public function __construct(BaseIndex $index)
56
    {
57
        $this->_index = $index;
58
    }
59
60
    /**
61
     * Returns the current settings of the index.
62
     *
63
     * If param is set, only specified setting is return.
64
     * 'index.' is added in front of $setting.
65
     *
66
     * @param string $setting OPTIONAL Setting name to return
67
     *
68
     * @return array|string|null Settings data
69
     *
70
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html
71
     */
72
    public function get($setting = '')
73
    {
74
        $requestData = $this->request()->getData();
75
        $data = reset($requestData);
76
77
        if (empty($data['settings']) || empty($data['settings']['index'])) {
78
            // should not append, the request should throw a ResponseException
79
            throw new NotFoundException('Index '.$this->getIndex()->getName().' not found');
80
        }
81
        $settings = $data['settings']['index'];
82
83
        if (!$setting) {
84
            // return all array
85
            return $settings;
86
        }
87
88 View Code Duplication
        if (isset($settings[$setting])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
89
            return $settings[$setting];
90
        } else {
91
            if (strpos($setting, '.') !== false) {
92
                // translate old dot-notation settings to nested arrays
93
                $keys = explode('.', $setting);
94
                foreach ($keys as $key) {
95
                    if (isset($settings[$key])) {
96
                        $settings = $settings[$key];
97
                    } else {
98
                        return;
99
                    }
100
                }
101
102
                return $settings;
103
            }
104
105
            return;
106
        }
107
    }
108
109
    /**
110
     * Returns a setting interpreted as a bool.
111
     *
112
     * One can use a real bool, int(0), int(1) to set bool settings.
113
     * But Elasticsearch stores and returns all settings as strings and does
114
     * not normalize bool values. This method ensures a bool is returned for
115
     * whichever string representation is used like 'true', '1', 'on', 'yes'.
116
     *
117
     * @param string $setting Setting name to return
118
     *
119
     * @return bool
120
     */
121
    public function getBool($setting)
122
    {
123
        $data = $this->get($setting);
124
125
        return 'true' === $data || '1' === $data || 'on' === $data || 'yes' === $data;
126
    }
127
128
    /**
129
     * Sets the number of replicas.
130
     *
131
     * @param int $replicas Number of replicas
132
     *
133
     * @return \Elastica\Response Response object
134
     */
135
    public function setNumberOfReplicas($replicas)
136
    {
137
        return $this->set(['number_of_replicas' => (int) $replicas]);
138
    }
139
140
    /**
141
     * Returns the number of replicas.
142
     *
143
     * If no number of replicas is set, the default number is returned
144
     *
145
     * @return int The number of replicas
146
     */
147
    public function getNumberOfReplicas()
148
    {
149
        $replicas = $this->get('number_of_replicas');
150
151
        if (null === $replicas) {
152
            $replicas = self::DEFAULT_NUMBER_OF_REPLICAS;
153
        }
154
155
        return $replicas;
156
    }
157
158
    /**
159
     * Returns the number of shards.
160
     *
161
     * If no number of shards is set, the default number is returned
162
     *
163
     * @return int The number of shards
164
     */
165
    public function getNumberOfShards()
166
    {
167
        $shards = $this->get('number_of_shards');
168
169
        if (null === $shards) {
170
            $shards = self::DEFAULT_NUMBER_OF_SHARDS;
171
        }
172
173
        return $shards;
174
    }
175
176
    /**
177
     * Sets the index to read only.
178
     *
179
     * @param bool $readOnly (default = true)
180
     *
181
     * @return \Elastica\Response
182
     */
183
    public function setReadOnly($readOnly = true)
184
    {
185
        return $this->set(['blocks.read_only' => $readOnly]);
186
    }
187
188
    /**
189
     * @return bool
190
     */
191
    public function getReadOnly()
192
    {
193
        return $this->getBool('blocks.read_only');
194
    }
195
196
    /**
197
     * @return bool
198
     */
199
    public function getBlocksRead()
200
    {
201
        return $this->getBool('blocks.read');
202
    }
203
204
    /**
205
     * @param bool $state OPTIONAL (default = true)
206
     *
207
     * @return \Elastica\Response
208
     */
209
    public function setBlocksRead($state = true)
210
    {
211
        return $this->set(['blocks.read' => $state]);
212
    }
213
214
    /**
215
     * @return bool
216
     */
217
    public function getBlocksWrite()
218
    {
219
        return $this->getBool('blocks.write');
220
    }
221
222
    /**
223
     * @param bool $state OPTIONAL (default = true)
224
     *
225
     * @return \Elastica\Response
226
     */
227
    public function setBlocksWrite($state = true)
228
    {
229
        return $this->set(['blocks.write' => $state]);
230
    }
231
232
    /**
233
     * @return bool
234
     */
235
    public function getBlocksMetadata()
236
    {
237
        // When blocks.metadata is enabled, reading the settings is not possible anymore.
238
        // So when a cluster_block_exception happened it must be enabled.
239
        try {
240
            return $this->getBool('blocks.metadata');
241
        } catch (ResponseException $e) {
242
            if ($e->getResponse()->getFullError()['type'] === 'cluster_block_exception') {
243
                return true;
244
            }
245
246
            throw $e;
247
        }
248
    }
249
250
    /**
251
     * Set to true to disable index metadata reads and writes.
252
     *
253
     * @param bool $state OPTIONAL (default = true)
254
     *
255
     * @return \Elastica\Response
256
     */
257
    public function setBlocksMetadata($state = true)
258
    {
259
        return $this->set(['blocks.metadata' => $state]);
260
    }
261
262
    /**
263
     * Sets the index refresh interval.
264
     *
265
     * Value can be for example 3s for 3 seconds or
266
     * 5m for 5 minutes. -1 to disabled refresh.
267
     *
268
     * @param string $interval Duration of the refresh interval
269
     *
270
     * @return \Elastica\Response Response object
271
     */
272
    public function setRefreshInterval($interval)
273
    {
274
        return $this->set(['refresh_interval' => $interval]);
275
    }
276
277
    /**
278
     * Returns the refresh interval.
279
     *
280
     * If no interval is set, the default interval is returned
281
     *
282
     * @return string Refresh interval
283
     */
284
    public function getRefreshInterval()
285
    {
286
        $interval = $this->get('refresh_interval');
287
288
        if (empty($interval)) {
289
            $interval = self::DEFAULT_REFRESH_INTERVAL;
290
        }
291
292
        return $interval;
293
    }
294
295
    /**
296
     * Sets the specific merge policies.
297
     *
298
     * To have this changes made the index has to be closed and reopened
299
     *
300
     * @param string $key   Merge policy key (for ex. expunge_deletes_allowed)
301
     * @param string $value
302
     *
303
     * @return \Elastica\Response
304
     *
305
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-merge.html
306
     */
307
    public function setMergePolicy($key, $value)
308
    {
309
        $this->getIndex()->close();
310
        $response = $this->set(['merge.policy.'.$key => $value]);
311
        $this->getIndex()->open();
312
313
        return $response;
314
    }
315
316
    /**
317
     * Returns the specific merge policy value.
318
     *
319
     * @param string $key Merge policy key (for ex. expunge_deletes_allowed)
320
     *
321
     * @return string Refresh interval
322
     *
323
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-merge.html
324
     */
325
    public function getMergePolicy($key)
326
    {
327
        $settings = $this->get();
328
        if (isset($settings['merge']['policy'][$key])) {
329
            return $settings['merge']['policy'][$key];
330
        }
331
332
        return;
333
    }
334
335
    /**
336
     * Can be used to set/update settings.
337
     *
338
     * @param array $data Arguments
339
     *
340
     * @return \Elastica\Response Response object
341
     */
342
    public function set(array $data)
343
    {
344
        return $this->request($data, Request::PUT);
345
    }
346
347
    /**
348
     * Returns the index object.
349
     *
350
     * @return \Elastica\Index Index object
351
     */
352
    public function getIndex()
353
    {
354
        return $this->_index;
355
    }
356
357
    /**
358
     * Updates the given settings for the index.
359
     *
360
     * With elasticsearch 0.16 the following settings are supported
361
     * - index.term_index_interval
362
     * - index.term_index_divisor
363
     * - index.translog.flush_threshold_ops
364
     * - index.translog.flush_threshold_size
365
     * - index.translog.flush_threshold_period
366
     * - index.refresh_interval
367
     * - index.merge.policy
368
     * - index.auto_expand_replicas
369
     *
370
     * @param array  $data   OPTIONAL Data array
371
     * @param string $method OPTIONAL Transfer method (default = \Elastica\Request::GET)
372
     *
373
     * @return \Elastica\Response Response object
374
     */
375
    public function request(array $data = [], $method = Request::GET)
376
    {
377
        $path = '_settings';
378
379
        if (!empty($data)) {
380
            $data = ['index' => $data];
381
        }
382
383
        return $this->getIndex()->request($path, $method, $data);
384
    }
385
}
386