Completed
Push — master ( f82663...d42560 )
by Peter
17:08
created

IndexManager::index()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 50
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 7.4937

Importance

Changes 7
Bugs 2 Features 1
Metric Value
c 7
b 2
f 1
dl 0
loc 50
ccs 17
cts 26
cp 0.6538
rs 8.6315
cc 6
eloc 23
nc 5
nop 0
crap 7.4937
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 Elasticsearch\Client;
16
use Elasticsearch\Common\Exceptions\BadRequest400Exception;
17
use Maslosoft\Addendum\Interfaces\AnnotatedInterface;
18
use Maslosoft\Mangan\Helpers\CollectionNamer;
19
use Maslosoft\Mangan\Mangan;
20
use Maslosoft\Manganel\Exceptions\ManganelException;
21
use Maslosoft\Manganel\Meta\ManganelMeta;
22
use MongoId;
23
use UnexpectedValueException;
24
25
/**
26
 * IndexMangager
27
 *
28
 * @author Piotr Maselkowski <pmaselkowski at gmail.com>
29
 */
30
class IndexManager
31
{
32
33
	/**
34
	 * Manganel instance
35
	 * @var Manganel
36
	 */
37
	private $manganel = null;
38
39
	/**
40
	 * Model meta data
41
	 * @var ManganelMeta
42
	 */
43
	private $meta = null;
44
45
	/**
46
	 * Annotated model
47
	 * @var AnnotatedInterface
48
	 */
49
	private $model;
50
51
	/**
52
	 * Whether model is indexable
53
	 * @var bool
54
	 */
55
	private $isIndexable = false;
56
57 18
	public function __construct($model)
58
	{
59 18
		$this->model = $model;
60 18
		$this->meta = ManganelMeta::create($this->model);
61 18
		if (!empty($this->meta->type()->indexId) && false !== $this->meta->type()->indexId)
62 18
		{
63 16
			$this->isIndexable = true;
64 16
		}
65 18
		if ($this->isIndexable)
66 18
		{
67 16
			if (!isset($this->model->_id))
68 16
			{
69
				throw new ManganelException(sprintf('Property `_id` is not set in model `%s`, this is required by Manganel', get_class($this->model)));
70
			}
71 16
			$this->manganel = Manganel::create($this->model);
72 16
		}
73 18
	}
74
75 18
	public function index()
76
	{
77 18
		if (!$this->isIndexable)
78 18
		{
79 3
			return;
80
		}
81
		// NOTE: Transformer must ensure that _id is string, not MongoId
82 16
		$body = SearchArray::fromModel($this->model);
83 16
		if (array_key_exists('_id', $body))
84 16
		{
85
			$config = Mangan::fromModel($this->model)->sanitizersMap;
86
			if (!array_key_exists(SearchArray::class, $config))
87
			{
88
				throw new UnexpectedValueException(sprintf('Mangan is not properly configured for Manganel. Signals must be generated or add configuration manually from `%s::getDefault()`', ConfigManager::class));
89
			}
90
			else
91
			{
92
				throw new UnexpectedValueException(sprintf('Cannot index `%s`, as it contains _id field. Either use MongoObjectId sanitizer on it, or rename.', get_class($this->model)));
93
			}
94
		}
95
96
		// In some cases $value *might* still be mongoId type,
97
		// see https://github.com/Maslosoft/Addendum/issues/43
98 16
		$func = function($value)
99
		{
100 16
			if ($value instanceof MongoId)
101 16
			{
102
				return (string) $value;
103
			}
104 16
			return $value;
105 16
		};
106 16
		$filtered = filter_var($body, \FILTER_CALLBACK, ['options' => $func]);
107
108
		// Create proper elastic search request array
109
		$params = [
110
			'body' => $filtered
111 16
		];
112
		try
113
		{
114 16
			$this->getClient()->index($this->getParams($params));
115
		}
116 16
		catch (BadRequest400Exception $e)
117
		{
118
			// Throw previous exception,
119
			// as it holds more meaningfull information
120
			$previous = $e->getPrevious();
121
			$message = sprintf('Exception while indexing `%s`: %s', get_class($this->model), $previous->getMessage());
122
			throw new BadRequest400Exception($message);
123
		}
124 16
	}
125
126 4
	public function delete()
127
	{
128 4
		if (!$this->isIndexable)
129 4
		{
130
			return;
131
		}
132 4
		$this->getClient()->delete($this->getParams());
133 4
	}
134
135 4
	public function get($id = null)
136
	{
137 4
		if (!$this->isIndexable)
138 4
		{
139
			return;
140
		}
141 4
		$params = $id ? ['id' => (string) $id] : [];
142 4
		$data = $this->getClient()->get($this->getParams($params))['_source'];
143 4
		return SearchArray::toModel($data);
144
	}
145
146
	/**
147
	 * Get client
148
	 * @return Client
149
	 */
150 16
	public function getClient()
151
	{
152 16
		return $this->manganel->getClient();
153
	}
154
155 16
	private function getParams($params = [])
156
	{
157
		$result = [
158 16
			'index' => strtolower($this->manganel->index),
159 16
			'type' => CollectionNamer::nameCollection($this->model),
160 16
			'id' => (string) $this->model->_id
161 16
		];
162 16
		return array_merge($result, $params);
163
	}
164
165
}
166