Completed
Push — master ( d3ac62...0cb203 )
by Federico
02:08
created

lib/Elastica/Scroll.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Elastica;
4
5
/**
6
 * Scroll Iterator.
7
 *
8
 * @author Manuel Andreo Garcia <[email protected]>
9
 *
10
 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-scroll.html
11
 */
12
class Scroll implements \Iterator
13
{
14
    /**
15
     * @var string
16
     */
17
    public $expiryTime;
18
19
    /**
20
     * @var Search
21
     */
22
    protected $_search;
23
24
    /**
25
     * @var string|null
26
     */
27
    protected $_nextScrollId;
28
29
    /**
30
     * @var ResultSet|null
31
     */
32
    protected $_currentResultSet;
33
34
    /**
35
     * 0: scroll<br>
36
     * 1: scroll id.
37
     *
38
     * @var array
39
     */
40
    protected $_options = [null, null];
41
42
    private $totalPages = 0;
43
    private $currentPage = 0;
44
45
    /**
46
     * Constructor.
47
     *
48
     * @param Search $search
49
     * @param string $expiryTime
50
     */
51
    public function __construct(Search $search, $expiryTime = '1m')
52
    {
53
        $this->_search = $search;
54
        $this->expiryTime = $expiryTime;
55
    }
56
57
    /**
58
     * Returns current result set.
59
     *
60
     * @see http://php.net/manual/en/iterator.current.php
61
     *
62
     * @return ResultSet
63
     */
64
    public function current()
65
    {
66
        return $this->_currentResultSet;
67
    }
68
69
    /**
70
     * Next scroll search.
71
     *
72
     * @see http://php.net/manual/en/iterator.next.php
73
     */
74
    public function next()
75
    {
76
        if ($this->currentPage < $this->totalPages) {
77
            $this->_saveOptions();
78
79
            $this->_search->setOption(Search::OPTION_SCROLL, $this->expiryTime);
80
            $this->_search->setOption(Search::OPTION_SCROLL_ID, $this->_nextScrollId);
81
82
            $this->_setScrollId($this->_search->search());
83
84
            $this->_revertOptions();
85
        } else {
86
            // If there are no pages left, we do not need to query ES.
87
            $this->clear();
88
        }
89
    }
90
91
    /**
92
     * Returns scroll id.
93
     *
94
     * @see http://php.net/manual/en/iterator.key.php
95
     *
96
     * @return string
97
     */
98
    public function key()
99
    {
100
        return $this->_nextScrollId;
101
    }
102
103
    /**
104
     * Returns true if current result set contains at least one hit.
105
     *
106
     * @see http://php.net/manual/en/iterator.valid.php
107
     *
108
     * @return bool
109
     */
110
    public function valid()
111
    {
112
        return null !== $this->_nextScrollId;
113
    }
114
115
    /**
116
     * Initial scroll search.
117
     *
118
     * @see http://php.net/manual/en/iterator.rewind.php
119
     */
120
    public function rewind()
121
    {
122
        // reset state
123
        $this->_options = [null, null];
124
        $this->currentPage = 0;
125
126
        // initial search
127
        $this->_saveOptions();
128
129
        $this->_search->setOption(Search::OPTION_SCROLL, $this->expiryTime);
130
        $this->_search->setOption(Search::OPTION_SCROLL_ID, null);
131
        $this->_setScrollId($this->_search->search());
132
133
        $this->_revertOptions();
134
    }
135
136
    /**
137
     * Cleares the search context on ES and marks this Scroll instance as finished.
138
     */
139
    public function clear()
140
    {
141
        if (null !== $this->_nextScrollId) {
142
            $this->_search->getClient()->request(
143
                '_search/scroll',
144
                Request::DELETE,
145
                [Search::OPTION_SCROLL_ID => [$this->_nextScrollId]]
146
            );
147
148
            // Reset scroll ID so valid() returns false.
149
            $this->_nextScrollId = null;
150
            $this->_currentResultSet = null;
151
        }
152
    }
153
154
    /**
155
     * Prepares Scroll for next request.
156
     *
157
     * @param ResultSet $resultSet
158
     */
159
    protected function _setScrollId(ResultSet $resultSet)
160
    {
161
        if (0 === $this->currentPage) {
162
            $this->totalPages = $resultSet->count() > 0 ? ceil($resultSet->getTotalHits() / $resultSet->count()) : 0;
163
        }
164
165
        $this->_currentResultSet = $resultSet;
166
        ++$this->currentPage;
167
        $this->_nextScrollId = $resultSet->getResponse()->isOk() && $resultSet->count() > 0 ? $resultSet->getResponse()->getScrollId() : null;
168
    }
169
170
    /**
171
     * Save all search options manipulated by Scroll.
172
     */
173
    protected function _saveOptions()
174
    {
175 View Code Duplication
        if ($this->_search->hasOption(Search::OPTION_SCROLL)) {
0 ignored issues
show
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...
176
            $this->_options[0] = $this->_search->getOption(Search::OPTION_SCROLL);
177
        }
178
179 View Code Duplication
        if ($this->_search->hasOption(Search::OPTION_SCROLL_ID)) {
0 ignored issues
show
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...
180
            $this->_options[1] = $this->_search->getOption(Search::OPTION_SCROLL_ID);
181
        }
182
    }
183
184
    /**
185
     * Revert search options to previously saved state.
186
     */
187
    protected function _revertOptions()
188
    {
189
        $this->_search->setOption(Search::OPTION_SCROLL, $this->_options[0]);
190
        $this->_search->setOption(Search::OPTION_SCROLL_ID, $this->_options[1]);
191
    }
192
}
193