Completed
Push — master ( 532b06...1ac1c9 )
by Peter
08:53
created

IndexManager   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 175
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 73.12%

Importance

Changes 5
Bugs 2 Features 0
Metric Value
wmc 25
c 5
b 2
f 0
lcom 1
cbo 11
dl 0
loc 175
ccs 49
cts 67
cp 0.7312
rs 10

6 Methods

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