Failed Conditions
Pull Request — 2.8.x (#8073)
by
unknown
63:26
created

RemoveUselessLeftJoinsWalker::removeUnusedJoins()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 24
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 13
c 1
b 0
f 0
dl 0
loc 24
rs 9.5222
cc 5
nc 4
nop 1
1
<?php
2
3
namespace Doctrine\ORM\Tools\Pagination;
4
5
use Doctrine\ORM\Query;
6
use Doctrine\ORM\Query\AST\SelectStatement;
7
use Doctrine\ORM\Query\TreeWalkerAdapter;
8
9
class RemoveUselessLeftJoinsWalker extends TreeWalkerAdapter
10
{
11
    /**
12
     * @return void
13
     *
14
     * @throws \RuntimeException
15
     */
16
    public function walkSelectStatement(SelectStatement $AST)
17
    {
18
        $this->removeUnusedJoins($AST);
19
    }
20
21
    private function removeUnusedJoins(SelectStatement $AST)
22
    {
23
        $from = $AST->fromClause->identificationVariableDeclarations;
24
        $fromRoot = reset($from);
25
26
        if (!isset($AST->whereClause) || !isset($AST->whereClause->conditionalExpression)) {
27
            return;
28
        }
29
30
        $expr = $AST->whereClause->conditionalExpression->simpleConditionalExpression;
0 ignored issues
show
Bug introduced by
The property simpleConditionalExpression does not seem to exist on Doctrine\ORM\Query\AST\ConditionalExpression.
Loading history...
31
32
        if (!isset($expr->subselect)) {
33
            return;
34
        }
35
36
        $subSelect = $expr->subselect;
37
        $subSelectUsages = $this->findSubSelectUsages($subSelect);
38
39
        foreach ($subSelect->subselectFromClause->identificationVariableDeclarations as $declaration) {
40
            $declaration->joins = $this->filterJoins($declaration->joins, $this->findUnusedJoins($declaration->joins, $subSelectUsages));
41
        }
42
43
        $usages = $this->findSubSelectUsages($AST);
44
        $fromRoot->joins = $this->filterJoins($fromRoot->joins, $this->findUnusedJoins($fromRoot->joins, $usages));
45
    }
46
47
    private function findUnusedJoins($joins, $names)
48
    {
49
        $unused = [];
50
51
        foreach ($joins as $join) {
52
            if (Query\AST\Join::JOIN_TYPE_LEFT === $join->joinType && !in_array($join->joinAssociationDeclaration->aliasIdentificationVariable, $names)) {
53
                $unused[] = $join;
54
            }
55
        }
56
57
        return array_unique($unused);
58
    }
59
60
    private function filterJoins($joins, $toRemove)
61
    {
62
        return array_filter($joins, function (Query\AST\Join $join) use ($toRemove) {
63
            return !in_array($join, $toRemove);
64
        });
65
    }
66
67
    private function extractIdentificationVariable($expression)
68
    {
69
        return $expression->simpleArithmeticExpression->identificationVariable;
70
    }
71
72
    private function findSubSelectUsages($select)
73
    {
74
        $usages = [];
75
76
        if (isset($select->whereClause)) {
77
            if ($select->whereClause->conditionalExpression instanceof Query\AST\ConditionalTerm) {
78
                foreach ($select->whereClause->conditionalExpression->conditionalFactors as $factor) {
79
                    $expr = $factor->simpleConditionalExpression;
80
                    if ($expr instanceof Query\AST\ComparisonExpression) {
81
                        $usages[] = $this->extractIdentificationVariable($expr->leftExpression);
82
                    } else {
83
                        $usages[] = $this->extractIdentificationVariable($expr->expression);
84
                    }
85
                }
86
            } elseif ($select->whereClause->conditionalExpression instanceof Query\AST\ConditionalPrimary) {
87
                $usages[] = $this->extractIdentificationVariable($select->whereClause->conditionalExpression->simpleConditionalExpression->expression);
88
            }
89
        }
90
91
        if (isset($select->orderByClause)) {
92
            foreach ($select->orderByClause->orderByItems as $item) {
93
                if ($item->expression instanceof Query\AST\OrderByItem) {
94
                    $usages[] = $item->expression->identificationVariable;
0 ignored issues
show
Bug introduced by
The property identificationVariable does not seem to exist on Doctrine\ORM\Query\AST\OrderByItem.
Loading history...
95
                }
96
            }
97
        }
98
99
        $usages = array_unique($usages);
100
101
        return $usages;
102
    }
103
}
104