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 — master (#37)
by Simone
08:46
created

QueryBuilderFactory::getSelect()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Mado\QueryBundle\Queries;
4
5
use Mado\QueryBundle\Objects\FilteringObject;
6
use Mado\QueryBundle\Objects\Operator;
7
use Mado\QueryBundle\Vocabulary\Operators;
8
9
class QueryBuilderFactory extends AbstractQuery
10
{
11
    const DIRECTION_AZ = 'asc';
12
13
    const DIRECTION_ZA = 'desc';
14
15
    /**
16
     * @var QueryBuilder
17
     */
18
    protected $qBuilder;
19
20
    protected $fields;
21
22
    protected $filtering;
23
24
    protected $orFiltering;
25
26
    protected $relationEntityAlias;
27
28
    protected $sorting;
29
30
    protected $joins;
31
32
    protected $rel;
33
34
    protected $printing;
35
36
    protected $page;
37
38
    protected $pageLength;
39
40
    protected $select;
41
42 1
    public function getAvailableFilters()
43
    {
44 1
        return array_keys(Operators::getAll());
45
    }
46
47
    public function setFields(array $fields = [])
48
    {
49
        $this->fields = $fields;
50
51
        return $this;
52
    }
53
54
    public function getFields()
55
    {
56
        if (null === $this->fields) {
57
            throw new \RuntimeException(
58
                'Oops! Fields are not defined'
59
            );
60
        }
61
62
        return $this->fields;
63
    }
64
65
    public function setFilters(array $filtering = [])
66
    {
67
        $this->filtering = $filtering;
68
69
        return $this;
70
    }
71
72
    public function setOrFilters(array $orFiltering = [])
73
    {
74
        $this->orFiltering = $orFiltering;
75
76
        return $this;
77
    }
78
79
    public function setSorting(array $sorting = [])
80
    {
81
        $this->sorting = $sorting;
82
83
        return $this;
84
    }
85
86
    public function getFilters()
87
    {
88
        return $this->filtering;
89
    }
90
91
    public function getOrFilters()
92
    {
93
        return $this->orFiltering;
94
    }
95
96
    private function noExistsJoin($prevEntityAlias, $currentEntityAlias)
97
    {
98
        if (null === $this->joins) {
99
            $this->joins = [];
100
        }
101
102
        $needle = $prevEntityAlias . "_" . $currentEntityAlias;
103
104
        return ! in_array($needle, $this->joins);
105
    }
106
107
    private function storeJoin($prevEntityAlias, $currentEntityAlias)
108
    {
109
        $needle = $prevEntityAlias . "_" . $currentEntityAlias;
110
        $this->joins[$needle] = $needle;
111
    }
112
113
    /**
114
     * @param String $relation Nome della relazione semplice (groups.name) o con embedded (_embedded.groups.name)
115
     * @return $this
116
     */
117
    public function join(String $relation)
118
    {
119
        $relation = explode('|', $relation)[0];
120
        $relations = [$relation];
121
122
        if (strstr($relation, '_embedded.')) {
123
            $embeddedFields = explode('.', $relation);
124
125
            // elimino l'ultimo elemento che dovrebbe essere il nome del campo
126
            unset($embeddedFields[count($embeddedFields) - 1]);
127
128
            // elimino il primo elemento _embedded
129
            unset($embeddedFields[0]);
130
131
            $relations = $embeddedFields;
132
        }
133
134
        $entityName = $this->getEntityName();
135
        $entityAlias = $this->entityAlias;
136
137
        foreach ($relations as $relation) {
138
139
            $relation = $this->parser->camelize($relation);
140
            $relationEntityAlias = 'table_' . $relation;
141
142
            $metadata = $this->manager->getClassMetadata($entityName);
143
144
            if ($metadata->hasAssociation($relation)) {
145
146
                $association = $metadata->getAssociationMapping($relation);
147
148
                $fieldName = $this->parser->camelize($association['fieldName']);
149
150
                if ($this->noExistsJoin($relationEntityAlias, $relation)) {
151
152
                    $this->qBuilder
153
                            ->join($entityAlias . "." . $fieldName, $relationEntityAlias);
154
155
                    $this->storeJoin($relationEntityAlias, $relation);
156
                }
157
                $entityName = $association['targetEntity'];
158
                $entityAlias = $relationEntityAlias;
159
            }
160
161
            $this->setRelationEntityAlias($relationEntityAlias);
162
        }
163
164
        return $this;
165
    }
166
167
    public function filter()
168
    {
169
        if (null === $this->filtering) {
170
            throw new \RuntimeException(
171
                'Oops! Filtering is not defined'
172
            );
173
        }
174
175
        if (!$this->fields) {
176
            throw new \RuntimeException(
177
                'Oops! Fields are not defined'
178
            );
179
        }
180
181
        foreach ($this->filtering as $filter => $value) {
182
            $this->applyFilterAnd($filter, $value);
183
        }
184
185
        if (null !== $this->orFiltering) {
186
            $orFilter = [];
187
            $orFilter['orCondition'] = null;
188
            $orFilter['parameters'] = [];
189
190
            foreach ($this->orFiltering as $filter => $value) {
191
                $orFilter = $this->applyFilterOr($filter, $value, $orFilter);
192
            }
193
194
            if ((count($orFilter) > 0) && ($orFilter['orCondition'] != null)) {
195
                $this->qBuilder->andWhere($orFilter['orCondition']);
196
197
                foreach ($orFilter['parameters'] as $parameter) {
198
                    $this->qBuilder->setParameter($parameter['field'], $parameter['value']);
199
                }
200
            }
201
        }
202
203
        return $this;
204
    }
205
206
    private function applyFilterAnd($filter, $value)
207
    {
208
        $whereCondition = null;
209
        $filtering = FilteringObject::fromFilter($filter);
210
        $fieldName = $this->parser->camelize($filtering->getFieldName());
211
212
        $op = Operator::fromFilteringObject($filtering);
213
214
        if (in_array($fieldName, $this->fields)) {
215
216
            $salt = '';
217 View Code Duplication
            foreach ($this->qBuilder->getParameters() as $parameter) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
218
                if ($parameter->getName() == 'field_' . $fieldName) {
219
                    $salt = '_' . rand(111, 999);
220
                }
221
            }
222
223
            if ($filtering->hasOperator()) {
224 View Code Duplication
                if ('list' == $filtering->getOperator()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
225
                    $whereCondition = $this->entityAlias.'.'.$fieldName.' '.
226
                        $op->getMeta()
227
                        .' (:field_'.$fieldName . $salt . ')';
228
                } else if ('field_eq' == $filtering->getOperator()) {
229
                    $whereCondition =
230
                        $this->entityAlias . '.' . $fieldName . ' '.
231
                        $op->getMeta() . ' ' .
232
                        $this->entityAlias . '.' . $value
233
                        ;
234
                } else {
235
                    $whereCondition = $this->entityAlias . '.' . $fieldName . ' ' .
236
                        $op->getMeta() . ' :field_' . $fieldName . $salt;
237
                }
238
            } else {
239
                $whereCondition = $this->entityAlias . '.' . $fieldName .  ' ' .
240
                    $op->getMeta() .
241
                    ' ' .  ':field_' . $fieldName . $salt;
242
            }
243
244
            $this->qBuilder->andWhere($whereCondition);
245
246 View Code Duplication
            if ($op->haveSubstitutionPattern()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
247
                if ($filtering->hasOperator() && 'list' == $filtering->getOperator()) {
248
                    $value = explode(',', $value);
249
                } else {
250
                    $value = str_replace(
251
                        '{string}',
252
                        $value,
253
                        $op->getSubstitutionPattern()
254
                    );
255
                }
256
            }
257
258
            $this->qBuilder->setParameter('field_' . $fieldName . $salt, $value);
259
        } else {
260
            $isNotARelation = 0 !== strpos($fieldName, 'Embedded.');
261
            if ($isNotARelation) {
262
                $whereCondition = $this->entityAlias.'.'.$fieldName.' '.
263
                    $op->getMeta()
264
                    .' ' . $this->entityAlias . '.' . $value;
265
                $this->qBuilder->andWhere($whereCondition);
266
            }
267
        }
268
269
        if (strstr($filter, '_embedded.')) {
270
271
            $this->join($filter);
272
            $relationEntityAlias = $this->getRelationEntityAlias();
273
274
            $embeddedFields = explode('.', $fieldName);
275
            $fieldName = $this->parser->camelize($embeddedFields[count($embeddedFields)-1]);
276
277
            $salt = '';
278 View Code Duplication
            foreach ($this->qBuilder->getParameters() as $parameter) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
279
                if ($parameter->getName() == 'field_' . $fieldName) {
280
                    $salt = '_' . rand(111, 999);
281
                }
282
            }
283
284 View Code Duplication
            if ($filtering->hasOperator() && 'list' == $filtering->getOperator()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
285
                $whereCondition = $relationEntityAlias . '.' . $fieldName . ' ' .
286
                    $op->getMeta() .
287
                    ' (:field_'.$fieldName . $salt . ')';
288
            } else {
289
                $whereCondition = $relationEntityAlias . '.' . $fieldName . ' ' .
290
                    $op->getMeta() .
291
                    ' :field_'.$fieldName . $salt;
292
            }
293
294
            $this->qBuilder->andWhere($whereCondition);
295 View Code Duplication
            if ($op->haveSubstitutionPattern()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
296
                if ($filtering->hasOperator() && 'list' == $filtering->getOperator()) {
297
                    $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

297
                    $value = explode(',', /** @scrutinizer ignore-type */ $value);
Loading history...
298
                } else {
299
                    $value = str_replace(
300
                        '{string}',
301
                        $value,
302
                        $op->getSubstitutionPattern()
303
                    );
304
                }
305
            }
306
307
            $this->qBuilder->setParameter('field_' . $fieldName . $salt, $value);
308
        }
309
    }
