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 — master ( 243f13...a9f992 )
by Simone
03:07
created

QueryBuilderFactory::buildSelectValue()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 9
ccs 0
cts 4
cp 0
crap 6
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
namespace Mado\QueryBundle\Queries;
4
5
use Doctrine\ORM\QueryBuilder;
6
use Mado\QueryBundle\Dictionary;
7
use Mado\QueryBundle\Exceptions;
8
use Mado\QueryBundle\Queries\Objects\FilterObject;
9
use Mado\QueryBundle\Queries\Objects\Operator;
0 ignored issues
show
Bug introduced by
The type Mado\QueryBundle\Queries\Objects\Operator was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
11
class QueryBuilderFactory extends AbstractQuery
12
{
13
    const DIRECTION_AZ = 'asc';
14
15
    const DIRECTION_ZA = 'desc';
16
17
    const DEFAULT_OPERATOR = 'eq';
18
19
    protected $qBuilder;
20
21
    protected $fields;
22
23
    protected $andFilters;
24
25
    protected $orFilters;
26
27
    protected $relationEntityAlias;
28
29
    protected $sorting;
30
31
    protected $joins;
32
33
    protected $rel;
34
35
    protected $printing;
36
37
    protected $page;
38
39
    protected $pageLength;
40
41
    protected $select;
42
43
    public function getAvailableFilters()
44
    {
45
        return array_keys($this->getValueAvailableFilters());
46
    }
47
48
    public function getValueAvailableFilters()
49
    {
50
        return Dictionary::getOperators();
51
    }
52
53
    public function setFields(array $fields = [])
54
    {
55
        $this->fields = $fields;
56
57
        return $this;
58
    }
59
60
    public function getFields()
61
    {
62
        if (null === $this->fields) {
63
            throw new \RuntimeException(
64
                'Oops! Fields are not defined'
65
            );
66
        }
67
68
        return $this->fields;
69
    }
70
71
    /** @deprecated since version 2.2.2 will be removed in version 2.3 */
72
    public function setFilters(array $andFilters = [])
73
    {
74
        $this->andFilters = $andFilters;
75
76 1
        return $this;
77
    }
78 1
79
    /** @since version 2.2.2 */
80
    public function setAndFilters(array $andFilters = [])
81
    {
82
        return $this->setFilters($andFilters);
0 ignored issues
show
Deprecated Code introduced by
The function Mado\QueryBundle\Queries...erFactory::setFilters() has been deprecated: since version 2.2.2 will be removed in version 2.3 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

82
        return /** @scrutinizer ignore-deprecated */ $this->setFilters($andFilters);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
83
    }
84
85
    public function setOrFilters(array $orFilters = [])
86
    {
87
        $this->orFilters = $orFilters;
88
89
        return $this;
90
    }
91
92
    public function setSorting(array $sorting = [])
93
    {
94
        $this->sorting = $sorting;
95
96
        return $this;
97
    }
98
99
    public function getAndFilters()
100
    {
101
        return $this->andFilters;
102
    }
103
104
    public function getOrFilters()
105
    {
106
        return $this->orFilters;
107
    }
108
109
    private function noExistsJoin($prevEntityAlias, $currentEntityAlias)
110
    {
111
        if (null === $this->joins) {
112
            $this->joins = [];
113
        }
114
115
        $needle = $prevEntityAlias . "_" . $currentEntityAlias;
116
117
        return ! in_array($needle, $this->joins);
118
    }
119
120
    private function storeJoin($prevEntityAlias, $currentEntityAlias)
121
    {
122
        $needle = $prevEntityAlias . "_" . $currentEntityAlias;
123
        $this->joins[$needle] = $needle;
124
    }
125
126
    /**
127
     * @param String $relation Nome della relazione semplice (groups.name) o con embedded (_embedded.groups.name)
128
     * @return $this
129
     */
130
    public function join(String $relation)
131
    {
132
        $relation = explode('|', $relation)[0];
133
        $relations = [$relation];
134
135
        if (strstr($relation, '_embedded.')) {
136
            $embeddedFields = explode('.', $relation);
137
            $relation = $this->parser->camelize($embeddedFields[1]);
0 ignored issues
show
Unused Code introduced by
The assignment to $relation is dead and can be removed.
Loading history...
138
139
            // elimino l'ultimo elemento che dovrebbe essere il nome del campo
140
            unset($embeddedFields[count($embeddedFields) - 1]);
141
142
            // elimino il primo elemento _embedded
143
            unset($embeddedFields[0]);
144
145
            $relations = $embeddedFields;
146
        }
147
148
        $entityName = $this->getEntityName();
149
        $entityAlias = $this->entityAlias;
150
151
        foreach ($relations as $relation) {
152
153
            $relation = $this->parser->camelize($relation);
154
            $relationEntityAlias = 'table_' . $relation;
155
156
            $metadata = $this->manager->getClassMetadata($entityName);
157
158
            if ($metadata->hasAssociation($relation)) {
159
160
                $association = $metadata->getAssociationMapping($relation);
161
162
                $fieldName = $this->parser->camelize($association['fieldName']);
163
164
                if ($this->noExistsJoin($relationEntityAlias, $relation)) {
165
                    $this->qBuilder->join($entityAlias . "." . $fieldName, $relationEntityAlias);
166
                    $this->storeJoin($relationEntityAlias, $relation);
167
                }
168
169
                $entityName = $association['targetEntity'];
170
                $entityAlias = $relationEntityAlias;
171
            }
172
173
            $this->setRelationEntityAlias($relationEntityAlias);
174
        }
175
176
        return $this;
177
    }
178
179
    public function filter()
180
    {
181
        if (null === $this->andFilters && null === $this->orFilters) {
182
            throw new Exceptions\MissingFiltersException();
183
        }
184
185
        if (!$this->fields) {
186
            throw new \RuntimeException(
187
                'Oops! Fields are not defined'
188
            );
189
        }
190
191
        if (null !== $this->andFilters) {
192
            foreach ($this->andFilters as $filter => $value) {
193
                $this->applyFilterAnd(
194
                    Objects\FilterObject::fromRawFilter($filter),
195
                    $value,
196
                    Objects\Value::fromFilter($value)
197
                );
198
            }
199
        }
200
201
        if (null !== $this->orFilters) {
202
            $orFilter = [];
203
            $orFilter['orCondition'] = null;
204
            $orFilter['parameters'] = [];
205
206
            foreach ($this->orFilters as $filter => $value) {
207
                $orFilter = $this->applyFilterOr(
208
                    Objects\FilterObject::fromRawFilter($filter),
209
                    $value,
210
                    $orFilter
211
                );
212
            }
213
214
            if ((count($orFilter) > 0) && ($orFilter['orCondition'] != null)) {
215
                $this->qBuilder->andWhere($orFilter['orCondition']);
216
217
                foreach ($orFilter['parameters'] as $parameter) {
218
                    $this->qBuilder->setParameter($parameter['field'], $parameter['value']);
219
                }
220
            }
221
        }
222
223
        return $this;
224
    }
225
226
    private function applyFilterAnd(
227
        Objects\FilterObject $filterObject,
228
        $value,
229
        Objects\Value $filterValue
230
    ) {
231
        $whereCondition = $this->entityAlias . '.' . $filterObject->getFieldName() . ' '
232
            . $filterObject->getOperatorMeta();
233
234
        if (in_array($filterObject->getFieldName(), $this->fields)) {
235
            $salt = '';
236
            foreach ($this->qBuilder->getParameters() as $parameter) {
237
                if ($parameter->getName() == 'field_' . $filterObject->getFieldName()) {
238
                    $salt = '_' . rand(111, 999);
239
                }
240
            }
241
242
            if ($filterObject->isListType()) {
243
                $whereCondition .= ' (:field_' . $filterObject->getFieldName() . $salt . ')';
244
            } elseif ($filterObject->isFieldEqualityType()) {
245
                $whereCondition .= ' ' . $this->entityAlias . '.' . $value;
246
            } else {
247
                $whereCondition .= ' :field_' . $filterObject->getFieldName() . $salt;
248
            }
249
250
            $this->qBuilder->andWhere($whereCondition);
251
252
            if ($filterObject->haveOperatorSubstitutionPattern()) {
253
                if ($filterObject->isListType()) {
254
                    $value = explode(',', $value);
255
                } else {
256
                    $value = str_replace(
257
                        '{string}',
258
                        $value,
259
                        $filterObject->getOperatorsSubstitutionPattern()
260
                    );
261
                }
262
            }
263
264
            $this->qBuilder->setParameter('field_' . $filterObject->getFieldName() . $salt, $value);
265
        } else {
266
            $isNotARelation = 0 !== strpos($filterObject->getFieldName(), 'Embedded.');
267
            if ($isNotARelation) {
268
                $whereCondition .= ' ' . $this->entityAlias . '.' . $value;
269
                $this->qBuilder->andWhere($whereCondition);
270
            }
271
        }
272
273
        // controllo se il filtro si riferisce ad una relazione dell'entità quindi devo fare dei join
274
        // esempio per users: filtering[_embedded.groups.name|eq]=admin
275
        if (strstr($filterObject->getRawFilter(), '_embedded.')) {
276
277
            $this->join($filterObject->getRawFilter());
278
            $relationEntityAlias = $this->getRelationEntityAlias();
279
280
            $embeddedFields = explode('.', $filterObject->getFieldName());
281
            $embeddedFieldName = $this->parser->camelize($embeddedFields[count($embeddedFields)-1]);
282
283
            $salt = '';
284
            foreach ($this->qBuilder->getParameters() as $parameter) {
285
                if ($parameter->getName() == 'field_' . $embeddedFieldName) {
286
                    $salt = '_' . rand(111, 999);
287
                }
288
            }
289
290
            $whereCondition = $relationEntityAlias . '.' . $embeddedFieldName . ' '
291
                . $filterObject->getOperatorMeta();
292
293
            if ($filterObject->isListType()) {
294
                $whereCondition .= ' (:field_' . $embeddedFieldName . $salt . ')';
295
            } else {
296
                $whereCondition .= ' :field_' . $embeddedFieldName . $salt;
297
            }
298
299
            $this->qBuilder->andWhere($whereCondition);
300
            if ($filterObject->haveOperatorSubstitutionPattern()) {
301
                if ($filterObject->isListType()) {
302
                    $value = explode(',', $filterValue->getFilter());
303
                } else {
304
                    $value = str_replace(
305
                        '{string}',
306
                        $value,
307
                        $filterObject->getOperatorsSubstitutionPattern()
308
                    );
309
                }
310
            }
311
312
            $this->qBuilder->setParameter('field_' . $embeddedFieldName . $salt, $value);
313
        }
314
    }
315
316
    private function applyFilterOr(
317
        Objects\FilterObject $filterObject,
318
        $value,
319
        $orCondition
320
    ) {
321
        $whereCondition = $this->entityAlias . '.' . $filterObject->getFieldName() . ' '
322
            . $filterObject->getOperatorMeta();
323
324
        // controllo se il filtro che mi arriva dalla richiesta è una proprietà di questa entità
325
        // esempio per users: filtering[username|contains]=mado
326
        if (in_array($filterObject->getFieldName(), $this->fields)) {
327
            $salt = '';
328
            foreach ($this->qBuilder->getParameters() as $parameter) {
329
                if ($parameter->getName() == 'field_' . $filterObject->getFieldName()) {
330
                    $salt = '_' . rand(111, 999);
331
                }
332
            }
333
334
            if ($salt == '') {
335
                $salt = '_' . rand(111, 999);
336
            }
337
338
            if ($filterObject->isListType()) {
339
                $whereCondition .= ' (:field_' . $filterObject->getFieldName() . $salt . ')';
340
            } else if ($filterObject->isFieldEqualityType()) {
341
                $whereCondition .= $this->entityAlias . '.' . $value;
342
            } else {
343
                $whereCondition .= ' :field_' . $filterObject->getFieldName() . $salt;
344
            }
345
346
            if ($orCondition['orCondition'] != null) {
347
                $orCondition['orCondition'] .= ' OR ' . $whereCondition;
348
            } else {
349
                $orCondition['orCondition'] = $whereCondition;
350
            }
351
352
            if ($filterObject->haveOperatorSubstitutionPattern()) {
353
                if ($filterObject->isListType()) {
354
                    $value = explode(',', $value);
355
                } else {
356
                    $value = str_replace(
357
                        '{string}',
358
                        $value,
359
                        $filterObject->getOperatorsSubstitutionPattern()
360
                    );
361
                }
362
            }
363
364
            $orCondition['parameters'][] = [
365
                'field' => 'field_' . $filterObject->getFieldName() . $salt,
366
                'value' => $value
367
            ];
368
        } else {
369
            $isNotARelation = 0 !== strpos($filterObject->getFieldName(), 'Embedded.');
370
            if ($isNotARelation) {
371
                    $whereCondition .= ' ' . $this->entityAlias . '.' . $value;
372
                if ($orCondition['orCondition'] != null) {
373
                    $orCondition['orCondition'] .= ' OR ' . $whereCondition;
374
                } else {
375
                    $orCondition['orCondition'] = $whereCondition;
376
                }
377
            }
378
        }
379
380
        // controllo se il filtro si riferisce ad una relazione dell'entità quindi devo fare dei join
381
        // esempio per users: filtering[_embedded.groups.name|eq]=admin
382
        if (strstr($filterObject->getRawFilter(), '_embedded.')) {
383
384
            $this->join($filterObject->getRawFilter());
385
            $relationEntityAlias = $this->getRelationEntityAlias();
386
387
            $embeddedFields = explode('.', $filterObject->getFieldName());
388
            $embeddableFieldName = $this->parser->camelize($embeddedFields[count($embeddedFields)-1]);
389
390
            $salt = '';
391
            foreach ($this->qBuilder->getParameters() as $parameter) {
392
                if ($parameter->getName() == 'field_' . $embeddableFieldName) {
393
                    $salt = '_' . rand(111, 999);
394
                }
395
            }
396
397
            if ($salt == '') {
398
                $salt = '_' . rand(111, 999);
399
            }
400
401
            $whereCondition = $relationEntityAlias . '.' . $embeddableFieldName . ' '
402
                . $filterObject->getOperatorMeta();
403
404
            if (isset($filterAndOperator[1]) && $op->isListOrNlist()) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $op seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $filterAndOperator seems to never exist and therefore isset should always be false.
Loading history...
405
                $whereCondition .= ' (:field_' . $embeddableFieldName . $salt . ')';
406
            } else {
407
                $whereCondition .=' :field_' . $embeddableFieldName . $salt;
408
            }
409
410
            if ($orCondition['orCondition'] != null) {
411
                $orCondition['orCondition'] .= ' OR ' . $whereCondition;
412
            } else {
413
                $orCondition['orCondition'] = $whereCondition;
414
            }
415
416
            if ($filterObject->haveOperatorSubstitutionPattern()) {
417
                if ($filterObject->isListType()) {
418
                    $value = explode(',', $value);
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type array; however, parameter $string of explode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

418
                    $value = explode(',', /** @scrutinizer ignore-type */ $value);
Loading history...
419
                } else {
420
                    $value = str_replace(
421
                        '{string}',
422
                        $value,
423
                        $filterObject->getOperatorsSubstitutionPattern()
424
                    );
425
                }
426
            }
427
428
            $orCondition['parameters'][] = [
429
                'field' => 'field_' . $embeddableFieldName . $salt,
430
                'value' => $value
431
            ];
432
        }
433
434
        return $orCondition;
435
    }
