Failed Conditions
Push — master ( 2ade86...13f838 )
by Jonathan
18s
created

Doctrine/Tests/ORM/Functional/PaginationTest.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
namespace Doctrine\Tests\ORM\Functional;
4
5
use Doctrine\ORM\Query;
6
use Doctrine\ORM\Tools\Pagination\Paginator;
7
use Doctrine\Tests\Models\CMS\CmsArticle;
8
use Doctrine\Tests\Models\CMS\CmsEmail;
9
use Doctrine\Tests\Models\CMS\CmsGroup;
10
use Doctrine\Tests\Models\CMS\CmsUser;
11
use Doctrine\Tests\Models\Company\CompanyManager;
12
use Doctrine\Tests\Models\Pagination\Company;
13
use Doctrine\Tests\Models\Pagination\Department;
14
use Doctrine\Tests\Models\Pagination\Logo;
15
use Doctrine\Tests\Models\Pagination\User1;
16
use Doctrine\Tests\OrmFunctionalTestCase;
17
use ReflectionMethod;
18
19
/**
20
 * @group DDC-1613
21
 */
22
class PaginationTest extends OrmFunctionalTestCase
23
{
24
    protected function setUp()
25
    {
26
        $this->useModelSet('cms');
27
        $this->useModelSet('pagination');
28
        $this->useModelSet('company');
29
        parent::setUp();
30
        $this->populate();
31
    }
32
33
    /**
34
     * @dataProvider useOutputWalkers
35
     */
36
    public function testCountSimpleWithoutJoin($useOutputWalkers)
37
    {
38
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u';
39
        $query = $this->_em->createQuery($dql);
40
41
        $paginator = new Paginator($query);
42
        $paginator->setUseOutputWalkers($useOutputWalkers);
43
        $this->assertCount(9, $paginator);
44
    }
45
46
    /**
47
     * @dataProvider useOutputWalkers
48
     */
49
    public function testCountWithFetchJoin($useOutputWalkers)
50
    {
51
        $dql = 'SELECT u,g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g';
52
        $query = $this->_em->createQuery($dql);
53
54
        $paginator = new Paginator($query);
55
        $paginator->setUseOutputWalkers($useOutputWalkers);
56
        $this->assertCount(9, $paginator);
57
    }
58
59 View Code Duplication
    public function testCountComplexWithOutputWalker()
60
    {
61
        $dql = 'SELECT g, COUNT(u.id) AS userCount FROM Doctrine\Tests\Models\CMS\CmsGroup g LEFT JOIN g.users u GROUP BY g HAVING COUNT(u.id) > 0';
62
        $query = $this->_em->createQuery($dql);
63
64
        $paginator = new Paginator($query);
65
        $paginator->setUseOutputWalkers(true);
66
        $this->assertCount(3, $paginator);
67
    }
68
69
    public function testCountComplexWithoutOutputWalker()
70
    {
71
        $dql = 'SELECT g, COUNT(u.id) AS userCount FROM Doctrine\Tests\Models\CMS\CmsGroup g LEFT JOIN g.users u GROUP BY g HAVING COUNT(u.id) > 0';
72
        $query = $this->_em->createQuery($dql);
73
74
        $paginator = new Paginator($query);
75
        $paginator->setUseOutputWalkers(false);
76
77
        $this->expectException(\RuntimeException::class);
78
        $this->expectExceptionMessage('Cannot count query that uses a HAVING clause. Use the output walkers for pagination');
79
80
        $this->assertCount(3, $paginator);
81
    }
82
83
    /**
84
     * @dataProvider useOutputWalkers
85
     */
86
    public function testCountWithComplexScalarOrderBy($useOutputWalkers)
87
    {
88
        $dql = 'SELECT l FROM Doctrine\Tests\Models\Pagination\Logo l ORDER BY l.image_width * l.image_height DESC';
89
        $query = $this->_em->createQuery($dql);
90
91
        $paginator = new Paginator($query);
92
        $paginator->setUseOutputWalkers($useOutputWalkers);
93
        $this->assertCount(9, $paginator);
94
    }
95
96
    /**
97
     * @dataProvider useOutputWalkersAndFetchJoinCollection
98
     */
99
    public function testIterateSimpleWithoutJoin($useOutputWalkers, $fetchJoinCollection)
100
    {
101
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u';
102
        $query = $this->_em->createQuery($dql);
103
104
        $paginator = new Paginator($query, $fetchJoinCollection);
105
        $paginator->setUseOutputWalkers($useOutputWalkers);
106
        $this->assertCount(9, $paginator->getIterator());
107
108
        // Test with limit
109
        $query->setMaxResults(3);
110
        $paginator = new Paginator($query, $fetchJoinCollection);
111
        $paginator->setUseOutputWalkers($useOutputWalkers);
112
        $this->assertCount(3, $paginator->getIterator());
113
114
        // Test with limit and offset
115
        $query->setMaxResults(3)->setFirstResult(4);
116
        $paginator = new Paginator($query, $fetchJoinCollection);
117
        $paginator->setUseOutputWalkers($useOutputWalkers);
118
        $this->assertCount(3, $paginator->getIterator());
119
    }
120
121 View Code Duplication
    private function iterateWithOrderAsc($useOutputWalkers, $fetchJoinCollection, $baseDql, $checkField)
122
    {
123
        // Ascending
124
        $dql = "$baseDql ASC";
125
        $query = $this->_em->createQuery($dql);
126
127
        $paginator = new Paginator($query, $fetchJoinCollection);
128
        $paginator->setUseOutputWalkers($useOutputWalkers);
129
        $iter = $paginator->getIterator();
130
        $this->assertCount(9, $iter);
131
        $result = iterator_to_array($iter);
132
        $this->assertEquals($checkField . "0", $result[0]->$checkField);
133
    }
134
135 View Code Duplication
    private function iterateWithOrderAscWithLimit($useOutputWalkers, $fetchJoinCollection, $baseDql, $checkField)
136
    {
137
        // Ascending
138
        $dql = "$baseDql ASC";
139
        $query = $this->_em->createQuery($dql);
140
141
        // With limit
142
        $query->setMaxResults(3);
143
        $paginator = new Paginator($query, $fetchJoinCollection);
144
        $paginator->setUseOutputWalkers($useOutputWalkers);
145
        $iter = $paginator->getIterator();
146
        $this->assertCount(3, $iter);
147
        $result = iterator_to_array($iter);
148
        $this->assertEquals($checkField . "0", $result[0]->$checkField);
149
    }
150
151 View Code Duplication
    private function iterateWithOrderAscWithLimitAndOffset($useOutputWalkers, $fetchJoinCollection, $baseDql, $checkField)
152
    {
153
        // Ascending
154
        $dql = "$baseDql ASC";
155
        $query = $this->_em->createQuery($dql);
156
157
        // With offset
158
        $query->setMaxResults(3)->setFirstResult(3);
159
        $paginator = new Paginator($query, $fetchJoinCollection);
160
        $paginator->setUseOutputWalkers($useOutputWalkers);
161
        $iter = $paginator->getIterator();
162
        $this->assertCount(3, $iter);
163
        $result = iterator_to_array($iter);
164
        $this->assertEquals($checkField . "3", $result[0]->$checkField);
165
    }
166
167 View Code Duplication
    private function iterateWithOrderDesc($useOutputWalkers, $fetchJoinCollection, $baseDql, $checkField)
168
    {
169
        $dql = "$baseDql DESC";
170
        $query = $this->_em->createQuery($dql);
171
172
        $paginator = new Paginator($query, $fetchJoinCollection);
173
        $paginator->setUseOutputWalkers($useOutputWalkers);
174
        $iter = $paginator->getIterator();
175
        $this->assertCount(9, $iter);
176
        $result = iterator_to_array($iter);
177
        $this->assertEquals($checkField . "8", $result[0]->$checkField);
178
    }
179
180 View Code Duplication
    private function iterateWithOrderDescWithLimit($useOutputWalkers, $fetchJoinCollection, $baseDql, $checkField)
181
    {
182
        $dql = "$baseDql DESC";
183
        $query = $this->_em->createQuery($dql);
184
185
        // With limit
186
        $query->setMaxResults(3);
187
        $paginator = new Paginator($query, $fetchJoinCollection);
188
        $paginator->setUseOutputWalkers($useOutputWalkers);
189
        $iter = $paginator->getIterator();
190
        $this->assertCount(3, $iter);
191
        $result = iterator_to_array($iter);
192
        $this->assertEquals($checkField . "8", $result[0]->$checkField);
193
    }
194
195 View Code Duplication
    private function iterateWithOrderDescWithLimitAndOffset($useOutputWalkers, $fetchJoinCollection, $baseDql, $checkField)
196
    {
197
        $dql = "$baseDql DESC";
198
        $query = $this->_em->createQuery($dql);
199
200
        // With offset
201
        $query->setMaxResults(3)->setFirstResult(3);
202
        $paginator = new Paginator($query, $fetchJoinCollection);
203
        $paginator->setUseOutputWalkers($useOutputWalkers);
204
        $iter = $paginator->getIterator();
205
        $this->assertCount(3, $iter);
206
        $result = iterator_to_array($iter);
207
        $this->assertEquals($checkField . "5", $result[0]->$checkField);
208
    }
209
210
    /**
211
     * @dataProvider useOutputWalkersAndFetchJoinCollection
212
     */
213
    public function testIterateSimpleWithoutJoinWithOrder($useOutputWalkers, $fetchJoinCollection)
214
    {
215
        // Ascending
216
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY u.username';
217
        $this->iterateWithOrderAsc($useOutputWalkers, $fetchJoinCollection, $dql, "username");
218
        $this->iterateWithOrderDesc($useOutputWalkers, $fetchJoinCollection, $dql, "username");
219
    }
220
221
    /**
222
     * @dataProvider useOutputWalkersAndFetchJoinCollection
223
     */
224
    public function testIterateSimpleWithoutJoinWithOrderAndLimit($useOutputWalkers, $fetchJoinCollection)
225
    {
226
        // Ascending
227
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY u.username';
228
        $this->iterateWithOrderAscWithLimit($useOutputWalkers, $fetchJoinCollection, $dql, "username");
229
        $this->iterateWithOrderDescWithLimit($useOutputWalkers, $fetchJoinCollection, $dql, "username");
230
    }
231
232
    /**
233
     * @dataProvider useOutputWalkersAndFetchJoinCollection
234
     */
235
    public function testIterateSimpleWithoutJoinWithOrderAndLimitAndOffset($useOutputWalkers, $fetchJoinCollection)
236
    {
237
        // Ascending
238
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY u.username';
239
        $this->iterateWithOrderAscWithLimitAndOffset($useOutputWalkers, $fetchJoinCollection, $dql, "username");
240
        $this->iterateWithOrderDescWithLimitAndOffset($useOutputWalkers, $fetchJoinCollection, $dql, "username");
241
    }
242
243
    /**
244
     * @dataProvider fetchJoinCollection
245
     */
246 View Code Duplication
    public function testIterateSimpleWithOutputWalkerWithoutJoinWithComplexOrder($fetchJoinCollection)
247
    {
248
        // Ascending
249
        $dql = 'SELECT l FROM Doctrine\Tests\Models\Pagination\Logo l ORDER BY l.image_width * l.image_height';
250
        $this->iterateWithOrderAsc(true, $fetchJoinCollection, $dql, "image");
251
        $this->iterateWithOrderDesc(true, $fetchJoinCollection, $dql, "image");
252
    }
253
254
    /**
255
     * @dataProvider fetchJoinCollection
256
     */
257 View Code Duplication
    public function testIterateSimpleWithOutputWalkerWithoutJoinWithComplexOrderAndLimit($fetchJoinCollection)
258
    {
259
        // Ascending
260
        $dql = 'SELECT l FROM Doctrine\Tests\Models\Pagination\Logo l ORDER BY l.image_width * l.image_height';
261
        $this->iterateWithOrderAscWithLimit(true, $fetchJoinCollection, $dql, "image");
262
        $this->iterateWithOrderDescWithLimit(true, $fetchJoinCollection, $dql, "image");
263
    }
264
265
    /**
266
     * @dataProvider fetchJoinCollection
267
     */
268 View Code Duplication
    public function testIterateSimpleWithOutputWalkerWithoutJoinWithComplexOrderAndLimitAndOffset($fetchJoinCollection)
269
    {
270
        // Ascending
271
        $dql = 'SELECT l FROM Doctrine\Tests\Models\Pagination\Logo l ORDER BY l.image_width * l.image_height';
272
        $this->iterateWithOrderAscWithLimitAndOffset(true, $fetchJoinCollection, $dql, "image");
273
        $this->iterateWithOrderDescWithLimitAndOffset(true, $fetchJoinCollection, $dql, "image");
274
    }
275
276
    /**
277
     * @dataProvider useOutputWalkers
278
     */
279
    public function testIterateWithFetchJoin($useOutputWalkers)
280
    {
281
        $dql = 'SELECT u,g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g';
282
        $query = $this->_em->createQuery($dql);
283
284
        $paginator = new Paginator($query, true);
285
        $paginator->setUseOutputWalkers($useOutputWalkers);
286
        $this->assertCount(9, $paginator->getIterator());
287
    }
288
289
    /**
290
     * @dataProvider useOutputWalkers
291
     */
292
    public function testIterateWithFetchJoinWithOrder($useOutputWalkers)
293
    {
294
        $dql = 'SELECT u,g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g ORDER BY u.username';
295
        $this->iterateWithOrderAsc($useOutputWalkers, true, $dql, "username");
296
        $this->iterateWithOrderDesc($useOutputWalkers, true, $dql, "username");
297
    }
298
299
    /**
300
     * @dataProvider useOutputWalkers
301
     */
302
    public function testIterateWithFetchJoinWithOrderAndLimit($useOutputWalkers)
303
    {
304
        $dql = 'SELECT u,g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g ORDER BY u.username';
305
        $this->iterateWithOrderAscWithLimit($useOutputWalkers, true, $dql, "username");
306
        $this->iterateWithOrderDescWithLimit($useOutputWalkers, true, $dql, "username");
307
    }
308
309
    /**
310
     * @dataProvider useOutputWalkers
311
     */
312
    public function testIterateWithFetchJoinWithOrderAndLimitAndOffset($useOutputWalkers)
313
    {
314
        $dql = 'SELECT u,g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g ORDER BY u.username';
315
        $this->iterateWithOrderAscWithLimitAndOffset($useOutputWalkers, true, $dql, "username");
316
        $this->iterateWithOrderDescWithLimitAndOffset($useOutputWalkers, true, $dql, "username");
317
    }
318
319
    /**
320
     * @dataProvider useOutputWalkersAndFetchJoinCollection
321
     */
322
    public function testIterateWithRegularJoinWithOrderByColumnFromJoined($useOutputWalkers, $fetchJoinCollection)
323
    {
324
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.email e ORDER BY e.email';
325
        $this->iterateWithOrderAsc($useOutputWalkers, $fetchJoinCollection, $dql, "username");
326
        $this->iterateWithOrderDesc($useOutputWalkers, $fetchJoinCollection, $dql, "username");
327
    }
328
329
    /**
330
     * @dataProvider useOutputWalkersAndFetchJoinCollection
331
     */
332
    public function testIterateWithRegularJoinWithOrderByColumnFromJoinedWithLimit($useOutputWalkers, $fetchJoinCollection)
333
    {
334
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.email e ORDER BY e.email';
335
        $this->iterateWithOrderAscWithLimit($useOutputWalkers, $fetchJoinCollection, $dql, "username");
336
        $this->iterateWithOrderDescWithLimit($useOutputWalkers, $fetchJoinCollection, $dql, "username");
337
    }
338
339
    /**
340
     * @dataProvider useOutputWalkersAndFetchJoinCollection
341
     */
342
    public function testIterateWithRegularJoinWithOrderByColumnFromJoinedWithLimitAndOffset($useOutputWalkers, $fetchJoinCollection)
343
    {
344
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.email e ORDER BY e.email';
345
        $this->iterateWithOrderAscWithLimitAndOffset($useOutputWalkers, $fetchJoinCollection, $dql, "username");
346
        $this->iterateWithOrderDescWithLimitAndOffset($useOutputWalkers, $fetchJoinCollection, $dql, "username");
347
    }
348
349
    /**
350
     * @dataProvider fetchJoinCollection
351
     */
352 View Code Duplication
    public function testIterateWithOutputWalkersWithRegularJoinWithComplexOrderByReferencingJoined($fetchJoinCollection)
353
    {
354
        // long function name is loooooooooooong
355
356
        $dql = 'SELECT c FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.logo l ORDER BY l.image_height * l.image_width';
357
        $this->iterateWithOrderAsc(true, $fetchJoinCollection, $dql, "name");
358
        $this->iterateWithOrderDesc(true, $fetchJoinCollection, $dql, "name");
359
    }
360
361
    /**
362
     * @dataProvider fetchJoinCollection
363
     */
364 View Code Duplication
    public function testIterateWithOutputWalkersWithRegularJoinWithComplexOrderByReferencingJoinedWithLimit($fetchJoinCollection)
365
    {
366
        // long function name is loooooooooooong
367
368
        $dql = 'SELECT c FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.logo l ORDER BY l.image_height * l.image_width';
369
        $this->iterateWithOrderAscWithLimit(true, $fetchJoinCollection, $dql, "name");
370
        $this->iterateWithOrderDescWithLimit(true, $fetchJoinCollection, $dql, "name");
371
    }
372
373
    /**
374
     * @dataProvider fetchJoinCollection
375
     */
376 View Code Duplication
    public function testIterateWithOutputWalkersWithRegularJoinWithComplexOrderByReferencingJoinedWithLimitAndOffset($fetchJoinCollection)
377
    {
378
        // long function name is loooooooooooong
379
380
        $dql = 'SELECT c FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.logo l ORDER BY l.image_height * l.image_width';
381
        $this->iterateWithOrderAscWithLimitAndOffset(true, $fetchJoinCollection, $dql, "name");
382
        $this->iterateWithOrderDescWithLimitAndOffset(true, $fetchJoinCollection, $dql, "name");
383
    }
384
385
    /**
386
     * @dataProvider useOutputWalkers
387
     */
388
    public function testIterateWithFetchJoinWithOrderByColumnFromJoined($useOutputWalkers)
389
    {
390
        $dql = 'SELECT u,g,e FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g JOIN u.email e ORDER BY e.email';
391
        $this->iterateWithOrderAsc($useOutputWalkers, true, $dql, "username");
392
        $this->iterateWithOrderDesc($useOutputWalkers, true, $dql, "username");
393
    }
394
395
    /**
396
     * @dataProvider useOutputWalkers
397
     */
398
    public function testIterateWithFetchJoinWithOrderByColumnFromJoinedWithLimit($useOutputWalkers)
399
    {
400
        $dql = 'SELECT u,g,e FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g JOIN u.email e ORDER BY e.email';
401
        $this->iterateWithOrderAscWithLimit($useOutputWalkers, true, $dql, "username");
402
        $this->iterateWithOrderDescWithLimit($useOutputWalkers, true, $dql, "username");
403
    }
404
405
    /**
406
     * @dataProvider useOutputWalkers
407
     */
408
    public function testIterateWithFetchJoinWithOrderByColumnFromJoinedWithLimitAndOffset($useOutputWalkers)
409
    {
410
        $dql = 'SELECT u,g,e FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g JOIN u.email e ORDER BY e.email';
411
        $this->iterateWithOrderAscWithLimitAndOffset($useOutputWalkers, true, $dql, "username");
412
        $this->iterateWithOrderDescWithLimitAndOffset($useOutputWalkers, true, $dql, "username");
413
    }
414
415
    /**
416
     * @dataProvider fetchJoinCollection
417
     */
418
    public function testIterateWithOutputWalkersWithFetchJoinWithComplexOrderByReferencingJoined($fetchJoinCollection)
419
    {
420
        $dql = 'SELECT c,l FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.logo l ORDER BY l.image_width * l.image_height';
421
        $this->iterateWithOrderAsc(true, $fetchJoinCollection, $dql, "name");
422
        $this->iterateWithOrderDesc(true, $fetchJoinCollection, $dql, "name");
423
    }
424
425
    /**
426
     * @dataProvider fetchJoinCollection
427
     */
428
    public function testIterateWithOutputWalkersWithFetchJoinWithComplexOrderByReferencingJoinedWithLimit($fetchJoinCollection)
429
    {
430
        $dql = 'SELECT c,l FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.logo l ORDER BY l.image_width * l.image_height';
431
        $this->iterateWithOrderAscWithLimit(true, $fetchJoinCollection, $dql, "name");
432
        $this->iterateWithOrderDescWithLimit(true, $fetchJoinCollection, $dql, "name");
433
    }
434
435
    /**
436
     * @dataProvider fetchJoinCollection
437
     */
438
    public function testIterateWithOutputWalkersWithFetchJoinWithComplexOrderByReferencingJoinedWithLimitAndOffset($fetchJoinCollection)
439
    {
440
        $dql = 'SELECT c,l FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.logo l ORDER BY l.image_width * l.image_height';
441
        $this->iterateWithOrderAscWithLimitAndOffset(true, $fetchJoinCollection, $dql, "name");
442
        $this->iterateWithOrderDescWithLimitAndOffset(true, $fetchJoinCollection, $dql, "name");
443
    }
444
445
    /**
446
     * @dataProvider fetchJoinCollection
447
     */
448
    public function testIterateWithOutputWalkersWithFetchJoinWithComplexOrderByReferencingJoinedWithLimitAndOffsetWithInheritanceType($fetchJoinCollection)
449
    {
450
        $dql = 'SELECT u FROM Doctrine\Tests\Models\Pagination\User u ORDER BY u.id';
451
        $this->iterateWithOrderAscWithLimit(true, $fetchJoinCollection, $dql, "name");
452
        $this->iterateWithOrderDescWithLimit(true, $fetchJoinCollection, $dql, "name");
453
    }
454
455 View Code Duplication
    public function testIterateComplexWithOutputWalker()
456
    {
457
        $dql = 'SELECT g, COUNT(u.id) AS userCount FROM Doctrine\Tests\Models\CMS\CmsGroup g LEFT JOIN g.users u GROUP BY g HAVING COUNT(u.id) > 0';
458
        $query = $this->_em->createQuery($dql);
459
460
        $paginator = new Paginator($query);
461
        $paginator->setUseOutputWalkers(true);
462
        $this->assertCount(3, $paginator->getIterator());
463
    }
464
465
    public function testJoinedClassTableInheritance()
466
    {
467
        $dql = 'SELECT c FROM Doctrine\Tests\Models\Company\CompanyManager c ORDER BY c.startDate';
468
        $query = $this->_em->createQuery($dql);
469
470
        $paginator = new Paginator($query);
471
        $this->assertCount(1, $paginator->getIterator());
472
    }
473
474
    /**
475
     * @dataProvider useOutputWalkers
476
     */
477
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromBoth($useOutputWalkers)
478
    {
479
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY c.name';
480
        $dqlAsc = $dql . " ASC, d.name";
481
        $dqlDesc = $dql . " DESC, d.name";
482
        $this->iterateWithOrderAsc($useOutputWalkers, true, $dqlAsc, "name");
483
        $this->iterateWithOrderDesc($useOutputWalkers, true, $dqlDesc, "name");
484
    }
485
486
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromBothWithLimitWithOutputWalker()
487
    {
488
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY c.name';
489
        $dqlAsc = $dql . " ASC, d.name";
490
        $dqlDesc = $dql . " DESC, d.name";
491
        $this->iterateWithOrderAscWithLimit(true, true, $dqlAsc, "name");
492
        $this->iterateWithOrderDescWithLimit(true, true, $dqlDesc, "name");
493
    }
494
495
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromBothWithLimitWithoutOutputWalker()
496
    {
497
        $this->expectException(\RuntimeException::class);
498
        $this->expectExceptionMessage('Cannot select distinct identifiers from query with LIMIT and ORDER BY on a column from a fetch joined to-many association. Use output walkers.');
499
500
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY c.name';
501
        $dqlAsc = $dql . " ASC, d.name";
502
        $dqlDesc = $dql . " DESC, d.name";
503
        $this->iterateWithOrderAscWithLimit(false, true, $dqlAsc, "name");
504
        $this->iterateWithOrderDescWithLimit(false, true, $dqlDesc, "name");
505
    }
506
507
    /**
508
     * @dataProvider useOutputWalkers
509
     */
510
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromRoot($useOutputWalkers)
511
    {
512
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY c.name';
513
        $this->iterateWithOrderAsc($useOutputWalkers, true, $dql, "name");
514
        $this->iterateWithOrderDesc($useOutputWalkers, true, $dql, "name");
515
    }
516
517
    /**
518
     * @dataProvider useOutputWalkers
519
     */
520
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromRootWithLimit($useOutputWalkers)
521
    {
522
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY c.name';
523
        $this->iterateWithOrderAscWithLimit($useOutputWalkers, true, $dql, "name");
524
        $this->iterateWithOrderDescWithLimit($useOutputWalkers, true, $dql, "name");
525
    }
526
527
    /**
528
     * @dataProvider useOutputWalkers
529
     */
530
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromRootWithLimitAndOffset($useOutputWalkers)
531
    {
532
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY c.name';
533
        $this->iterateWithOrderAscWithLimitAndOffset($useOutputWalkers, true, $dql, "name");
534
        $this->iterateWithOrderDescWithLimitAndOffset($useOutputWalkers, true, $dql, "name");
535
    }
536
537
    /**
538
     * @dataProvider useOutputWalkers
539
     */
540
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromJoined($useOutputWalkers)
541
    {
542
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY d.name';
543
        $this->iterateWithOrderAsc($useOutputWalkers, true, $dql, "name");
544
        $this->iterateWithOrderDesc($useOutputWalkers, true, $dql, "name");
545
    }
546
547
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromJoinedWithLimitWithOutputWalker()
548
    {
549
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY d.name';
550
        $this->iterateWithOrderAscWithLimit(true, true, $dql, "name");
551
        $this->iterateWithOrderDescWithLimit(true, true, $dql, "name");
552
    }
553
554
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromJoinedWithLimitWithoutOutputWalker()
555
    {
556
        $this->expectException(\RuntimeException::class);
557
        $this->expectExceptionMessage('Cannot select distinct identifiers from query with LIMIT and ORDER BY on a column from a fetch joined to-many association. Use output walkers.');
558
559
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY d.name';
560
561
        $this->iterateWithOrderAscWithLimit(false, true, $dql, "name");
562
        $this->iterateWithOrderDescWithLimit(false, true, $dql, "name");
563
    }
564
565
    public function testCountWithCountSubqueryInWhereClauseWithOutputWalker()
566
    {
567
        $dql = "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE ((SELECT COUNT(s.id) FROM Doctrine\Tests\Models\CMS\CmsUser s) = 9) ORDER BY u.id desc";
568
        $query = $this->_em->createQuery($dql);
569
570
        $paginator = new Paginator($query, true);
571
        $paginator->setUseOutputWalkers(true);
572
        $this->assertCount(9, $paginator);
573
    }
574
575
    public function testIterateWithCountSubqueryInWhereClause()
576
    {
577
        $dql = "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE ((SELECT COUNT(s.id) FROM Doctrine\Tests\Models\CMS\CmsUser s) = 9) ORDER BY u.id desc";
578
        $query = $this->_em->createQuery($dql);
579
580
        $paginator = new Paginator($query, true);
581
        $paginator->setUseOutputWalkers(true);
582
583
        $users = iterator_to_array($paginator->getIterator());
584
        $this->assertCount(9, $users);
585
        foreach ($users as $i => $user) {
586
            $this->assertEquals("username" . (8 - $i), $user->username);
587
        }
588
    }
589
590
    public function testDetectOutputWalker()
591
    {
592
        // This query works using the output walkers but causes an exception using the TreeWalker
593
        $dql = 'SELECT g, COUNT(u.id) AS userCount FROM Doctrine\Tests\Models\CMS\CmsGroup g LEFT JOIN g.users u GROUP BY g HAVING COUNT(u.id) > 0';
594
        $query = $this->_em->createQuery($dql);
595
596
        // If the Paginator detects the custom output walker it should fall back to using the
597
        // Tree walkers for pagination, which leads to an exception. If the query works, the output walkers were used
598
        $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, Query\SqlWalker::class);
599
        $paginator = new Paginator($query);
600
601
        $this->expectException(\RuntimeException::class);
602
        $this->expectExceptionMessage('Cannot count query that uses a HAVING clause. Use the output walkers for pagination');
603
604
        count($paginator);
605
    }