310
311
    private function applyFilterOr($filter, $value, $orCondition)
312
    {
313
        $whereCondition = null;
314
        $filtering = FilteringObject::fromFilter($filter);
315
316
        $fieldName = $this->parser->camelize($filtering->getFieldName());
317
318
        $op = Operator::fromFilteringObject($filtering);
319
320
        if (in_array($fieldName, $this->fields)) {
321
322
            $salt = '';
323 View Code Duplication
            foreach ($this->qBuilder->getParameters() as $parameter) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
324
                if ($parameter->getName() == 'field_' . $fieldName) {
325
                    $salt = '_' . rand(111, 999);
326
                }
327
            }
328
329
            if ($filtering->hasOperator()) {
330 View Code Duplication
                if ('list' == $filtering->getOperator()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
331
                    $whereCondition = $this->entityAlias.'.'.$fieldName.' '.
332
                        $op->getMeta()
333
                        .' (:field_'.$fieldName . $salt . ')';
334
                } else if ('field_eq' == $filtering->getOperator()) {
335
                    $whereCondition =
336
                        $this->entityAlias . '.' . $fieldName . ' '.
337
                        $op->getMeta()
338
                        . '' .
339
                        $this->entityAlias . '.' . $value
340
                    ;
341
                    //} else {
342
                    //throw new \RuntimeException(
343
                    //'Oops! Eccezzione'
344
                    //);
345
                } else {
346
                    $whereCondition = $this->entityAlias.'.'.$fieldName.' '.
347
                        $op->getMeta()
348
                        .' :field_'.$fieldName . $salt;
349
                }
350
            } else {
351
                $whereCondition = $this->entityAlias.'.'.$fieldName.' = :field_'.$fieldName . $salt;
352
            }
353
354 View Code Duplication
            if ($orCondition['orCondition'] != null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
355
                $orCondition['orCondition'] .= ' OR ' . $whereCondition;
356
            } else {
357
                $orCondition['orCondition'] = $whereCondition;
358
            }
359
360 View Code Duplication
            if ($op->haveSubstitutionPattern()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
361
                if ($filtering->hasOperator() && 'list' == $filtering->getOperator()) {
362
                    $value = explode(',', $value);
363
                } else {
364
                    $value = str_replace(
365
                        '{string}',
366
                        $value,
367
                        $op->getSubstitutionPattern()
368
                    );
369
                }
370
            }
371
372
            $orCondition['parameters'][] = [
373
                'field' => 'field_' . $fieldName . $salt,
374
                'value' => $value
375
            ];
376
        } else {
377
            $isNotARelation = 0 !== strpos($fieldName, 'Embedded.');
378
            if ($isNotARelation) {
379
                $whereCondition = $this->entityAlias.'.'.$fieldName.' '.
380
                    $op->getMeta()
381
                    .' ' . $this->entityAlias . '.' . $value;
382 View Code Duplication
                if ($orCondition['orCondition'] != null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
383
                    $orCondition['orCondition'] .= ' OR ' . $whereCondition;
384
                } else {
385
                    $orCondition['orCondition'] = $whereCondition;
386
                }
387
            }
388
        }
