1: <?php
2:
3: declare(strict_types=1);
4:
5: /**
6: * Copyright OpenSearch Contributors
7: * SPDX-License-Identifier: Apache-2.0
8: *
9: * OpenSearch PHP client
10: *
11: * @link https://github.com/opensearch-project/opensearch-php/
12: * @copyright Copyright (c) Elasticsearch B.V (https://www.elastic.co)
13: * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
14: * @license https://www.gnu.org/licenses/lgpl-2.1.html GNU Lesser General Public License, Version 2.1
15: *
16: * Licensed to Elasticsearch B.V under one or more agreements.
17: * Elasticsearch B.V licenses this file to you under the Apache 2.0 License or
18: * the GNU Lesser General Public License, Version 2.1, at your option.
19: * See the LICENSE file in the project root for more information.
20: */
21:
22: namespace OpenSearch\Helper\Iterators;
23:
24: use OpenSearch\Client;
25: use Iterator;
26:
27: class SearchResponseIterator implements Iterator
28: {
29: /**
30: * @var Client
31: */
32: private $client;
33:
34: /**
35: * @var array
36: */
37: private $params;
38:
39: /**
40: * @var int
41: */
42: private $current_key = 0;
43:
44: /**
45: * @var array
46: */
47: private $current_scrolled_response;
48:
49: /**
50: * @var string|null
51: */
52: private $scroll_id;
53:
54: /**
55: * @var string duration
56: */
57: private $scroll_ttl;
58:
59: /**
60: * Constructor
61: *
62: * @param Client $client
63: * @param array $search_params Associative array of parameters
64: * @see Client::search()
65: */
66: public function __construct(Client $client, array $search_params)
67: {
68: $this->client = $client;
69: $this->params = $search_params;
70:
71: if (isset($search_params['scroll'])) {
72: $this->scroll_ttl = $search_params['scroll'];
73: }
74: }
75:
76: /**
77: * Destructor
78: */
79: public function __destruct()
80: {
81: $this->clearScroll();
82: }
83:
84: /**
85: * Sets the time to live duration of a scroll window
86: *
87: * @param string $time_to_live
88: * @return $this
89: */
90: public function setScrollTimeout(string $time_to_live): SearchResponseIterator
91: {
92: $this->scroll_ttl = $time_to_live;
93: return $this;
94: }
95:
96: /**
97: * Clears the current scroll window if there is a scroll_id stored
98: *
99: * @return void
100: */
101: private function clearScroll(): void
102: {
103: if (!empty($this->scroll_id)) {
104: $this->client->clearScroll(
105: array(
106: 'scroll_id' => $this->scroll_id,
107: 'client' => array(
108: 'ignore' => 404
109: )
110: )
111: );
112: $this->scroll_id = null;
113: }
114: }
115:
116: /**
117: * Rewinds the iterator by performing the initial search.
118: *
119: * @return void
120: * @see Iterator::rewind()
121: */
122: public function rewind(): void
123: {
124: $this->clearScroll();
125: $this->current_key = 0;
126: $this->current_scrolled_response = $this->client->search($this->params);
127: $this->scroll_id = $this->current_scrolled_response['_scroll_id'];
128: }
129:
130: /**
131: * Fetches every "page" after the first one using the lastest "scroll_id"
132: *
133: * @return void
134: * @see Iterator::next()
135: */
136: public function next(): void
137: {
138: $this->current_scrolled_response = $this->client->scroll(
139: [
140: 'scroll_id' => $this->scroll_id,
141: 'scroll' => $this->scroll_ttl
142: ]
143: );
144: $this->scroll_id = $this->current_scrolled_response['_scroll_id'];
145: $this->current_key++;
146: }
147:
148: /**
149: * Returns a boolean value indicating if the current page is valid or not
150: *
151: * @return bool
152: * @see Iterator::valid()
153: */
154: public function valid(): bool
155: {
156: return isset($this->current_scrolled_response['hits']['hits'][0]);
157: }
158:
159: /**
160: * Returns the current "page"
161: *
162: * @return array
163: * @see Iterator::current()
164: */
165: public function current(): array
166: {
167: return $this->current_scrolled_response;
168: }
169:
170: /**
171: * Returns the current "page number" of the current "page"
172: *
173: * @return int
174: * @see Iterator::key()
175: */
176: public function key(): int
177: {
178: return $this->current_key;
179: }
180: }
181: