Failed Conditions
Push — master ( 2b8acb...aa13e4 )
by Luís
14s
created

Doctrine/ORM/Query/AST/Functions/SizeFunction.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\ORM\Query\AST\Functions;
21
22
use Doctrine\ORM\Query\Lexer;
23
24
/**
25
 * "SIZE" "(" CollectionValuedPathExpression ")"
26
 *
27
 * 
28
 * @link    www.doctrine-project.org
29
 * @since   2.0
30
 * @author  Guilherme Blanco <[email protected]>
31
 * @author  Jonathan Wage <[email protected]>
32
 * @author  Roman Borschel <[email protected]>
33
 * @author  Benjamin Eberlei <[email protected]>
34
 */
35
class SizeFunction extends FunctionNode
36
{
37
    /**
38
     * @var \Doctrine\ORM\Query\AST\PathExpression
39
     */
40
    public $collectionPathExpression;
41
42
    /**
43
     * @override
44
     * @inheritdoc
45
     * @todo If the collection being counted is already joined, the SQL can be simpler (more efficient).
46
     */
47 9
    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
48
    {
49 9
        $platform       = $sqlWalker->getEntityManager()->getConnection()->getDatabasePlatform();
50 9
        $quoteStrategy  = $sqlWalker->getEntityManager()->getConfiguration()->getQuoteStrategy();
51 9
        $dqlAlias       = $this->collectionPathExpression->identificationVariable;
52 9
        $assocField     = $this->collectionPathExpression->field;
53
54 9
        $qComp  = $sqlWalker->getQueryComponent($dqlAlias);
55 9
        $class  = $qComp['metadata'];
56 9
        $assoc  = $class->associationMappings[$assocField];
57 9
        $sql    = 'SELECT COUNT(*) FROM ';
58
59 9
        if ($assoc['type'] == \Doctrine\ORM\Mapping\ClassMetadata::ONE_TO_MANY) {
60 4
            $targetClass        = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']);
61 4
            $targetTableAlias   = $sqlWalker->getSQLTableAlias($targetClass->getTableName());
62 4
            $sourceTableAlias   = $sqlWalker->getSQLTableAlias($class->getTableName(), $dqlAlias);
63
64 4
            $sql .= $quoteStrategy->getTableName($targetClass, $platform) . ' ' . $targetTableAlias . ' WHERE ';
65
66 4
            $owningAssoc = $targetClass->associationMappings[$assoc['mappedBy']];
67
68 4
            $first = true;
69
70 4 View Code Duplication
            foreach ($owningAssoc['targetToSourceKeyColumns'] as $targetColumn => $sourceColumn) {
71 4
                if ($first) $first = false; else $sql .= ' AND ';
72
73 4
                $sql .= $targetTableAlias . '.' . $sourceColumn
74 4
                      . ' = '
75 4
                      . $sourceTableAlias . '.' . $quoteStrategy->getColumnName($class->fieldNames[$targetColumn], $class, $platform);
76
            }
77
        } else { // many-to-many
78 5
            $targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']);
79
80 5
            $owningAssoc = $assoc['isOwningSide'] ? $assoc : $targetClass->associationMappings[$assoc['mappedBy']];
81 5
            $joinTable = $owningAssoc['joinTable'];
82
83
            // SQL table aliases
84 5
            $joinTableAlias = $sqlWalker->getSQLTableAlias($joinTable['name']);
85 5
            $sourceTableAlias = $sqlWalker->getSQLTableAlias($class->getTableName(), $dqlAlias);
86
87
            // join to target table
88 5
            $sql .= $quoteStrategy->getJoinTableName($owningAssoc, $targetClass, $platform) . ' ' . $joinTableAlias . ' WHERE ';
89
90 5
            $joinColumns = $assoc['isOwningSide']
91 4
                ? $joinTable['joinColumns']
92 5
                : $joinTable['inverseJoinColumns'];
93
94 5
            $first = true;
95
96 5 View Code Duplication
            foreach ($joinColumns as $joinColumn) {
0 ignored issues
show
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...
97 5
                if ($first) $first = false; else $sql .= ' AND ';
98
99 5
                $sourceColumnName = $quoteStrategy->getColumnName(
100 5
                    $class->fieldNames[$joinColumn['referencedColumnName']], $class, $platform
101
                );
102
103 5
                $sql .= $joinTableAlias . '.' . $joinColumn['name']
104 5
                      . ' = '
105 5
                      . $sourceTableAlias . '.' . $sourceColumnName;
106
            }
107
        }
108
109 9
        return '(' . $sql . ')';
110
    }
111
112
    /**
113
     * @override
114
     * @inheritdoc
115
     */
116 11
    public function parse(\Doctrine\ORM\Query\Parser $parser)
117
    {
118 11
        $parser->match(Lexer::T_IDENTIFIER);
119 11
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
120
121 11
        $this->collectionPathExpression = $parser->CollectionValuedPathExpression();
122
123 11
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
124 11
    }
125
}
126