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 ( 1ab2ca...448645 )
by Simone
07:34 queued 05:12
created

QueryBuilderFactory::setSorting()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
ccs 0
cts 3
cp 0
crap 2
rs 9.4285
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
    protected $qBuilder;
16
17
    protected $fields;
18
19
    protected $filtering;
20
21
    protected $orFiltering;
22
23
    protected $relationEntityAlias;
24
25
    protected $sorting;
26
27
    protected $joins;
28
29
    protected $rel;
30
31
    protected $printing;
32
33
    protected $page;
34
35
    protected $pageLength;
36
37
    protected $select;
38
39
    private function ensureFieldsDefined()
40
    {
41
        if (!$this->fields) {
42
            throw new \RuntimeException(
43
                'Oops! Fields are not defined'
44
            );
45
        }
46
    }
47
48
    private function ensureSortingIsDefined()
49
    {
50
        if (null === $this->sorting) {
51
            throw new \RuntimeException(
52
                'Oops! Sorting is not defined'
53
            );
54
        }
55
    }
56
57
    private function ensureFilteringIsDefined()
58
    {
59
        if (null === $this->filtering) {
60
            throw new \RuntimeException(
61
                'Oops! Filtering is not defined'
62
            );
63
        }
64
    }
65
66
    private function ensureQueryBuilderIsDefined()
67
    {
68
        if (!$this->qBuilder) {
69
            throw new \RuntimeException(
70
                "Oops! Query builder was never initialized! call ::createQueryBuilder('entityName', 'alias') to start."
71
            );
72
        }
73
    }
74
75 1
    public function getAvailableFilters()
76
    {
77 1
        return array_keys(Operators::getAll());
78
    }
79
80
    public function setFields(array $fields = [])
81
    {
82
        $this->fields = $fields;
83
84
        return $this;
85
    }
86
87
    public function getFields()
88
    {
89
        $this->ensureFieldsDefined();
90
91
        return $this->fields;
92
    }
93
94
    public function setFilters(array $filtering = [])
95
    {
96
        $this->filtering = $filtering;
97
98
        return $this;
99
    }
100
101
    public function setOrFilters(array $orFiltering = [])
102
    {
103
        $this->orFiltering = $orFiltering;
104
105
        return $this;
106
    }
107
108
    public function setSorting(array $sorting = [])
109
    {
110
        $this->sorting = $sorting;
111
112
        return $this;
113
    }
114
115
    public function getFilters()
116
    {
117
        return $this->filtering;
118
    }
119
120
    public function getOrFilters()
121
    {
122
        return $this->orFiltering;
123
    }
124
125
    private function noExistsJoin($prevEntityAlias, $currentEntityAlias)
126
    {
127
        if (null === $this->joins) {
128
            $this->joins = [];
129
        }
130
131
        $needle = $prevEntityAlias . "_" . $currentEntityAlias;
132
133
        return ! in_array($needle, $this->joins);
134
    }
135
136
    private function storeJoin($prevEntityAlias, $currentEntityAlias)
137
    {
138
        $needle = $prevEntityAlias . "_" . $currentEntityAlias;
139
        $this->joins[$needle] = $needle;
140
    }
141
142
    public function join(String $relation)
143
    {
144
        $relation = explode('|', $relation)[0];
145
        $relations = [$relation];
146
147
        if (strstr($relation, '_embedded.')) {
148
            $embeddedFields = explode('.', $relation);
149
            unset($embeddedFields[count($embeddedFields) - 1]);
150
            unset($embeddedFields[0]);
151
            $relations = $embeddedFields;
152
        }
153
154
        $entityName = $this->getEntityName();
155
        $entityAlias = $this->entityAlias;
156
157
        foreach ($relations as $relation) {
158
159
            $relation = $this->parser->camelize($relation);
160
            $relationEntityAlias = 'table_' . $relation;
161
162
            $metadata = $this->manager->getClassMetadata($entityName);
163
164
            if ($metadata->hasAssociation($relation)) {
165
166
                $association = $metadata->getAssociationMapping($relation);
167
168
                $fieldName = $this->parser->camelize($association['fieldName']);
169
170
                if ($this->noExistsJoin($relationEntityAlias, $relation)) {
171
172
                    $this->qBuilder
173
                            ->join($entityAlias . "." . $fieldName, $relationEntityAlias);
174
175
                    $this->storeJoin($relationEntityAlias, $relation);
176
                }
177
                $entityName = $association['targetEntity'];
178
                $entityAlias = $relationEntityAlias;
179
            }
180
181
            $this->setRelationEntityAlias($relationEntityAlias);
182
        }
183
184
        return $this;
185
    }
