Failed Conditions
Pull Request — 2.7 (#7940)
by Benjamin
07:27
created

testRemoveElementManyToManyInverse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 13
dl 0
loc 22
rs 9.8333
c 1
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Doctrine\Tests\ORM\Functional;
4
5
use Doctrine\ORM\Mapping\ClassMetadataInfo;
6
use Doctrine\Tests\Models\CMS\CmsArticle;
7
use Doctrine\Tests\Models\CMS\CmsGroup;
8
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
9
use Doctrine\Tests\Models\CMS\CmsUser;
10
use Doctrine\Tests\Models\DDC2504\DDC2504ChildClass;
11
use Doctrine\Tests\Models\DDC2504\DDC2504OtherClass;
12
use Doctrine\Tests\Models\Tweet\Tweet;
13
use Doctrine\Tests\Models\Tweet\User;
14
use Doctrine\Tests\Models\Tweet\UserList;
15
use Doctrine\Tests\OrmFunctionalTestCase;
16
17
/**
18
 * Description of ExtraLazyCollectionTest
19
 *
20
 * @author beberlei
21
 */
22
class ExtraLazyCollectionTest extends OrmFunctionalTestCase
23
{
24
    private $userId;
25
    private $userId2;
26
    private $groupId;
27
    private $articleId;
28
    private $ddc2504OtherClassId;
29
    private $ddc2504ChildClassId;
30
31
    private $username;
32
    private $groupname;
33
    private $topic;
34
    private $phonenumber;
35
36
    public function setUp()
37
    {
38
        $this->useModelSet('tweet');
39
        $this->useModelSet('cms');
40
        $this->useModelSet('ddc2504');
41
        parent::setUp();
42
43
        $class = $this->_em->getClassMetadata(CmsUser::class);
44
        $class->associationMappings['groups']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
45
        $class->associationMappings['groups']['indexBy'] = 'name';
46
        $class->associationMappings['articles']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
47
        $class->associationMappings['articles']['indexBy'] = 'topic';
48
        $class->associationMappings['phonenumbers']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
49
        $class->associationMappings['phonenumbers']['indexBy'] = 'phonenumber';
50
51
        unset($class->associationMappings['phonenumbers']['cache']);
52
        unset($class->associationMappings['articles']['cache']);
53
        unset($class->associationMappings['users']['cache']);
54
55
        $class = $this->_em->getClassMetadata(CmsGroup::class);
56
        $class->associationMappings['users']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
57
        $class->associationMappings['users']['indexBy'] = 'username';
58
59
        $this->loadFixture();
60
    }
61
62
    public function tearDown()
63
    {
64
        parent::tearDown();
65
66
        $class = $this->_em->getClassMetadata(CmsUser::class);
67
        $class->associationMappings['groups']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
68
        $class->associationMappings['articles']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
69
        $class->associationMappings['phonenumbers']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
70
71
        unset($class->associationMappings['groups']['indexBy']);
72
        unset($class->associationMappings['articles']['indexBy']);
73
        unset($class->associationMappings['phonenumbers']['indexBy']);
74
75
        $class = $this->_em->getClassMetadata(CmsGroup::class);
76
        $class->associationMappings['users']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
77
78
        unset($class->associationMappings['users']['indexBy']);
79
    }
80
81
    /**
82
     * @group DDC-546
83
     * @group non-cacheable
84
     */
85
    public function testCountNotInitializesCollection()
86
    {
87
        $user = $this->_em->find(CmsUser::class, $this->userId);
88
        $queryCount = $this->getCurrentQueryCount();
89
90
        $this->assertFalse($user->groups->isInitialized());
0 ignored issues
show
Bug introduced by
The method isInitialized() does not exist on Doctrine\Common\Collections\ArrayCollection. ( Ignorable by Annotation )

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

90
        $this->assertFalse($user->groups->/** @scrutinizer ignore-call */ isInitialized());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
91
        $this->assertEquals(3, count($user->groups));
92
        $this->assertFalse($user->groups->isInitialized());
93
94
        foreach ($user->groups AS $group) { }
95
96
        $this->assertEquals($queryCount + 2, $this->getCurrentQueryCount(), "Expecting two queries to be fired for count, then iteration.");
97
    }
98
99
    /**
100
     * @group DDC-546
101
     */
102
    public function testCountWhenNewEntityPresent()
103
    {
104
        $user = $this->_em->find(CmsUser::class, $this->userId);
105
106
        $newGroup = new CmsGroup();
107
        $newGroup->name = "Test4";
108
109
        $user->addGroup($newGroup);
110
        $this->_em->persist($newGroup);
111
112
        $this->assertFalse($user->groups->isInitialized());
113
        $this->assertEquals(4, count($user->groups));
114
        $this->assertFalse($user->groups->isInitialized());
115
    }
116
117
    /**
118
     * @group DDC-546
119
     * @group non-cacheable
120
     */
121
    public function testCountWhenInitialized()
122
    {
123
        $user = $this->_em->find(CmsUser::class, $this->userId);
124
        $queryCount = $this->getCurrentQueryCount();
125
126
        foreach ($user->groups AS $group) { }
127
128
        $this->assertTrue($user->groups->isInitialized());
129
        $this->assertEquals(3, count($user->groups));
130
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), "Should only execute one query to initialize collection, no extra query for count() more.");
131
    }
132
133
    /**
134
     * @group DDC-546
135
     */
136
    public function testCountInverseCollection()
137
    {
138
        $group = $this->_em->find(CmsGroup::class, $this->groupId);
139
        $this->assertFalse($group->users->isInitialized(), "Pre-Condition");
140
141
        $this->assertEquals(4, count($group->users));
142
        $this->assertFalse($group->users->isInitialized(), "Extra Lazy collection should not be initialized by counting the collection.");
143
    }
