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
Push — resolve/103/add-relation ( 9d4faf )
by Simone
41:55 queued 38:41
created

QueryBuilderFactory::setRelationEntityAlias()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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