Issues (3627)

Query/Filter/ForeignFuncFilterQueryBuilder.php (7 issues)

1
<?php
2
/*
3
 * @copyright   2018 Mautic Contributors. All rights reserved
4
 * @author      Mautic, Inc.
5
 *
6
 * @link        https://mautic.org
7
 *
8
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
9
 */
10
11
namespace Mautic\LeadBundle\Segment\Query\Filter;
12
13
use Mautic\LeadBundle\Segment\ContactSegmentFilter;
14
use Mautic\LeadBundle\Segment\Query\QueryBuilder;
15
16
/**
17
 * Class ForeignFuncFilterQueryBuilder.
18
 */
19
class ForeignFuncFilterQueryBuilder extends BaseFilterQueryBuilder
20
{
21
    /**
22
     * {@inheritdoc}
23
     */
24
    public static function getServiceId()
25
    {
26
        return 'mautic.lead.query.builder.foreign.func';
27
    }
28
29
    /**
30
     * {@inheritdoc}
31
     */
32
    public function applyQuery(QueryBuilder $queryBuilder, ContactSegmentFilter $filter)
33
    {
34
        $filterOperator = $filter->getOperator();
35
        $filterGlue     = $filter->getGlue();
36
        $filterAggr     = $filter->getAggregateFunction();
37
38
        $filterParameters = $filter->getParameterValue();
39
40
        if (is_array($filterParameters)) {
41
            $parameters = [];
42
            foreach ($filterParameters as $filterParameter) {
43
                $parameters[] = $this->generateRandomParameterName();
44
            }
45
        } else {
46
            $parameters = $this->generateRandomParameterName();
47
        }
48
49
        // Check if the column exists in the table
50
        $filter->getColumn();
51
52
        $filterParametersHolder = $filter->getParameterHolder($parameters);
53
54
        $filterGlueFunc = $filterGlue.'Where';
0 ignored issues
show
The assignment to $filterGlueFunc is dead and can be removed.
Loading history...
55
56
        $tableAlias = $queryBuilder->getTableAlias($filter->getTable());
57
58
        // for aggregate function we need to create new alias and not reuse the old one
59
        if ($filterAggr) {
60
            $tableAlias = false;
61
        }
62
63
        if (!$tableAlias) {
64
            $tableAlias = $this->generateRandomParameterName();
65
            if ($filterAggr) {
66
                // No join needed, it is placed in exist/not exists
67
            } else {
68
                if ('companies' == $filter->getTable()) {
69
                    $relTable = $this->generateRandomParameterName();
70
                    $queryBuilder->leftJoin('l', MAUTIC_TABLE_PREFIX.'companies_leads', $relTable, $relTable.'.lead_id = l.id');
71
                    $queryBuilder->leftJoin($relTable, $filter->getTable(), $tableAlias, $tableAlias.'.id = '.$relTable.'.company_id');
72
                } else { // This should never happen
73
                    $queryBuilder->leftJoin(
74
                        $queryBuilder->getTableAlias(MAUTIC_TABLE_PREFIX.'leads'),
0 ignored issues
show
It seems like $queryBuilder->getTableA...TABLE_PREFIX . 'leads') can also be of type array; however, parameter $fromAlias of Mautic\LeadBundle\Segmen...ueryBuilder::leftJoin() 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

74
                        /** @scrutinizer ignore-type */ $queryBuilder->getTableAlias(MAUTIC_TABLE_PREFIX.'leads'),
Loading history...
75
                        $filter->getTable(),
76
                        $tableAlias,
77
                        sprintf('%s.id = %s.lead_id', $queryBuilder->getTableAlias(MAUTIC_TABLE_PREFIX.'leads'), $tableAlias)
0 ignored issues
show
It seems like $queryBuilder->getTableA...TABLE_PREFIX . 'leads') can also be of type array; however, parameter $values of sprintf() does only seem to accept double|integer|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

77
                        sprintf('%s.id = %s.lead_id', /** @scrutinizer ignore-type */ $queryBuilder->getTableAlias(MAUTIC_TABLE_PREFIX.'leads'), $tableAlias)
Loading history...
78
                    );
79
                }
80
            }
81
        }