606
607
    /**
608
     * Test using a paginator when the entity attribute name and corresponding column name are not the same.
609
     */
610 View Code Duplication
    public function testPaginationWithColumnAttributeNameDifference()
611
    {
612
        $dql = 'SELECT c FROM Doctrine\Tests\Models\Pagination\Company c ORDER BY c.id';
613
        $query = $this->_em->createQuery($dql);
614
615
        $paginator = new Paginator($query);
616
        $paginator->getIterator();
617
618
        $this->assertCount(9, $paginator->getIterator());
619
    }
620
621 View Code Duplication
    public function testCloneQuery()
622
    {
623
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u';
624
        $query = $this->_em->createQuery($dql);
625
626
        $paginator = new Paginator($query);
627
        $paginator->getIterator();
628
629
        $this->assertTrue($query->getParameters()->isEmpty());
630
    }
631
632
    public function testQueryWalkerIsKept()
633
    {
634
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u';
635
        $query = $this->_em->createQuery($dql);
636
        $query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, [CustomPaginationTestTreeWalker::class]);
637
638
        $paginator = new Paginator($query, true);
639
        $paginator->setUseOutputWalkers(false);
640
        $this->assertCount(1, $paginator->getIterator());
641
        $this->assertEquals(1, $paginator->count());
642
    }