186
187
    public function filter()
188
    {
189
        $this->ensureFilteringIsDefined();
190
        $this->ensureFieldsDefined();
191
192
        foreach ($this->filtering as $filter => $value) {
193
            $this->applyFilterAnd($filter, $value);
194
        }
195
196
        if (null !== $this->orFiltering) {
197
            $orFilter = [];
198
            $orFilter['orCondition'] = null;
199
            $orFilter['parameters'] = [];
200
201
            foreach ($this->orFiltering as $filter => $value) {
202
                $orFilter = $this->applyFilterOr($filter, $value, $orFilter);
203
            }
204
205
            if ((count($orFilter) > 0) && ($orFilter['orCondition'] != null)) {
206
                $this->qBuilder->andWhere($orFilter['orCondition']);
207
208
                foreach ($orFilter['parameters'] as $parameter) {
209
                    $this->qBuilder->setParameter($parameter['field'], $parameter['value']);
210
                }
211
            }
212
        }
213
214
        return $this;
215
    }
216
217
    private function applyFilterAnd($filter, $value)
218
    {
219
        $whereCondition = null;
220
        $filtering = FilteringObject::fromFilter($filter);
221
        $fieldName = $this->parser->camelize($filtering->getFieldName());
222
223
        $op = Operator::fromFilteringObject($filtering);
224
225
        if (in_array($fieldName, $this->fields)) {
226
227
            $salt = '';
228 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...
229
                if ($parameter->getName() == 'field_' . $fieldName) {
230
                    $salt = '_' . rand(111, 999);
231
                }
232
            }
233
234 View Code Duplication
            if ($filtering->hasOperator()) {
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
                if ('list' == $filtering->getOperator()) {
236
                    $whereCondition =
237
                        $this->entityAlias . '.' . $fieldName . ' ' .
238
                        $op->getMeta() .' ' .
239
                        '(:field_' . $fieldName . $salt . ')';
240
                } else if ('field_eq' == $filtering->getOperator()) {
241
                    $whereCondition =
242
                        $this->entityAlias . '.' . $fieldName . ' '.
243
                        $op->getMeta() . ' ' .
244
                        $this->entityAlias . '.' . $value;
245
                } else {
246
                    $whereCondition =
247
                        $this->entityAlias . '.' . $fieldName . ' ' .
248
                        $op->getMeta() . ' ' .
249
                        ':field_' . $fieldName . $salt;
250
                }
251
            } else {
252
                $whereCondition =
253
                    $this->entityAlias . '.' . $fieldName .  ' ' .
254
                    $op->getMeta() . ' ' .
255
                    ':field_' . $fieldName . $salt;
256
            }
257
258
            $this->qBuilder->andWhere($whereCondition);
259
260 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...
261
                if ($filtering->hasOperator() && 'list' == $filtering->getOperator()) {
262
                    $value = explode(',', $value);
263
                } else {
264
                    $value = str_replace(
265
                        '{string}',
266
                        $value,
267
                        $op->getSubstitutionPattern()
268
                    );
269
                }
270
            }
271
272
            $this->qBuilder->setParameter('field_' . $fieldName . $salt, $value);
