|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/* |
|
4
|
|
|
* This file is part of the API Platform project. |
|
5
|
|
|
* |
|
6
|
|
|
* (c) Kévin Dunglas <[email protected]> |
|
7
|
|
|
* |
|
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
|
9
|
|
|
* file that was distributed with this source code. |
|
10
|
|
|
*/ |
|
11
|
|
|
|
|
12
|
|
|
namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Util; |
|
13
|
|
|
|
|
14
|
|
|
use Doctrine\Common\Persistence\ManagerRegistry; |
|
15
|
|
|
use Doctrine\ORM\QueryBuilder; |
|
16
|
|
|
|
|
17
|
|
|
/** |
|
18
|
|
|
* Utility functions for working with Doctrine ORM query. |
|
19
|
|
|
* |
|
20
|
|
|
* @author Teoh Han Hui <[email protected]> |
|
21
|
|
|
* @author Vincent Chalamon <[email protected]> |
|
22
|
|
|
*/ |
|
23
|
|
|
abstract class QueryChecker |
|
24
|
|
|
{ |
|
25
|
|
|
/** |
|
26
|
|
|
* Determines whether the query builder uses a HAVING clause. |
|
27
|
|
|
* |
|
28
|
|
|
* @param QueryBuilder $queryBuilder |
|
29
|
|
|
* |
|
30
|
|
|
* @return bool |
|
31
|
|
|
*/ |
|
32
|
|
|
public static function hasHavingClause(QueryBuilder $queryBuilder) : bool |
|
33
|
|
|
{ |
|
34
|
|
|
return !empty($queryBuilder->getDQLPart('having')); |
|
35
|
|
|
} |
|
36
|
|
|
|
|
37
|
|
|
/** |
|
38
|
|
|
* Determines whether the query builder has any root entity with foreign key identifier. |
|
39
|
|
|
* |
|
40
|
|
|
* @param QueryBuilder $queryBuilder |
|
41
|
|
|
* @param ManagerRegistry $managerRegistry |
|
42
|
|
|
* |
|
43
|
|
|
* @return bool |
|
44
|
|
|
*/ |
|
45
|
|
View Code Duplication |
public static function hasRootEntityWithForeignKeyIdentifier(QueryBuilder $queryBuilder, ManagerRegistry $managerRegistry) : bool |
|
|
|
|
|
|
46
|
|
|
{ |
|
47
|
|
|
foreach ($queryBuilder->getRootEntities() as $rootEntity) { |
|
48
|
|
|
$rootMetadata = $managerRegistry |
|
49
|
|
|
->getManagerForClass($rootEntity) |
|
50
|
|
|
->getClassMetadata($rootEntity); |
|
51
|
|
|
|
|
52
|
|
|
if ($rootMetadata->containsForeignIdentifier) { |
|
53
|
|
|
return true; |
|
54
|
|
|
} |
|
55
|
|
|
} |
|
56
|
|
|
|
|
57
|
|
|
return false; |
|
58
|
|
|
} |
|
59
|
|
|
|
|
60
|
|
|
/** |
|
61
|
|
|
* Determines whether the query builder has any composite identifier. |
|
62
|
|
|
* |
|
63
|
|
|
* @param QueryBuilder $queryBuilder |
|
64
|
|
|
* @param ManagerRegistry $managerRegistry |
|
65
|
|
|
* |
|
66
|
|
|
* @return bool |
|
67
|
|
|
*/ |
|
68
|
|
View Code Duplication |
public static function hasRootEntityWithCompositeIdentifier(QueryBuilder $queryBuilder, ManagerRegistry $managerRegistry) : bool |
|
|
|
|
|
|
69
|
|
|
{ |
|
70
|
|
|
foreach ($queryBuilder->getRootEntities() as $rootEntity) { |
|
71
|
|
|
$rootMetadata = $managerRegistry |
|
72
|
|
|
->getManagerForClass($rootEntity) |
|
73
|
|
|
->getClassMetadata($rootEntity); |
|
74
|
|
|
|
|
75
|
|
|
if ($rootMetadata->isIdentifierComposite) { |
|
76
|
|
|
return true; |
|
77
|
|
|
} |
|
78
|
|
|
} |
|
79
|
|
|
|
|
80
|
|
|
return false; |
|
81
|
|
|
} |
|
82
|
|
|
|
|
83
|
|
|
/** |
|
84
|
|
|
* Determines whether the query builder has the maximum number of results specified. |
|
85
|
|
|
* |
|
86
|
|
|
* @param QueryBuilder $queryBuilder |
|
87
|
|
|
* |
|
88
|
|
|
* @return bool |
|
89
|
|
|
*/ |
|
90
|
|
|
public static function hasMaxResults(QueryBuilder $queryBuilder) : bool |
|
91
|
|
|
{ |
|
92
|
|
|
return null !== $queryBuilder->getMaxResults(); |
|
93
|
|
|
} |
|
94
|
|
|
|
|
95
|
|
|
/** |
|
96
|
|
|
* Determines whether the query builder has ORDER BY on entity joined through |
|
97
|
|
|
* to-many association. |
|
98
|
|
|
* |
|
99
|
|
|
* @param QueryBuilder $queryBuilder |
|
100
|
|
|
* @param ManagerRegistry $managerRegistry |
|
101
|
|
|
* |
|
102
|
|
|
* @return bool |
|
103
|
|
|
*/ |
|
104
|
|
|
public static function hasOrderByOnToManyJoin(QueryBuilder $queryBuilder, ManagerRegistry $managerRegistry) : bool |
|
105
|
|
|
{ |
|
106
|
|
|
if ( |
|
107
|
|
|
empty($orderByParts = $queryBuilder->getDQLPart('orderBy')) || |
|
108
|
|
|
empty($joinParts = $queryBuilder->getDQLPart('join')) |
|
109
|
|
|
) { |
|
110
|
|
|
return false; |
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
$orderByAliases = []; |
|
114
|
|
|
foreach ($orderByParts as $orderBy) { |
|
115
|
|
|
$parts = QueryNameGenerator::getOrderByParts($orderBy); |
|
116
|
|
|
|
|
117
|
|
|
foreach ($parts as $part) { |
|
118
|
|
|
if (false !== ($pos = strpos($part, '.'))) { |
|
119
|
|
|
$alias = substr($part, 0, $pos); |
|
120
|
|
|
|
|
121
|
|
|
$orderByAliases[$alias] = true; |
|
122
|
|
|
} |
|
123
|
|
|
} |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
|
if (!empty($orderByAliases)) { |
|
127
|
|
|
foreach ($joinParts as $rootAlias => $joins) { |
|
128
|
|
|
foreach ($joins as $join) { |
|
129
|
|
|
$alias = QueryNameGenerator::getJoinAlias($join); |
|
130
|
|
|
|
|
131
|
|
|
if (isset($orderByAliases[$alias])) { |
|
132
|
|
|
$relationship = QueryNameGenerator::getJoinRelationship($join); |
|
133
|
|
|
|
|
134
|
|
|
$relationshipParts = explode('.', $relationship); |
|
135
|
|
|
$parentAlias = $relationshipParts[0]; |
|
136
|
|
|
$association = $relationshipParts[1]; |
|
137
|
|
|
|
|
138
|
|
|
$parentMetadata = QueryNameGenerator::getClassMetadataFromJoinAlias($parentAlias, $queryBuilder, $managerRegistry); |
|
139
|
|
|
|
|
140
|
|
|
if ($parentMetadata->isCollectionValuedAssociation($association)) { |
|
141
|
|
|
return true; |
|
142
|
|
|
} |
|
143
|
|
|
} |
|
144
|
|
|
} |
|
145
|
|
|
} |
|
146
|
|
|
} |
|
147
|
|
|
|
|
148
|
|
|
return false; |
|
149
|
|
|
} |
|
150
|
|
|
} |
|
151
|
|
|
|
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.