643
644
    public function testCountQueryStripsParametersInSelect()
645
    {
646
        $query = $this->_em->createQuery(
647
            'SELECT u, (CASE WHEN u.id < :vipMaxId THEN 1 ELSE 0 END) AS hidden promotedFirst
648
            FROM Doctrine\\Tests\\Models\\CMS\\CmsUser u
649
            WHERE u.id < :id or 1=1'
650
        );
651
        $query->setParameter('vipMaxId', 10);
652
        $query->setParameter('id', 100);
653
        $query->setFirstResult(null)->setMaxResults(null);
654
655
        $paginator = new Paginator($query);
656
657
        $getCountQuery = new ReflectionMethod($paginator, 'getCountQuery');
658
659
        $getCountQuery->setAccessible(true);
660
661
        $this->assertCount(2, $getCountQuery->invoke($paginator)->getParameters());
662
        $this->assertCount(9, $paginator);
663
664
        $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, Query\SqlWalker::class);
665
666
        $paginator = new Paginator($query);
667
668
        // if select part of query is replaced with count(...) paginator should remove
669
        // parameters from query object not used in new query.
670
        $this->assertCount(1, $getCountQuery->invoke($paginator)->getParameters());
671
        $this->assertCount(9, $paginator);
672
    }
673
674
    /**
675
     * @dataProvider useOutputWalkersAndFetchJoinCollection
676
     */