273
        } else {
274
            $isNotARelation = 0 !== strpos($fieldName, 'Embedded.');
275
            if ($isNotARelation) {
276
                $whereCondition =
277
                    $this->entityAlias . '.' . $fieldName . ' ' .
278
                    $op->getMeta() .' ' .
279
                    $this->entityAlias . '.' . $value;
280
                $this->qBuilder->andWhere($whereCondition);
281
            }
282
        }
283
284
        if (strstr($filter, '_embedded.')) {
285
286
            $this->join($filter);
287
            $relationEntityAlias = $this->getRelationEntityAlias();
288
289
            $embeddedFields = explode('.', $fieldName);
290
            $fieldName = $this->parser->camelize($embeddedFields[count($embeddedFields)-1]);
291
292
            $salt = '';
293 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...
294
                if ($parameter->getName() == 'field_' . $fieldName) {
295
                    $salt = '_' . rand(111, 999);
296
                }
297
            }
298
299 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...
300
                $whereCondition =
301
                    $relationEntityAlias . '.' . $fieldName . ' ' .
302
                    $op->getMeta() . ' ' .
303
                    '(:field_' . $fieldName . $salt . ')';
304
            } else {
305
                $whereCondition =
306
                    $relationEntityAlias . '.' . $fieldName . ' ' .
307
                    $op->getMeta() .
308
                    ' :field_' . $fieldName . $salt;
309
            }
310
311
            $this->qBuilder->andWhere($whereCondition);
312 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...
313
                if ($filtering->hasOperator() && 'list' == $filtering->getOperator()) {
314
                    $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

314
                    $value = explode(',', /** @scrutinizer ignore-type */ $value);
Loading history...
315
                } else {
316
                    $value = str_replace(
317
                        '{string}',
318
                        $value,
319
                        $op->getSubstitutionPattern()
320
                    );
321
                }
322
            }
323
324
            $this->qBuilder->setParameter('field_' . $fieldName . $salt, $value);
325
        }
326
    }
327
328
    private function applyFilterOr($filter, $value, $orCondition)
329
    {
330
        $whereCondition = null;
331
        $filtering = FilteringObject::fromFilter($filter);
332
333
        $fieldName = $this->parser->camelize($filtering->getFieldName());
334
335
        $op = Operator::fromFilteringObject($filtering);
336
337
        if (in_array($fieldName, $this->fields)) {
338
339
            $salt = '';
340 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...
341
                if ($parameter->getName() == 'field_' . $fieldName) {
342
                    $salt = '_' . rand(111, 999);
343
                }
344
            }
345
346 View Code Duplication
            if ($filtering->hasOperator()) {
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...
347
                if ('list' == $filtering->getOperator()) {
348
                    $whereCondition =
349
                        $this->entityAlias.'.'.$fieldName.' '.
350
                        $op->getMeta()
351
                        .' (:field_' . $fieldName . $salt . ')';
352
                } else if ('field_eq' == $filtering->getOperator()) {
353
                    $whereCondition =
354
                        $this->entityAlias . '.' . $fieldName . ' '.
355
                        $op->getMeta() . ' ' .
356
                        $this->entityAlias . '.' . $value
357
                    ;
358
                } else {
359
                    $whereCondition =
360
                        $this->entityAlias . '.' . $fieldName . ' ' .
361
                        $op->getMeta() .' ' .
362
                        ':field_' . $fieldName . $salt;
363
                }
364
            } else {
365
                $whereCondition =
366
                    $this->entityAlias . '.' . $fieldName . ' ' .
367
                    '=' . ' ' .
368
                    ':field_' . $fieldName . $salt;
369
            }
370
371 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...
372
                $orCondition['orCondition'] .= ' OR ' . $whereCondition;
373
            } else {
374
                $orCondition['orCondition'] = $whereCondition;
375
            }
376
377 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...
378
                if ($filtering->hasOperator() && 'list' == $filtering->getOperator()) {
379
                    $value = explode(',', $value);
380
                } else {
381
                    $value = str_replace(
382
                        '{string}',
383
                        $value,
384
                        $op->getSubstitutionPattern()
385
                    );
386
                }
387
            }