389
390
        // controllo se il filtro si riferisce ad una relazione dell'entità quindi devo fare dei join
391
        // esempio per users: filtering[_embedded.groups.name|eq]=admin
392
        if (strstr($filter, '_embedded.')) {
393
394
            $this->join($filter);
395
            $relationEntityAlias = $this->getRelationEntityAlias();
396
397
            $embeddedFields = explode('.', $fieldName);
398
            $fieldName = $this->parser->camelize($embeddedFields[count($embeddedFields)-1]);
399
400
            $salt = '';
401 View Code Duplication
            foreach ($this->qBuilder->getParameters() as $parameter) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
402
                if ($parameter->getName() == 'field_' . $fieldName) {
403
                    $salt = '_' . rand(111, 999);
404
                }
405
            }
406
407 View Code Duplication
            if ($filtering->hasOperator() && 'list' == $filtering->getOperator()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
408
                $whereCondition = $relationEntityAlias.'.'.$fieldName.' '.
409
                    $op->getMeta()
410
                    .' (:field_'.$fieldName . $salt . ')';
411
            } else {
412
                $whereCondition = $relationEntityAlias.'.'.$fieldName.' '.
413
                    $op->getMeta()
414
                    .' :field_'.$fieldName . $salt;
415
            }
416
417 View Code Duplication
            if ($orCondition['orCondition'] != null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
418
                $orCondition['orCondition'] .= ' OR ' . $whereCondition;
419
            } else {
420
                $orCondition['orCondition'] = $whereCondition;
421
            }
