Completed
Push — master ( 3fab57...455a7d )
by Peter
14:19
created

IndexManager::delete()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 15.566

Importance

Changes 0
Metric Value
dl 0
loc 29
ccs 5
cts 14
cp 0.357
rs 8.8337
c 0
b 0
f 0
cc 6
nc 10
nop 0
crap 15.566
1
<?php
2
3
/**
4
 * This software package is licensed under `AGPL-3.0-only, proprietary` license[s].
5
 *
6
 * @package maslosoft/manganel
7
 * @license AGPL-3.0-only, proprietary
8
 *
9
 * @copyright Copyright (c) Peter Maselkowski <[email protected]>
10
 * @link https://maslosoft.com/manganel/
11
 */
12
13
namespace Maslosoft\Manganel;
14
15
use Closure;
16
use Elasticsearch\Client;
17
use Elasticsearch\Common\Exceptions\BadRequest400Exception;
18
use Exception;
19
use Maslosoft\Addendum\Interfaces\AnnotatedInterface;
20
use Maslosoft\Mangan\Mangan;
21
use Maslosoft\Manganel\Events\ErrorEvent;
22
use Maslosoft\Manganel\Exceptions\ManganelException;
23
use Maslosoft\Manganel\Helpers\ExceptionHandler;
24
use Maslosoft\Manganel\Helpers\RecursiveFilter;
25
use Maslosoft\Manganel\Helpers\TypeNamer;
26
use Maslosoft\Manganel\Meta\ManganelMeta;
27
use UnexpectedValueException;
28
29
/**
30
 * IndexManager
31
 *
32
 * @author Piotr Maselkowski <pmaselkowski at gmail.com>
33
 */
