Completed
Pull Request — master (#22)
by Sergey
24:02 queued 09:01
created

QueryBuilder::getQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1.125

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 4
cp 0.5
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1.125
1
<?php
2
3
namespace Isswp101\Persimmon\QueryBuilder;
4
5
use Isswp101\Persimmon\QueryBuilder\Aggregations\Aggregation;
6
use Isswp101\Persimmon\QueryBuilder\Filters\Filter;
7
use ONGR\ElasticsearchDSL\Search;
8
9
class QueryBuilder implements IQueryBuilder
10
{
11
    protected $query = [];
12
    protected $chunk = 0;
13
14
    /**
15
     * @param Search|array|null $query
16
     */
17
    public function __construct($query = null)
18
    {
19
        if ($query instanceof Search) {
20
            $query = $query->toArray();
21
        }
22 7
        $this->query = is_array($query) ? $query : $this->getMatchAllQuery();
23
    }
24 7
25 7
    protected function getMatchAllQuery()
26
    {
27
        return ['query' => ['match_all' => new \stdClass()]];
28
    }
29
30
    public function from(int $from): QueryBuilder
31 1
    {
32
        $this->query['from'] = $from;
33 1
        return $this;
34 1
    }
35
36
    public function size(int $size): QueryBuilder
37
    {
38
        $this->query['size'] = $size;
39
        return $this;
40
    }
41 2
42
    public function hasSort(): bool
43 2
    {
44 2
        return !empty($this->query['body']['sort']);
45
    }
46
47
    /**
48
     * @param array|string $sort
49
     * @return $this
50
     */
51
    public function sort($sort)
52
    {
53
        $this->query['body']['sort'] = $sort;
54
        return $this;
55
    }
56
57
    /**
58
     * @param Filter|array $filter
59
     * @param string $mode
60
     * @return $this
61
     */
62
    public function filter($filter = [], $mode = Filter::MODE_INCLUDE)
63
    {
64
        if (!$filter) {
65
            unset($this->query['body']['filter']);
66
            return $this;
67
        }
68
69
        if ($filter instanceof Filter) {
70 5
            $filter = $filter->makeQuery();
71
        }
72 5
73
        $map = [
74
            Filter::MODE_INCLUDE => 'must',
75
            Filter::MODE_EXCLUDE => 'must_not',
76
            'should' => 'should'
77 5
        ];
78 5
79 5
        $mode = $map[$mode];
80
81
        $this->merge($filter, $mode);
82 5
83 5
        return $this;
84
    }
85 5
86
    /**
87 5
     * Set _source to search query.
88
     *
89 5
     * @param mixed $fields
90
     * @return $this
91 5
     */
92
    public function fields($fields = false)
93
    {
94
        if ($fields === false) {
95
            $this->query['body']['_source'] = false;
96
        } elseif ((array)$fields == ['*']) {
97
            unset($this->query['body']['_source']);
98
        } else {
99
            $this->query['body']['_source'] = $fields;
100 1
        }
101
        return $this;
102 1
    }
103 1
104 1
    /**
105
     * Return only _id.
106
     *
107
     * @return $this
108
     */
109 1
    public function getOnlyIds()
110
    {
111
        return $this->fields(false);
112
    }
113
114
    public function build(): array
115
    {
116
        return $this->query;
117
    }
118
119
    /**
120
     * @return string
121
     */
122
    public function __toString()
123
    {
124
        return $this->toJson();
125
    }
126
127 7
    /**
128
     * @param int $options
129 7
     * @return string
130
     */
131
    public function toJson($options = 0)
132
    {
133
        return json_encode($this->query, $options);
134
    }
135
136
    protected function merge(array $query, $mode = 'must')
137 7
    {
138
        if (!array_key_exists('filter', $this->query['body'])) {
139 7
            $this->query['body']['filter']['bool'][$mode] = [];
140
        }
141
142
        $this->query['body']['filter']['bool'][$mode][] = $query;
143
144
        return $this;
145
    }
146
147
    public function aggregation(Aggregation $aggregation)
148
    {
149
        $this->query['body']['aggs'][$aggregation->getName()] = $aggregation->make();
150
        return $this;
151
    }
152
153
    public function where($field, $value)
154
    {
155
        $query = ['term' => [$field => $value]];
156
        $this->merge($query);
157
        return $this;
158
    }
159 5
160
    public function notWhere($field, $value)
161 5
    {
162 5
        $query = ['term' => [$field => $value]];
163 5
        $this->merge($query, 'must_not');
164
        return $this;
165 5
    }
166
167 5
    public function orWhere($field, $value)
168
    {
169
        $query = ['term' => [$field => $value]];
170 1
        $this->merge($query, 'should');
171
        return $this;
172 1
    }
173 1
174
    public function between($field, $start, $end)
175
    {
176
        $query = ['range' => [$field => ['gt' => $start, 'lt' => $end]]];
177
        $this->merge($query);
178
        return $this;
179
    }
180
181
    public function betweenOrEquals($field, $start, $end)
182
    {
183
        $query = ['range' => [$field => ['gte' => $start, 'lte' => $end]]];
184
        $this->merge($query);
185
        return $this;
186
    }
187
188
    public function range($field, $start, $end)
189
    {
190
        return $this->betweenOrEquals($field, $start, $end);
191
    }
192
193
    public function greaterThan($field, $start)
194
    {
195
        $query = ['range' => [$field => ['gt' => $start]]];
196
        $this->merge($query);
197
        return $this;
198
    }
199
200
    public function gt($field, $start)
201
    {
202
        return $this->greaterThan($field, $start);
203
    }
204 1
205
    public function greaterThanOrEquals($field, $start)
206 1
    {
207 1
        $query = ['range' => [$field => ['gte' => $start]]];
208 1
        $this->merge($query);
209
        return $this;
210
    }
211
212
    public function gte($field, $start)
213
    {
214
        return $this->greaterThanOrEquals($field, $start);
215
    }
216 1
217
    public function lessThan($field, $end)
218 1
    {
219 1
        $query = ['range' => [$field => ['lt' => $end]]];
220 1
        $this->merge($query);
221
        return $this;
222
    }
223
224
    public function lt($field, $start)
225
    {
226
        return $this->lessThan($field, $start);
227
    }
228
229
    public function lessThanOrEquals($field, $end)
230
    {
231
        $query = ['range' => [$field => ['lte' => $end]]];
232
        $this->merge($query);
233
        return $this;
234
    }
235
236
    public function lte($field, $start)
237
    {
238
        return $this->lessThanOrEquals($field, $start);
239
    }
240
241
    public function match($field, $value)
242
    {
243
        $query = ['query' => ['match' => [$field => $value]]];
244
        $this->merge($query);
245
        return $this;
246
    }
247
248
    public function notMatch($field, $value)
249
    {
250
        $query = ['query' => ['match' => [$field => $value]]];
251
        $this->merge($query, 'must_not');
252
        return $this;
253
    }
254
255
    public function orMatch($field, $value)
256
    {
257
        $query = ['query' => ['match' => [$field => $value]]];
258
        $this->merge($query, 'should');
259
        return $this;
260
    }
261
262
    public function columns(array $columns): IQueryBuilder
263
    {
264 1
        $this->query['_source'] = $columns;
265
        return $this;
266 1
    }
267 1
268 1
    public function noColumns(): IQueryBuilder
269
    {
270
        $this->query['_source'] = false;
271
        return $this;
272
    }
273
274
    public function chunk(int $count = null): IQueryBuilder
275
    {
276
        if ($count != null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $count of type null|integer against null; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
277
            $this->chunk = $count;
278 1
        }
279
        return $this;
280 1
    }
281
}
282