144
145
    /**
146
     * @group DDC-546
147
     */
148
    public function testCountOneToMany()
149
    {
150
        $user = $this->_em->find(CmsUser::class, $this->userId);
151
        $this->assertFalse($user->groups->isInitialized(), "Pre-Condition");
152
153
        $this->assertEquals(2, count($user->articles));
154
    }
155
156
    /**
157
     * @group DDC-2504
158
     */
159
    public function testCountOneToManyJoinedInheritance()
160
    {
161
        $otherClass = $this->_em->find(DDC2504OtherClass::class, $this->ddc2504OtherClassId);
162
163
        $this->assertFalse($otherClass->childClasses->isInitialized(), "Pre-Condition");
0 ignored issues
show
Bug introduced by
The method isInitialized() does not exist on Doctrine\Tests\Models\DDC2504\DDC2504ChildClass. ( Ignorable by Annotation )

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

163
        $this->assertFalse($otherClass->childClasses->/** @scrutinizer ignore-call */ isInitialized(), "Pre-Condition");

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
164
        $this->assertEquals(2, count($otherClass->childClasses));
0 ignored issues
show
Bug introduced by
$otherClass->childClasses of type Doctrine\Tests\Models\DDC2504\DDC2504ChildClass is incompatible with the type Countable|array expected by parameter $var of count(). ( Ignorable by Annotation )

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

164
        $this->assertEquals(2, count(/** @scrutinizer ignore-type */ $otherClass->childClasses));
Loading history...
165
    }
166
167
    /**
168
     * @group DDC-546
169
     */
170
    public function testFullSlice()
171
    {
172
        $user = $this->_em->find(CmsUser::class, $this->userId);
173
        $this->assertFalse($user->groups->isInitialized(), "Pre-Condition: Collection is not initialized.");
174
175
        $someGroups = $user->groups->slice(null);
176
        $this->assertEquals(3, count($someGroups));
177
    }
178
179
    /**
180
     * @group DDC-546
181
     * @group non-cacheable
182
     */
183
    public function testSlice()
184
    {
185
        $user = $this->_em->find(CmsUser::class, $this->userId);
186
        $this->assertFalse($user->groups->isInitialized(), "Pre-Condition: Collection is not initialized.");
187
188
        $queryCount = $this->getCurrentQueryCount();
189
190
        $someGroups = $user->groups->slice(0, 2);
191
192
        $this->assertContainsOnly(CmsGroup::class, $someGroups);
193
        $this->assertEquals(2, count($someGroups));
194
        $this->assertFalse($user->groups->isInitialized(), "Slice should not initialize the collection if it wasn't before!");
195
196
        $otherGroup = $user->groups->slice(2, 1);
197
198
        $this->assertContainsOnly(CmsGroup::class, $otherGroup);
199
        $this->assertEquals(1, count($otherGroup));
200
        $this->assertFalse($user->groups->isInitialized());
201
202
        foreach ($user->groups AS $group) { }
203
204
        $this->assertTrue($user->groups->isInitialized());
205
        $this->assertEquals(3, count($user->groups));
206
207
        $this->assertEquals($queryCount + 3, $this->getCurrentQueryCount());
208
    }
209
210
    /**
211
     * @group DDC-546
212
     * @group non-cacheable
213
     */
214
    public function testSliceInitializedCollection()
215
    {
216
        $user = $this->_em->find(CmsUser::class, $this->userId);
217
        $queryCount = $this->getCurrentQueryCount();
218
219
        foreach ($user->groups AS $group) { }
220
221
        $someGroups = $user->groups->slice(0, 2);
222
223
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
224
225
        $this->assertEquals(2, count($someGroups));
226
        $this->assertTrue($user->groups->contains(array_shift($someGroups)));
227
        $this->assertTrue($user->groups->contains(array_shift($someGroups)));
228
    }
229
230
    /**
231
     * @group DDC-546
232
     */
233
    public function testSliceInverseCollection()
234
    {
235
        $group = $this->_em->find(CmsGroup::class, $this->groupId);
236
        $this->assertFalse($group->users->isInitialized(), "Pre-Condition");
237
        $queryCount = $this->getCurrentQueryCount();
238
239
        $someUsers = $group->users->slice(0, 2);
240
        $otherUsers = $group->users->slice(2, 2);
241
242
        $this->assertContainsOnly(CmsUser::class, $someUsers);
243
        $this->assertContainsOnly(CmsUser::class, $otherUsers);
244
        $this->assertEquals(2, count($someUsers));
245
        $this->assertEquals(2, count($otherUsers));
246
247
        // +2 queries executed by slice
248
        $this->assertEquals($queryCount + 2, $this->getCurrentQueryCount(), "Slicing two parts should only execute two additional queries.");
249
    }
250
251
    /**
252
     * @group DDC-546
253
     */
254
    public function testSliceOneToMany()
255
    {
256
        $user = $this->_em->find(CmsUser::class, $this->userId);
257
        $this->assertFalse($user->articles->isInitialized(), "Pre-Condition: Collection is not initialized.");
258
259
        $queryCount = $this->getCurrentQueryCount();
260
261
        $someArticle = $user->articles->slice(0, 1);
0 ignored issues
show
Unused Code introduced by
The assignment to $someArticle is dead and can be removed.
Loading history...
262
        $otherArticle = $user->articles->slice(1, 1);
0 ignored issues
show
Unused Code introduced by
The assignment to $otherArticle is dead and can be removed.
Loading history...
263
264
        $this->assertEquals($queryCount + 2, $this->getCurrentQueryCount());
265
    }
266
267
    /**
268
     * @group DDC-546
269
     */
270
    public function testContainsOneToMany()