34
class IndexManager
35
{
36
	/**
37
	 * Alias to ErrorEvent::EventIndexingError
38
	 */
39
	const EventIndexingError = ErrorEvent::EventIndexingError;
40
41
	/**
42
	 * Manganel instance
43
	 * @var Manganel
44
	 */
45
	private $manganel = null;
46
47
	/**
48
	 * Model meta data
49
	 * @var ManganelMeta
50
	 */
51
	private $meta = null;
52
53
	/**
54
	 * Annotated model
55
	 * @var AnnotatedInterface
56
	 */
57
	private $model;
58
59
	/**
60
	 * Whether model is indexable
61
	 * @var bool
62
	 */
63
	private $isIndexable = false;
64
65 86
	public function __construct($model)
66
	{
67 86
		$this->model = $model;
68 86
		$this->meta = ManganelMeta::create($this->model);
69 86
		if (!empty($this->meta->type()->indexId) && false !== $this->meta->type()->indexId)
70
		{
71 84
			$this->isIndexable = true;
72
		}
73 86
		if ($this->isIndexable)
74
		{
75 84
			if (!isset($this->model->_id))
76
			{
77
				throw new ManganelException(sprintf('Property `_id` is not set in model `%s`, this is required by Manganel', get_class($this->model)));
78
			}
79 84
			$this->manganel = Manganel::create($this->model);
80
		}
81 86
	}
82
83
	/**
84
	 * Add or replace document in index
85
	 *
86
	 * @return bool
87
	 * @throws BadRequest400Exception
88
	 */
89 86
	public function index()
90
	{
91 86
		if (!$this->isIndexable)
92
		{
93 3
			return false;
94
		}
95
		// NOTE: Transformer must ensure that _id is string, not MongoId
96 84
		$body = SearchArray::fromModel($this->model);
97 84
		if (array_key_exists('_id', $body))
98
		{
99
			$config = Mangan::fromModel($this->model)->sanitizersMap;
100
			if (!array_key_exists(SearchArray::class, $config))
101
			{
102
				throw new UnexpectedValueException(sprintf('Mangan is not properly configured for Manganel. Signals must be generated or add configuration manually from `%s::getDefault()`', ConfigManager::class));
103
			}
104
			else
105
			{
106
				throw new UnexpectedValueException(sprintf('Cannot index `%s`, as it contains _id field. Either use MongoObjectId sanitizer on it, or rename.', get_class($this->model)));
107
			}
108
		}
109
110
		// Create proper elastic search request array
111
		$params = [
112 84
			'body' => RecursiveFilter::mongoIdToString($body),
113
		];
114
		try
115
		{
116 84
			$fullParams = $this->getParams($params);
117
			// Need to check if exists, or update will fail
118
			$existsParams = [
119 84
				'index' => $fullParams['index'],
120 84
				'type' => $fullParams['type'],
121 84
				'id' => $fullParams['id']
122
			];
123 84
			$exists = $this->getClient()->exists($existsParams);
124
125 84
			if (!$exists)
126
			{
127 84
				$result = $this->getClient()->index($fullParams);
128
			}
129
			else
130
			{
131 13
				$updateParams = $fullParams;
132 13
				$updateParams['body'] = [
133 13
					'doc' => $fullParams['body']
134
				];
135 13
				$result = $this->getClient()->update($updateParams);
136
			}
137 84
			if (array_key_exists('result', $result) && $result['result'] === 'updated')
138
			{
139
				// For ES 5
140 3
				return true;
141
			}
142 84
			elseif (is_array($result))
143
			{
144
				// For earlier ES
145 84
				return true;
146
			}
147
		}
148
		catch (BadRequest400Exception $e)
149
		{
150
			if(ExceptionHandler::handled($e, $this->model, self::EventIndexingError))
151
			{
152
				return false;
153
			}
154
			throw ExceptionHandler::getDecorated($this->manganel, $e, $params);
155
		}
156
		catch(Exception $e)
157
		{
158
			if(ExceptionHandler::handled($e, $this->model, self::EventIndexingError))
159
			{
160
				return false;
161
			}
162
			throw $e;
163
		}
164
		return false;
165
	}
166
167
	/**
168
	 * Delete document from index
169
	 *
170
	 * @return bool
171
	 * @throws BadRequest400Exception
172
	 */
173 5
	public function delete()
174
	{
175 5
		if (!$this->isIndexable)
176
		{
177
			return false;
178
		}
179
		try
180
		{
181 5
			$params = $this->getParams();
182 5
			$this->getClient()->delete($params);
183 5
			return true;
184
		}
185
		catch (BadRequest400Exception $e)
186
		{
187
			if(ExceptionHandler::handled($e, $this->model, self::EventIndexingError))
188
			{
189
				return false;
190
			}
191
			throw ExceptionHandler::getDecorated($this->manganel, $e, $params);
192
		}
193
		catch(Exception $e)
194
		{
195
			if(ExceptionHandler::handled($e, $this->model, self::EventIndexingError))
196
			{
197
				return false;
198
			}
199
			throw $e;
200
		}
201
	}
202
203 28
	public function get($id = null)
204
	{
205 28
		if (!$this->isIndexable)
206
		{
207
			return null;
208
		}
209 28
		$params = $id ? ['id' => (string) $id] : [];
210 28
		$data = $this->getClient()->get($this->getParams($params))['_source'];
211 28
		return SearchArray::toModel($data);
212
	}
213
214
	/**
215
	 * Get client
216
	 * @return Client
217
	 */
218 84
	public function getClient()
219
	{
220 84
		return $this->manganel->getClient();
221
	}
222
223 84
	private function getParams($params = [])
224
	{
225
		// Check refresh option
226 84
		if ($this->manganel->refresh instanceof Closure)
227
		{
228
			$func = $this->manganel->refresh;
229
			$refresh = (bool) $func($this->model);
230
		}
231
		else
232
		{
233 84
			$refresh = $this->manganel->refresh;
234
		}
235
		$result = [
236 84
			'index' => strtolower($this->manganel->index),
237 84
			'type' => TypeNamer::nameType($this->model),
238 84
			'id' => (string) $this->model->_id,
239 84
			'refresh' => $refresh
240
		];
241 84
		return array_merge($result, $params);
242
	}
243
244
}
245