Completed
Pull Request — master (#514)
by Mantas
03:31
created

AbstractResultsIterator::next()   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
     * @return array
103
     */
104
    protected function getAggregations()
105
    {
106
        return $this->aggregations;
107
    }
108
109
    /**
110
     * @return Manager
111
     */
112
    protected function getManager()
113
    {
114
        return $this->manager;
115
    }
116
117
    /**
118
     * Returns total count of documents.
119
     *
120
     * @return int
121
     */
122
    public function count()
123
    {
124
        return $this->count;
125
    }
126
127
    /**
128
     * Return the current element.
129
     *
130
     * @return mixed
131
     */
132
    public function current()
133
    {
134
        return $this->getDocument($this->key());
135
    }
136
137
    /**
138
     * Move forward to next element.
139
     */
140
    public function next()
141
    {
142
        $this->advanceKey();
143
    }
144
145
    /**
146
     * Return the key of the current element.
147
     *
148
     * @return mixed
149
     */
150
    public function key()
151
    {
152
        return $this->key;
153
    }
154
155
    /**
156
     * Checks if current position is valid.
157
     *
158
     * @return bool
159
     */
160
    public function valid()
161
    {
162
        if (!isset($this->documents)) {
163
            return false;
164
        }
165
166
        $valid = $this->documentExists($this->key());
167
        if ($valid) {
168
            return true;
169
        }
170
171
        $this->page();
172
173
        return $this->documentExists($this->key());
174
    }
175
176
    /**
177
     * Rewind the Iterator to the first element.
178
     */
179
    public function rewind()
180
    {
181
        $this->key = 0;
182
    }
183
184
    /**
185
     * @return bool
186
     */
187
    public function isScrollable()
188
    {
189
        return !empty($this->scrollId);
190
    }
191
192
    /**
193
     * @return array
194
     */
195
    protected function getManagerConfig()
196
    {
197
        return $this->managerConfig;
198
    }
199
200
    /**
201
     * @return Converter
202
     */
203
    protected function getConverter()
204
    {
205
        return $this->converter;
206
    }
207
208
    /**
209
     * Gets document array from the container.
210
     *
211
     * @param mixed $key
212
     *
213
     * @return mixed
214
     */
215
    protected function getDocument($key)
216
    {
217
        if (!$this->documentExists($key)) {
218
            return null;
219
        }
220
221
        return $this->convertDocument($this->documents[$key]);
222
    }
223
224
    /**
225
     * Checks whether document exists in the container.
226
     *
227
     * @param mixed $key
228
     *
229
     * @return bool
230
     */
231
    protected function documentExists($key)
232
    {
233
        return array_key_exists($key, $this->documents);
234
    }
235
236
    /**
237
     * Advances key.
238
     *
239
     * @return $this
240
     */
241
    protected function advanceKey()
242
    {
243
        if ($this->isScrollable() && ($this->documents[$this->key()] == end($this->documents))) {
244
            $this->page();
245
        } else {
246
            $this->key++;
247
        }
248
249
        return $this;
250
    }
251
252
    /**
253
     * Rewind's the iteration and returns first result.
254
     *
255
     * @return mixed|null
256
     */
257
    public function first()
258
    {
259
        $this->rewind();
260
261
        return $this->getDocument($this->key());
262
    }
263
264
    /**
265
     * Advances scan page.
266
     *
267
     * @return $this
268
     */
269
    protected function page()
270
    {
271
        if ($this->key() == $this->count() || !$this->isScrollable()) {
272
            return $this;
273
        }
274
275
        $raw = $this->manager->scroll($this->scrollId, $this->scrollDuration, Result::RESULTS_RAW);
276
        $this->rewind();
277
        $this->scrollId = $raw['_scroll_id'];
278
        $this->documents = $raw['hits']['hits'];
279
280
        return $this;
281
    }
282
283
    /**
284
     * Converts raw array to document object or array, depends on iterator type.
285
     *
286
     * @param array $document
287
     *
288
     * @return object|array
289
     */
290
    abstract protected function convertDocument(array $document);
291
}
292