271
    {
272
        $user = $this->_em->find(CmsUser::class, $this->userId);
273
        $this->assertFalse($user->articles->isInitialized(), "Pre-Condition: Collection is not initialized.");
274
275
        // Test One to Many existence retrieved from DB
276
        $article    = $this->_em->find(CmsArticle::class, $this->articleId);
277
        $queryCount = $this->getCurrentQueryCount();
278
279
        $this->assertTrue($user->articles->contains($article));
280
        $this->assertFalse($user->articles->isInitialized(), "Post-Condition: Collection is not initialized.");
281
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
282
283
        // Test One to Many existence with state new
284
        $article = new CmsArticle();
285
        $article->topic = "Testnew";
286
        $article->text = "blub";
287
288
        $queryCount = $this->getCurrentQueryCount();
289
        $this->assertFalse($user->articles->contains($article));
290
        $this->assertEquals($queryCount, $this->getCurrentQueryCount(), "Checking for contains of new entity should cause no query to be executed.");
291
292
        // Test One to Many existence with state clear
293
        $this->_em->persist($article);
294
        $this->_em->flush();
295
296
        $queryCount = $this->getCurrentQueryCount();
297
        $this->assertFalse($user->articles->contains($article));
298
        $this->assertEquals($queryCount+1, $this->getCurrentQueryCount(), "Checking for contains of persisted entity should cause one query to be executed.");
299
        $this->assertFalse($user->articles->isInitialized(), "Post-Condition: Collection is not initialized.");
300
301
        // Test One to Many existence with state managed
302
        $article = new CmsArticle();
303
        $article->topic = "How to not fail anymore on tests";
304
        $article->text = "That is simple! Just write more tests!";
305
306
        $this->_em->persist($article);
307
308
        $queryCount = $this->getCurrentQueryCount();
309
310
        $this->assertFalse($user->articles->contains($article));
311
        $this->assertEquals($queryCount, $this->getCurrentQueryCount(), "Checking for contains of managed entity (but not persisted) should cause no query to be executed.");
312
        $this->assertFalse($user->articles->isInitialized(), "Post-Condition: Collection is not initialized.");
313
    }
314
315
    /**
316
     * @group DDC-2504
317
     */
318
    public function testLazyOneToManyJoinedInheritanceIsLazilyInitialized()
319
    {
320
        $otherClass = $this->_em->find(DDC2504OtherClass::class, $this->ddc2504OtherClassId);
321
322
        $this->assertFalse($otherClass->childClasses->isInitialized(), 'Collection is not initialized.');
323
    }
324
325
    /**
326
     * @group DDC-2504
327
     */
328
    public function testContainsOnOneToManyJoinedInheritanceWillNotInitializeCollectionWhenMatchingItemIsFound()
329
    {
330
        $otherClass = $this->_em->find(DDC2504OtherClass::class, $this->ddc2504OtherClassId);
331
332
        // Test One to Many existence retrieved from DB
333
        $childClass = $this->_em->find(DDC2504ChildClass::class, $this->ddc2504ChildClassId);
334
        $queryCount = $this->getCurrentQueryCount();
335
336
        $this->assertTrue($otherClass->childClasses->contains($childClass));
0 ignored issues
show
Bug introduced by
The method contains() does not exist on Doctrine\Tests\Models\DDC2504\DDC2504ChildClass. ( Ignorable by Annotation )

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

336
        $this->assertTrue($otherClass->childClasses->/** @scrutinizer ignore-call */ contains($childClass));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
337
        $this->assertFalse($otherClass->childClasses->isInitialized(), 'Collection is not initialized.');
338
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), 'Search operation was performed via SQL');
339
    }
340
341
    /**
342
     * @group DDC-2504
343
     */
344
    public function testContainsOnOneToManyJoinedInheritanceWillNotCauseQueriesWhenNonPersistentItemIsMatched()
345
    {
346
        $otherClass = $this->_em->find(DDC2504OtherClass::class, $this->ddc2504OtherClassId);
347
        $queryCount = $this->getCurrentQueryCount();
348
349
        $this->assertFalse($otherClass->childClasses->contains(new DDC2504ChildClass()));
350
        $this->assertEquals(
351
            $queryCount,
352
            $this->getCurrentQueryCount(),
353
            'Checking for contains of new entity should cause no query to be executed.'
354
        );
355
    }
356
357
    /**
358
     * @group DDC-2504
359
     */
360
    public function testContainsOnOneToManyJoinedInheritanceWillNotInitializeCollectionWithClearStateMatchingItem()
361
    {
362
        $otherClass = $this->_em->find(DDC2504OtherClass::class, $this->ddc2504OtherClassId);
363
        $childClass = new DDC2504ChildClass();
364
365
        // Test One to Many existence with state clear
366
        $this->_em->persist($childClass);
367
        $this->_em->flush();
368
369
        $queryCount = $this->getCurrentQueryCount();
370
        $this->assertFalse($otherClass->childClasses->contains($childClass));
371
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), "Checking for contains of persisted entity should cause one query to be executed.");
372
        $this->assertFalse($otherClass->childClasses->isInitialized(), "Post-Condition: Collection is not initialized.");
373
    }
374
375
    /**
376
     * @group DDC-2504
377
     */
378
    public function testContainsOnOneToManyJoinedInheritanceWillNotInitializeCollectionWithNewStateNotMatchingItem()
379
    {
380
        $otherClass = $this->_em->find(DDC2504OtherClass::class, $this->ddc2504OtherClassId);
381
        $childClass = new DDC2504ChildClass();
382
383
        $this->_em->persist($childClass);
384
385
        $queryCount = $this->getCurrentQueryCount();
386
387
        $this->assertFalse($otherClass->childClasses->contains($childClass));
388
        $this->assertEquals($queryCount, $this->getCurrentQueryCount(), "Checking for contains of managed entity (but not persisted) should cause no query to be executed.");
389
        $this->assertFalse($otherClass->childClasses->isInitialized(), "Post-Condition: Collection is not initialized.");
390
    }