422
423 View Code Duplication
            if ($op->haveSubstitutionPattern()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
424
                if ($filtering->hasOperator() && 'list' == $filtering->getOperator()) {
425
                    $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

425
                    $value = explode(',', /** @scrutinizer ignore-type */ $value);
Loading history...
426
                } else {
427
                    $value = str_replace(
428
                        '{string}',
429
                        $value,
430
                        $op->getSubstitutionPattern()
431
                    );
432
                }
433
            }
434
435
            $orCondition['parameters'][] = [
436
                'field' => 'field_' . $fieldName . $salt,
437
                'value' => $value
438
            ];
439
        }
440
441
        return $orCondition;
442
    }
443
444
    public function sort()
445
    {
446
        if (!$this->fields) {
447
            throw new \RuntimeException(
448
                'Oops! Fields are not defined'
449
            );
450
        }
451
452
        if (null === $this->sorting) {
453
            throw new \RuntimeException(
454
                'Oops! Sorting is not defined'
455
            );
456
        }
457
458
        foreach ($this->sorting as $sort => $val) {
459
            $val = strtolower($val);
460
461
            $fieldName = $this->parser->camelize($sort);
462
463
            if (in_array($fieldName, $this->fields)) {
464
                $direction = ($val === self::DIRECTION_AZ) ? self::DIRECTION_AZ : self::DIRECTION_ZA;
465
                $this->qBuilder->addOrderBy($this->entityAlias .'.'. $fieldName, $direction);
466
            }
467
468
            if (strstr($sort, '_embedded.')) {
469
                $this->join($sort);
470
                $relationEntityAlias = $this->getRelationEntityAlias();
471
472
                $embeddedFields = explode('.', $sort);
473
                $fieldName = $this->parser->camelize($embeddedFields[2]);
474
                $direction = ($val === self::DIRECTION_AZ) ? self::DIRECTION_AZ : self::DIRECTION_ZA;
475
476
                $this->qBuilder->addOrderBy($relationEntityAlias.'.'.$fieldName, $direction);
477
            }
478
479
        }
480
481
        return $this;
482
    }
483
484
    public function getQueryBuilder()
485
    {
486
        if (!$this->qBuilder) {
487
            throw new \RuntimeException(
488
                "Oops! Query builder was never initialized! call ::createQueryBuilder('entityName', 'alias') to start."
489
            );
490
        }
491
492
        return $this->qBuilder;
493
    }
494
495
    public function buildSelectValue() : string
496
    {
497
        if ("" == $this->getSelect()) {
498
            return $this->getEntityAlias(
0 ignored issues
show
Bug introduced by
The method getEntityAlias() does not exist on Mado\QueryBundle\Queries\QueryBuilderFactory. Did you maybe mean getEntityName()? ( Ignorable by Annotation )

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

498
            return $this->/** @scrutinizer ignore-call */ getEntityAlias(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
499
                $this->getEntityName()
500
            );
501
        }
502
503
        return $this->getSelect();
504
    }
505
506
    private function setRelationEntityAlias(string $relationEntityAlias)
507
    {
508
        $this->relationEntityAlias = $relationEntityAlias;
509
    }
510
511
    private function getRelationEntityAlias()
512
    {
513
        return $this->relationEntityAlias;
514
    }
515
516
    public function setRel($rel)
517
    {
518
        $this->rel = $rel;
519
520
        return $this;
521
    }
522
523
    public function getRel()
524
    {
525
        return $this->rel;
526
    }
527
528
    public function setPrinting($printing)
529
    {
530
        $this->printing = $printing;
531
532
        return $this;
533
    }
534
535
    public function getPrinting()
536
    {
537
        return $this->printing;
538
    }
539
540
    public function setPage($page)
541
    {
542
        $this->page = $page;
543
544
        return $this;
545
    }
546
547
    public function getPage()
548
    {
549
        return $this->page;
550
    }
551
552
    public function setPageLength($pageLength)
553
    {
554
        $this->pageLength = $pageLength;
555
556
        return $this;
557
    }
558
559
    public function getPageLength()
560
    {
561
        return $this->pageLength;
562
    }
563
564
    public function setSelect(string $select) : QueryBuilderFactory
565
    {
566
        $this->select = $select;
567
568
        return $this;
569
    }
570
571
    public function getSelect()
572
    {
573
        return $this->select;
574
    }
575
576
    public function getEntityManager()
577
    {
578
        return $this->manager;
579
    }
580
}
581