Completed
Push — master ( 550d3d...251c7d )
by Peter
06:02
created

Manganel   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 232
Duplicated Lines 0 %

Coupling/Cohesion

Components 5
Dependencies 7

Test Coverage

Coverage 52.63%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 21
lcom 5
cbo 7
dl 0
loc 232
ccs 10
cts 19
cp 0.5263
rs 10
c 2
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 15 3
A create() 0 14 2
A fly() 0 12 3
A init() 0 4 1
A getVersion() 0 8 2
A drop() 0 12 4
A getClient() 0 16 2
A getProfiler() 0 12 3
A setProfiler() 0 5 1
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\ClientBuilder;
18
use Maslosoft\Addendum\Interfaces\AnnotatedInterface;
19
use Maslosoft\EmbeDi\EmbeDi;
20
use Maslosoft\Mangan\Interfaces\ProfilerInterface;
21
use Maslosoft\Mangan\Profillers\NullProfiler;
22
use Maslosoft\Manganel\Decorators\QueryBuilder\ConditionDecorator;
23
use Maslosoft\Manganel\Decorators\QueryBuilder\ConditionsDecorator;
24
use Maslosoft\Manganel\Decorators\QueryBuilder\Operators\InDecorator;
25
use Maslosoft\Manganel\Decorators\QueryBuilder\Operators\SimpleTermDecorator;
26
use Maslosoft\Manganel\Decorators\QueryBuilder\QueryString\BoostDecorator;
27
use Maslosoft\Manganel\Decorators\QueryBuilder\QueryString\PrefixQueryDecorator;
28
use Maslosoft\Manganel\Decorators\QueryBuilder\ScrollDecorator;
29
use Maslosoft\Manganel\Decorators\QueryBuilder\SearchDecorator;
30
use Maslosoft\Manganel\Interfaces\ManganelAwareInterface;
31
use Maslosoft\Manganel\Meta\ManganelMeta;
32
33
/**
34
 * Manganel
35
 *
36
 * @author Piotr Maselkowski <pmaselkowski at gmail.com>
37
 */