391
392
    /**
393
     * @group DDC-2504
394
     */
395
    public function testCountingOnOneToManyJoinedInheritanceWillNotInitializeCollection()
396
    {
397
        $otherClass = $this->_em->find(DDC2504OtherClass::class, $this->ddc2504OtherClassId);
398
399
        $this->assertEquals(2, count($otherClass->childClasses));
0 ignored issues
show
Bug introduced by
$otherClass->childClasses of type Doctrine\Tests\Models\DDC2504\DDC2504ChildClass is incompatible with the type Countable|array expected by parameter $var of count(). ( Ignorable by Annotation )

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

399
        $this->assertEquals(2, count(/** @scrutinizer ignore-type */ $otherClass->childClasses));
Loading history...
400
401
        $this->assertFalse($otherClass->childClasses->isInitialized());
402
    }
403
404
    /**
405
     * @group DDC-546
406
     */
407
    public function testContainsManyToMany()
408
    {
409
        $user = $this->_em->find(CmsUser::class, $this->userId);
410
        $this->assertFalse($user->groups->isInitialized(), "Pre-Condition: Collection is not initialized.");
411
412
        // Test Many to Many existence retrieved from DB
413
        $group      = $this->_em->find(CmsGroup::class, $this->groupId);
414
        $queryCount = $this->getCurrentQueryCount();
415
416
        $this->assertTrue($user->groups->contains($group));
417
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), "Checking for contains of managed entity should cause one query to be executed.");
418
        $this->assertFalse($user->groups->isInitialized(), "Post-Condition: Collection is not initialized.");
419
420
        // Test Many to Many existence with state new
421
        $group = new CmsGroup();
422
        $group->name = "A New group!";
423
424
        $queryCount = $this->getCurrentQueryCount();
425
426
        $this->assertFalse($user->groups->contains($group));
427
        $this->assertEquals($queryCount, $this->getCurrentQueryCount(), "Checking for contains of new entity should cause no query to be executed.");
428
        $this->assertFalse($user->groups->isInitialized(), "Post-Condition: Collection is not initialized.");
429
430
        // Test Many to Many existence with state clear
431
        $this->_em->persist($group);
432
        $this->_em->flush();
433
434
        $queryCount = $this->getCurrentQueryCount();
435
436
        $this->assertFalse($user->groups->contains($group));
437
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), "Checking for contains of persisted entity should cause one query to be executed.");
438
        $this->assertFalse($user->groups->isInitialized(), "Post-Condition: Collection is not initialized.");
439
440
        // Test Many to Many existence with state managed
441
        $group = new CmsGroup();
442
        $group->name = "My managed group";
443
444
        $this->_em->persist($group);
445
446
        $queryCount = $this->getCurrentQueryCount();
447
448
        $this->assertFalse($user->groups->contains($group));
449
        $this->assertEquals($queryCount, $this->getCurrentQueryCount(), "Checking for contains of managed entity (but not persisted) should cause no query to be executed.");
450
        $this->assertFalse($user->groups->isInitialized(), "Post-Condition: Collection is not initialized.");
451
    }
452
453
    /**
454
     * @group DDC-546
455
     */
456
    public function testContainsManyToManyInverse()
457
    {
458
        $group = $this->_em->find(CmsGroup::class, $this->groupId);
459
        $this->assertFalse($group->users->isInitialized(), "Pre-Condition: Collection is not initialized.");
460
461
        $user = $this->_em->find(CmsUser::class, $this->userId);
462
463
        $queryCount = $this->getCurrentQueryCount();
464
        $this->assertTrue($group->users->contains($user));
465
        $this->assertEquals($queryCount+1, $this->getCurrentQueryCount(), "Checking for contains of managed entity should cause one query to be executed.");
466
        $this->assertFalse($user->groups->isInitialized(), "Post-Condition: Collection is not initialized.");
467
468
        $newUser = new CmsUser();
469
        $newUser->name = "A New group!";
470
471
        $queryCount = $this->getCurrentQueryCount();
472
        $this->assertFalse($group->users->contains($newUser));
473
        $this->assertEquals($queryCount, $this->getCurrentQueryCount(), "Checking for contains of new entity should cause no query to be executed.");
474
        $this->assertFalse($user->groups->isInitialized(), "Post-Condition: Collection is not initialized.");
475
    }
476
477
    /**
478
     * @group DDC-2504
479
     */
480
    public function testRemovalOfNewManagedElementFromOneToManyJoinedInheritanceCollectionDoesNotInitializeIt()
481
    {
482
        $otherClass = $this->_em->find(DDC2504OtherClass::class, $this->ddc2504OtherClassId);
483
        $childClass = new DDC2504ChildClass();
484
485
        $this->_em->persist($childClass);
486
        $this->_em->flush();
487
488
        $queryCount = $this->getCurrentQueryCount();
489
490
        $otherClass->childClasses->add($childClass);
0 ignored issues
show
Bug introduced by
The method add() does not exist on Doctrine\Tests\Models\DDC2504\DDC2504ChildClass. ( Ignorable by Annotation )

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

490
        $otherClass->childClasses->/** @scrutinizer ignore-call */ 
491
                                   add($childClass);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
491
        $otherClass->childClasses->removeElement($childClass);
0 ignored issues
show
Bug introduced by
The method removeElement() does not exist on Doctrine\Tests\Models\DDC2504\DDC2504ChildClass. ( Ignorable by Annotation )

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

491
        $otherClass->childClasses->/** @scrutinizer ignore-call */ 
492
                                   removeElement($childClass);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
492
493
        $this->assertEquals(
494
            $queryCount,
495
            $this->getCurrentQueryCount(),
496
            'No queries are executed, as the owning side of the association is not actually updated.'
497
        );
498
        $this->assertFalse($otherClass->childClasses->isInitialized(), 'Collection is not initialized.');
499
    }
