Completed
Push — master ( 1833b5...550d3d )
by Peter
06:20
created

IndexManager   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 166
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 76.19%

Importance

Changes 1
Bugs 1 Features 0
Metric Value
wmc 22
lcom 1
cbo 10
dl 0
loc 166
ccs 48
cts 63
cp 0.7619
rs 10
c 1
b 1
f 0

6 Methods

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