388
389
            $orCondition['parameters'][] = [
390
                'field' => 'field_' . $fieldName . $salt,
391
                'value' => $value
392
            ];
393
        } else {
394
            $isNotARelation = 0 !== strpos($fieldName, 'Embedded.');
395
            if ($isNotARelation) {
396
                $whereCondition =
397
                    $this->entityAlias . '.' . $fieldName . ' ' .
398
                    $op->getMeta() . ' ' .
399
                    $this->entityAlias . '.' . $value;
400 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...
401
                    $orCondition['orCondition'] .= ' OR ' . $whereCondition;
402
                } else {
403
                    $orCondition['orCondition'] = $whereCondition;
404
                }
405
            }
406
        }
407
408
        if (strstr($filter, '_embedded.')) {
409
410
            $this->join($filter);
411
            $relationEntityAlias = $this->getRelationEntityAlias();
412
413
            $embeddedFields = explode('.', $fieldName);
414
            $fieldName = $this->parser->camelize($embeddedFields[count($embeddedFields)-1]);
415
416
            $salt = '';
417 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...
418
                if ($parameter->getName() == 'field_' . $fieldName) {
419
                    $salt = '_' . rand(111, 999);
420
                }
421
            }
422
423 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...
424
                $whereCondition =
425
                    $relationEntityAlias . '.' . $fieldName . ' ' .
426
                    $op->getMeta() .' ' .
427
                    '(:field_' . $fieldName . $salt . ')';
428
            } else {
429
                $whereCondition =
430
                    $relationEntityAlias . '.' . $fieldName . ' '.
431
                    $op->getMeta() .' ' .
432
                    ':field_' . $fieldName . $salt;
433
            }
434
435 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...
436
                $orCondition['orCondition'] .= ' OR ' . $whereCondition;
437
            } else {
438
                $orCondition['orCondition'] = $whereCondition;
439
            }
440
441 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...
442
                if ($filtering->hasOperator() && 'list' == $filtering->getOperator()) {
443
                    $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

443
                    $value = explode(',', /** @scrutinizer ignore-type */ $value);
Loading history...
444
                } else {
445
                    $value = str_replace(
446
                        '{string}',
447
                        $value,
448
                        $op->getSubstitutionPattern()
449
                    );
450
                }
451
            }
452
453
            $orCondition['parameters'][] = [
454
                'field' => 'field_' . $fieldName . $salt,
455
                'value' => $value
456
            ];
457
        }
458
459
        return $orCondition;
460
    }
461
462
    public function sort()
463
    {
464
        $this->ensureFieldsDefined();
465
        $this->ensureSortingIsDefined();
466
467
        foreach ($this->sorting as $sort => $val) {
468
            $val = strtolower($val);
469
470
            $fieldName = $this->parser->camelize($sort);
471
472
            if (in_array($fieldName, $this->fields)) {
473
                $direction = ($val === self::DIRECTION_AZ) ? self::DIRECTION_AZ : self::DIRECTION_ZA;
474
                $this->qBuilder->addOrderBy($this->entityAlias . '.' . $fieldName, $direction);
475
            }
476
477
            if (strstr($sort, '_embedded.')) {
478
                $this->join($sort);
479
                $relationEntityAlias = $this->getRelationEntityAlias();
480
481
                $embeddedFields = explode('.', $sort);
482
                $fieldName = $this->parser->camelize($embeddedFields[2]);
483
                $direction = ($val === self::DIRECTION_AZ) ? self::DIRECTION_AZ : self::DIRECTION_ZA;
484
485
                $this->qBuilder->addOrderBy($relationEntityAlias . '.' . $fieldName, $direction);
486
            }
487
488
        }
489
490
        return $this;
491
    }
492
493
    public function getQueryBuilder()
494
    {
495
        $this->ensureQueryBuilderIsDefined();
496
497
        return $this->qBuilder;
498
    }
499
500
    public function buildSelectValue() : string
501
    {
502
        if ("" == $this->getSelect()) {
503
            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

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