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.
Passed
Pull Request — 2.4 (#133)
by Alessandro
06:28 queued 03:16
created

QueryBuilderFactory::join()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 54
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 7.002

Importance

Changes 0
Metric Value
dl 0
loc 54
ccs 28
cts 29
cp 0.9655
rs 7.8331
c 0
b 0
f 0
cc 7
eloc 29
nc 12
nop 2
crap 7.002

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 Mado\QueryBundle\Queries;
4
5
use Doctrine\ORM\EntityManager;
6
use Doctrine\ORM\QueryBuilder;
7
use Mado\QueryBundle\Component\Meta\Exceptions\UnInitializedQueryBuilderException;
8
use Mado\QueryBundle\Dictionary;
9
use Mado\QueryBundle\Exceptions;
10
use Mado\QueryBundle\Queries\Objects\FilterObject;
11
12
class QueryBuilderFactory extends AbstractQuery
13
{
14
    const DIRECTION_AZ = 'asc';
15
16
    const DIRECTION_ZA = 'desc';
17
18
    const DEFAULT_OPERATOR = 'eq';
19
20
    private const AND_OPERATOR_LOGIC = 'AND';
21
22
    private const OR_OPERATOR_LOGIC = 'OR';
23
24
    protected $qBuilder;
25
26
    protected $fields;
27
28
    protected $andFilters;
29
30
    protected $orFilters;
31
32
    private $relationEntityAlias;
33
34
    protected $sorting;
35
36
    private $joins;
37
38
    protected $rel;
39
40
    protected $printing;
41
42
    protected $page;
43
44
    protected $pageLength;
45
46
    protected $select;
47
48 1
    public function getAvailableFilters()
49
    {
50 1
        return array_keys($this->getValueAvailableFilters());
51
    }
52
53 2
    public function getValueAvailableFilters()
54
    {
55 2
        return Dictionary::getOperators();
56
    }
57
58 21
    public function setFields(array $fields = [])
59
    {
60 21
        $this->fields = $fields;
61
62 21
        return $this;
63
    }
64
65 2
    public function getFields()
66
    {
67 2
        if (null === $this->fields) {
68 1
            throw new \RuntimeException(
69 1
                'Oops! Fields are not defined'
70
            );
71
        }
72
73 1
        return $this->fields;
74
    }
75
76
    /** @since version 2.2 */
77 10
    public function setAndFilters(array $andFilters = [])
78
    {
79 10
        $this->andFilters = $andFilters;
80
81 10
        return $this;
82
    }
83
84 9
    public function setOrFilters(array $orFilters = [])
85
    {
86 9
        $this->orFilters = $orFilters;
87
88 9
        return $this;
89
    }
90
91 4
    public function setSorting(array $sorting = [])
92
    {
93 4
        $this->sorting = $sorting;
94
95 4
        return $this;
96
    }
97
98 1
    public function getAndFilters()
99
    {
100 1
        return $this->andFilters;
101
    }
102
103 1
    public function getOrFilters()
104
    {
105 1
        return $this->orFilters;
106
    }
107
108 7
    private function noExistsJoin($prevEntityAlias, $currentEntityAlias)
109
    {
110 7
        if (null === $this->joins) {
111 7
            $this->joins = [];
112
        }
113
114 7
        $needle = $prevEntityAlias . '_' . $currentEntityAlias;
115
116 7
        return !in_array($needle, $this->joins);
117
    }
118
119 7
    private function storeJoin($prevEntityAlias, $currentEntityAlias)
120
    {
121 7
        $needle = $prevEntityAlias . '_' . $currentEntityAlias;
122 7
        $this->joins[$needle] = $needle;
123 7
    }
124
125
    /**
126
     * @param String $relation Nome della relazione semplice (groups.name) o con embedded (_embedded.groups.name)
127
     * @return $this
128
     */
129 7
    public function join(String $relation, $logicOperator = self::AND_OPERATOR_LOGIC)
130
    {
131 7
        $relation = explode('|', $relation)[0];
132 7
        $relations = [$relation];
133
134
135 7
        if (strstr($relation, '_embedded.')) {
136 7
            $embeddedFields = explode('.', $relation);
137 7
            $this->parser->camelize($embeddedFields[1]);
138
139
            // elimino l'ultimo elemento che dovrebbe essere il nome del campo
140 7
            unset($embeddedFields[count($embeddedFields) - 1]);
141
142
            // elimino il primo elemento _embedded
143 7
            unset($embeddedFields[0]);
144
145 7
            $relations = $embeddedFields;
146
        }
147
148 7
        $entityName = $this->getEntityName();
149 7
        $entityAlias = $this->entityAlias;
150
151 7
        foreach ($relations as $relation) {
152 7
            $relation = $this->parser->camelize($relation);
153 7
            $relationEntityAlias = 'table_' . $relation;
154
155 7
            $metadata = $this->manager->getClassMetadata($entityName);
156
157 7
            if ($metadata->hasAssociation($relation)) {
158
159 7
                $association = $metadata->getAssociationMapping($relation);
160
161 7
                $fieldName = $this->parser->camelize($association['fieldName']);
162
163 7
                if ($this->noExistsJoin($relationEntityAlias, $relation)) {
164 7
                    if ($logicOperator === self::AND_OPERATOR_LOGIC) {
165 4
                        $this->qBuilder->innerJoin($entityAlias . "." . $fieldName, $relationEntityAlias);
166 3
                    } elseif ($logicOperator === self::OR_OPERATOR_LOGIC) {
167 3
                        $this->qBuilder->leftJoin($entityAlias . "." . $fieldName, $relationEntityAlias);
168
                    } else {
169
                        throw new Exceptions('Missing Logic operator');
170
                    }
171
172 7
                    $this->storeJoin($relationEntityAlias, $relation);
173
                }
174
175 7
                $entityName = $association['targetEntity'];
176 7
                $entityAlias = $relationEntityAlias;
177
            }
178
179 7
            $this->setRelationEntityAlias($relationEntityAlias);
180
        }
181
182 7
        return $this;
183
    }
184
185 17
    public function filter()
186
    {
187 17
        if (null === $this->andFilters && null === $this->orFilters) {
188 1
            throw new Exceptions\MissingFiltersException();
189
        }
190
191 16
        if (!$this->fields) {
192 1
            throw new Exceptions\MissingFieldsException();
193
        }
194
195 15
        if (null !== $this->andFilters) {
196 8
            foreach ($this->andFilters as $filter => $value) {
197 8
                $this->applyFilterAnd(
198 8
                    Objects\FilterObject::fromRawFilter($filter),
199 8
                    $value,
200 8
                    Objects\Value::fromFilter($value)
201
                );
202
            }
203
        }
204
205 15
        if (null !== $this->orFilters) {
206 7
            $orFilter = [];
207 7
            $orFilter['orCondition'] = null;
208 7
            $orFilter['parameters'] = [];
209
210 7
            foreach ($this->orFilters as $filter => $value) {
211 7
                $orFilter = $this->applyFilterOr(
212 7
                    Objects\FilterObject::fromRawFilter($filter),
213 7
                    $value,
214 7
                    $orFilter
215
                );
216
            }
217
218 7
            if ((count($orFilter) > 0) && (null != $orFilter['orCondition'])) {
219 7
                $this->qBuilder->andWhere($orFilter['orCondition']);
220
221 7
                foreach ($orFilter['parameters'] as $parameter) {
222 7
                    $this->qBuilder->setParameter($parameter['field'], $parameter['value']);
223
                }
224
            }
225
        }
226
227 15
        return $this;
228
    }
229
230 8
    private function applyFilterAnd(
231
        Objects\FilterObject $filterObject,
232
        $value,
233
        Objects\Value $filterValue
234
    ) {
235 8
        $whereCondition = $this->entityAlias . '.' . $filterObject->getFieldName() . ' '
236 8
            . $filterObject->getOperatorMeta();
237
238 8
        if (in_array($filterObject->getFieldName(), $this->fields)) {
239 5
            $salt = '_' . random_int(111, 999);
240
241 5
            if ($filterObject->isListType()) {
242 1
                $whereCondition .= ' (:field_' . $filterObject->getFieldName() . $salt . ')';
243 4
            } elseif ($filterObject->isFieldEqualityType()) {
244 1
                $whereCondition .= ' ' . $this->entityAlias . '.' . $value;
245
            } else {
246 3
                $whereCondition .= ' :field_' . $filterObject->getFieldName() . $salt;
247
            }
248
249 5
            $this->qBuilder->andWhere($whereCondition);
250
251 5
            if ($filterObject->haveOperatorSubstitutionPattern()) {
252 2
                if ($filterObject->isListType()) {
253 1
                    $value = explode(',', $value);
254
                } else {
255 1
                    $value = str_replace(
256 1
                        '{string}',
257 1
                        $value,
258 1
                        $filterObject->getOperatorsSubstitutionPattern()
259
                    );
260
                }
261
            }
262
263 5
            $this->qBuilder->setParameter('field_' . $filterObject->getFieldName() . $salt, $value);
264
        } else {
265 3
            if (strpos($filterObject->getFieldName(), 'Embedded.') === false) {
266
                $whereCondition .= ' ' . $this->entityAlias . '.' . $value;
267
                $this->qBuilder->andWhere($whereCondition);
268
            }
269
        }
270
271
        // controllo se il filtro si riferisce ad una relazione dell'entità quindi devo fare dei join
272
        // esempio per users: filtering[_embedded.groups.name|eq]=admin
273 8
        if (strstr($filterObject->getRawFilter(), '_embedded.')) {
274
275 3
            $this->join($filterObject->getRawFilter());
276 3
            $relationEntityAlias = $this->getRelationEntityAlias();
277
278 3
            $embeddedFields = explode('.', $filterObject->getFieldName());
279 3
            $embeddedFieldName = $this->parser->camelize($embeddedFields[count($embeddedFields) - 1]);
280
281 3
            $salt = '_' . random_int(111, 999);
282
283 3
            $whereCondition = $relationEntityAlias . '.' . $embeddedFieldName . ' '
284 3
                . $filterObject->getOperatorMeta();
285
286 3
            if ($filterObject->isListType()) {
287 1
                $whereCondition .= ' (:field_' . $embeddedFieldName . $salt . ')';
288
            } else {
289 2
                $whereCondition .= ' :field_' . $embeddedFieldName . $salt;
290
            }
291
292 3
            $this->qBuilder->andWhere($whereCondition);
293 3
            if ($filterObject->haveOperatorSubstitutionPattern()) {
294 2
                if ($filterObject->isListType()) {
295 1
                    $value = explode(',', $filterValue->getFilter());
296
                } else {
297 1
                    $value = str_replace(
298 1
                        '{string}',
299 1
                        $value,
300 1
                        $filterObject->getOperatorsSubstitutionPattern()
301
                    );
302
                }
303
            }
304
305 3
            $this->qBuilder->setParameter('field_' . $embeddedFieldName . $salt, $value);
306
        }
307 8
    }
308
309 7
    private function applyFilterOr(
310
        Objects\FilterObject $filterObject,
311
        $value,
312
        $orCondition
313
    ) {
314 7
        $whereCondition = $this->entityAlias . '.' . $filterObject->getFieldName() . ' '
315 7
            . $filterObject->getOperatorMeta();
316
317
        // controllo se il filtro che mi arriva dalla richiesta è una proprietà di questa entità
318
        // esempio per users: filtering[username|contains]=mado
319 7
        if (in_array($filterObject->getFieldName(), $this->fields)) {
320 4
            $salt = '_' . random_int(111, 999);
321
322 4
            if ($filterObject->isListType()) {
323 1
                $whereCondition .= ' (:field_' . $filterObject->getFieldName() . $salt . ')';
324 3
            } else if ($filterObject->isFieldEqualityType()) {
325 1
                $whereCondition .= $this->entityAlias . '.' . $value;
326
            } else {
327 2
                $whereCondition .= ' :field_' . $filterObject->getFieldName() . $salt;
328
            }
329
330 4
            if (null != $orCondition['orCondition']) {
331
                $orCondition['orCondition'] .= ' OR ' . $whereCondition;
332
            } else {
333 4
                $orCondition['orCondition'] = $whereCondition;
334
            }
335
336 4
            if ($filterObject->haveOperatorSubstitutionPattern()) {
337 2
                if ($filterObject->isListType()) {
338 1
                    $value = explode(',', $value);
339
                } else {
340 1
                    $value = str_replace(
341 1
                        '{string}',
342 1
                        $value,
343 1
                        $filterObject->getOperatorsSubstitutionPattern()
344
                    );
345
                }
346
            }
347
348 4
            $orCondition['parameters'][] = [
349 4
                'field' => 'field_' . $filterObject->getFieldName() . $salt,
350 4
                'value' => $value
351
            ];
352
        } else {
353 3
            $isNotARelation = 0 !== strpos($filterObject->getFieldName(), 'Embedded.');
354 3
            if ($isNotARelation) {
355
                    $whereCondition .= ' ' . $this->entityAlias . '.' . $value;
356
                if (null != $orCondition['orCondition']) {
357
                    $orCondition['orCondition'] .= ' OR ' . $whereCondition;
358
                } else {
359
                    $orCondition['orCondition'] = $whereCondition;
360
                }
361
            }
362
        }
363
364
        // controllo se il filtro si riferisce ad una relazione dell'entità quindi devo fare dei join
365
        // esempio per users: filtering[_embedded.groups.name|eq]=admin
366 7
        if (strstr($filterObject->getRawFilter(), '_embedded.')) {
367
368 3
            $this->join($filterObject->getRawFilter(), self::OR_OPERATOR_LOGIC);
369 3
            $relationEntityAlias = $this->getRelationEntityAlias();
370
371 3
            $embeddedFields = explode('.', $filterObject->getFieldName());
372 3
            $embeddableFieldName = $this->parser->camelize($embeddedFields[count($embeddedFields) - 1]);
373
374 3
            $salt = '_' . random_int(111, 999);
375
376 3
            $whereCondition = $relationEntityAlias . '.' . $embeddableFieldName . ' '
377 3
                . $filterObject->getOperatorMeta();
378
379 3
            if ($filterObject->isListType()) {
380 1
                $whereCondition .= ' (:field_' . $embeddableFieldName . $salt . ')';
381
            } else {
382 2
                $whereCondition .= ' :field_' . $embeddableFieldName . $salt;
383
            }
384
385 3
            if (null != $orCondition['orCondition']) {
386 1
                $orCondition['orCondition'] .= ' OR ' . $whereCondition;
387
            } else {
388 3
                $orCondition['orCondition'] = $whereCondition;
389
            }
390
391 3
            if ($filterObject->haveOperatorSubstitutionPattern()) {
392 2
                if ($filterObject->isListType()) {
393 1
                    $value = explode(',', $value);
394
                } else {
395 1
                    $value = str_replace(
396 1
                        '{string}',
397 1
                        $value,
398 1
                        $filterObject->getOperatorsSubstitutionPattern()
399
                    );
400
                }
401
            }
402
403 3
            $orCondition['parameters'][] = [
404 3
                'field' => 'field_' . $embeddableFieldName . $salt,
405 3
                'value' => $value
406
            ];
407
        }
408
409 7
        return $orCondition;
410
    }
411
412 5
    public function sort()
413
    {
414 5
        if (!$this->fields) {
415 1
            throw new \RuntimeException(
416 1
                'Oops! Fields are not defined'
417
            );
418
        }
419
420 4
        if (null === $this->sorting) {
421 1
            throw new \RuntimeException(
422 1
                'Oops! Sorting is not defined'
423
            );
424
        }
425
426 3
        foreach ($this->sorting as $sort => $val) {
427 3
            $val = strtolower($val);
428
429 3
            $fieldName = $this->parser->camelize($sort);
430
431 3
            if (in_array($fieldName, $this->fields)) {
432 2
                $direction = ($val === self::DIRECTION_AZ) ? self::DIRECTION_AZ : self::DIRECTION_ZA;
433 2
                $this->ensureQueryBuilderIsDefined();
434 1
                $this->qBuilder->addOrderBy($this->entityAlias . '.' . $fieldName, $direction);
435
            }
436
437 2
            if (strstr($sort, '_embedded.')) {
438 1
                $this->join($sort);
439 1
                $relationEntityAlias = $this->getRelationEntityAlias();
440
441 1
                $embeddedFields = explode('.', $sort);
442 1
                $fieldName = $this->parser->camelize($embeddedFields[2]);
443 1
                $direction = ($val === self::DIRECTION_AZ) ? self::DIRECTION_AZ : self::DIRECTION_ZA;
444
445 2
                $this->qBuilder->addOrderBy($relationEntityAlias . '.' . $fieldName, $direction);
446
            }
447
448
        }
449
450 2
        return $this;
451
    }
452
453 14
    public function getQueryBuilder() :QueryBuilder
454
    {
455 14
        if (!$this->qBuilder) {
456 1
            throw new UnInitializedQueryBuilderException();
457
        }
458
459 13
        return $this->qBuilder;
460
    }
461
462 7
    private function setRelationEntityAlias(string $relationEntityAlias)
463
    {
464 7
        $this->relationEntityAlias = $relationEntityAlias;
465 7
    }
466
467 7
    private function getRelationEntityAlias()
468
    {
469 7
        return $this->relationEntityAlias;
470
    }
471
472 6
    public function setRel(array $rel)
473
    {
474 6
        $this->rel = $rel;
475
476 6
        return $this;
477
    }
478
479 2
    public function getRel() : array
480
    {
481 2
        return $this->rel;
482
    }
483
484 1
    public function addRel($relation)
485
    {
486 1
        array_push($this->rel, $relation);
487 1
    }
488
489 2
    public function setPrinting($printing)
490
    {
491 2
        $this->printing = $printing;
492
493 2
        return $this;
494
    }
495
496 1
    public function getPrinting()
497
    {
498 1
        return $this->printing;
499
    }
500
501 2
    public function setPage(int $page)
502
    {
503 2
        $this->page = $page;
504
505 2
        return $this;
506
    }
507
508 1
    public function getPage() :int
509
    {
510 1
        return $this->page;
511
    }
512
513 2
    public function setPageLength($pageLength)
514
    {
515 2
        $this->pageLength = $pageLength;
516
517 2
        return $this;
518
    }
519
520 1
    public function getPageLength()
521
    {
522 1
        return $this->pageLength;
523
    }
524
525 2
    public function setSelect($select) : QueryBuilderFactory
526
    {
527 2
        $this->select = $select;
528
529 2
        return $this;
530
    }
531
532 1
    public function getSelect()
533
    {
534 1
        return $this->select;
535
    }
536
537 1
    public function getEntityManager() : EntityManager
538
    {
539 1
        return $this->manager;
540
    }
541
542 2
    public function ensureQueryBuilderIsDefined()
543
    {
544 2
        if (!$this->qBuilder) {
545 1
            throw new \RuntimeException(
546
                'Oops! QueryBuilder was never initialized. '
547
                . "\n" . 'QueryBuilderFactory::createQueryBuilder()'
548 1
                . "\n" . 'QueryBuilderFactory::createSelectAndGroupBy()'
549
            );
550
        }
551 1
    }
552
}
553