Completed
Pull Request — master (#534)
by Mantas
09:54 queued 10s
created

AbstractResultsIterator::key()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
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
     * @var array Documents.
23
     */
24
    protected $documents = [];
25
26
    /**
27
     * @var int
28
     */
29
    private $count = 0;
30
31
    /**
32
     * @var array
33
     */
34
    private $aggregations = [];
35
36
    /**
37
     * @var Converter
38
     */
39
    private $converter;
40
41
    /**
42
     * @var Manager
43
     */
44
    private $manager;
45
46
    /**
47
     * Elasticsearch manager configuration.
48
     *
49
     * @var array
50
     */
51
    private $managerConfig = [];
52
53
    /**
54
     * @var string If value is not null then results are scrollable.
55
     */
56
    private $scrollId;
57
58
    /**
59
     * @var string Scroll duration.
60
     */
61
    private $scrollDuration;
62
63
    /**
64
     * Used to count iteration.
65
     *
66
     * @var int
67
     */
68
    private $key = 0;
69
70
    /**
71
     * @param array   $rawData
72
     * @param Manager $manager
73
     * @param array   $scroll
74
     */
75
    public function __construct(
76
        array $rawData,
77
        Manager $manager,
78
        array $scroll = []
79
    ) {
80
        $this->manager = $manager;
81
        $this->converter = $manager->getConverter();
82
        $this->managerConfig = $manager->getConfig();
83
84
        if (isset($scroll['_scroll_id']) && isset($scroll['duration'])) {
85
            $this->scrollId = $scroll['_scroll_id'];
86
            $this->scrollDuration = $scroll['duration'];
87
        }
88
89
        if (isset($rawData['aggregations'])) {
90
            $this->aggregations = &$rawData['aggregations'];
91
        }
92
93
        if (isset($rawData['hits']['hits'])) {
94
            $this->documents = $rawData['hits']['hits'];
95
        }
96
        if (isset($rawData['hits']['total'])) {
97
            $this->count = $rawData['hits']['total'];
98
        }
99
    }
100
101
    /**
102
     * Destructor.
103
     */
104
    public function __destruct()
105
    {
106
        // Clear scroll if initialized
107
        if ($this->isScrollable()) {
108
            $this->manager->clearScroll($this->scrollId);
109
        }
110
    }
111
112
    /**
113
     * @return array
114
     */
115
    protected function getAggregations()
116
    {
117
        return $this->aggregations;
118
    }
119
120
    /**
121
     * @return Manager
122
     */
123
    protected function getManager()
124
    {
125
        return $this->manager;
126
    }
127
128
    /**
129
     * Returns total count of documents.
130
     *
131
     * @return int
132
     */
133
    public function count()
134
    {
135
        return $this->count;
136
    }
137
138
    /**
139
     * Return the current element.
140
     *
141
     * @return mixed
142
     */
143
    public function current()
144
    {
145
        return $this->getDocument($this->key());
146
    }
147
148
    /**
149
     * Move forward to next element.
150
     */
151
    public function next()
152
    {
153
        $this->advanceKey();
154
    }
155
156
    /**
157
     * Return the key of the current element.
158
     *
159
     * @return mixed
160
     */
161
    public function key()
162
    {
163
        return $this->key;
164
    }
165
166
    /**
167
     * Checks if current position is valid.
168
     *
169
     * @return bool
170
     */
171
    public function valid()
172
    {
173
        if (!isset($this->documents)) {
174
            return false;
175
        }
176
177
        $valid = $this->documentExists($this->key());
178
        if ($valid) {
179
            return true;
180
        }
181
182
        $this->page();
183
184
        return $this->documentExists($this->key());
185
    }
186
187
    /**
188
     * Rewind the Iterator to the first element.
189
     */
190
    public function rewind()
191
    {
192
        $this->key = 0;
193
    }
194
195
    /**
196
     * @return bool
197
     */
198
    public function isScrollable()
199
    {
200
        return !empty($this->scrollId);
201
    }
202
203
    /**
204
     * @return array
205
     */
206
    protected function getManagerConfig()
207
    {
208
        return $this->managerConfig;
209
    }
210
211
    /**
212
     * @return Converter
213
     */
214
    protected function getConverter()
215
    {
216
        return $this->converter;
217
    }
218
219
    /**
220
     * Gets document array from the container.
221
     *
222
     * @param mixed $key
223
     *
224
     * @return mixed
225
     */
226
    protected function getDocument($key)
227
    {
228
        if (!$this->documentExists($key)) {
229
            return null;
230
        }
231
232
        return $this->convertDocument($this->documents[$key]);
233
    }
234
235
    /**
236
     * Checks whether document exists in the container.
237
     *
238
     * @param mixed $key
239
     *
240
     * @return bool
241
     */
242
    protected function documentExists($key)
243
    {
244
        return array_key_exists($key, $this->documents);
245
    }
246
247
    /**
248
     * Advances key.
249
     *
250
     * @return $this
251
     */
252
    protected function advanceKey()
253
    {
254
        if ($this->isScrollable() && ($this->documents[$this->key()] == end($this->documents))) {
255
            $this->page();
256
        } else {
257
            $this->key++;
258
        }
259
260
        return $this;
261
    }
262
263
    /**
264
     * Rewind's the iteration and returns first result.
265
     *
266
     * @return mixed|null
267
     */
268
    public function first()
269
    {
270
        $this->rewind();
271
272
        return $this->getDocument($this->key());
273
    }
274
275
    /**
276
     * Advances scan page.
277
     *
278
     * @return $this
279
     */
280
    protected function page()
281
    {
282
        if ($this->key() == $this->count() || !$this->isScrollable()) {
283
            return $this;
284
        }
285
286
        $raw = $this->manager->scroll($this->scrollId, $this->scrollDuration, Result::RESULTS_RAW);
287
        $this->rewind();
288
        $this->scrollId = $raw['_scroll_id'];
289
        $this->documents = $raw['hits']['hits'];
290
291
        return $this;
292
    }
293
294
    /**
295
     * Returns score of current hit.
296
     *
297
     * @return int
298
     */
299
    public function getHitScore()
300
    {
301
        if (!$this->valid()) {
302
            throw new \LogicException('Hit score is available only while iterating over results.');
303
        }
304
305
        if (!isset($this->documents[$this->key]['_score'])) {
306
            return null;
307
        }
308
309
        return $this->documents[$this->key]['_score'];
310
    }
311
312
    /**
313
     * Converts raw array to document object or array, depends on iterator type.
314
     *
315
     * @param array $document
316
     *
317
     * @return object|array
318
     */
319
    abstract protected function convertDocument(array $document);
320
}
321