500
501
    /**
502
     *
503
     */
504
    public function testRemoveElementManyToMany()
505
    {
506
        $user = $this->_em->find(CmsUser::class, $this->userId);
507
        $this->assertFalse($user->groups->isInitialized(), "Pre-Condition: Collection is not initialized.");
508
509
        // Test Many to Many removal with Entity retrieved from DB
510
        $group      = $this->_em->find(CmsGroup::class, $this->groupId);
511
        $queryCount = $this->getCurrentQueryCount();
512
513
        $this->assertTrue($user->groups->removeElement($group));
514
515
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), "Removing a persisted entity should cause one query to be executed.");
516
        $this->assertFalse($user->groups->isInitialized(), "Post-Condition: Collection is not initialized.");
517
518
        $this->assertFalse($user->groups->removeElement($group), "Removing an already removed element returns false");
519
        $this->assertTrue($user->groups->isInitialized(), "Post-Condition: Remmoving entity that isnt in collection initializes");
520
        $this->_em->clear();
521
522
        $user = $this->_em->find(CmsUser::class, $this->userId);
523
        // Test Many to Many removal with Entity state as new
524
        $group = new CmsGroup();
525
        $group->name = "A New group!";
526
527
        $queryCount = $this->getCurrentQueryCount();
528
529
        $user->groups->removeElement($group);
530
531
        $this->assertEquals($queryCount, $this->getCurrentQueryCount(), "Removing new entity should cause no query to be executed.");
532
        $this->assertFalse($user->groups->isInitialized(), "Post-Condition: Collection is not initialized.");
533
534
        // Test Many to Many removal with Entity state as clean
535
        $this->_em->persist($group);
536
        $this->_em->flush();
537
538
        $queryCount = $this->getCurrentQueryCount();
539
540
        $user->groups->removeElement($group);
541
542
        $this->assertEquals($queryCount + 2, $this->getCurrentQueryCount(), "Removing a persisted entity should cause one query to be executed.");
543
        $this->assertTrue($user->groups->isInitialized(), "Post-Condition: Collection is initialized.");
544
        $this->_em->clear();
545
546
        $user = $this->_em->find(CmsUser::class, $this->userId);
547
548
        // Test Many to Many removal with Entity state as managed
549
        $group = new CmsGroup();
550
        $group->name = "A New group!";
551
552
        $this->_em->persist($group);
553
554
        $queryCount = $this->getCurrentQueryCount();
555
556
        $user->groups->removeElement($group);
557
558
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), "Removing a managed entity should cause query to be executed.");
559
        $this->assertTrue($user->groups->isInitialized(), "Post-Condition: Collection is initialized.");
560
    }
561
562
    /**
563
     *
564
     */
565
    public function testRemoveElementManyToManyInverse()
566
    {
567
        $group = $this->_em->find(CmsGroup::class, $this->groupId);
568
        $this->assertFalse($group->users->isInitialized(), "Pre-Condition: Collection is not initialized.");
569
570
        $user       = $this->_em->find(CmsUser::class, $this->userId);
571
        $queryCount = $this->getCurrentQueryCount();
572
573
        $group->users->removeElement($user);
574
575
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), "Removing a managed entity should cause one query to be executed.");
576
        $this->assertFalse($user->groups->isInitialized(), "Post-Condition: Collection is not initialized.");
577
578
        $newUser = new CmsUser();
579
        $newUser->name = "A New group!";
580
581
        $queryCount = $this->getCurrentQueryCount();
582
583
        $group->users->removeElement($newUser);
584
585
        $this->assertEquals($queryCount, $this->getCurrentQueryCount(), "Removing a new entity should cause no query to be executed.");
586
        $this->assertFalse($user->groups->isInitialized(), "Post-Condition: Collection is not initialized.");
587
    }
588
589
    /**
590
     * @group DDC-1399
591
     */
592
    public function testCountAfterAddThenFlush()
593
    {
594
        $user = $this->_em->find(CmsUser::class, $this->userId);
595
596
        $newGroup = new CmsGroup();
597
        $newGroup->name = "Test4";
598
599
        $user->addGroup($newGroup);
600
        $this->_em->persist($newGroup);
601
602
        $this->assertFalse($user->groups->isInitialized());
603
        $this->assertEquals(4, count($user->groups));
604
        $this->assertFalse($user->groups->isInitialized());
605
606
        $this->_em->flush();
607
608
        $this->assertEquals(4, count($user->groups));
609
    }
610
611
    /**
612
     * @group DDC-1462
613
     * @group non-cacheable
614
     */
615
    public function testSliceOnDirtyCollection()
616
    {
617
        $user = $this->_em->find(CmsUser::class, $this->userId);
618
        /* @var $user CmsUser */
619
620
        $newGroup = new CmsGroup();
621
        $newGroup->name = "Test4";
622
623
        $user->addGroup($newGroup);
624
        $this->_em->persist($newGroup);
625
626
        $qc = $this->getCurrentQueryCount();
627
        $groups = $user->groups->slice(0, 10);
628
629
        $this->assertEquals(4, count($groups));
630
        $this->assertEquals($qc + 1, $this->getCurrentQueryCount());
631
    }
632
633
    /**
634
     * @group DDC-1398
635
     * @group non-cacheable
636
     */
637
    public function testGetIndexByIdentifier()