82
83
        switch ($filterOperator) {
84
            case 'empty':
85
                $expression = $queryBuilder->expr()->orX(
86
                    $queryBuilder->expr()->isNull($tableAlias.'.'.$filter->getField()),
0 ignored issues
show
Are you sure $tableAlias of type array|boolean|string can be used in concatenation? ( Ignorable by Annotation )

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

86
                    $queryBuilder->expr()->isNull(/** @scrutinizer ignore-type */ $tableAlias.'.'.$filter->getField()),
Loading history...
87
                    $queryBuilder->expr()->eq($tableAlias.'.'.$filter->getField(), ':'.$emptyParameter = $this->generateRandomParameterName())
88
                );
89
                $queryBuilder->setParameter($emptyParameter, '');
90
                break;
91
            case 'notEmpty':
92
                $expression = $queryBuilder->expr()->andX(
93
                    $queryBuilder->expr()->isNotNull($tableAlias.'.'.$filter->getField()),
94
                    $queryBuilder->expr()->neq($tableAlias.'.'.$filter->getField(), ':'.$emptyParameter = $this->generateRandomParameterName())
95
                );
96
                $queryBuilder->setParameter($emptyParameter, '');
97
                break;
98
            default:
99
                if ($filterAggr) {
100
                    if (!is_null($filter)) {
101
                        if ('sum' === $filterAggr) {
102
                            $expressionArg = $queryBuilder->expr()->func('COALESCE',
103
                                $queryBuilder->expr()->func('SUM', $tableAlias.'.'.$filter->getField()),
104
                                0
105
                            );
106
                            $expression = $queryBuilder->expr()->$filterOperator($expressionArg,
107
                                $filterParametersHolder);
108
                        } else {
109
                            $expressionArg = sprintf('%s(DISTINCT %s)', $filterAggr, $tableAlias.'.'
0 ignored issues
show
It seems like $filterAggr can also be of type true; however, parameter $values of sprintf() does only seem to accept double|integer|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

109
                            $expressionArg = sprintf('%s(DISTINCT %s)', /** @scrutinizer ignore-type */ $filterAggr, $tableAlias.'.'
Loading history...
110
                                .$filter->getField());
111
                            $expression = $queryBuilder->expr()->$filterOperator(
112
                                $expressionArg,
113
                                $filterParametersHolder
114
                            );
115
                        }
116
                    } else {
117
                        $expressionArg = $queryBuilder->expr()->func($filterAggr, $tableAlias.'.'.$filter->getField());
0 ignored issues
show
The method getField() does not exist on null. ( Ignorable by Annotation )

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

117
                        $expressionArg = $queryBuilder->expr()->func($filterAggr, $tableAlias.'.'.$filter->/** @scrutinizer ignore-call */ getField());

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...
118
                        $expression    = $queryBuilder->expr()->$filterOperator(
119
                            $expressionArg,
120
                            $filterParametersHolder
121
                        );
122
                    }
123
                } else { // This should never happen
124
                    $expression = $queryBuilder->expr()->$filterOperator(
125
                        $tableAlias.'.'.$filter->getField(),
126
                        $filterParametersHolder
127
                    );
128
                }
129
                break;
130
        }
131
132
        if ($queryBuilder->isJoinTable($filter->getTable()) && !$filterAggr) { // This should never happen
133
            $queryBuilder->addJoinCondition($tableAlias, ' ('.$expression.')');
134
            $queryBuilder->addGroupBy('l.id');
135
        } else {
136
            if ($filterAggr) {
137
                $expression = $queryBuilder->expr()->exists('SELECT '.$expressionArg.' FROM '.$filter->getTable().' '.
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $expressionArg does not seem to be defined for all execution paths leading up to this point.
Loading history...
138
                    $tableAlias.' WHERE l.id='.$tableAlias.'.lead_id HAVING '.$expression);
139
            } else { // This should never happen
140
                $queryBuilder->addGroupBy('l.id');
141
            }
142
143
            $queryBuilder->addLogic($expression, $filter->getGlue());
144
        }
145
146
        $queryBuilder->setParametersPairs($parameters, $filterParameters);
147
148
        return $queryBuilder;
149
    }
150
}
151