Completed
Pull Request — master (#678)
by Simonas
03:24
created

AbstractResultsIterator::getRaw()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
/*
4
 * This file is part of the ONGR package.
5
 *
6
 * (c) NFQ Technologies UAB <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace ONGR\ElasticsearchBundle\Result;
13
14
use ONGR\ElasticsearchBundle\Service\Manager;
15
16
/**
17
 * Class AbstractResultsIterator.
18
 */
19
abstract class AbstractResultsIterator implements \Countable, \Iterator
20
{
21
    /**
22
     * Raw data returned from elasticsearch.
23
     *
24
     * @var array
25
     */
26
    private $raw;
27
28
    /**
29
     * @var array Documents.
30
     */
31
    protected $documents = [];
32
33
    /**
34
     * @var int
35
     */
36
    private $count = 0;
37
38
    /**
39
     * @var array
40
     */
41
    private $aggregations = [];
42
43
    /**
44
     * @var Converter
45
     */
46
    private $converter;
47
48
    /**
49
     * @var Manager
50
     */
51
    private $manager;
52
53
    /**
54
     * Elasticsearch manager configuration.
55
     *
56
     * @var array
57
     */
58
    private $managerConfig = [];
59
60
    /**
61
     * @var string If value is not null then results are scrollable.
62
     */
63
    private $scrollId;
64
65
    /**
66
     * @var string Scroll duration.
67
     */
68
    private $scrollDuration;
69
70
    /**
71
     * Used to count iteration.
72
     *
73
     * @var int
74
     */
75
    private $key = 0;
76
77
    /**
78
     * @param array   $rawData
79
     * @param Manager $manager
80
     * @param array   $scroll
81
     */
82
    public function __construct(
83
        array $rawData,
84
        Manager $manager,
85
        array $scroll = []
86
    ) {
87
        $this->manager = $manager;
88
        $this->converter = $manager->getConverter();
89
        $this->managerConfig = $manager->getConfig();
90
91
        if (isset($scroll['_scroll_id']) && isset($scroll['duration'])) {
92
            $this->scrollId = $scroll['_scroll_id'];
93
            $this->scrollDuration = $scroll['duration'];
94
        }
95
96
        if (isset($rawData['aggregations'])) {
97
            $this->aggregations = &$rawData['aggregations'];
98
        }
99
100
        if (isset($rawData['hits']['hits'])) {
101
            $this->documents = $rawData['hits']['hits'];
102
        }
103
        if (isset($rawData['hits']['total'])) {
104
            $this->count = $rawData['hits']['total'];
105
        }
106
    }
107
108
    /**
109
     * Destructor.
110
     */
111
    public function __destruct()
112
    {
113
        // Clear scroll if initialized
114
        if ($this->isScrollable()) {
115
            $this->manager->clearScroll($this->scrollId);
116
        }
117
    }
118
119
    /**
120
     * @return array
121
     */
122
    public function getRaw()
123
    {
124
        return $this->raw;
125
    }
126
127
    /**
128
     * @return array
129
     */
130
    public function getAggregations()
131
    {
132
        return $this->aggregations;
133
    }
134
135
    /**
136
     * Returns specific aggregation by name.
137
     *
138
     * @param string $name
139
     *
140
     * @return array
141
     */
142
    public function getAggregation($name)
143
    {
144
        if (isset($this->aggregations[$name])) {
145
            return $this->aggregations[$name];
146
        }
147
        return null;
148
    }
149
150
    /**
151
     * @return Manager
152
     */
153
    protected function getManager()
154
    {
155
        return $this->manager;
156
    }
157
158
    /**
159
     * Returns total count of documents.
160
     *
161
     * @return int
162
     */
163
    public function count()
164
    {
165
        return $this->count;
166
    }
167
168
    /**
169
     * Return the current element.
170
     *
171
     * @return mixed
172
     */
173
    public function current()
174
    {
175
        return $this->getDocument($this->key());
176
    }
177
178
    /**
179
     * Move forward to next element.
180
     */
181
    public function next()
182
    {
183
        $this->advanceKey();
184
    }
185
186
    /**
187
     * Return the key of the current element.
188
     *
189
     * @return mixed
190
     */
191
    public function key()
192
    {
193
        return $this->key;
194
    }
195
196
    /**
197
     * Checks if current position is valid.
198
     *
199
     * @return bool
200
     */
201
    public function valid()
202
    {
203
        if (!isset($this->documents)) {
204
            return false;
205
        }
206
207
        $valid = $this->documentExists($this->key());
208
        if ($valid) {
209
            return true;
210
        }
211
212
        $this->page();
213
214
        return $this->documentExists($this->key());
215
    }
216
217
    /**
218
     * Rewind the Iterator to the first element.
219
     */
220
    public function rewind()
221
    {
222
        $this->key = 0;
223
    }
224
225
    /**
226
     * @return bool
227
     */
228
    public function isScrollable()
229
    {
230
        return !empty($this->scrollId);
231
    }
232
233
    /**
234
     * @return array
235
     */
236
    protected function getManagerConfig()
237
    {
238
        return $this->managerConfig;
239
    }
240
241
    /**
242
     * @return Converter
243
     */
244
    protected function getConverter()
245
    {
246
        return $this->converter;
247
    }
248
249
    /**
250
     * Gets document array from the container.
251
     *
252
     * @param mixed $key
253
     *
254
     * @return mixed
255
     */
256
    protected function getDocument($key)
257
    {
258
        if (!$this->documentExists($key)) {
259
            return null;
260
        }
261
262
        return $this->convertDocument($this->documents[$key]);
263
    }
264
265
    /**
266
     * Checks whether document exists in the container.
267
     *
268
     * @param mixed $key
269
     *
270
     * @return bool
271
     */
272
    protected function documentExists($key)
273
    {
274
        return array_key_exists($key, $this->documents);
275
    }
276
277
    /**
278
     * Advances key.
279
     *
280
     * @return $this
281
     */
282
    protected function advanceKey()
283
    {
284
        if ($this->isScrollable() && ($this->documents[$this->key()] == end($this->documents))) {
285
            $this->page();
286
        } else {
287
            $this->key++;
288
        }
289
290
        return $this;
291
    }
292
293
    /**
294
     * Rewind's the iteration and returns first result.
295
     *
296
     * @return mixed|null
297
     */
298
    public function first()
299
    {
300
        $this->rewind();
301
302
        return $this->getDocument($this->key());
303
    }
304
305
    /**
306
     * Advances scan page.
307
     *
308
     * @return $this
309
     */
310
    protected function page()
311
    {
312
        if ($this->key() == $this->count() || !$this->isScrollable()) {
313
            return $this;
314
        }
315
316
        $raw = $this->manager->scroll($this->scrollId, $this->scrollDuration, Result::RESULTS_RAW);
317
        $this->rewind();
318
        $this->scrollId = $raw['_scroll_id'];
319
        $this->documents = $raw['hits']['hits'];
320
321
        return $this;
322
    }
323
324
    /**
325
     * Returns score of current hit.
326
     *
327
     * @return int
328
     */
329 View Code Duplication
    public function getDocumentScore()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
330
    {
331
        if (!$this->valid()) {
332
            throw new \LogicException('Document score is available only while iterating over results.');
333
        }
334
335
        if (!isset($this->documents[$this->key]['_score'])) {
336
            return null;
337
        }
338
339
        return $this->documents[$this->key]['_score'];
340
    }
341
342
    /**
343
    * Returns sort of current hit.
344
    *
345
    * @return mixed
346
    */
347 View Code Duplication
    public function getDocumentSort()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
348
    {
349
        if (!$this->valid()) {
350
            throw new \LogicException('Document sort is available only while iterating over results.');
351
        }
352
353
        if (!isset($this->documents[$this->key]['sort'])) {
354
            return null;
355
        }
356
357
        return $this->documents[$this->key]['sort'][0];
358
    }
359
360
    /**
361
     * Converts raw array to document object or array, depends on iterator type.
362
     *
363
     * @param array $document
364
     *
365
     * @return object|array
366
     */
367
    abstract protected function convertDocument(array $document);
368
}
369