638
    {
639
        $user = $this->_em->find(CmsUser::class, $this->userId);
640
        /* @var $user CmsUser */
641
642
        $queryCount = $this->getCurrentQueryCount();
643
        $phonenumber = $user->phonenumbers->get($this->phonenumber);
644
645
        $this->assertFalse($user->phonenumbers->isInitialized());
646
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
647
        $this->assertSame($phonenumber, $this->_em->find(CmsPhonenumber::class, $this->phonenumber));
648
649
        $article = $user->phonenumbers->get($this->phonenumber);
0 ignored issues
show
Unused Code introduced by
The assignment to $article is dead and can be removed.
Loading history...
650
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), "Getting the same entity should not cause an extra query to be executed");
651
    }
652
653
    /**
654
     * @group DDC-1398
655
     */
656
    public function testGetIndexByOneToMany()
657
    {
658
        $user = $this->_em->find(CmsUser::class, $this->userId);
659
        /* @var $user CmsUser */
660
661
        $queryCount = $this->getCurrentQueryCount();
662
663
        $article = $user->articles->get($this->topic);
664
665
        $this->assertFalse($user->articles->isInitialized());
666
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
667
        $this->assertSame($article, $this->_em->find(CmsArticle::class, $this->articleId));
668
    }
669
670
    /**
671
     * @group DDC-1398
672
     */
673
    public function testGetIndexByManyToManyInverseSide()
674
    {
675
        $group = $this->_em->find(CmsGroup::class, $this->groupId);
676
        /* @var $group CmsGroup */
677
678
        $queryCount = $this->getCurrentQueryCount();
679
680
        $user = $group->users->get($this->username);
681
682
        $this->assertFalse($group->users->isInitialized());
683
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
684
        $this->assertSame($user, $this->_em->find(CmsUser::class, $this->userId));
685
    }
686
687
    /**
688
     * @group DDC-1398
689
     */
690
    public function testGetIndexByManyToManyOwningSide()
691
    {
692
        $user = $this->_em->find(CmsUser::class, $this->userId);
693
        /* @var $user CmsUser */
694
695
        $queryCount = $this->getCurrentQueryCount();
696
697
        $group = $user->groups->get($this->groupname);
698
699
        $this->assertFalse($user->groups->isInitialized());
700
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
701
        $this->assertSame($group, $this->_em->find(CmsGroup::class, $this->groupId));
702
    }
703
704
    /**
705
     * @group DDC-1398
706
     */
707
    public function testGetNonExistentIndexBy()
708
    {
709
        $user = $this->_em->find(CmsUser::class, $this->userId);
710
        $this->assertNull($user->articles->get(-1));
711
        $this->assertNull($user->groups->get(-1));
712
    }
713
714
    public function testContainsKeyIndexByOneToMany()
715
    {
716
        $user = $this->_em->find(CmsUser::class, $this->userId);
717
        /* @var $user CmsUser */
718
719
        $queryCount = $this->getCurrentQueryCount();
720
721
        $contains = $user->articles->containsKey($this->topic);
722
723
        $this->assertTrue($contains);
724
        $this->assertFalse($user->articles->isInitialized());
725
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
726
    }
727
728
    public function testContainsKeyIndexByOneToManyJoinedInheritance()
729
    {
730
        $class = $this->_em->getClassMetadata(DDC2504OtherClass::class);
731
        $class->associationMappings['childClasses']['indexBy'] = 'id';
732
733
        $otherClass = $this->_em->find(DDC2504OtherClass::class, $this->ddc2504OtherClassId);
734
735
        $queryCount = $this->getCurrentQueryCount();
736
737
        $contains = $otherClass->childClasses->containsKey($this->ddc2504ChildClassId);
0 ignored issues
show
Bug introduced by
The method containsKey() does not exist on Doctrine\Tests\Models\DDC2504\DDC2504ChildClass. ( Ignorable by Annotation )

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

737
        /** @scrutinizer ignore-call */ 
738
        $contains = $otherClass->childClasses->containsKey($this->ddc2504ChildClassId);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
738
739
        $this->assertTrue($contains);
740
        $this->assertFalse($otherClass->childClasses->isInitialized());
741
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
742
    }
743
744
    public function testContainsKeyIndexByManyToMany()
745
    {
746
        $user = $this->_em->find(CmsUser::class, $this->userId2);
747
748
        $group = $this->_em->find(CmsGroup::class, $this->groupId);
749
750
        $queryCount = $this->getCurrentQueryCount();
751
752
        $contains = $user->groups->containsKey($group->name);
753
754
        $this->assertTrue($contains, "The item is not into collection");
755
        $this->assertFalse($user->groups->isInitialized(), "The collection must not be initialized");
756
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
757
    }
758
    public function testContainsKeyIndexByManyToManyNonOwning()
759
    {
760
        $user = $this->_em->find(CmsUser::class, $this->userId2);
761
        $group = $this->_em->find(CmsGroup::class, $this->groupId);
762
763
        $queryCount = $this->getCurrentQueryCount();
764
765
        $contains = $group->users->containsKey($user->username);
766
767
        $this->assertTrue($contains, "The item is not into collection");
768
        $this->assertFalse($group->users->isInitialized(), "The collection must not be initialized");
769
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
770
    }
771
772
    public function testContainsKeyIndexByWithPkManyToMany()
773
    {
774
        $class = $this->_em->getClassMetadata(CmsUser::class);
775
        $class->associationMappings['groups']['indexBy'] = 'id';
776
777
        $user = $this->_em->find(CmsUser::class, $this->userId2);
778
779
        $queryCount = $this->getCurrentQueryCount();
780
781
        $contains = $user->groups->containsKey($this->groupId);
782
783
        $this->assertTrue($contains, "The item is not into collection");
784
        $this->assertFalse($user->groups->isInitialized(), "The collection must not be initialized");
785
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
786
    }
787
    public function testContainsKeyIndexByWithPkManyToManyNonOwning()