677 View Code Duplication
    public function testPaginationWithSubSelectOrderByExpression($useOutputWalker, $fetchJoinCollection)
678
    {
679
        $query = $this->_em->createQuery(
680
            "SELECT u, 
681
                (
682
                    SELECT MAX(a.version)
683
                    FROM Doctrine\\Tests\\Models\\CMS\\CmsArticle a
684
                    WHERE a.user = u
685
                ) AS HIDDEN max_version
686
            FROM Doctrine\\Tests\\Models\\CMS\\CmsUser u
687
            ORDER BY max_version DESC"
688
        );
689
690
        $paginator = new Paginator($query, $fetchJoinCollection);
691
        $paginator->setUseOutputWalkers($useOutputWalker);
692
693
        $this->assertCount(9, $paginator->getIterator());
694
    }
695
696
    public function populate()
697
    {
698
        $groups = [];
699 View Code Duplication
        for ($j = 0; $j < 3; $j++) {;
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...
700
            $group = new CmsGroup();
701
            $group->name = "group$j";
702
            $groups[] = $group;
703
            $this->_em->persist($group);
704
        }
705
706
        for ($i = 0; $i < 9; $i++) {
707
            $user = new CmsUser();
708
            $user->name = "Name$i";
709
            $user->username = "username$i";
710
            $user->status = "active";
711
            $user->email = new CmsEmail();
712
            $user->email->user = $user;
713
            $user->email->email = "email$i";
714
            for ($j = 0; $j < 3; $j++) {
715
                $user->addGroup($groups[$j]);
716
            }
717
            $this->_em->persist($user);
718
            for ($j = 0; $j < $i + 1; $j++) {
719
                $article = new CmsArticle();
720
                $article->topic = "topic$i$j";
721
                $article->text = "text$i$j";
722
                $article->setAuthor($user);
723
                $article->version = 0;
724
                $this->_em->persist($article);
725
            }
726
        }
727
728
        for ($i = 0; $i < 9; $i++) {
729
            $company = new Company();
730
            $company->name = "name$i";
731
            $company->logo = new Logo();
732
            $company->logo->image = "image$i";
733
            $company->logo->image_width = 100 + $i;
734
            $company->logo->image_height = 100 + $i;
735
            $company->logo->company = $company;
736
            for($j=0;$j<3;$j++) {
737
                $department = new Department();
738
                $department->name = "name$i$j";
739
                $department->company = $company;
740
                $company->departments[] = $department;
741
            }
742
            $this->_em->persist($company);
743
        }
744
745
        for ($i = 0; $i < 9; $i++) {
746
            $user = new User1();
747
            $user->name = "name$i";
748
            $user->email = "email$i";
749
            $this->_em->persist($user);
750
        }
751
752
        $manager = new CompanyManager();
753
        $manager->setName('Roman B.');
754
        $manager->setTitle('Foo');
755
        $manager->setDepartment('IT');
756
        $manager->setSalary(100000);
757
758
        $this->_em->persist($manager);
759
760
        $this->_em->flush();
761
    }
