Completed
Pull Request — master (#476)
by
unknown
02:36
created

AbstractResultsIterator::offsetExists()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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