Failed Conditions
Push — 2.7 ( c036c0...266f0d )
by Jonathan
57:23 queued 50:07
created

ORM/Functional/ManyToManyBasicAssociationTest.php (4 issues)

1
<?php
2
3
namespace Doctrine\Tests\ORM\Functional;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Doctrine\Common\Collections\Criteria;
7
use Doctrine\ORM\PersistentCollection;
8
use Doctrine\ORM\UnitOfWork;
9
use Doctrine\Tests\Models\CMS\CmsGroup;
10
use Doctrine\Tests\Models\CMS\CmsTag;
11
use Doctrine\Tests\Models\CMS\CmsUser;
12
use Doctrine\Tests\OrmFunctionalTestCase;
13
14
/**
15
 * Basic many-to-many association tests.
16
 * ("Working with associations")
17
 *
18
 * @author robo
19
 */
20
class ManyToManyBasicAssociationTest extends OrmFunctionalTestCase
21
{
22
    protected function setUp()
23
    {
24
        $this->useModelSet('cms');
25
        parent::setUp();
26
    }
27
28
    public function testUnsetManyToMany()
29
    {
30
        $user = $this->addCmsUserGblancoWithGroups(1);
31
32
        unset($user->groups[0]->users[0]); // inverse side
33
        unset($user->groups[0]); // owning side!
34
35
        $this->_em->flush();
36
37
        // Check that the link in the association table has been deleted
38
        $this->assertGblancoGroupCountIs(0);
39
    }
40
41
    public function testBasicManyToManyJoin()
42
    {
43
        $user = $this->addCmsUserGblancoWithGroups(1);
44
        $this->_em->clear();
45
46
        $this->assertEquals(0, $this->_em->getUnitOfWork()->size());
47
48
        $query = $this->_em->createQuery("select u, g from Doctrine\Tests\Models\CMS\CmsUser u join u.groups g");
49
50
        $result = $query->getResult();
51
52
        $this->assertEquals(2, $this->_em->getUnitOfWork()->size());
53
        $this->assertInstanceOf(CmsUser::class, $result[0]);
54
        $this->assertEquals('Guilherme', $result[0]->name);
55
        $this->assertEquals(1, $result[0]->getGroups()->count());
56
        $groups = $result[0]->getGroups();
57
        $this->assertEquals('Developers_0', $groups[0]->getName());
58
59
        $this->assertEquals(UnitOfWork::STATE_MANAGED, $this->_em->getUnitOfWork()->getEntityState($result[0]));
60
        $this->assertEquals(UnitOfWork::STATE_MANAGED, $this->_em->getUnitOfWork()->getEntityState($groups[0]));
61
62
        $this->assertInstanceOf(PersistentCollection::class, $groups);
63
        $this->assertInstanceOf(PersistentCollection::class, $groups[0]->getUsers());
64
65
        $groups[0]->getUsers()->clear();
66
        $groups->clear();
67
68
        $this->_em->flush();
69
        $this->_em->clear();
70
71
        $query = $this->_em->createQuery("select u, g from Doctrine\Tests\Models\CMS\CmsUser u join u.groups g");
72
        $this->assertEquals(0, count($query->getResult()));
73
    }
74
75
    public function testManyToManyAddRemove()
76
    {
77
        $user = $this->addCmsUserGblancoWithGroups(2);
78
        $this->_em->clear();
79
80
        $uRep = $this->_em->getRepository(get_class($user));
81
82
        // Get user
83
        $user = $uRep->findOneById($user->getId());
84
85
        $this->assertNotNull($user, "Has to return exactly one entry.");
86
87
        $this->assertFalse($user->getGroups()->isInitialized());
88
89
        // Check groups
90
        $this->assertEquals(2, $user->getGroups()->count());
91
92
        $this->assertTrue($user->getGroups()->isInitialized());
93
94
        // Remove first group
95
        unset($user->groups[0]);
96
        //$user->getGroups()->remove(0);
97
98
        $this->_em->flush();
99
        $this->_em->clear();
100
101
        // Reload same user
102
        $user2 = $uRep->findOneById($user->getId());
103
104
        // Check groups
105
        $this->assertEquals(1, $user2->getGroups()->count());
106
    }
107
108
    public function testManyToManyInverseSideIgnored()
109
    {
110
        $user = $this->addCmsUserGblancoWithGroups(0);
111
112
        $group = new CmsGroup;
113
        $group->name = 'Humans';
114
115
        // modify directly, addUser() would also (properly) set the owning side
116
        $group->users[] = $user;
117
118
        $this->_em->persist($user);
119
        $this->_em->persist($group);
120
        $this->_em->flush();
121
        $this->_em->clear();
122
123
        // Association should not exist
124
        $user2 = $this->_em->find(get_class($user), $user->getId());
125
126
        $this->assertNotNull($user2, "Has to return exactly one entry.");
127
        $this->assertEquals(0, $user2->getGroups()->count());
128
    }
129
130
    public function testManyToManyCollectionClearing()
131
    {
132
        $user = $this->addCmsUserGblancoWithGroups($groupCount = 10);
133
134
        // Check that there are indeed 10 links in the association table
135
        $this->assertGblancoGroupCountIs($groupCount);
136
137
        $user->groups->clear();
138
139
        $this->_em->flush();
140
141
        // Check that the links in the association table have been deleted
142
        $this->assertGblancoGroupCountIs(0);
143
    }
144
145
    public function testManyToManyCollectionClearAndAdd()
146
    {
147
        $user = $this->addCmsUserGblancoWithGroups($groupCount = 10);
148
149
        $groups = $user->groups->toArray();
150
        $user->groups->clear();
151
152
        foreach ($groups AS $group) {
153
            $user->groups[] = $group;
154
        }
155
156
        $this->assertInstanceOf(PersistentCollection::class, $user->groups);
157
        $this->assertTrue($user->groups->isDirty());
158
159
        $this->assertEquals($groupCount, count($user->groups), "There should be 10 groups in the collection.");
160
161
        $this->_em->flush();
162
163
        $this->assertGblancoGroupCountIs($groupCount);
164
    }
165
166
    /**
167
     * @param int $expectedGroupCount
168
     */
169
    public function assertGblancoGroupCountIs($expectedGroupCount)
170
    {
171
        $countDql = "SELECT count(g.id) FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g WHERE u.username = 'gblanco'";
172
        $this->assertEquals(
173
            $expectedGroupCount,
174
            $this->_em->createQuery($countDql)->getSingleScalarResult(),
175
            "Failed to verify that CmsUser with username 'gblanco' has a group count of 10 with a DQL count query."
176
        );
177
    }
178
179
    public function testRetrieveManyToManyAndAddMore()
180
    {
181
        $user = $this->addCmsUserGblancoWithGroups(2);
182
183
        $group = new CmsGroup();
184
        $group->name = 'Developers_Fresh';
185
        $this->_em->persist($group);
186
        $this->_em->flush();
187
188
        $this->_em->clear();
189
190
        /* @var $freshUser CmsUser */
191
        $freshUser = $this->_em->find(CmsUser::class, $user->getId());
192
        $newGroup = new CmsGroup();
193
        $newGroup->setName('12Monkeys');
194
        $freshUser->addGroup($newGroup);
195
196
        $this->assertFalse($freshUser->groups->isInitialized(), "CmsUser::groups Collection has to be uninitialized for this test.");
197
198
        $this->_em->flush();
199
200
        $this->assertFalse($freshUser->groups->isInitialized(), "CmsUser::groups Collection has to be uninitialized for this test.");
201
        $this->assertEquals(3, count($freshUser->getGroups()));
202
        $this->assertEquals(3, count($freshUser->getGroups()->getSnapshot()), "Snapshot of CmsUser::groups should contain 3 entries.");
203
204
        $this->_em->clear();
205
206
        $freshUser = $this->_em->find(CmsUser::class, $user->getId());
207
        $this->assertEquals(3, count($freshUser->getGroups()));
208
    }
209
210
    /**
211
     * @group DDC-130
212
     */
213
    public function testRemoveUserWithManyGroups()
214
    {
215
        $user = $this->addCmsUserGblancoWithGroups(2);
216
        $userId = $user->getId();
217
218
        $this->_em->remove($user);
219
        $this->_em->flush();
220
221
        $newUser = $this->_em->find(get_class($user), $userId);
222
        $this->assertNull($newUser);
223
    }
224
225
    /**
226
     * @group DDC-130
227
     */
228
    public function testRemoveGroupWithUser()
229
    {
230
        $user = $this->addCmsUserGblancoWithGroups(2);
231
232
        foreach ($user->getGroups() AS $group) {
233
            $this->_em->remove($group);
234
        }
235
        $this->_em->flush();
236
        $this->_em->clear();
237
238
        $newUser = $this->_em->find(get_class($user), $user->getId());
239
        $this->assertEquals(0, count($newUser->getGroups()));
240
    }
241
242
    public function testDereferenceCollectionDelete()
243
    {
244
        $user = $this->addCmsUserGblancoWithGroups(2);
245
        $user->groups = null;
246
247
        $this->_em->flush();
248
        $this->_em->clear();
249
250
        $newUser = $this->_em->find(get_class($user), $user->getId());
251
        $this->assertEquals(0, count($newUser->getGroups()));
252
    }
253
254
    /**
255
     * @group DDC-839
256
     */
257
    public function testWorkWithDqlHydratedEmptyCollection()
258
    {
259
        $user = $this->addCmsUserGblancoWithGroups(0);
260
        $group = new CmsGroup();
261
        $group->name = "Developers0";
262
        $this->_em->persist($group);
263
264
        $this->_em->flush();
265
        $this->_em->clear();
266
267
        $newUser = $this->_em->createQuery('SELECT u, g FROM Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN u.groups g WHERE u.id = ?1')
268
                             ->setParameter(1, $user->getId())
269
                             ->getSingleResult();
270
        $this->assertEquals(0, count($newUser->groups));
271
        $this->assertInternalType('array', $newUser->groups->getMapping());
272
273
        $newUser->addGroup($group);
274
275
        $this->_em->flush();
276
        $this->_em->clear();
277
278
        $newUser = $this->_em->find(get_class($user), $user->getId());
279
        $this->assertEquals(1, count($newUser->groups));
280
    }
281
282
    /**
283
     * @param  int $groupCount
284
     * @return CmsUser
285
     */
286
    public function addCmsUserGblancoWithGroups($groupCount = 1)
287
    {
288
        $user = new CmsUser;
289
        $user->name = 'Guilherme';
290
        $user->username = 'gblanco';
291
        $user->status = 'developer';
292
293
        for ($i=0; $i < $groupCount; ++$i) {
294
            $group = new CmsGroup;
295
            $group->name = 'Developers_' . $i;
296
            $user->addGroup($group);
297
        }
298
299
        $this->_em->persist($user);
300
        $this->_em->flush();
301
302
        $this->assertNotNull($user->getId(), "User 'gblanco' should have an ID assigned after the persist()/flush() operation.");
303
304
        return $user;
305
    }
306
307
    /**
308
     * @group DDC-978
309
     */
310
    public function testClearAndResetCollection()
311
    {
312
        $user = $this->addCmsUserGblancoWithGroups(2);
313
        $group1 = new CmsGroup;
314
        $group1->name = 'Developers_New1';
315
        $group2 = new CmsGroup;
316
        $group2->name = 'Developers_New2';
317
318
        $this->_em->persist($group1);
319
        $this->_em->persist($group2);
320
        $this->_em->flush();
321
        $this->_em->clear();
322
323
        $user = $this->_em->find(get_class($user), $user->id);
324
325
        $coll = new ArrayCollection([$group1, $group2]);
326
        $user->groups = $coll;
327
        $this->_em->flush();
328
        $this->assertInstanceOf(PersistentCollection::class, $user->groups,
329
            "UnitOfWork should have replaced ArrayCollection with PersistentCollection.");
330
        $this->_em->flush();
331
332
        $this->_em->clear();
333
334
        $user = $this->_em->find(get_class($user), $user->id);
335
        $this->assertEquals(2, count($user->groups));
336
        $this->assertEquals('Developers_New1', $user->groups[0]->name);
337
        $this->assertEquals('Developers_New2', $user->groups[1]->name);
338
    }
339
340
    /**
341
     * @group DDC-733
342
     */
343
    public function testInitializePersistentCollection()
344
    {
345
        $user = $this->addCmsUserGblancoWithGroups(2);
346
        $this->_em->clear();
347
348
        $user = $this->_em->find(get_class($user), $user->id);
349
350
        $this->assertFalse($user->groups->isInitialized(), "Pre-condition: lazy collection");
351
        $this->_em->getUnitOfWork()->initializeObject($user->groups);
352
        $this->assertTrue($user->groups->isInitialized(), "Collection should be initialized after calling UnitOfWork::initializeObject()");
353
    }
354
355
    /**
356
     * @group DDC-1189
357
     * @group DDC-956
358
     */
359
    public function testClearBeforeLazyLoad()
360
    {
361
        $user = $this->addCmsUserGblancoWithGroups(4);
362
363
        $this->_em->clear();
364
365
        $user = $this->_em->find(get_class($user), $user->id);
366
        $user->groups->clear();
367
        $this->assertEquals(0, count($user->groups));
368
369
        $this->_em->flush();
370
371
        $user = $this->_em->find(get_class($user), $user->id);
372
        $this->assertEquals(0, count($user->groups));
373
    }
374
375
    /**
376
     * @group DDC-3952
377
     */
378
    public function testManyToManyOrderByIsNotIgnored()
379
    {
380
        $user = $this->addCmsUserGblancoWithGroups(1);
381
382
        $group1 = new CmsGroup;
383
        $group2 = new CmsGroup;
384
        $group3 = new CmsGroup;
385
386
        $group1->name = 'C';
387
        $group2->name = 'A';
388
        $group3->name = 'B';
389
390
        $user->addGroup($group1);
391
        $user->addGroup($group2);
392
        $user->addGroup($group3);
393
394
        $this->_em->persist($user);
395
        $this->_em->flush();
396
397
        $this->_em->clear();
398
399
        $user = $this->_em->find(get_class($user), $user->id);
400
401
        $criteria = Criteria::create()
402
            ->orderBy(['name' => Criteria::ASC]);
403
404
        $this->assertEquals(
405
            ['A', 'B', 'C', 'Developers_0'],
406
            $user
407
                ->getGroups()
408
                ->matching($criteria)
409
                ->map(function (CmsGroup $group) {
410
                    return $group->getName();
411
                })
412
                ->toArray()
413
        );
414
    }
415
416
    /**
417
     * @group DDC-3952
418
     */
419
    public function testManyToManyOrderByHonorsFieldNameColumnNameAliases()
420
    {
421
        $user = new CmsUser;
422
        $user->name = 'Guilherme';
423
        $user->username = 'gblanco';
424
        $user->status = 'developer';
425
426
        $tag1 = new CmsTag;
427
        $tag2 = new CmsTag;
428
        $tag3 = new CmsTag;
429
430
        $tag1->name = 'C';
431
        $tag2->name = 'A';
432
        $tag3->name = 'B';
433
434
        $user->addTag($tag1);
435
        $user->addTag($tag2);
436
        $user->addTag($tag3);
437
438
        $this->_em->persist($user);
439
        $this->_em->flush();
440
441
        $this->_em->clear();
442
443
        $user = $this->_em->find(get_class($user), $user->id);
444
445
        $criteria = Criteria::create()
446
            ->orderBy(['name' => Criteria::ASC]);
447
448
        $this->assertEquals(
449
            ['A', 'B', 'C'],
450
            $user
451
                ->getTags()
452
                ->matching($criteria)
453
                ->map(function (CmsTag $tag) {
454
                    return $tag->getName();
455
                })
456
                ->toArray()
457
        );
458
    }
459
460
    public function testMatchingWithLimit()
461
    {
462
        $user = $this->addCmsUserGblancoWithGroups(2);
463
        $this->_em->clear();
464
465
        $user = $this->_em->find(get_class($user), $user->id);
466
467
        $groups = $user->groups;
468
        $this->assertFalse($user->groups->isInitialized(), "Pre-condition: lazy collection");
469
470
        $criteria = Criteria::create()->setMaxResults(1);
471
        $result   = $groups->matching($criteria);
472
473
        $this->assertCount(1, $result);
474
475
        $this->assertFalse($user->groups->isInitialized(), "Post-condition: matching does not initialize collection");
476
    }
477
478
    public function testMatchingWithOffset()
479
    {
480
        $user = $this->addCmsUserGblancoWithGroups(2);
481
        $this->_em->clear();
482
483
        $user = $this->_em->find(get_class($user), $user->id);
484
485
        $groups = $user->groups;
486
        $this->assertFalse($user->groups->isInitialized(), "Pre-condition: lazy collection");
487
488
        $criteria = Criteria::create()->setFirstResult(1);
489
        $result   = $groups->matching($criteria);
490
491
        $this->assertCount(1, $result);
492
493
        $firstGroup = $result->first();
0 ignored issues
show
The method first() does not exist on Countable. It seems like you code against a sub-type of Countable such as Doctrine\Common\Collections\Collection. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

493
        /** @scrutinizer ignore-call */ 
494
        $firstGroup = $result->first();
Loading history...
The method first() does not exist on Traversable. It seems like you code against a sub-type of Traversable such as IntlCodePointBreakIterator or IntlRuleBasedBreakIterator or IntlBreakIterator or Doctrine\Common\Collections\Collection. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

493
        /** @scrutinizer ignore-call */ 
494
        $firstGroup = $result->first();
Loading history...
494
        $this->assertEquals('Developers_1', $firstGroup->name);
495
496
        $this->assertFalse($user->groups->isInitialized(), "Post-condition: matching does not initialize collection");
497
    }
498
499
    public function testMatchingWithLimitAndOffset()
500
    {
501
        $user = $this->addCmsUserGblancoWithGroups(5);
502
        $this->_em->clear();
503
504
        $user = $this->_em->find(get_class($user), $user->id);
505
506
        $groups = $user->groups;
507
        $this->assertFalse($user->groups->isInitialized(), "Pre-condition: lazy collection");
508
509
        $criteria = Criteria::create()->setFirstResult(1)->setMaxResults(3);
510
        $result   = $groups->matching($criteria);
511
512
        $this->assertCount(3, $result);
513
514
        $firstGroup = $result->first();
515
        $this->assertEquals('Developers_1', $firstGroup->name);
516
517
        $lastGroup = $result->last();
0 ignored issues
show
The method last() does not exist on Countable. It seems like you code against a sub-type of Countable such as Doctrine\Common\Collections\Collection. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

517
        /** @scrutinizer ignore-call */ 
518
        $lastGroup = $result->last();
Loading history...
The method last() does not exist on Traversable. It seems like you code against a sub-type of Traversable such as IntlCodePointBreakIterator or IntlRuleBasedBreakIterator or IntlBreakIterator or Doctrine\Common\Collections\Collection. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

517
        /** @scrutinizer ignore-call */ 
518
        $lastGroup = $result->last();
Loading history...
518
        $this->assertEquals('Developers_3', $lastGroup->name);
519
520
        $this->assertFalse($user->groups->isInitialized(), "Post-condition: matching does not initialize collection");
521
    }
522
523
    public function testMatching()
524
    {
525
        $user = $this->addCmsUserGblancoWithGroups(2);
526
        $this->_em->clear();
527
528
        $user = $this->_em->find(get_class($user), $user->id);
529
530
        $groups = $user->groups;
531
        $this->assertFalse($user->groups->isInitialized(), "Pre-condition: lazy collection");
532
533
        $criteria = Criteria::create()->where(Criteria::expr()->eq('name', (string) 'Developers_0'));
534
        $result   = $groups->matching($criteria);
535
536
        $this->assertCount(1, $result);
537
538
        $firstGroup = $result->first();
539
        $this->assertEquals('Developers_0', $firstGroup->name);
540
541
        $this->assertFalse($user->groups->isInitialized(), "Post-condition: matching does not initialize collection");
542
    }
543
}
544