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

QueryBuilder   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 9

Test Coverage

Coverage 79.69%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 24
lcom 2
cbo 9
dl 0
loc 165
ccs 51
cts 64
cp 0.7969
rs 10
c 2
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 15 3
A setCriteria() 0 7 1
A add() 0 12 3
B count() 0 22 4
B search() 0 24 5
C getParams() 0 46 8
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\Common\Exceptions\BadRequest400Exception;
16
use Maslosoft\Addendum\Interfaces\AnnotatedInterface;
17
use Maslosoft\Mangan\Interfaces\CriteriaAwareInterface;
18
use Maslosoft\Mangan\Interfaces\CriteriaInterface;
19
use Maslosoft\Mangan\Traits\CriteriaAwareTrait;
20
use Maslosoft\Manganel\Helpers\QueryBuilderDecorator;
21
use Maslosoft\Manganel\Helpers\RecursiveFilter;
22
use Maslosoft\Manganel\Helpers\TypeNamer;
23
use Maslosoft\Manganel\Traits\UniqueModelsAwareTrait;
24
use UnexpectedValueException;
25
26
/**
27
 * QueryBuilder
28
 * @method SearchCriteria getCriteria()
29
 * @author Piotr Maselkowski <pmaselkowski at gmail.com>
30
 */
31
class QueryBuilder implements CriteriaAwareInterface
32
{
33
34
	use CriteriaAwareTrait,
35
	  UniqueModelsAwareTrait;
36
37
	/**
38
	 * Manganel instance
39
	 * @var Manganel
40
	 */
41
	private $manganel = null;
42
43 38
	public function __construct($model = null)
44
	{
45 38
		if (!empty($model))
46
		{
47 17
			$this->addModel($model);
48
		}
49 38
		if (!empty($model))
50
		{
51 17
			$this->manganel = Manganel::create($model);
52
		}
53
		else
54
		{
55 33
			$this->manganel = Manganel::fly();
56
		}
57 38
	}
58
59
	/**
60
	 * Add model or array of models
61
	 * @param AnnotatedInterface|AnnotatedInterface[] $model
62
	 * @return void
63
	 */
64 34
	public function add($model)
65
	{
66 34
		if (is_array($model))
67
		{
68 32
			foreach ($model as $m)
69
			{
70 32
				$this->addModel($m);
71
			}
72 32
			return;
73
		}
74 2
		$this->addModel($model);
75 2
	}
76
77
	/**
78
	 * Set criteria
79
	 * @param CriteriaInterface|array $criteria
80
	 * @return static
81
	 */
82 32
	public function setCriteria($criteria)
83
	{
84 32
		$this->criteria = $criteria;
85 32
		assert($criteria instanceof SearchCriteria);
86 32
		$this->add($criteria->getModels());
87 32
		return $this;
88
	}
89
90
	/**
91
	 *
92
	 * @param string $q
93
	 * @return int
94
	 */
95 21
	public function count($q = null)
96
	{
97 21
		$params = $this->getParams($q);
98
		try
99
		{
100 21
			$result = $this->manganel->getClient()->count($params);
101
		}
102
		catch (BadRequest400Exception $e)
103
		{
104
			// Throw previous exception,
105
			// as it holds more meaningfull information
106
			$json = json_encode($params, JSON_PRETTY_PRINT);
107
			$previous = $e->getPrevious();
108
			$message = sprintf("Exception (%s) while querying `%s`: \n%s\n", $previous->getMessage(), $this->manganel->indexId, $json);
109
			throw new BadRequest400Exception($message, 400, $e);
110
		}
111 21
		if (empty($result) && empty($result['count']))
112
		{
113
			return 0; // @codeCoverageIgnore
114
		}
115 21
		return $result['count'];
116
	}
117
118
	/**
119
	 * Get search results
120
	 * @param string $q
121
	 * @return array
122
	 */
123 31
	public function search($q = null)
124
	{
125 31
		$params = $this->getParams($q);
126
127
		try
128
		{
129 31
			$result = $this->manganel->getClient()->search($params);
130
		}
131
		catch (BadRequest400Exception $e)
132
		{
133
			// Throw previous exception,
134
			// as it holds more meaningfull information
135
			$json = json_encode($params, JSON_PRETTY_PRINT);
136
			$previous = $e->getPrevious();
137
			$message = sprintf("Exception (%s) while querying `%s`: \n%s\n", $previous->getMessage(), $this->manganel->indexId, $json);
138
			throw new BadRequest400Exception($message, 400, $e);
139
		}
140
141 31
		if (empty($result) && empty($result['hits']) && empty($result['hits']['hits']))
142
		{
143
			return [];
144
		}
145 31
		return $result['hits']['hits'];
146
	}
147
148 38
	public function getParams($q = null)
149
	{
150 38
		$body = [];
151
		// Try to get query from criteria if empty
152 38
		$criteria = $this->getCriteria();
153 38
		if (!$criteria instanceof SearchCriteria && $criteria instanceof CriteriaInterface)
154
		{
155
			$criteria = new SearchCriteria($criteria);
156
		}
157 38
		if (empty($criteria))
158
		{
159 6
			$criteria = new SearchCriteria;
160
		}
161 38
		if (!empty($q))
162
		{
163 14
			$criteria->search($q);
164
		}
165
166 38
		$criteria->setModels($this->getModels());
167
168 38
		$decorator = new QueryBuilderDecorator($this->manganel);
169 38
		$decorator->decorate($body, $criteria);
170 38
		$models = $this->getModels();
171 38
		if (empty($models))
172
		{
173
			$type = '_all';
174
		}
175
		else
176
		{
177 38
			$types = [];
178 38
			foreach ($models as $model)
179
			{
180 38
				assert($model instanceof AnnotatedInterface, new UnexpectedValueException(sprintf('Expected `%s` instance, got `%s`', AnnotatedInterface::class, is_object($model) ? get_class($model) : gettype($model))));
181 38
				$types[] = TypeNamer::nameType($model);
182
			}
183 38
			$type = implode(',', array_unique($types));
184
		}
185
186
		$params = [
187 38
			'index' => strtolower($this->manganel->index),
188 38
			'type' => $type,
189 38
			'body' => $body
190
		];
191
//		return $params;
192 38
		return RecursiveFilter::mongoIdToString($params);
193
	}
194
195
}
196