788
    {
789
        $class = $this->_em->getClassMetadata(CmsGroup::class);
790
        $class->associationMappings['users']['indexBy'] = 'id';
791
792
        $group = $this->_em->find(CmsGroup::class, $this->groupId);
793
794
        $queryCount = $this->getCurrentQueryCount();
795
796
        $contains = $group->users->containsKey($this->userId2);
797
798
        $this->assertTrue($contains, "The item is not into collection");
799
        $this->assertFalse($group->users->isInitialized(), "The collection must not be initialized");
800
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
801
    }
802
803
    public function testContainsKeyNonExistentIndexByOneToMany()
804
    {
805
        $user = $this->_em->find(CmsUser::class, $this->userId2);
806
807
        $queryCount = $this->getCurrentQueryCount();
808
809
        $contains = $user->articles->containsKey("NonExistentTopic");
810
811
        $this->assertFalse($contains);
812
        $this->assertFalse($user->articles->isInitialized());
813
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
814
    }
815
816
    public function testContainsKeyNonExistentIndexByManyToMany()
817
    {
818
        $user = $this->_em->find(CmsUser::class, $this->userId2);
819
820
821
        $queryCount = $this->getCurrentQueryCount();
822
823
        $contains = $user->groups->containsKey("NonExistentTopic");
824
825
        $this->assertFalse($contains);
826
        $this->assertFalse($user->groups->isInitialized());
827
        $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
828
    }
829
830
    private function loadFixture()
831
    {
832
        $user1 = new CmsUser();
833
        $user1->username = "beberlei";
834
        $user1->name = "Benjamin";
835
        $user1->status = "active";
836
837
        $user2 = new CmsUser();
838
        $user2->username = "jwage";
839
        $user2->name = "Jonathan";
840
        $user2->status = "active";
841
842
        $user3 = new CmsUser();
843
        $user3->username = "romanb";
844
        $user3->name = "Roman";
845
        $user3->status = "active";
846
847
        $user4 = new CmsUser();
848
        $user4->username = "gblanco";
849
        $user4->name = "Guilherme";
850
        $user4->status = "active";
851
852
        $this->_em->persist($user1);
853
        $this->_em->persist($user2);
854
        $this->_em->persist($user3);
855
        $this->_em->persist($user4);
856
857
        $group1 = new CmsGroup();
858
        $group1->name = "Test1";
859
860
        $group2 = new CmsGroup();
861
        $group2->name = "Test2";
862
863
        $group3 = new CmsGroup();
864
        $group3->name = "Test3";
865
866
        $user1->addGroup($group1);
867
        $user1->addGroup($group2);
868
        $user1->addGroup($group3);
869
870
        $user2->addGroup($group1);
871
        $user3->addGroup($group1);
872
        $user4->addGroup($group1);
873
874
        $this->_em->persist($group1);
875
        $this->_em->persist($group2);
876
        $this->_em->persist($group3);
877
878
        $article1 = new CmsArticle();
879
        $article1->topic = "Test1";
880
        $article1->text = "Test1";
881
        $article1->setAuthor($user1);
882
883
        $article2 = new CmsArticle();
884
        $article2->topic = "Test2";
885
        $article2->text = "Test2";
886
        $article2->setAuthor($user1);
887
888
        $this->_em->persist($article1);
889
        $this->_em->persist($article2);
890
891
        $phonenumber1 = new CmsPhonenumber();
892
        $phonenumber1->phonenumber = '12345';
893
894
        $phonenumber2 = new CmsPhonenumber();
895
        $phonenumber2->phonenumber = '67890';
896
897
        $this->_em->persist($phonenumber1);
898
        $this->_em->persist($phonenumber2);
899
900
        $user1->addPhonenumber($phonenumber1);
901
902
        // DDC-2504
903
        $otherClass = new DDC2504OtherClass();
904
        $childClass1 = new DDC2504ChildClass();
905
        $childClass2 = new DDC2504ChildClass();
906
907
        $childClass1->other = $otherClass;
908
        $childClass2->other = $otherClass;
909
910
        $otherClass->childClasses[] = $childClass1;
911
        $otherClass->childClasses[] = $childClass2;
912
913
        $this->_em->persist($childClass1);
914
        $this->_em->persist($childClass2);
915
        $this->_em->persist($otherClass);
916
917
        $this->_em->flush();
918
        $this->_em->clear();
919
920
        $this->articleId = $article1->id;
921
        $this->userId = $user1->getId();
922
        $this->userId2 = $user2->getId();
923
        $this->groupId = $group1->id;
924
        $this->ddc2504OtherClassId = $otherClass->id;
925
        $this->ddc2504ChildClassId = $childClass1->id;
926
927
        $this->username = $user1->username;
928
        $this->groupname = $group1->name;
929
        $this->topic = $article1->topic;
930
        $this->phonenumber = $phonenumber1->phonenumber;
931
932
    }
933
934
    /**
935
     * @group DDC-3343
936
     */
937
    public function testRemoveManagedElementFromOneToManyExtraLazyCollectionIsNoOp()
938
    {
939
        list($userId, $tweetId) = $this->loadTweetFixture();
940
941
        /* @var $user User */
942
        $user = $this->_em->find(User::class, $userId);
943
944
        $user->tweets->removeElement($this->_em->find(Tweet::class, $tweetId));
945
946
        $this->_em->clear();
947
948
        /* @var $user User */
949
        $user = $this->_em->find(User::class, $userId);
950
951
        $this->assertCount(1, $user->tweets, 'Element was not removed - need to update the owning side first');
952
    }
953
954
    /**
955
     * @group DDC-3343
956
     */
957
    public function testRemoveManagedElementFromOneToManyExtraLazyCollectionWithoutDeletingTheTargetEntityEntryIsNoOp()