436
437
    public function sort()
438
    {
439
        if (!$this->fields) {
440
            throw new \RuntimeException(
441
                'Oops! Fields are not defined'
442
            );
443
        }
444
445
        if (null === $this->sorting) {
446
            throw new \RuntimeException(
447
                'Oops! Sorting is not defined'
448
            );
449
        }
450
451
        foreach ($this->sorting as $sort => $val) {
452
            $val = strtolower($val);
453
454
            $fieldName = $this->parser->camelize($sort);
455
456
            if (in_array($fieldName, $this->fields)) {
457
                $direction = ($val === self::DIRECTION_AZ) ? self::DIRECTION_AZ : self::DIRECTION_ZA;
458
                $this->qBuilder->addOrderBy($this->entityAlias .'.'. $fieldName, $direction);
459
            }
460
461
            if (strstr($sort, '_embedded.')) {
462
                $this->join($sort);
463
                $relationEntityAlias = $this->getRelationEntityAlias();
464
465
                $embeddedFields = explode('.', $sort);
466
                $fieldName = $this->parser->camelize($embeddedFields[2]);
467
                $direction = ($val === self::DIRECTION_AZ) ? self::DIRECTION_AZ : self::DIRECTION_ZA;
468
469
                $this->qBuilder->addOrderBy($relationEntityAlias.'.'.$fieldName, $direction);
470
            }
471
472
        }
473
474
        return $this;
475
    }
