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 — 2.2 (#94)
by Simone
07:27 queued 04:26
created

QueryBuilderFactory::getPage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Mado\QueryBundle\Queries;
4
5
use Doctrine\ORM\EntityManager;
6
use Doctrine\ORM\QueryBuilder;
7
use Mado\QueryBundle\Component\Meta\Exceptions\UnInitializedQueryBuilderException;
8
use Mado\QueryBundle\Dictionary;
9
use Mado\QueryBundle\Exceptions;
10
use Mado\QueryBundle\Queries\Objects\FilterObject;
11
use Mado\QueryBundle\Queries\Objects\Operator;
12
13
class QueryBuilderFactory extends AbstractQuery
14
{
15
    const DIRECTION_AZ = 'asc';
16
17
    const DIRECTION_ZA = 'desc';
18
19
    const DEFAULT_OPERATOR = 'eq';
20
21
    protected $qBuilder;
22
23
    protected $fields;
24
25
    protected $andFilters;
26
27
    protected $orFilters;
28
29
    private $relationEntityAlias;
30
31
    protected $sorting;
32
33
    private $joins;
34
35
    protected $rel;
36
37
    protected $printing;
38
39
    protected $page;
40
41
    protected $pageLength;
42
43
    protected $select;
44
45
    public function getAvailableFilters()
46
    {
47
        return array_keys($this->getValueAvailableFilters());
48
    }
49
50
    public function getValueAvailableFilters()
51
    {
52
        return Dictionary::getOperators();
53
    }
54
55
    public function setFields(array $fields = [])
56
    {
57
        $this->fields = $fields;
58
59
        return $this;
60
    }
61
62
    public function getFields()
63
    {
64
        if (null === $this->fields) {
65
            throw new \RuntimeException(
66
                'Oops! Fields are not defined'
67
            );
68
        }
69
70
        return $this->fields;
71
    }
72
73
    /** @deprecated since version 2.2.2 will be removed in version 2.3 */
74
    public function setFilters(array $andFilters = [])
75
    {
76
        $this->andFilters = $andFilters;
77
78
        return $this;
79
    }
80
81
    /** @since version 2.2.2 */
82
    public function setAndFilters(array $andFilters = [])
83
    {
84
        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

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