958
    {
959
        list($userId, $tweetId) = $this->loadTweetFixture();
960
961
        /* @var $user User */
962
        $user  = $this->_em->find(User::class, $userId);
963
        $tweet = $this->_em->find(Tweet::class, $tweetId);
964
965
        $user->tweets->removeElement($tweet);
966
967
        $this->_em->clear();
968
969
        /* @var $tweet Tweet */
970
        $tweet = $this->_em->find(Tweet::class, $tweetId);
971
        $this->assertInstanceOf(
972
            Tweet::class,
973
            $tweet,
974
            'Even though the collection is extra lazy, the tweet should not have been deleted'
975
        );
976
977
        $this->assertInstanceOf(
978
            User::class,
979
            $tweet->author,
980
            'Tweet author link has not been removed - need to update the owning side first'
981
        );
982
    }
983
984
    /**
985
     * @group DDC-3343
986
     */
987
    public function testRemovingManagedLazyProxyFromExtraLazyOneToManyDoesRemoveTheAssociationButNotTheEntity()
988
    {
989
        list($userId, $tweetId) = $this->loadTweetFixture();
990
991
        /* @var $user User */
992
        $user  = $this->_em->find(User::class, $userId);
993
        $tweet = $this->_em->getReference(Tweet::class, $tweetId);
994
995
        $user->tweets->removeElement($this->_em->getReference(Tweet::class, $tweetId));
996
997
        $this->_em->clear();
998
999
        /* @var $tweet Tweet */
1000
        $tweet = $this->_em->find(Tweet::class, $tweet->id);
1001
        $this->assertInstanceOf(
1002
            Tweet::class,
1003
            $tweet,
1004
            'Even though the collection is extra lazy, the tweet should not have been deleted'
1005
        );
1006
1007
        $this->assertInstanceOf(User::class, $tweet->author);
1008
1009
        /* @var $user User */
1010
        $user = $this->_em->find(User::class, $userId);
1011
1012
        $this->assertCount(1, $user->tweets, 'Element was not removed - need to update the owning side first');
1013
    }
1014
1015
    /**
1016
     * @group DDC-3343
1017
     */
1018
    public function testRemoveOrphanedManagedElementFromOneToManyExtraLazyCollection()
1019
    {
1020
        list($userId, $userListId) = $this->loadUserListFixture();
1021
1022
        /* @var $user User */
1023
        $user = $this->_em->find(User::class, $userId);
1024
1025
        $user->userLists->removeElement($this->_em->find(UserList::class, $userListId));
1026
1027
        $this->_em->clear();
1028
1029
        /* @var $user User */
1030
        $user = $this->_em->find(User::class, $userId);
1031
1032
        $this->assertCount(0, $user->userLists, 'Element was removed from association due to orphan removal');
1033
        $this->assertNull(
1034
            $this->_em->find(UserList::class, $userListId),
1035
            'Element was deleted due to orphan removal'
1036
        );
1037
    }
1038
1039
    /**
1040
     * @group DDC-3343
1041
     */
1042
    public function testRemoveOrphanedUnManagedElementFromOneToManyExtraLazyCollection()
1043
    {
1044
        list($userId, $userListId) = $this->loadUserListFixture();
1045
1046
        /* @var $user User */
1047
        $user = $this->_em->find(User::class, $userId);
1048
1049
        $user->userLists->removeElement(new UserList());
1050
1051
        $this->_em->clear();
1052
1053
        /* @var $userList UserList */
1054
        $userList = $this->_em->find(UserList::class, $userListId);
1055
        $this->assertInstanceOf(
1056
            UserList::class,
1057
            $userList,
1058
            'Even though the collection is extra lazy + orphan removal, the user list should not have been deleted'
1059
        );
1060
1061
        $this->assertInstanceOf(
1062
            User::class,
1063
            $userList->owner,
1064
            'User list to owner link has not been removed'
1065
        );
1066
    }
1067
1068
    /**
1069
     * @group DDC-3343
1070
     */
1071
    public function testRemoveOrphanedManagedLazyProxyFromExtraLazyOneToMany()
1072
    {
1073
        list($userId, $userListId) = $this->loadUserListFixture();
1074
1075
        /* @var $user User */
1076
        $user = $this->_em->find(User::class, $userId);
1077
1078
        $user->userLists->removeElement($this->_em->getReference(UserList::class, $userListId));
1079
1080
        $this->_em->clear();
1081
1082
        /* @var $user User */
1083
        $user = $this->_em->find(User::class, $userId);
1084
1085
        $this->assertCount(0, $user->userLists, 'Element was removed from association due to orphan removal');
1086
        $this->assertNull(
1087
            $this->_em->find(UserList::class, $userListId),
1088
            'Element was deleted due to orphan removal'
1089
        );
1090
    }
1091
1092
    /**
1093
     * @return int[] ordered tuple: user id and tweet id
1094
     */
1095
    private function loadTweetFixture()
1096
    {
1097
        $user  = new User();
1098
        $tweet = new Tweet();
1099
1100
        $user->name     = 'ocramius';
1101
        $tweet->content = 'The cat is on the table';
1102
1103
        $user->addTweet($tweet);
1104
1105
        $this->_em->persist($user);
1106
        $this->_em->persist($tweet);
1107
        $this->_em->flush();
1108
        $this->_em->clear();
1109
1110
        return [$user->id, $tweet->id];
1111
    }
1112
1113
    /**
1114
     * @return int[] ordered tuple: user id and user list id
1115
     */
1116
    private function loadUserListFixture()
1117
    {
1118
        $user     = new User();
1119
        $userList = new UserList();
1120
1121
        $user->name     = 'ocramius';
1122
        $userList->listName = 'PHP Developers to follow closely';
1123
1124
        $user->addUserList($userList);
1125
1126
        $this->_em->persist($user);
1127
        $this->_em->persist($userList);
1128
        $this->_em->flush();
1129
        $this->_em->clear();
1130
1131
        return [$user->id, $userList->id];
1132
    }
1133
}
1134