Completed
Push — master ( 4d44a5...1590a9 )
by Sergey
12:05
created

Filter::makeQuery()   C

Complexity

Conditions 9
Paths 24

Size

Total Lines 63
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 63
rs 6.6149
cc 9
eloc 33
nc 24
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Isswp101\Persimmon\QueryBuilder\Filters;
4
5
abstract class Filter
6
{
7
    const MODE_INCLUDE = 'include';
8
    const MODE_EXCLUDE = 'exclude';
9
    const MODE_OFF = 'off';
10
11
    const MERGE_AND = 'AND';
12
    const MERGE_OR = 'OR';
13
14
    /**
15
     * Filter mode.
16
     *
17
     * @var string Can be as include, exclude or off.
18
     */
19
    protected $mode;
20
21
    /**
22
     * Filter values.
23
     *
24
     * @var mixed
25
     */
26
    protected $values;
27
28
    /**
29
     * This array contains linked instances of current filter.
30
     *
31
     * @var array
32
     */
33
    protected $linkedFilters = [];
34
35
    /**
36
     * Filters are merged using AND (must) by default.
37
     * But you can override it and merge them using OR (should).
38
     *
39
     * @var string
40
     */
41
    protected $mergeType = Filter::MERGE_AND;
42
43
    /**
44
     * Linked filters are merged using AND (must) by default.
45
     * But you can override it and merge them using OR (should).
46
     *
47
     * @var string
48
     */
49
    protected $logicalOperator = Filter::MERGE_OR;
50
51
    /**
52
     * Constructor.
53
     *
54
     * @param mixed $values Filter values.
55
     */
56
    public function __construct($values = null)
57
    {
58
        $this->values = $values;
59
    }
60
61
    /**
62
     * Set filter options.
63
     *
64
     * @param string $mode
65
     * @param string $logicalOperator
66
     * @param array $linkedFilters
67
     * @return $this
68
     */
69
    public function setOptions($mode = null, $logicalOperator = null, array $linkedFilters = [])
70
    {
71
        $this->mode = is_null($mode) ? Filter::MODE_INCLUDE : $mode;
72
        $this->logicalOperator = is_null($logicalOperator) ? Filter::MERGE_OR : $logicalOperator;
73
        $this->linkedFilters = $linkedFilters;
74
        return $this;
75
    }
76
77
    /**
78
     * Returns the actual elasticsearch query for one filter.
79
     * {
80
     *   "term": {
81
     *     "price": "0"
82
     *   }
83
     * }
84
     *
85
     * @param mixed $values
86
     * @return array
87
     */
88
    abstract public function query($values);
89
90
    /**
91
     * Returns wrapped elasticsearch filter query.
92
     * {
93
     *   "bool": {
94
     *     "should": [],
95
     *     "must_not": []
96
     *   }
97
     * }
98
     *
99
     * @return array
100
     */
101
    public function makeQuery()
102
    {
103
        $query = $this->query($this->getValues());
104
105
        $map = [
106
            Filter::MERGE_AND => 'must',
107
            Filter::MERGE_OR => 'should'
108
        ];
109
110
        if ($this->isInclude()) {
111
            if ($this->getLogicalOperator() == Filter::MERGE_AND) {
112
                $query = [
113
                    'bool' => [
114
                        'must' => [
115
                            $query
116
                        ]
117
                    ]
118
                ];
119
            } elseif ($this->getLogicalOperator() == Filter::MERGE_OR) {
120
                $query = [
121
                    'bool' => [
122
                        'should' => [
123
                            $query
124
                        ]
125
                    ]
126
                ];
127
            }
128
        } elseif ($this->isExclude()) {
129
            $mergeOperator = $map[$this->getLogicalOperator()];
130
            $query = [
131
                'bool' => [
132
                    $mergeOperator => [
133
                        [
134
                            'bool' => [
135
                                'must_not' => [
136
                                    $query
137
                                ]
138
                            ]
139
                        ]
140
                    ]
141
                ]
142
            ];
143
        } elseif ($this->isOff()) {
144
            $query = [];
145
        }
146
147
        foreach ($this->getLinkedFilters() as $filter) {
148
            $extraQuery = $filter->makeQuery();
149
150
//            if ($filter->isInclude()) {
1 ignored issue
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
151
            if ($this->getLogicalOperator() == Filter::MERGE_AND) {
152
                $query = $this->mergeBoolQuery($query, $extraQuery, 'must');
153
            } elseif ($this->getLogicalOperator() == Filter::MERGE_OR) {
154
                $query = $this->mergeBoolQuery($query, $extraQuery, 'should');
155
            }
156
//            }
1 ignored issue
show
Unused Code Comprehensibility introduced by
57% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
157
//            elseif ($filter->isExclude()) {
158
//                $query = $this->mergeBoolQuery($query, $extraQuery, 'must_not');
159
//            }
160
        }
161
162
        return $query;
163
    }
164
165
    /**
166
     * Merges elastcisearch query with current filter query.
167
     *
168
     * @param array $query Elastcisearch query.
169
     * @return array Merged elasticsearch query.
170
     */
171
    public function mergeQuery(array $query)
172
    {
173
        $types = [
174
            Filter::MERGE_AND => 'must',
175
            Filter::MERGE_OR => 'should'
176
        ];
177
178
        $type = $this->getMergeType();
179
180
        $query['body']['filter']['bool'][$types[$type]][] = $this->makeQuery();
181
182
        return $query;
183
    }
184
185
    /**
186
     * Returns filter mode.
187
     *
188
     * @return string Can be as include, exclude or off.
189
     */
190
    public function getMode()
191
    {
192
        return $this->mode;
193
    }
194
195
    /**
196
     * Returns true if mode is include.
197
     *
198
     * @return bool
199
     */
200
    public function isInclude()
201
    {
202
        return $this->getMode() == Filter::MODE_INCLUDE;
203
    }
204
205
    /**
206
     * Returns true if mode is exclude.
207
     *
208
     * @return bool
209
     */
210
    public function isExclude()
211
    {
212
        return $this->getMode() == Filter::MODE_EXCLUDE;
213
    }
214
215
    /**
216
     * Returns true if mode is off.
217
     *
218
     * @return bool
219
     */
220
    public function isOff()
221
    {
222
        return $this->getMode() == Filter::MODE_OFF;
223
    }
224
225
    /**
226
     * Retuns filter values as array.
227
     *
228
     * @return mixed
229
     */
230
    public function getValues()
231
    {
232
        return $this->values;
233
    }
234
235
    /**
236
     * Returns linked instances of current filter.
237
     *
238
     * @return Filter[]
239
     */
240
    public function getLinkedFilters()
241
    {
242
        return $this->linkedFilters;
243
    }
244
245
    /**
246
     * Returns true if filter has linked filters.
247
     *
248
     * @return bool
249
     */
250
    public function hasLinkedFilters()
251
    {
252
        return !empty($this->linkedFilters);
253
    }
254
255
    /**
256
     * Returns filter merge type.
257
     *
258
     * @return string - "AND" || "OR"
259
     */
260
    public function getMergeType()
261
    {
262
        return $this->mergeType;
263
    }
264
265
    /**
266
     * Sets filter merge type.
267
     *
268
     * @param string $mergeType - "AND" || "OR"
269
     */
270
    public function setMergeType($mergeType)
271
    {
272
        $this->mergeType = $mergeType;
273
    }
274
275
    /**
276
     * Returns linked filters logical operator.
277
     *
278
     * @return string - "AND" || "OR"
279
     */
280
    public function getLogicalOperator()
281
    {
282
        return $this->logicalOperator;
283
    }
284
285
    /**
286
     * Updates linked filters logical operator.
287
     *
288
     * @param string $logicalOperator - "AND" || "OR"
289
     */
290
    public function setLogicalOperator($logicalOperator)
291
    {
292
        $this->logicalOperator = $logicalOperator;
293
    }
294
295
    /**
296
     * Returns true if merge type is valid.
297
     * @return bool
298
     */
299
    public function isMergeTypeValid()
300
    {
301
        return in_array($this->mergeType, [Filter::MERGE_AND, Filter::MERGE_OR]);
302
    }
303
304
    /**
305
     * Merges BOOL elasticsearch queries.
306
     *
307
     * @param array $query1
308
     * @param array $query2
309
     * @param string $type must, must_not, should
310
     * @return array
311
     */
312
    protected function mergeBoolQuery(array $query1, array $query2, $type)
313
    {
314
        if (empty($query2['bool'][$type])) {
315
            return $query1;
316
        } else {
317
            if (empty($query1['bool'][$type])) {
318
                $query1['bool'][$type] = [];
319
            }
320
        }
321
322
        $query1['bool'][$type] = array_merge($query1['bool'][$type], $query2['bool'][$type]);
323
324
        return $query1;
325
    }
326
}