QueryWorker::getMetaAndAliases()   C
last analyzed

Complexity

Conditions 12
Paths 148

Size

Total Lines 45
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 30
dl 0
loc 45
rs 6.5666
c 1
b 0
f 0
cc 12
nc 148
nop 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Bludata\Doctrine\ORM\Repositories;
4
5
use Bludata\Doctrine\Common\Contracts as BdContracts;
6
use Doctrine\Common\Collections\ArrayCollection;
7
8
class QueryWorker implements BdContracts\QueryWorkerContract, BdContracts\ToArrayContract
9
{
10
    const DEFAULT_TABLE_ALIAS = 't';
11
12
    protected $queryBuilder;
13
14
    protected $em;
15
16
    protected $classMetadata;
17
18
    protected $entitys = [];
19
20
    protected $tables = [];
21
22
    protected $queryFields = [];
23
24
    protected $expressions = [];
25
26
    protected $groupFields = [];
27
28
    protected $field = [];
29
30
    protected $position = 0;
31
32
    protected $fieldValue = [];
33
34
    public function __construct(BdContracts\RepositoryContract $repository)
35
    {
36
        $this->em = $repository->getEntityManager();
37
        $this->queryBuilder = $repository->createQueryBuilder(self::DEFAULT_TABLE_ALIAS);
0 ignored issues
show
Bug introduced by
The method createQueryBuilder() does not exist on Bludata\Doctrine\Common\...acts\RepositoryContract. Did you maybe mean createQueryWorker()? ( Ignorable by Annotation )

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

37
        /** @scrutinizer ignore-call */ 
38
        $this->queryBuilder = $repository->createQueryBuilder(self::DEFAULT_TABLE_ALIAS);

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...
38
        $this->classMetadata = $repository->getClassMetadata();
39
    }
40
41
    public function getResult(): ArrayCollection
42
    {
43
        return new ArrayCollection($this->queryBuilder->getQuery()->execute());
44
    }
45
46
    public function getOneResult(): ?BdContracts\EntityContract
47
    {
48
        return $this->queryBuilder->getQuery()->getOneOrNullResult();
49
    }
50
51
    public function toArray(array $options = []): array
52
    {
53
        return $this->getResult()
54
                    ->map(function ($element) use ($options) {
55
                        return $element->toArray($options);
56
                    })->toArray();
57
    }
58
59
    /**
60
     * Aplica filtros em $this->queryBuilder.
61
     *
62
     * @param array $filters
63
     *
64
     * @return QueryWorker
65
     */
66
    public function withFilters(array $filters = null)
67
    {
68
        if ($filters) {
69
            foreach ($filters as $filter) {
70
                switch ($filter['type']) {
71
                    case 'select':
72
                        $this->select($filter['fields']);
73
                        break;
74
                    case 'andWhere':
75
                        $this->andWhere($filter['field'], $filter['operation'], $filter['value']);
76
                        break;
77
                    case 'orWhere':
78
                        $this->orWhere($filter['field'], $filter['operation'], $filter['value']);
79
                        break;
80
                    case 'andHaving':
81
                        $this->andHaving($filter['field'], $filter['operation'], $filter['value']);
82
                        break;
83
                    case 'orHaving':
84
                        $this->orHaving($filter['field'], $filter['operation'], $filter['value']);
85
                        break;
86
                    case 'addGroupBy':
87
                        $this->addGroupBy($filter['field']);
88
                        break;
89
                    case 'addOrderBy':
90
                        $this->addOrderBy($filter['field'], $filter['order']);
91
                        break;
92
                    case 'fkAddOrderBy':
93
                        $this->fkAddOrderBy($filter['field'], $filter['fkField'], $filter['order']);
94
                        break;
95
                    case 'paginate':
96
                        if (isset($filter['page'])) {
97
                            $this->paginate($filter['limit'], $filter['page']);
98
                        } else {
99
                            $this->paginate($filter['limit']);
100
                        }
101
                        break;
102
                }
103
            }
104
        }
105
106
        return $this;
107
    }
108
109
    /**
110
     * Set the page with paginate attribute.
111
     *
112
     * @param int $page
113
     * @param int $limit
114
     *
115
     * @return $this
116
     */
117
    public function paginate($limit = 25, $page = 0)
118
    {
119
        if ($limit > 0) {
120
            $this->queryBuilder->setMaxResults($limit);
121
        }
122
123
        if ($page > 0) {
124
            $this->queryBuilder->setFirstResult($page * $limit);
125
        }
126
127
        return $this;
128
    }
129
130
    /**
131
     * Add a "and where" filter.
132
     *
133
     * @param string $field
134
     * @param string $operation
135
     * @param string $value
136
     *
137
     * @return $this
138
     */
139
    public function andWhere($field, $operation, $value = null, $alias = self::DEFAULT_TABLE_ALIAS)
140
    {
141
        if (strpos($field, '.') > 0) {
142
            //monta os joins
143
            $this->fieldValue = [
144
                'value'     => $value,
145
                'operation' => $operation,
146
            ];
147
            $newAliasField = $this->associationQueryFields($field);
148
            $alias = $newAliasField['alias'];
149
            $field = $newAliasField['field'];
150
        }
151
        $this->queryBuilder->andWhere($this->makeExpression($field, $operation, $value, $alias));
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type string; however, parameter $value of Bludata\Doctrine\ORM\Rep...orker::makeExpression() does only seem to accept null, 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

151
        $this->queryBuilder->andWhere($this->makeExpression($field, $operation, /** @scrutinizer ignore-type */ $value, $alias));
Loading history...
152
153
        return $this;
154
    }
155
156
    /**
157
     * Add a "or where" filter.
158
     *
159
     * @param string $field
160
     * @param string $operation
161
     * @param string $value
162
     *
163
     * @return $this
164
     */
165
    public function orWhere($field, $operation, $value = null, $alias = self::DEFAULT_TABLE_ALIAS)
166
    {
167
        if (strpos($field, '.') > 0) {
168
            //monta os joins
169
            $newAliasField = $this->associationQueryFields($field);
170
            $alias = $newAliasField['alias'];
171
            $field = $newAliasField['field'];
172
        }
173
        $this->queryBuilder->orWhere($this->makeExpression($field, $operation, $value, $alias));
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type string; however, parameter $value of Bludata\Doctrine\ORM\Rep...orker::makeExpression() does only seem to accept null, 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

173
        $this->queryBuilder->orWhere($this->makeExpression($field, $operation, /** @scrutinizer ignore-type */ $value, $alias));
Loading history...
174
175
        return $this;
176
    }
177
178
    /**
179
     * Create an array of expressions.
180
     *
181
     * @param array $conditions
182
     *
183
     * @return $this
184
     */
185
    private function makeExpressions($conditions, $alias = self::DEFAULT_TABLE_ALIAS)
186
    {
187
        $expressions = [];
188
        foreach ($conditions as $attr) {
189
            $field = $attr['field'];
190
            if (strpos($field, '.') > 0) {
191
                //monta os joins
192
                $newAliasField = $this->associationQueryFields($field);
193
                $alias = $newAliasField['alias'];
194
                $field = $newAliasField['field'];
195
            }
196
            $expressions[] = $this->makeExpression($field, $attr['operation'], $attr['value'], $alias);
197
        }
198
199
        return $expressions;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $expressions returns the type array which is incompatible with the documented return type Bludata\Doctrine\ORM\Repositories\QueryWorker.
Loading history...
200
    }
201
202
    /**
203
     * Add a "group by" key.
204
     *
205
     * @param string $field
206
     */
207
    public function addGroupBy($field)
208
    {
209
        $alias = self::DEFAULT_TABLE_ALIAS;
0 ignored issues
show
Unused Code introduced by
The assignment to $alias is dead and can be removed.
Loading history...
210
        if (strpos($field, '.') > 0) {
211
            //monta os joins
212
            $newAliasField = $this->associationQueryFields($field);
0 ignored issues
show
Unused Code introduced by
The assignment to $newAliasField is dead and can be removed.
Loading history...
213
        }
214
        if (count($this->queryFields) > 0) {
215
            foreach ($this->queryFields as $item) {
216
                $parts = [];
217
                if (strpos($item, ' AS ')) {
218
                    $item = str_replace(')', '', str_replace('(', '', $item));
219
                    $parts = explode('AS', $item);
220
                    $item = trim($parts[0]);
221
                }
222
                if (!in_array($item, $this->groupFields)) {
223
                    $this->queryBuilder->addGroupBy($item);
224
                    $this->groupFields[] = $item;
225
                }
226
            }
227
        }
228
229
        return $this;
230
    }
231
232
    /**
233
     * Add a "and having" filter.
234
     *
235
     * @param string $field
236
     * @param string $operation
237
     * @param string $value
238
     *
239
     * @return $this
240
     */
241
    public function andHaving($field, $operation, $value = null)
0 ignored issues
show
Unused Code introduced by
The parameter $operation is not used and could be removed. ( Ignorable by Annotation )

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

241
    public function andHaving($field, /** @scrutinizer ignore-unused */ $operation, $value = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $field is not used and could be removed. ( Ignorable by Annotation )

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

241
    public function andHaving(/** @scrutinizer ignore-unused */ $field, $operation, $value = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $value is not used and could be removed. ( Ignorable by Annotation )

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

241
    public function andHaving($field, $operation, /** @scrutinizer ignore-unused */ $value = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
242
    {
243
        throw new \Exception('Not implemented');
244
    }
245
246
    /**
247
     * Add a "or having" filter.
248
     *
249
     * @param string $field
250
     */
251
    public function orHaving($field, $operation, $value = null)
0 ignored issues
show
Unused Code introduced by
The parameter $operation is not used and could be removed. ( Ignorable by Annotation )

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

251
    public function orHaving($field, /** @scrutinizer ignore-unused */ $operation, $value = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $field is not used and could be removed. ( Ignorable by Annotation )

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

251
    public function orHaving(/** @scrutinizer ignore-unused */ $field, $operation, $value = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $value is not used and could be removed. ( Ignorable by Annotation )

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

251
    public function orHaving($field, $operation, /** @scrutinizer ignore-unused */ $value = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
252
    {
253
        throw new \Exception('Not implemented');
254
    }
255
256
    /**
257
     * Add a "order by" filter.
258
     *
259
     * @param string $field
260
     * @param string $order
261
     */
262
    public function addOrderBy($field, $order = 'ASC')
263
    {
264
        $alias = self::DEFAULT_TABLE_ALIAS;
265
        if (strpos($field, '.') > 0) {
266
            //monta os joins
267
            $newAliasField = $this->associationQueryFields($field);
268
            $alias = $newAliasField['alias'];
269
            $field = $newAliasField['field'];
270
        }
271
        $this->queryBuilder->addOrderBy($this->getFullFieldName($field, $alias), $order);
272
273
        return $this;
274
    }
275
276
    /**
277
     * Add a "order by" filter.
278
     *
279
     * @param string $field
280
     * @param string $order
281
     */
282
    public function fkAddOrderBy($field, $fkField, $order = 'ASC')
283
    {
284
        $alias = $this->tableAlias();
285
        $this->queryBuilder->join($this->getFullFieldName($field), $alias);
286
        $this->queryBuilder->addOrderBy($this->getFullFieldName($fkField, $alias), $order);
287
288
        return $this;
289
    }
290
291
    /**
292
     * Add a select statement.
293
     *
294
     * @param associationField.fkField
295
     * @param $field
296
     */
297
    public function select($fields)
298
    {
299
        foreach ($fields as $key => $value) {
300
            if (is_int($key)) {
301
                $this->associationQueryFields($value);
302
            } elseif (is_array($value)) {
303
                $alias = $this->tableAlias();
304
                $this->queryBuilder->join($this->getFullFieldName($key, self::DEFAULT_TABLE_ALIAS), $alias);
305
                foreach ($value as $valueField) {
306
                    $this->queryFields[] = $this->getFullFieldName($valueField, $alias);
307
                }
308
            } else {
309
                $this->queryFields[] = $value;
310
            }
311
        }
312
        $this->queryBuilder->select(implode(',', $this->queryFields));
313
314
        return $this;
315
    }
316
317
    /**
318
     * Add association join and select fields.
319
     *
320
     * @param associationField.fkField
321
     * @param $field
322
     */
323
    public function associationQueryFields($campo)
324
    {
325
        $this->field = $campo;
326
        $pos = strpos($campo, '.');
327
        if ($pos > 0) {
328
            $arr = explode('.', $campo);
329
            $lastField = end($arr);
330
331
            if (count($arr) == 2 && $arr[0] == self::DEFAULT_TABLE_ALIAS) {
332
                //não é um campo composto
333
                return [
334
                    'field' => $lastField,
335
                    'alias' => $arr[0],
336
                ];
337
            }
338
339
            $tempMeta = '';
340
            foreach ($arr as $key => $value) {
341
                $this->position = $key;
342
343
                if ($this->position < count($arr) - 1) {
344
                    $dados = $this->getMetaAndAliases();
345
346
                    $alias = $dados['alias'];
347
                    $parentAlias = $dados['parentAlias'];
348
349
                    if ($tempMeta) {
350
                        $meta = $tempMeta;
351
                        $tempMeta = '';
352
                    } else {
353
                        $meta = $dados['parentMeta'];
354
                    }
355
356
                    if ($meta->isAssociationWithSingleJoinColumn($value)) {
357
                        //manyToOne
358
                        $association = $meta->getAssociationMapping($value);
359
                        $this->setLeftJoin(
360
                            $meta->getAssociationTargetClass($value),
361
                            $association['joinColumns'][0]['referencedColumnName'],
362
                            $association['fieldName'],
363
                            $alias,
364
                            $parentAlias
365
                        );
366
                    } elseif ($meta->isCollectionValuedAssociation($value)) {
367
                        $association = $meta->getAssociationMapping($value);
368
                        if (empty($association['mappedBy']) && empty($association['joinTable'])) {
369
                            //não tem como fazer o join
370
                            $this->critical(sprintf('"%s" não é uma associação válida', $campo));
0 ignored issues
show
Bug introduced by
The method critical() does not exist on Bludata\Doctrine\ORM\Repositories\QueryWorker. ( Ignorable by Annotation )

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

370
                            $this->/** @scrutinizer ignore-call */ 
371
                                   critical(sprintf('"%s" não é uma associação válida', $campo));

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...
371
                            continue;
372
                        }
373
                        if (!empty($association['joinTable'])) {
374
                            //manyToMany
375
                            $this->setManyToManyJoin(
376
                                $this->getFullFieldName($association['fieldName'], $parentAlias),
377
                                $alias,
378
                                $this->setManyToManyValuedCondition($association, $alias, $arr)
379
                            );
380
                        } else {
381
                            //oneToMany
382
                            $this->setLeftJoin(
383
                                $meta->getAssociationTargetClass($value),
384
                                $this->getTargetField($dados['meta'], $meta, $value),
385
                                $meta->getIdentifierColumnNames()[0],
386
                                $alias,
387
                                $parentAlias
388
                            );
389
                        }
390
                    } else {
391
                        //subClass
392
                        if (count($meta->subClasses) > 0) {
393
                            $temp = $this->getSubClassFields($meta, $value);
394
                            if (!empty($temp['meta'])) {
395
                                $this->setLeftJoin($temp['table'], $temp['targetField'], $temp['parentField'], $alias, $parentAlias);
396
                                $tempMeta = $temp['meta'];
397
                            }
398
                        }
399
                    }
400
                }
401
            }
402
        } else {
403
            //não possui joins
404
            $this->position = 0;
405
            $meta = $this->classMetadata;
406
            $lastField = $campo;
407
            $alias = self::DEFAULT_TABLE_ALIAS;
408
        }
409
        //adiciona o campo ao select
410
        $this->setQueryField($meta, $lastField, $alias);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $alias does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $meta does not seem to be defined for all execution paths leading up to this point.
Loading history...
411
412
        return [
413
            'field' => $lastField,
414
            'alias' => $alias,
415
        ];
416
    }
417
418
    /**
419
     * Get the classMetadata and alias from the current position in the field.
420
     *
421
     * @return string
422
     */
423
    private function getMetaAndAliases()
424
    {
425
        $arr = explode('.', $this->field);
0 ignored issues
show
Bug introduced by
$this->field of type array is incompatible with the type string expected by parameter $string of explode(). ( Ignorable by Annotation )

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

425
        $arr = explode('.', /** @scrutinizer ignore-type */ $this->field);
Loading history...
426
        $meta = $this->classMetadata;
427
        $metaAnterior = [];
428
        $parent = '';
429
        $alias = '';
430
431
        for ($i = 0; $i <= $this->position; $i++) {
432
            $metaAnterior = $meta;
433
434
            if ($meta->hasAssociation($arr[$i])) {
435
                $class = $meta->getAssociationTargetClass($arr[$i]);
436
            } elseif (count($meta->subClasses) > 0) {
437
                $temp = $this->getSubClassFields($meta, $arr[$i]);
438
                if (!empty($temp['meta'])) {
439
                    $class = $temp['table'];
440
                }
441
            }
442
443
            $meta = $this->em->getClassMetadata($class);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $class does not seem to be defined for all execution paths leading up to this point.
Loading history...
444
445
            if ($i < $this->position) {
446
                $parent .= $parent != '' ? '_' : '';
447
                $parent .= $arr[$i];
448
            }
449
            if ($i == $this->position) {
450
                $alias .= $parent;
451
                $alias .= $parent != '' ? '_' : '';
452
                $alias .= $arr[$i];
453
            }
454
        }
455
456
        if ($parent == '' && $alias != '') {
0 ignored issues
show
introduced by
The condition $alias != '' is always false.
Loading history...
457
            $parent = self::DEFAULT_TABLE_ALIAS;
458
        }
459
        if ($alias == '') {
460
            $alias = self::DEFAULT_TABLE_ALIAS;
461
        }
462
463
        return [
0 ignored issues
show
Bug Best Practice introduced by
The expression return array('meta' => $...arentAlias' => $parent) returns the type array<string,Doctrine\OR...sMetadata|array|string> which is incompatible with the documented return type string.
Loading history...
464
            'meta'        => $meta,
465
            'parentMeta'  => $metaAnterior,
466
            'alias'       => $alias,
467
            'parentAlias' => $parent,
468
        ];
469
    }
470
471
    /**
472
     * Create a join.
473
     *
474
     * @param string $table
475
     * @param string $field
476
     * @param string $parentField
477
     * @param string $alias
478
     * @param string $parentAlias
479
     */
480
    private function setJoin($table, $field, $parentField, $alias, $parentAlias)
0 ignored issues
show
Unused Code introduced by
The method setJoin() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
481
    {
482
        if (!in_array($alias, $this->tables)) {
483
            $condition = $this->getFullFieldName($field, $alias).' = '.$this->getFullFieldName($parentField, $parentAlias);
484
            $this->queryBuilder->join($table, $alias, 'WITH', $condition);
485
            $this->tables[] = $alias;
486
        }
487
    }
488
489
    /**
490
     * Create a left join with optional where.
491
     *
492
     * @param string $table
493
     * @param string $field
494
     * @param string $parentField
495
     * @param string $alias
496
     * @param string $parentAlias
497
     * @param bool   $withWhere
498
     */
499
    private function setLeftJoin($table, $field, $parentField, $alias, $parentAlias, $withWhere = false)
500
    {
501
        if (!in_array($alias, $this->tables)) {
502
            $condition = $this->getFullFieldName($field, $alias).' = '.$this->getFullFieldName($parentField, $parentAlias);
503
            $this->queryBuilder->leftJoin($table, $alias, 'WITH', $condition);
504
            if ($withWhere) {
505
                $this->queryBuilder->andWhere($condition);
506
            }
507
            $this->tables[] = $alias;
508
        }
509
    }
510
511
    /**
512
     * Create a condition with the value.
513
     *
514
     * @param array  $association
515
     * @param string $alias
516
     * @param array  $arr
517
     *
518
     * @return mix|null
0 ignored issues
show
Bug introduced by
The type Bludata\Doctrine\ORM\Repositories\mix was not found. Maybe you did not declare it correctly or list all dependencies?

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

filter:
    dependency_paths: ["lib/*"]

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

Loading history...
519
     */
520
    private function setManyToManyValuedCondition($association, $alias, $arr)
521
    {
522
        if (empty($this->fieldValue['value']) || $this->position < count($arr) - 2) {
523
            return null;
524
        }
525
        $targetField = $this->position == count($arr) - 1 ? $association['joinTable']['joinColumns'][0]['referencedColumnName'] : end($arr);
526
527
        return $this->makeExpression($targetField, $this->fieldValue['operation'], $this->fieldValue['value'], $alias);
528
    }
529
530
    /**
531
     * Create a manyToMany join.
532
     *
533
     * @param string $table
534
     * @param string $alias
535
     * @param mix    $condition
536
     */
537
    private function setManyToManyJoin($table, $alias, $condition = null)
538
    {
539
        if (!in_array($alias, $this->tables)) {
540
            if ($condition) {
541
                $this->queryBuilder->join($table, $alias, 'WITH', $condition);
542
            } else {
543
                $this->queryBuilder->join($table, $alias);
544
            }
545
            $this->tables[] = $alias;
546
        }
547
    }
548
549
    /**
550
     * Add the field in the select field list.
551
     *
552
     * @param $meta
553
     * @param $value
554
     * @param $alias
555
     */
556
    private function setQueryField($meta, $value, $alias)
557
    {
558
        $campo = $this->getFullFieldName($value, $alias);
559
560
        if ($meta->isSingleValuedAssociation($value)) {
561
            $targetField = $meta->getAssociationMapping($value)['joinColumns'][0]['referencedColumnName'];
562
            $alias = $alias == self::DEFAULT_TABLE_ALIAS ? substr($campo, strpos($campo, '.') + 1) : $alias.'_'.$targetField;
563
            $campo = 'IDENTITY('.$campo.') '.$alias;
564
        } elseif ($this->position > 0) {
565
            $campo = '('.$campo.') AS '.$alias.'_'.$value;
566
        }
567
        // acrescenta o campo ao select
568
        $this->queryFields[] = $campo;
569
    }
570
571
    /**
572
     * Get the fields to create a join with a subClass.
573
     *
574
     * @param $meta
575
     * @param $value
576
     *
577
     * @return string
578
     */
579
    private function getSubClassFields($meta, $value)
580
    {
581
        foreach ($meta->subClasses as $subClass) {
582
            $delimiter = strpos($subClass, '/') > 0 ? '/' : '\\';
583
            $temp = explode($delimiter, $subClass);
584
            $tempMeta = $this->em->getClassMetadata($subClass);
585
            if (end($temp) == $value) {
586
                return [
0 ignored issues
show
Bug Best Practice introduced by
The expression return array('table' => ...], 'meta' => $tempMeta) returns the type array<string,Doctrine\OR...ng\ClassMetadata|mixed> which is incompatible with the documented return type string.
Loading history...
587
                    'table'       => $subClass,
588
                    'parentField' => $meta->getIdentifierColumnNames()[0],
589
                    'targetField' => $tempMeta->getIdentifierColumnNames()[0],
590
                    'meta'        => $tempMeta,
591
                ];
592
            }
593
        }
594
    }
595
596
    /**
597
     * Get the target field.
598
     *
599
     * @param $meta
600
     * @param $parentMeta
601
     * @param $value
602
     *
603
     * @return string
604
     */
605
    private function getTargetField($meta, $parentMeta, $value)
606
    {
607
        if (count($parentMeta->parentClasses) > 0) {
608
            foreach ($parentMeta->parentClasses as $classe) {
609
                $associationsByTargetClass = $meta->getAssociationsByTargetClass($classe);
610
                if (count($associationsByTargetClass) > 0) {
611
                    $parentTable = lcfirst(substr($classe, strrpos($classe, strpos($classe, '\\') !== false ? '\\' : '/') + 1));
612
                    $field = $this->searchAssociationField($associationsByTargetClass, $parentTable, $value);
613
                    if ($field) {
614
                        return $field;
615
                    }
616
                }
617
            }
618
        }
619
        $associationsByTargetClass = $meta->getAssociationsByTargetClass($parentMeta->getName());
620
        $field = $this->searchAssociationField($associationsByTargetClass, lcfirst($parentMeta->getTableName()), $value);
621
        if ($field) {
622
            return $field;
623
        }
624
625
        return $meta->getIdentifierColumnNames()[0];
626
    }
627
628
    /**
629
     * Search the field in the associations list.
630
     *
631
     * @param $associationsByTargetClass
632
     * @param string $parentTable
633
     * @param $value
634
     *
635
     * @return string
636
     */
637
    private function searchAssociationField($associationsByTargetClass, $parentTable, $value)
638
    {
639
        foreach ($associationsByTargetClass as $table => $association) {
640
            if ($table == $parentTable && $association['inversedBy'] == $value) {
641
                return $association['fieldName'];
642
            }
643
        }
644
    }
645
646
    /**
647
     * @param mixed  $field
648
     * @param string $expression
649
     * @param string $alias
650
     */
651
    private function getSelectExpression($expression, $field, $alias, $fieldAlias = self::DEFAULT_TABLE_ALIAS)
0 ignored issues
show
Unused Code introduced by
The method getSelectExpression() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
652
    {
653
        $validExpressions = ['SUM', 'MIN', 'MAX', 'AVG', 'COUNT'];
654
        if (in_array(trim(strtoupper($expression)), $validExpressions)) {
655
            if (strpos($field, '.') === false) {
656
                $field = getFullFieldName($field, $fieldAlias);
0 ignored issues
show
Bug introduced by
The function getFullFieldName was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

656
                $field = /** @scrutinizer ignore-call */ getFullFieldName($field, $fieldAlias);
Loading history...
657
            }
658
            $this->queryFields[] = sprintf('%s(%s) AS %s', $expression, $field, $alias);
659
        }
660
    }
661
662
    /**
663
     * @param $field
664
     * @param string $alias
665
     *
666
     * @return string
667
     */
668
    protected function getFullFieldName($field, $alias = self::DEFAULT_TABLE_ALIAS, $separator = '.')
669
    {
670
        return sprintf('%s%s%s', $alias, $separator, $field);
671
    }
672
673
    /**
674
     * @param $field
675
     * @param $operation
676
     * @param null   $value
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $value is correct as it would always require null to be passed?
Loading history...
677
     * @param string $alias
678
     */
679
    protected function makeExpression($field, $operation, $value = null, $alias = self::DEFAULT_TABLE_ALIAS)
680
    {
681
        $originalValue = $value;
682
683
        if (!is_array($value)) {
0 ignored issues
show
introduced by
The condition is_array($value) is always false.
Loading history...
684
            $value = $this->queryBuilder->expr()->literal($value);
685
        }
686
        if ($field) {
687
            $field = $this->getFullFieldName($field, $alias);
688
        }
689
        $expression = null;
690
        switch (strtolower($operation)) {
691
            case '>':
692
                $expression = $this->queryBuilder->expr()->gt($field, $value);
693
                break;
694
            case '=':
695
                $expression = $this->queryBuilder->expr()->eq($field, $value);
696
                break;
697
            case '<':
698
                $expression = $this->queryBuilder->expr()->lt($field, $value);
699
                break;
700
            case '>=':
701
                $expression = $this->queryBuilder->expr()->gte($field, $value);
702
                break;
703
            case '<=':
704
                $expression = $this->queryBuilder->expr()->lte($field, $value);
705
                break;
706
            case '<>':
707
                $expression = $this->queryBuilder->expr()->neq($field, $value);
708
                break;
709
            case 'isnull':
710
                $expression = $this->queryBuilder->expr()->isNull($field);
711
                break;
712
            case 'isnotnull':
713
                $expression = $this->queryBuilder->expr()->isNotNull($field);
714
                break;
715
            case 'in':
716
                $expression = $this->queryBuilder->expr()->in($field, $value);
717
                break;
718
            case 'orx':
719
                $expression = $this->queryBuilder->expr()->orX()->addMultiple($this->makeExpressions($value, $alias));
720
                break;
721
            case 'andx':
722
                $expression = $this->queryBuilder->expr()->andX()->addMultiple($this->makeExpressions($value, $alias));
723
                break;
724
            case 'notin':
725
                $expression = $this->queryBuilder->expr()->notIn($field, $value);
726
                break;
727
            case 'memberof':
728
                $expression = ':memberId MEMBER OF '.$field;
729
                $this->queryBuilder->setParameter('memberId', $originalValue);
730
                break;
731
            case 'like':
732
                $expression = $this->queryBuilder->expr()->like('LOWER('.$field.')', strtolower($value));
733
                break;
734
            case 'notlike':
735
                $expression = $this->queryBuilder->expr()->notLike($field, $value);
736
                break;
737
            case 'isinstanceof':
738
                $expression = $alias.' INSTANCE OF '.$value;
739
                break;
740
            case 'between':
741
                $expression = $this->queryBuilder->expr()->between($field, $this->queryBuilder->expr()->literal($value[0]), $this->queryBuilder->expr()->literal($value[1]));
742
                break;
743
            case 'dateparteq':
744
                $expression = $this->queryBuilder->expr()->eq("DATEPART('".$value['format']."', ".$field.')', $value['value']);
745
        }
746
747
        return $expression;
748
    }
749
750
    /**
751
     * @return string
752
     */
753
    protected function tableAlias()
754
    {
755
        return self::DEFAULT_TABLE_ALIAS.count($this->queryBuilder->getAllAliases());
756
    }
757
}
758