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
07:10
created

QueryBuilderFactory::getRelationEntityAlias()   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
                if ('list' == $filtering->getOperator()) {
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 View Code Duplication
                } else {
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...
235
                    $whereCondition = $this->entityAlias . '.' . $fieldName . ' ' .
236
                        $op->getMeta() . ' :field_' . $fieldName . $salt;
237
                }
238 View Code Duplication
            } else {
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...
239
                $whereCondition = $this->entityAlias . '.' . $fieldName .  ' ' .
240
                    $op->getMeta() .
241
                    ' ' .  ':field_' . $fieldName . $salt;
242
            }
243
244
            $this->qBuilder->andWhere($whereCondition);
245
246
            if ($op->haveSubstitutionPattern()) {
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
            if ($filtering->hasOperator() && 'list' == $filtering->getOperator()) {
285
                $whereCondition = $relationEntityAlias . '.' . $fieldName . ' ' .
286
                    $op->getMeta() .
287
                    ' (:field_'.$fieldName . $salt . ')';
288 View Code Duplication
            } else {
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...
289
                $whereCondition = $relationEntityAlias . '.' . $fieldName . ' ' .
290
                    $op->getMeta() .
291
                    ' :field_'.$fieldName . $salt;
292
            }
293
294
            $this->qBuilder->andWhere($whereCondition);
295
            if ($op->haveSubstitutionPattern()) {
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
        $operator = Operators::getDefaultOperator();
319
        if($filtering->hasOperator()) {
320
            $operator = Operators::get($filtering->getOperator());
321
        }
322
323
        // controllo se il filtro che mi arriva dalla richiesta è una proprietà di questa entità
324
        // esempio per users: filtering[username|contains]=mado
325
        if (in_array($fieldName, $this->fields)) {
326
327
            $salt = '';
328 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...
329
                if ($parameter->getName() == 'field_' . $fieldName) {
330
                    $salt = '_' . rand(111, 999);
331
                }
332
            }
333
334
            if ($filtering->hasOperator()) {
335
                if ('list' == $filtering->getOperator()) {
336
                    $whereCondition = $this->entityAlias.'.'.$fieldName.' '.$operator['meta'].' (:field_'.$fieldName . $salt . ')';
337
                } else if ('field_eq' == $filtering->getOperator()) {
338
                    $whereCondition =
339
                        $this->entityAlias . '.' . $fieldName . ' '.
340
                        $operator['meta'] . '' .
341
                        $this->entityAlias . '.' . $value
342
                    ;
343
                    //} else {
344
                    //throw new \RuntimeException(
345
                    //'Oops! Eccezzione'
346
                    //);
347
                } else {
348
                    $whereCondition = $this->entityAlias.'.'.$fieldName.' '.$operator['meta'].' :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 (isset($operator['substitution_pattern'])) {
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
                        $operator['substitution_pattern']
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.' '.$operator['meta'].' ' . $this->entityAlias . '.' . $value;
380 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...
381
                    $orCondition['orCondition'] .= ' OR ' . $whereCondition;
382
                } else {
383
                    $orCondition['orCondition'] = $whereCondition;
384
                }
385
            }
386
        }
387
388
        // controllo se il filtro si riferisce ad una relazione dell'entità quindi devo fare dei join
389
        // esempio per users: filtering[_embedded.groups.name|eq]=admin
390
        if (strstr($filter, '_embedded.')) {
391
392
            $this->join($filter);
393
            $relationEntityAlias = $this->getRelationEntityAlias();
394
395
            $embeddedFields = explode('.', $fieldName);
396
            $fieldName = $this->parser->camelize($embeddedFields[count($embeddedFields)-1]);
397
398
            $salt = '';
399 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...
400
                if ($parameter->getName() == 'field_' . $fieldName) {
401
                    $salt = '_' . rand(111, 999);
402
                }
403
            }
404
405
            if ($filtering->hasOperator() && 'list' == $filtering->getOperator()) {
406
                $whereCondition = $relationEntityAlias.'.'.$fieldName.' '.$operator['meta'].' (:field_'.$fieldName . $salt . ')';
407
            } else {
408
                $whereCondition = $relationEntityAlias.'.'.$fieldName.' '.$operator['meta'].' :field_'.$fieldName . $salt;
409
            }
410
411 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...
412
                $orCondition['orCondition'] .= ' OR ' . $whereCondition;
413
            } else {
414
                $orCondition['orCondition'] = $whereCondition;
415
            }
416
417 View Code Duplication
            if (isset($operator['substitution_pattern'])) {
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
                if ($filtering->hasOperator() && 'list' == $filtering->getOperator()) {
419
                    $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

419
                    $value = explode(',', /** @scrutinizer ignore-type */ $value);
Loading history...
420
                } else {
421
                    $value = str_replace(
422
                        '{string}',
423
                        $value,
424
                        $operator['substitution_pattern']
425
                    );
426
                }
427
            }
428
429
            $orCondition['parameters'][] = [
430
                'field' => 'field_' . $fieldName . $salt,
431
                'value' => $value
432
            ];
433
        }
434
435
        return $orCondition;
436
    }
437
438
    public function sort()
439
    {
440
        if (!$this->fields) {
441
            throw new \RuntimeException(
442
                'Oops! Fields are not defined'
443
            );
444
        }
445
446
        if (null === $this->sorting) {
447
            throw new \RuntimeException(
448
                'Oops! Sorting is not defined'
449
            );
450
        }
451
452
        foreach ($this->sorting as $sort => $val) {
453
            $val = strtolower($val);
454
455
            $fieldName = $this->parser->camelize($sort);
456
457
            if (in_array($fieldName, $this->fields)) {
458
                $direction = ($val === self::DIRECTION_AZ) ? self::DIRECTION_AZ : self::DIRECTION_ZA;
459
                $this->qBuilder->addOrderBy($this->entityAlias .'.'. $fieldName, $direction);
460
            }
461
462
            if (strstr($sort, '_embedded.')) {
463
                $this->join($sort);
464
                $relationEntityAlias = $this->getRelationEntityAlias();
465
466
                $embeddedFields = explode('.', $sort);
467
                $fieldName = $this->parser->camelize($embeddedFields[2]);
468
                $direction = ($val === self::DIRECTION_AZ) ? self::DIRECTION_AZ : self::DIRECTION_ZA;
469
470
                $this->qBuilder->addOrderBy($relationEntityAlias.'.'.$fieldName, $direction);
471
            }
472
473
        }
474
475
        return $this;
476
    }
477
478
    public function getQueryBuilder()
479
    {
480
        if (!$this->qBuilder) {
481
            throw new \RuntimeException(
482
                "Oops! Query builder was never initialized! call ::createQueryBuilder('entityName', 'alias') to start."
483
            );
484
        }
485
486
        return $this->qBuilder;
487
    }
488
489
    public function buildSelectValue() : string
490
    {
491
        if ("" == $this->getSelect()) {
492
            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

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