Completed
Push — master ( 321c29...f7acb7 )
by Peter
05:07
created

Manganel   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 213
Duplicated Lines 0 %

Coupling/Cohesion

Components 4
Dependencies 7

Test Coverage

Coverage 66.67%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 19
lcom 4
cbo 7
dl 0
loc 213
ccs 10
cts 15
cp 0.6667
rs 10
c 1
b 0
f 0

8 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 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
	 * Instances of manganel
96
	 * @var Manganel[]
97
	 */
98
	private static $mnl = [];
99
100
	/**
101
	 * Hash map of class name to id. This is to reduce overhead of Mangan::fromModel()
102
	 * @var string[]
103
	 */
104
	private static $classToId = [];
105
106
	/**
107
	 * Profiler instance
108
	 * @var ProfilerInterface
109
	 */
110
	private $profiler = null;
111
112
	/**
113
	 * Class constructor
114
	 * @codeCoverageIgnore This is implicitly tested
115
	 * @param string $indexId
116
	 */
117
	public function __construct($indexId = self::DefaultIndexId)
118
	{
119
		if (empty($indexId))
120
		{
121
			$indexId = self::DefaultIndexId;
122
		}
123
		$this->indexId = $indexId;
124
		$this->di = new EmbeDi($this->indexId);
125
		$this->di->configure($this);
126
127
		if (empty(self::$mnl[$indexId]))
128
		{
129
			self::$mnl[$indexId] = $this;
130
		}
131
	}
132
133
	/**
134
	 * @codeCoverageIgnore This is implicitly tested
135
	 * @param AnnotatedInterface $model
136
	 * @return static
137
	 */
138
	public static function create(AnnotatedInterface $model)
139
	{
140
		$key = get_class($model);
141
		if (isset(self::$classToId[$key]))
142
		{
143
			$indexId = self::$classToId[$key];
144
		}
145
		else
146
		{
147
			$indexId = ManganelMeta::create($model)->type()->indexId;
148
			self::$classToId[$key] = $indexId;
149
		}
150
		return static::fly($indexId);
151
	}
152
153
	/**
154
	 * Get flyweight instance of Manganel component.
155
	 * Only one instance will be created for each `$indexId`.
156
	 *
157
	 * @codeCoverageIgnore This is implicitly tested
158
	 * @new
159
	 * @param string $indexId
160
	 * @return Manganel
161
	 */
162
	public static function fly($indexId = self::DefaultIndexId)
163
	{
164
		if (empty($indexId))
165
		{
166
			$indexId = self::DefaultIndexId;
167
		}
168
		if (empty(self::$mnl[$indexId]))
169
		{
170
			self::$mnl[$indexId] = new static($indexId);
171
		}
172
		return self::$mnl[$indexId];
173
	}
174
175
	/**
176
	 * @codeCoverageIgnore This is implicitly tested
177
	 */
178
	public function init()
179
	{
180
		$this->di->store($this);
181
	}
182
183
	/**
184
	 * Drop current index
185
	 * @return bool
186
	 */
187 1
	public function drop()
188
	{
189
		$params = [
190 1
			'index' => strtolower($this->index)
191
		];
192 1
		$result = $this->getClient()->indices()->delete($params);
193 1
		if (is_array($result) && array_key_exists('acknowledged', $result) && $result['acknowledged'])
194
		{
195 1
			return true;
196
		}
197
		return false;
198
	}
199
200
	/**
201
	 * @codeCoverageIgnore This is implicitly tested
202
	 * @return Client
203
	 */
204
	public function getClient()
205
	{
206
		if (null === $this->client)
207
		{
208
			$this->params['hosts'] = $this->hosts;
209
			$this->params['connectionParams']['auth'] = [
210
				$this->username,
211
				$this->password,
212
				$this->auth
213
			];
214
			$cb = ClientBuilder::create();
215
			$cb->setHosts($this->hosts);
216
			$this->client = $cb->build();
217
		}
218
		return $this->client;
219
	}
220
221
	/**
222
	 * Get profiler instance. This is guaranted, if not configured will return NullProfiller.
223
	 * @see NullProfiler
224
	 * @return ProfilerInterface
225
	 */
226 31
	public function getProfiler()
227
	{
228 31
		if (null === $this->profiler)
229
		{
230 1
			$this->profiler = new NullProfiler;
231
		}
232 31
		if ($this->profiler instanceof ManganelAwareInterface)
233
		{
234
			$this->profiler->setManganel($this);
235
		}
236 31
		return $this->profiler;
237
	}
238
239
	/**
240
	 * Set profiler instance
241
	 * @param ProfilerInterface $profiller
242
	 * @return static
243
	 */
244
	public function setProfiler(ProfilerInterface $profiller)
245
	{
246
		$this->profiler = $profiller;
247
		return $this;
248
	}
249
250
}
251