762
763
    public function useOutputWalkers()
764
    {
765
        return [
766
            [true],
767
            [false],
768
        ];
769
    }
770
771
    public function fetchJoinCollection()
772
    {
773
        return [
774
            [true],
775
            [false],
776
        ];
777
    }
778
779
    public function useOutputWalkersAndFetchJoinCollection()
780
    {
781
        return [
782
            [true, false],
783
            [true, true],
784
            [false, false],
785
            [false, true],
786
        ];
787
    }
788
}
789
790
class CustomPaginationTestTreeWalker extends Query\TreeWalkerAdapter
791
{
792
    public function walkSelectStatement(Query\AST\SelectStatement $selectStatement)
793
    {
794
        $condition = new Query\AST\ConditionalPrimary();
795
796
        $path = new Query\AST\PathExpression(Query\AST\PathExpression::TYPE_STATE_FIELD, 'u', 'name');
797
        $path->type = Query\AST\PathExpression::TYPE_STATE_FIELD;
798
799
        $condition->simpleConditionalExpression = new Query\AST\ComparisonExpression(
800
            $path,
801
            '=',
802
            new Query\AST\Literal(Query\AST\Literal::STRING, 'Name1')
803
        );
804
805
        $selectStatement->whereClause = new Query\AST\WhereClause($condition);
806
    }
807
}
808