38
class Manganel
39
{
40
41
	const DefaultIndexId = 'manganel';
42
43
	public $decorators = [
44
		SearchCriteria::class => [
45
			ConditionDecorator::class,
46
			ConditionsDecorator::class,
47
			ScrollDecorator::class,
48
			SearchDecorator::class,
49
			InDecorator::class,
50
			SimpleTermDecorator::class,
51
			BoostDecorator::class,
52
			PrefixQueryDecorator::class,
53
		]
54
	];
55
	public $hosts = [
56
		'localhost:9200'
57
	];
58
	public $auth = null;
59
	public $username = '';
60
	public $password = '';
61
	public $params = [];
62
63
	/**
64
	 * TODO Enforce lowercase
65
	 */
66
	public $index = 'my_index';
67
	public $indexId = self::DefaultIndexId;
68
69
	/**
70
	 * Whether to use refresh option when indexing document.
71
	 * NOTE: Due to performance reasons, this should be set to `true` only when
72
	 * really necessary - so it can be also callback.
73
	 *
74
	 * Callback function signature:
75
	 * ```
76
	 * function(AnnotatedInterface $model)
77
	 * ```
78
	 * @var string|Closure
79
	 */
80
	public $refresh = false;
81
82
	/**
83
	 *
84
	 * @var Client
85
	 */
86
	private $client = null;
87
88
	/**
89
	 * Dependency injection container
90
	 * @var EmbeDi
91
	 */
92
	private $di = null;
93
94
	/**
95
	 * Version number holder
96
	 * @var string
97
	 */
98
	private static $_version = null;
99
100
	/**
101
	 * Instances of manganel
102
	 * @var Manganel[]
103
	 */
104
	private static $mnl = [];
105
106
	/**
107
	 * Hash map of class name to id. This is to reduce overhead of Mangan::fromModel()
108
	 * @var string[]
109
	 */
110
	private static $classToId = [];
111
112
	/**
113
	 * Profiler instance
114
	 * @var ProfilerInterface
115
	 */
116
	private $profiler = null;
117
118
	/**
119
	 * Class constructor
120
	 * @codeCoverageIgnore This is implicitly tested
121
	 * @param string $indexId
122
	 */
123
	public function __construct($indexId = self::DefaultIndexId)
124
	{
125
		if (empty($indexId))
126
		{
127
			$indexId = self::DefaultIndexId;
128
		}
129
		$this->indexId = $indexId;
130
		$this->di = new EmbeDi($this->indexId);
131
		$this->di->configure($this);
132
133
		if (empty(self::$mnl[$indexId]))
134
		{
135
			self::$mnl[$indexId] = $this;
136
		}
137
	}
138
139
	/**
140
	 * @codeCoverageIgnore This is implicitly tested
141
	 * @param AnnotatedInterface $model
142
	 * @return static
143
	 */
144
	public static function create(AnnotatedInterface $model)
145
	{
146
		$key = get_class($model);
147
		if (isset(self::$classToId[$key]))
148
		{
149
			$indexId = self::$classToId[$key];
150
		}
151
		else
152
		{
153
			$indexId = ManganelMeta::create($model)->type()->indexId;
154
			self::$classToId[$key] = $indexId;
155
		}
156
		return static::fly($indexId);
157
	}
158
159
	/**
160
	 * Get flyweight instance of Manganel component.
161
	 * Only one instance will be created for each `$indexId`.
162
	 *
163
	 * @codeCoverageIgnore This is implicitly tested
164
	 * @new
165
	 * @param string $indexId
166
	 * @return Manganel
167
	 */
168
	public static function fly($indexId = self::DefaultIndexId)
169
	{
170
		if (empty($indexId))
171
		{
172
			$indexId = self::DefaultIndexId;
173
		}
174
		if (empty(self::$mnl[$indexId]))
175
		{
176
			self::$mnl[$indexId] = new static($indexId);
177
		}
178
		return self::$mnl[$indexId];
179
	}
180
181
	/**
182
	 * @codeCoverageIgnore This is implicitly tested
183
	 */
184
	public function init()
185
	{
186
		$this->di->store($this);
187
	}
188
189
	/**
190
	 * Get mangan version
191
	 * @return string
192
	 */
193
	public function getVersion()
194
	{
195
		if (null === self::$_version)
196
		{
197
			self::$_version = require __DIR__ . '/version.php';
198
		}
199
		return self::$_version;
200
	}
201
202
	/**
203
	 * Drop current index
204
	 * @return bool
205
	 */
206 1
	public function drop()
207
	{
208
		$params = [
209 1
			'index' => strtolower($this->index)
210
		];
211 1
		$result = $this->getClient()->indices()->delete($params);
212 1
		if (is_array($result) && array_key_exists('acknowledged', $result) && $result['acknowledged'])
213
		{
214 1
			return true;
215
		}
216
		return false;
217
	}
218
219
	/**
220
	 * @codeCoverageIgnore This is implicitly tested
221
	 * @return Client
222
	 */
223
	public function getClient()
224
	{
225
		if (null === $this->client)
226
		{
227
			$this->params['hosts'] = $this->hosts;
228
			$this->params['connectionParams']['auth'] = [
229
				$this->username,
230
				$this->password,
231
				$this->auth
232
			];
233
			$cb = ClientBuilder::create();
234
			$cb->setHosts($this->hosts);
235
			$this->client = $cb->build();
236
		}
237
		return $this->client;
238
	}
239
240
	/**
241
	 * Get profiler instance. This is guaranted, if not configured will return NullProfiller.
242
	 * @see NullProfiler
243
	 * @return ProfilerInterface
244
	 */
245 33
	public function getProfiler()
246
	{
247 33
		if (null === $this->profiler)
248
		{
249 1
			$this->profiler = new NullProfiler;
250
		}
251 33
		if ($this->profiler instanceof ManganelAwareInterface)
252
		{
253
			$this->profiler->setManganel($this);
254
		}
255 33
		return $this->profiler;
256
	}
257
258
	/**
259
	 * Set profiler instance
260
	 * @param ProfilerInterface $profiller
261
	 * @return static
262
	 */
263
	public function setProfiler(ProfilerInterface $profiller)
264
	{
265
		$this->profiler = $profiller;
266
		return $this;
267
	}
268
269
}
270