15
15
use ApiPlatform \Core \Bridge \Doctrine \Orm \Util \QueryNameGeneratorInterface ;
16
16
use ApiPlatform \Core \Metadata \Resource \Factory \ResourceMetadataFactoryInterface ;
17
17
use ApiPlatform \Core \Metadata \Resource \ResourceMetadata ;
18
+ use ApiPlatform \Core \Tests \Fixtures \TestBundle \Entity \CompositeRelation ;
18
19
use ApiPlatform \Core \Tests \Fixtures \TestBundle \Entity \DummyCar ;
19
20
use ApiPlatform \Core \Tests \Fixtures \TestBundle \Entity \Foo ;
20
21
use Doctrine \ORM \EntityManager ;
22
+ use Doctrine \ORM \Mapping \ClassMetadataInfo ;
21
23
use Doctrine \ORM \Query \Expr ;
22
24
use Doctrine \ORM \QueryBuilder ;
23
25
@@ -112,6 +114,7 @@ public function testApplyCollection()
112
114
113
115
$ em = $ this ->prophesize (EntityManager::class);
114
116
$ em ->getExpressionBuilder ()->shouldBeCalled ()->willReturn (new Expr ());
117
+ $ em ->getClassMetadata (DummyCar::class)->shouldBeCalled ()->willReturn (new ClassMetadataInfo (DummyCar::class));
115
118
116
119
$ qb = new QueryBuilder ($ em ->reveal ());
117
120
@@ -123,10 +126,150 @@ public function testApplyCollection()
123
126
124
127
$ queryNameGenerator = $ this ->prophesize (QueryNameGeneratorInterface::class);
125
128
$ queryNameGenerator ->generateJoinAlias ('colors ' )->shouldBeCalled ()->willReturn ('colors_2 ' );
129
+ $ queryNameGenerator ->generateJoinAlias ('o ' )->shouldBeCalled ()->willReturn ('o_2 ' );
126
130
127
131
$ filterEagerLoadingExtension = new FilterEagerLoadingExtension ($ resourceMetadataFactoryProphecy ->reveal (), true );
128
132
$ filterEagerLoadingExtension ->applyToCollection ($ qb , $ queryNameGenerator ->reveal (), DummyCar::class, 'get ' );
129
133
130
134
$ this ->assertEquals ('SELECT o FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCar o LEFT JOIN o.colors colors WHERE o IN(SELECT o_2 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCar o_2 LEFT JOIN o_2.colors colors_2 WHERE o_2.colors = :foo) ' , $ qb ->getDQL ());
131
135
}
136
+
137
+ /**
138
+ * https://github.com/api-platform/core/issues/1021.
139
+ */
140
+ public function testHiddenOrderBy ()
141
+ {
142
+ $ resourceMetadataFactoryProphecy = $ this ->prophesize (ResourceMetadataFactoryInterface::class);
143
+ $ resourceMetadataFactoryProphecy ->create (DummyCar::class)->willReturn (new ResourceMetadata (DummyCar::class));
144
+
145
+ $ em = $ this ->prophesize (EntityManager::class);
146
+ $ em ->getExpressionBuilder ()->shouldBeCalled ()->willReturn (new Expr ());
147
+ $ em ->getClassMetadata (DummyCar::class)->shouldBeCalled ()->willReturn (new ClassMetadataInfo (DummyCar::class));
148
+
149
+ $ qb = new QueryBuilder ($ em ->reveal ());
150
+
151
+ $ qb ->select ('o ' , 'CASE WHEN o.dateCreated IS NULL THEN 0 ELSE 1 END AS HIDDEN _o_dateCreated_null_rank ' )
152
+ ->from (DummyCar::class, 'o ' )
153
+ ->leftJoin ('o.colors ' , 'colors ' )
154
+ ->where ('o.colors = :foo ' )
155
+ ->orderBy ('_o_dateCreated_null_rank DESC ' )
156
+ ->setParameter ('foo ' , 1 );
157
+
158
+ $ queryNameGenerator = $ this ->prophesize (QueryNameGeneratorInterface::class);
159
+ $ queryNameGenerator ->generateJoinAlias ('colors ' )->shouldBeCalled ()->willReturn ('colors_2 ' );
160
+ $ queryNameGenerator ->generateJoinAlias ('o ' )->shouldBeCalled ()->willReturn ('o_2 ' );
161
+ $ filterEagerLoadingExtension = new FilterEagerLoadingExtension ($ resourceMetadataFactoryProphecy ->reveal (), true );
162
+ $ filterEagerLoadingExtension ->applyToCollection ($ qb , $ queryNameGenerator ->reveal (), DummyCar::class, 'get ' );
163
+
164
+ $ expected = <<<SQL
165
+ SELECT o, CASE WHEN o.dateCreated IS NULL THEN 0 ELSE 1 END AS HIDDEN _o_dateCreated_null_rank
166
+ FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCar o
167
+ LEFT JOIN o.colors colors
168
+ WHERE o IN(
169
+ SELECT o_2 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCar o_2
170
+ LEFT JOIN o_2.colors colors_2
171
+ WHERE o_2.colors = :foo
172
+ ) ORDER BY _o_dateCreated_null_rank DESC ASC
173
+ SQL ;
174
+
175
+ $ this ->assertEquals ($ this ->toDQLString ($ expected ), $ qb ->getDQL ());
176
+ }
177
+
178
+ public function testGroupBy ()
179
+ {
180
+ $ resourceMetadataFactoryProphecy = $ this ->prophesize (ResourceMetadataFactoryInterface::class);
181
+ $ resourceMetadataFactoryProphecy ->create (DummyCar::class)->willReturn (new ResourceMetadata (DummyCar::class));
182
+
183
+ $ em = $ this ->prophesize (EntityManager::class);
184
+ $ em ->getExpressionBuilder ()->shouldBeCalled ()->willReturn (new Expr ());
185
+ $ em ->getClassMetadata (DummyCar::class)->shouldBeCalled ()->willReturn (new ClassMetadataInfo (DummyCar::class));
186
+
187
+ $ qb = new QueryBuilder ($ em ->reveal ());
188
+
189
+ $ qb ->select ('o ' , 'count(o.id) as counter ' )
190
+ ->from (DummyCar::class, 'o ' )
191
+ ->leftJoin ('o.colors ' , 'colors ' )
192
+ ->where ('o.colors = :foo ' )
193
+ ->orderBy ('o.colors ' )
194
+ ->groupBy ('o.colors ' )
195
+ ->having ('counter > 3 ' )
196
+ ->setParameter ('foo ' , 1 );
197
+
198
+ $ queryNameGenerator = $ this ->prophesize (QueryNameGeneratorInterface::class);
199
+ $ queryNameGenerator ->generateJoinAlias ('colors ' )->shouldBeCalled ()->willReturn ('colors_2 ' );
200
+ $ queryNameGenerator ->generateJoinAlias ('o ' )->shouldBeCalled ()->willReturn ('o_2 ' );
201
+ $ filterEagerLoadingExtension = new FilterEagerLoadingExtension ($ resourceMetadataFactoryProphecy ->reveal (), true );
202
+ $ filterEagerLoadingExtension ->applyToCollection ($ qb , $ queryNameGenerator ->reveal (), DummyCar::class, 'get ' );
203
+
204
+ $ expected = <<<SQL
205
+ SELECT o, count(o.id) as counter
206
+ FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCar o
207
+ LEFT JOIN o.colors colors WHERE o
208
+ IN(
209
+ SELECT o_2 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCar o_2
210
+ LEFT JOIN o_2.colors colors_2
211
+ WHERE o_2.colors = :foo
212
+ )
213
+ GROUP BY o.colors HAVING counter > 3
214
+ ORDER BY o.colors ASC
215
+ SQL ;
216
+
217
+ $ this ->assertEquals ($ this ->toDQLString ($ expected ), $ qb ->getDQL ());
218
+ }
219
+
220
+ public function testCompositeIdentifiers ()
221
+ {
222
+ $ resourceMetadataFactoryProphecy = $ this ->prophesize (ResourceMetadataFactoryInterface::class);
223
+ $ resourceMetadataFactoryProphecy ->create (CompositeRelation::class)->willReturn (new ResourceMetadata (CompositeRelation::class));
224
+
225
+ $ classMetadata = new ClassMetadataInfo (CompositeRelation::class);
226
+ $ classMetadata ->isIdentifierComposite = true ;
227
+ $ classMetadata ->identifier = ['item ' , 'label ' ];
228
+
229
+ $ em = $ this ->prophesize (EntityManager::class);
230
+ $ em ->getExpressionBuilder ()->shouldBeCalled ()->willReturn (new Expr ());
231
+ $ em ->getClassMetadata (CompositeRelation::class)->shouldBeCalled ()->willReturn ($ classMetadata );
232
+
233
+ $ qb = new QueryBuilder ($ em ->reveal ());
234
+
235
+ $ qb ->select ('o ' )
236
+ ->from (CompositeRelation::class, 'o ' )
237
+ ->innerJoin ('o.compositeItem ' , 'item ' )
238
+ ->innerJoin ('o.compositeLabel ' , 'label ' )
239
+ ->where ('item.field1 = :foo ' )
240
+ ->setParameter ('foo ' , 1 );
241
+
242
+ $ queryNameGenerator = $ this ->prophesize (QueryNameGeneratorInterface::class);
243
+ $ queryNameGenerator ->generateJoinAlias ('item ' )->shouldBeCalled ()->willReturn ('item_2 ' );
244
+ $ queryNameGenerator ->generateJoinAlias ('label ' )->shouldBeCalled ()->willReturn ('label_2 ' );
245
+ $ queryNameGenerator ->generateJoinAlias ('o ' )->shouldBeCalled ()->willReturn ('o_2 ' );
246
+
247
+ $ filterEagerLoadingExtension = new FilterEagerLoadingExtension ($ resourceMetadataFactoryProphecy ->reveal (), true );
248
+ $ filterEagerLoadingExtension ->applyToCollection ($ qb , $ queryNameGenerator ->reveal (), CompositeRelation::class, 'get ' );
249
+
250
+ $ expected = <<<SQL
251
+ SELECT o
252
+ FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeRelation o
253
+ INNER JOIN o.compositeItem item
254
+ INNER JOIN o.compositeLabel label
255
+ WHERE o.item IN(
256
+ SELECT IDENTITY(o_2.item) FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeRelation o_2
257
+ INNER JOIN o_2.compositeItem item_2
258
+ INNER JOIN o_2.compositeLabel label_2
259
+ WHERE item_2.field1 = :foo
260
+ ) AND o.label IN(
261
+ SELECT IDENTITY(o_2.label) FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeRelation o_2
262
+ INNER JOIN o_2.compositeItem item_2
263
+ INNER JOIN o_2.compositeLabel label_2
264
+ WHERE item_2.field1 = :foo
265
+ )
266
+ SQL ;
267
+
268
+ $ this ->assertEquals ($ this ->toDQLString ($ expected ), $ qb ->getDQL ());
269
+ }
270
+
271
+ private function toDQLString (string $ dql ): string
272
+ {
273
+ return preg_replace ('/ \\r \\n| \\n/ ' , '' , str_replace (' ' , '' , $ dql ));
274
+ }
132
275
}
0 commit comments