Passed
Branch main (b6a268)
by Iain
04:11
created

QueryBuilder::build()   C

Complexity

Conditions 13
Paths 10

Size

Total Lines 65
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 13
eloc 35
c 1
b 0
f 0
nc 10
nop 0
dl 0
loc 65
rs 6.6166

How to fix   Long Method    Complexity   

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
declare(strict_types=1);
4
5
/*
6
 * Copyright Humbly Arrogant Ltd 2020-2022.
7
 *
8
 * Use of this software is governed by the Business Source License included in the LICENSE file and at https://getparthenon.com/docs/next/license.
9
 *
10
 * Change Date: TBD ( 3 years after 2.0.0 release )
11
 *
12
 * On the date above, in accordance with the Business Source License, use of this software will be governed by the open source license specified in the LICENSE file.
13
 */
14
15
namespace Parthenon\Common\Elasticsearch;
16
17
final class QueryBuilder
18
{
19
    private array $filters = [];
20
21
    private array $queries = [];
22
23
    private array $aggregations = [];
24
25
    public function query(string $queryType, string $fieldName, mixed $fieldValue): self
26
    {
27
        $this->addQuery($queryType, 'must', $fieldName, $fieldValue);
28
29
        return $this;
30
    }
31
32
    public function andQuery(string $queryType, string $fieldName, mixed $fieldValue): self
33
    {
34
        $this->addQuery($queryType, 'must', $fieldName, $fieldValue);
35
36
        return $this;
37
    }
38
39
    public function notQuery(string $queryType, string $fieldName, mixed $fieldValue): self
40
    {
41
        $this->addQuery($queryType, 'must_not', $fieldName, $fieldValue);
42
43
        return $this;
44
    }
45
46
    public function orQuery(string $queryType, string $fieldName, mixed $fieldValue): self
47
    {
48
        $this->addQuery($queryType, 'should', $fieldName, $fieldValue);
49
50
        return $this;
51
    }
52
53
    public function filter(string $filterType, string $fieldName, mixed $fieldValue): self
54
    {
55
        $this->addFilter($filterType, 'must', $fieldName, $fieldValue);
56
57
        return $this;
58
    }
59
60
    public function andFilter(string $filterType, string $fieldName, mixed $fieldValue): self
61
    {
62
        $this->addFilter($filterType, 'must', $fieldName, $fieldValue);
63
64
        return $this;
65
    }
66
67
    public function notFilter(string $filterType, string $fieldName, mixed $fieldValue): self
68
    {
69
        $this->addFilter($filterType, 'must_not', $fieldName, $fieldValue);
70
71
        return $this;
72
    }
73
74
    public function orFilter(string $filterType, string $fieldName, mixed $fieldValue): self
75
    {
76
        $this->addFilter($filterType, 'should', $fieldName, $fieldValue);
77
78
        return $this;
79
    }
80
81
    public function aggregation(string $term, string $fieldName): self
82
    {
83
        $this->aggregations[$term] = $fieldName;
84
85
        return $this;
86
    }
87
88
    public function build(): array
89
    {
90
        $output = [];
91
92
        if (1 === sizeof($this->queries) && 0 === sizeof($this->filters) && 0 === sizeof($this->aggregations)) {
93
            $query = current($this->queries);
94
95
            return $this->addAggregation([
96
              'query' => [
97
                  $query['queryType'] => [
98
                      $query['fieldName'] => $query['fieldValue'],
99
                  ],
100
              ],
101
            ]);
102
        }
103
104
        if (1 === sizeof($this->filters)) {
105
            $filters = current($this->filters);
106
            $output['bool'] = [
107
                'filter' => [
108
                    $filters['filterType'] => [
109
                        $filters['fieldName'] => $filters['fieldValue'],
110
                    ],
111
                ],
112
            ];
113
114
            return $this->addAggregation(['query' => $output]);
115
        }
116
117
        if (sizeof($this->filters) > 1 && sizeof($this->queries) > 1) {
118
            $output['bool'] = [
119
            ];
120
        }
121
122
        if (sizeof($this->queries) > 1) {
123
            $output['bool']['must'] = [];
124
            foreach ($this->queries as $query) {
125
                $qualifierType = $query['qualifierType'];
126
                if (!isset($output['bool'][$qualifierType])) {
127
                    $output['bool'][$qualifierType] = [];
128
                }
129
                $output['bool'][$qualifierType][] = [
130
                   $query['queryType'] => [
131
                       $query['fieldName'] => $query['fieldValue'],
132
                   ],
133
               ];
134
            }
135
        }
136
137
        if (sizeof($this->filters) > 1) {
138
            $output['bool']['filter']['bool'] = [];
139
            foreach ($this->filters as $filter) {
140
                $qualifierType = $filter['qualifierType'];
141
                if (!isset($output['bool']['filter']['bool'][$qualifierType])) {
142
                    $output['bool']['filter']['bool'][$qualifierType] = [];
143
                }
144
                $output['bool']['filter']['bool'][$qualifierType][] = [
145
                    $filter['filterType'] => [
146
                        $filter['fieldName'] => $filter['fieldValue'],
147
                    ],
148
                ];
149
            }
150
        }
151
152
        return $this->addAggregation(['query' => $output]);
153
    }
154
155
    private function addAggregation($output)
156
    {
157
        if (0 === sizeof($this->aggregations)) {
158
            return $output;
159
        }
160
161
        $output['aggs'] = [];
162
163
        foreach ($this->aggregations as $term => $fieldName) {
164
            $key = sprintf('agg_%s_%s', $term, $fieldName);
165
            $output['aggs'][$key] = [$term => ['field' => $fieldName]];
166
        }
167
168
        return $output;
169
    }
170
171
    private function addFilter(string $filterType, string $qualifierType, string $fieldName, mixed $fieldValue): void
172
    {
173
        $this->filters[] = [
174
            'filterType' => $filterType,
175
            'qualifierType' => $qualifierType,
176
            'fieldName' => $fieldName,
177
            'fieldValue' => $fieldValue,
178
        ];
179
    }
180
181
    private function addQuery(string $queryType, string $qualifierType, string $fieldName, mixed $fieldValue): void
182
    {
183
        $this->queries[] = [
184
            'queryType' => $queryType,
185
            'qualifierType' => $qualifierType,
186
            'fieldName' => $fieldName,
187
            'fieldValue' => $fieldValue,
188
        ];
189
    }
190
}
191