476
477
    public function getQueryBuilder()
478
    {
479
        if (!$this->qBuilder) {
480
            throw new \RuntimeException(
481
                "Oops! Query builder was never initialized! call ::createQueryBuilder('entityName', 'alias') to start."
482
            );
483
        }
484
485
        return $this->qBuilder;
486
    }
487
488
    private function setRelationEntityAlias(string $relationEntityAlias)
489
    {
490
        $this->relationEntityAlias = $relationEntityAlias;
491
    }
492
493
    private function getRelationEntityAlias()
494
    {
495
        return $this->relationEntityAlias;
496
    }
497
498
    public function setRel($rel)
499
    {
500
        $this->rel = $rel;
501
502
        return $this;
503
    }
504
505
    public function getRel()
506
    {
507
        return $this->rel;
508
    }
509
510
    public function setPrinting($printing)
511
    {
512
        $this->printing = $printing;
513
514
        return $this;
515
    }
516
517
    public function getPrinting()
518
    {
519
        return $this->printing;
520
    }
521
522
    public function setPage($page)
523
    {
524
        $this->page = $page;
525
526
        return $this;
527
    }
528
529
    public function getPage()
530
    {
531
        return $this->page;
532
    }
533
534
    public function setPageLength($pageLength)
535
    {
536
        $this->pageLength = $pageLength;
537
538
        return $this;
539
    }
540
541
    public function getPageLength()
542
    {
543
        return $this->pageLength;
544
    }
545
546
    public function setSelect( $select) : QueryBuilderFactory
547
    {
548
        $this->select = $select;
549
550
        return $this;
551
    }
552
553
    public function getSelect()
554
    {
555
        return $this->select;
556
    }
557
558
    public function getEntityManager()
559
    {
560
        return $this->manager;
561
    }
562
}
563