GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

QueryFilter   D
last analyzed

Complexity

Total Complexity 58

Size/Duplication

Total Lines 303
Duplicated Lines 0 %

Importance

Changes 5
Bugs 3 Features 0
Metric Value
eloc 137
c 5
b 3
f 0
dl 0
loc 303
rs 4.5599
wmc 58

16 Methods

Rating   Name   Duplication   Size   Complexity  
A getEntityManager() 0 3 1
A addUserCity() 0 25 5
A addProduct() 0 9 3
A addUserProvince() 0 27 6
A addUserGender() 0 14 5
A __construct() 0 5 1
A addProductCategory() 0 5 3
A reset() 0 4 1
A getQueryBuilder() 0 3 1
A addUserPostcode() 0 25 5
A addLeftJoin() 0 9 2
B addTimePeriod() 0 39 6
A hasRootEntity() 0 3 1
A getGroupByParts() 0 26 4
B addChannel() 0 28 9
A addUserCountry() 0 21 5

How to fix   Complexity   

Complex Class

Complex classes like QueryFilter often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use QueryFilter, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Odiseo\SyliusReportPlugin\Filter;
6
7
use DateTime;
8
use Doctrine\ORM\EntityManager;
9
use Doctrine\ORM\QueryBuilder;
10
use Exception;
11
use Sylius\Component\Core\Model\AddressInterface;
12
use Sylius\Component\Core\Model\ChannelInterface;
13
use Sylius\Component\Core\Model\Customer;
14
use Sylius\Component\Core\Model\ProductInterface;
15
16
/**
17
 * @author Odiseo Team <[email protected]>
18
 * @author Rimas Kudelis <[email protected]>
19
 */
20
class QueryFilter implements QueryFilterInterface
21
{
22
    protected EntityManager $em;
23
24
    protected QueryBuilder $qb;
25
26
    protected array $joins = [];
27
28
    public function __construct(EntityManager $entityManager)
29
    {
30
        $this->em = $entityManager;
31
32
        $this->qb = $this->em->createQueryBuilder();
33
    }
34
35
    public function getQueryBuilder(): QueryBuilder
36
    {
37
        return $this->qb;
38
    }
39
40
    public function getEntityManager(): EntityManager
41
    {
42
        return $this->em;
43
    }
44
45
    public function reset(): void
46
    {
47
        $this->qb = $this->em->createQueryBuilder();
48
        $this->joins = [];
49
    }
50
51
    protected function getGroupByParts(
52
        QueryBuilder $qb,
53
        array $configuration = [],
54
        string $dateField = 'checkoutCompletedAt'
55
    ): array {
56
        if (false === strpos($dateField, '.')) {
57
            $rootAlias = $qb->getRootAliases()[0];
58
            $dateF = $rootAlias.'.'.$dateField;
59
        } else {
60
            $dateF = $dateField;
61
        }
62
63
        $selectPeriod = '';
64
        $selectGroupBy = '';
65
        foreach ($configuration['groupBy'] as $groupByElement) {
66
            if (strlen($selectPeriod) > 0) {
67
                $selectPeriod .= ', ';
68
                $selectGroupBy .= ',';
69
            }
70
            $salias = ucfirst(strtolower($groupByElement)).'Date';
71
            $selectPeriod .= $groupByElement.'('.$dateF.') as '.$salias;
72
73
            $selectGroupBy .= $salias;
74
        }
75
76
        return [$selectPeriod, $selectGroupBy];
77
    }
78
79
    public function addLeftJoin(string $join, string $alias): string
80
    {
81
        if (!isset($this->joins[$join])) {
82
            $this->joins[$join] = $alias;
83
84
            $this->qb->leftJoin($join, $alias);
85
        }
86
87
        return $this->joins[$join];
88
    }
89
90
    public function addTimePeriod(
91
        array $configuration = [],
92
        string $dateField = 'checkoutCompletedAt',
93
        ?string $rootAlias = null
94
    ): void {
95
        if (false === strpos($dateField, '.')) {
96
            if (!$rootAlias) {
97
                $rootAlias = $this->qb->getRootAliases()[0];
98
            }
99
100
            $dateF = $rootAlias.'.'.$dateField;
101
        } else {
102
            $dateF = $dateField;
103
        }
104
105
        $groupByParts = $this->getGroupByParts($this->qb, $configuration, $dateField);
106
107
        /** @var DateTime $startDateTime */
108
        $startDateTime = $configuration['timePeriod']['start'];
109
        /** @var DateTime $endDateTime */
110
        $endDateTime = $configuration['timePeriod']['end']?:new DateTime();
111
112
        if ($groupByParts[0] && $groupByParts[1]) {
113
            $this->qb
114
                ->addSelect($groupByParts[0])
115
                ->andWhere($this->qb->expr()->gte($dateF, ':from'))
116
                ->andWhere($this->qb->expr()->lte($dateF, ':to'))
117
                ->setParameter('from', $startDateTime->format('Y-m-d H:i:s'))
118
                ->setParameter('to', $endDateTime->format('Y-m-d H:i:s'))
119
                ->groupBy($groupByParts[1])
120
                ->orderBy('date,' . $groupByParts[1])
121
            ;
122
        } else {
123
            $this->qb
124
                ->andWhere($this->qb->expr()->gte($dateF, ':from'))
125
                ->andWhere($this->qb->expr()->lte($dateF, ':to'))
126
                ->setParameter('from', $startDateTime->format('Y-m-d H:i:s'))
127
                ->setParameter('to', $endDateTime->format('Y-m-d H:i:s'))
128
                ->orderBy('date')
129
            ;
130
        }
131
    }
132
133
    public function addChannel(
134
        array $configuration = [],
135
        ?string $field = null,
136
        ?string $rootAlias = null
137
    ): void {
138
        if (isset($configuration['channel']) && count($configuration['channel']) > 0) {
139
            $storeIds = [];
140
141
            if ($configuration['channel'] instanceof ChannelInterface) {
142
                $storeIds[] = $configuration['channel']->getId();
143
            } elseif (is_array($configuration['channel']) && !in_array(0, $configuration['channel'])) {
144
                $storeIds = $configuration['channel'];
145
            }
146
147
            if (!(count($storeIds) > 0)) {
148
                return;
149
            }
150
151
            if (!$field) {
152
                if (!$rootAlias) {
153
                    $rootAlias = $this->qb->getRootAliases()[0];
154
                }
155
156
                $field = $rootAlias.'.channel';
157
            }
158
159
            $this->qb
160
                ->andWhere($this->qb->expr()->in($field, $storeIds))
161
            ;
162
        }
163
    }
164
165
    public function addUserGender(array $configuration = [], ?string $rootAlias = null): void
166
    {
167
        if (isset($configuration['userGender']) && count($configuration['userGender']) > 0) {
168
            $cAlias = $rootAlias;
169
            if (!$rootAlias) {
170
                $rootAlias = $cAlias = $this->qb->getRootAliases()[0];
171
            }
172
173
            if (!$this->hasRootEntity(Customer::class)) {
174
                $cAlias = $this->addLeftJoin($rootAlias.'.customer', 'c');
175
            }
176
177
            $this->qb
178
                ->andWhere($this->qb->expr()->in($cAlias.'.gender', $configuration['userGender']))
179
            ;
180
        }
181
    }
182
183
    public function addUserCountry(
184
        array $configuration = [],
185
        string $addressType = 'shipping',
186
        ?string $rootAlias = null
187
    ): void {
188
        $type = 'user'.ucfirst($addressType).'Country';
189
190
        if (isset($configuration[$type]) && count($configuration[$type]) > 0) {
191
            $cAlias = $rootAlias;
192
            if (!$rootAlias) {
193
                $rootAlias = $cAlias = $this->qb->getRootAliases()[0];
194
            }
195
196
            if (!$this->hasRootEntity(Customer::class)) {
197
                $cAlias = $this->addLeftJoin($rootAlias.'.customer', 'c');
198
            }
199
200
            $caAlias = $this->addLeftJoin($cAlias.'.addresses', 'c'.substr($addressType, 0, 1).'a');
201
202
            $this->qb
203
                ->andWhere($this->qb->expr()->in($caAlias.'.countryCode', $configuration[$type]))
204
            ;
205
        }
206
    }
207
208
    public function addUserProvince(
209
        array $configuration = [],
210
        string $addressType = 'shipping',
211
        ?string $rootAlias = null
212
    ): void {
213
        $type = 'user'.ucfirst($addressType).'Province';
214
215
        if (isset($configuration[$type]) && count($configuration[$type]) > 0) {
216
            $provinces = $configuration[$type]->map(function (AddressInterface $address) {
217
                return $address->getProvinceCode() ?: $address->getProvinceName();
218
            })->toArray();
219
220
            $cAlias = $rootAlias;
221
            if (!$rootAlias) {
222
                $rootAlias = $cAlias = $this->qb->getRootAliases()[0];
223
            }
224
225
            if (!$this->hasRootEntity(Customer::class)) {
226
                $cAlias = $this->addLeftJoin($rootAlias.'.customer', 'c');
227
            }
228
229
            $caAlias = $this->addLeftJoin($cAlias.'.addresses', 'c'.substr($addressType, 0, 1).'a');
230
231
            $this->qb
232
                ->andWhere($this->qb->expr()->orX(
233
                    $this->qb->expr()->in($caAlias.'.provinceCode', $provinces),
234
                    $this->qb->expr()->in($caAlias.'.provinceName', $provinces)
235
                ))
236
            ;
237
        }
238
    }
239
240
    public function addUserCity(
241
        array $configuration = [],
242
        string $addressType = 'shipping',
243
        ?string $rootAlias = null
244
    ): void {
245
        $type = 'user'.ucfirst($addressType).'City';
246
247
        if (isset($configuration[$type]) && count($configuration[$type]) > 0) {
248
            $cities = $configuration[$type]->map(function (AddressInterface $address) {
249
                return $address->getCity();
250
            })->toArray();
251
252
            $cAlias = $rootAlias;
253
            if (!$rootAlias) {
254
                $rootAlias = $cAlias = $this->qb->getRootAliases()[0];
255
            }
256
257
            if (!$this->hasRootEntity(Customer::class)) {
258
                $cAlias = $this->addLeftJoin($rootAlias.'.customer', 'c');
259
            }
260
261
            $caAlias = $this->addLeftJoin($cAlias.'.addresses', 'c'.substr($addressType, 0, 1).'a');
262
263
            $this->qb
264
                ->andWhere($this->qb->expr()->in($caAlias.'.city', $cities))
265
            ;
266
        }
267
    }
268
269
    public function addUserPostcode(
270
        array $configuration = [],
271
        string $addressType = 'shipping',
272
        ?string $rootAlias = null
273
    ): void {
274
        $type = 'user'.ucfirst($addressType).'Postcode';
275
276
        if (isset($configuration[$type]) && count($configuration[$type]) > 0) {
277
            $codes = $configuration[$type]->map(function (AddressInterface $address) {
278
                return $address->getPostcode();
279
            })->toArray();
280
281
            $cAlias = $rootAlias;
282
            if (!$rootAlias) {
283
                $rootAlias = $cAlias = $this->qb->getRootAliases()[0];
284
            }
285
286
            if (!$this->hasRootEntity(Customer::class)) {
287
                $cAlias = $this->addLeftJoin($rootAlias.'.customer', 'c');
288
            }
289
290
            $caAlias = $this->addLeftJoin($cAlias.'.addresses', 'c'.substr($addressType, 0, 1).'2a');
291
292
            $this->qb
293
                ->andWhere($this->qb->expr()->in($caAlias.'.postcode', $codes))
294
            ;
295
        }
296
    }
297
298
    public function addProduct(array $configuration = [], string $field = 'p.id'): void
299
    {
300
        if (isset($configuration['product']) && count($configuration['product']) > 0) {
301
            $products = $configuration['product']->map(function (ProductInterface $product) {
302
                return $product->getId();
303
            })->toArray();
304
305
            $this->qb
306
                ->andWhere($this->qb->expr()->in($field, $products))
307
            ;
308
        }
309
    }
310
311
    public function addProductCategory(array $configuration = [], string $field = 'pt.taxon'): void
312
    {
313
        if (isset($configuration['productCategory']) && count($configuration['productCategory']) > 0) {
314
            $this->qb
315
                ->andWhere($this->qb->expr()->in($field, $configuration['productCategory']))
316
            ;
317
        }
318
    }
319
320
    protected function hasRootEntity(string $rootEntityClassname): bool
321
    {
322
        return in_array($rootEntityClassname, $this->qb->getRootEntities());
323
    }
324
}
325