Failed Conditions
Push — master ( 7c9ab7...fa4d3b )
by Marco
13:03
created

Doctrine/Tests/ORM/PersistentCollectionTest.php (2 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\ORM;
6
7
use Doctrine\Common\Collections\ArrayCollection;
8
use Doctrine\ORM\PersistentCollection;
9
use Doctrine\ORM\UnitOfWork;
10
use Doctrine\Tests\Mocks\ConnectionMock;
11
use Doctrine\Tests\Mocks\DriverMock;
12
use Doctrine\Tests\Mocks\EntityManagerMock;
13
use Doctrine\Tests\Models\ECommerce\ECommerceCart;
14
use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
15
use Doctrine\Tests\OrmTestCase;
16
use PHPUnit_Framework_MockObject_MockObject;
17
use stdClass;
18
use function array_keys;
19
20
/**
21
 * Tests the lazy-loading capabilities of the PersistentCollection and the initialization of collections.
22
 */
23
class PersistentCollectionTest extends OrmTestCase
24
{
25
    /** @var PersistentCollection */
26
    protected $collection;
27
28
    /** @var EntityManagerMock */
29
    private $emMock;
30
31
    protected function setUp() : void
32
    {
33
        parent::setUp();
34
35
        $this->emMock = EntityManagerMock::create(new ConnectionMock([], new DriverMock()));
36
37
        $this->setUpPersistentCollection();
38
    }
39
40
    /**
41
     * Set up the PersistentCollection used for collection initialization tests.
42
     */
43
    public function setUpPersistentCollection()
44
    {
45
        $classMetaData    = $this->emMock->getClassMetadata(ECommerceCart::class);
46
        $this->collection = new PersistentCollection($this->emMock, $classMetaData, new ArrayCollection());
0 ignored issues
show
$classMetaData of type Doctrine\Common\Persistence\Mapping\ClassMetadata is incompatible with the type Doctrine\ORM\Mapping\ClassMetadata expected by parameter $class of Doctrine\ORM\PersistentCollection::__construct(). ( Ignorable by Annotation )

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

46
        $this->collection = new PersistentCollection($this->emMock, /** @scrutinizer ignore-type */ $classMetaData, new ArrayCollection());
Loading history...
47
        $this->collection->setInitialized(false);
48
        $this->collection->setOwner(new ECommerceCart(), $classMetaData->getProperty('products'));
49
    }
50
51
    public function testCanBePutInLazyLoadingMode() : void
52
    {
53
        $class      = $this->emMock->getClassMetadata(ECommerceProduct::class);
54
        $collection = new PersistentCollection($this->emMock, $class, new ArrayCollection());
0 ignored issues
show
$class of type Doctrine\Common\Persistence\Mapping\ClassMetadata is incompatible with the type Doctrine\ORM\Mapping\ClassMetadata expected by parameter $class of Doctrine\ORM\PersistentCollection::__construct(). ( Ignorable by Annotation )

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

54
        $collection = new PersistentCollection($this->emMock, /** @scrutinizer ignore-type */ $class, new ArrayCollection());
Loading history...
55
        $collection->setInitialized(false);
56
        self::assertFalse($collection->isInitialized());
57
    }
58
59
    /**
60
     * Test that PersistentCollection::current() initializes the collection.
61
     */
62
    public function testCurrentInitializesCollection() : void
63
    {
64
        $this->collection->current();
65
        self::assertTrue($this->collection->isInitialized());
66
    }
67
68
    /**
69
     * Test that PersistentCollection::key() initializes the collection.
70
     */
71
    public function testKeyInitializesCollection() : void
72
    {
73
        $this->collection->key();
74
        self::assertTrue($this->collection->isInitialized());
75
    }
76
77
    /**
78
     * Test that PersistentCollection::next() initializes the collection.
79
     */
80
    public function testNextInitializesCollection() : void
81
    {
82
        $this->collection->next();
83
        self::assertTrue($this->collection->isInitialized());
84
    }
85
86
    /**
87
     * @group DDC-3382
88
     */
89
    public function testNonObjects() : void
90
    {
91
        $this->setUpPersistentCollection();
92
93
        self::assertEmpty($this->collection);
94
95
        $this->collection->add('dummy');
96
97
        self::assertNotEmpty($this->collection);
98
99
        $product = new ECommerceProduct();
100
101
        $this->collection->set(1, $product);
102
        $this->collection->set(2, 'dummy');
103
        $this->collection->set(3, null);
104
105
        self::assertSame($product, $this->collection->get(1));
106
        self::assertSame('dummy', $this->collection->get(2));
107
        self::assertNull($this->collection->get(3));
108
    }
109
110
    /**
111
     * @group 6110
112
     */
113
    public function testRemovingElementsAlsoRemovesKeys() : void
114
    {
115
        $dummy = new stdClass();
116
117
        $this->setUpPersistentCollection();
118
119
        $this->collection->add($dummy);
120
        self::assertEquals([0], array_keys($this->collection->toArray()));
121
122
        $this->collection->removeElement($dummy);
123
        self::assertEquals([], array_keys($this->collection->toArray()));
124
    }
125
126
    /**
127
     * @group 6110
128
     */
129
    public function testClearWillAlsoClearKeys() : void
130
    {
131
        $this->collection->add(new stdClass());
132
        $this->collection->clear();
133
        self::assertEquals([], array_keys($this->collection->toArray()));
134
    }
135
136
    /**
137
     * @group 6110
138
     */
139
    public function testClearWillAlsoResetKeyPositions() : void
140
    {
141
        $dummy = new stdClass();
142
143
        $this->collection->add($dummy);
144
        $this->collection->removeElement($dummy);
145
        $this->collection->clear();
146
147
        $this->collection->add($dummy);
148
149
        self::assertEquals([0], array_keys($this->collection->toArray()));
150
    }
151
152
    /**
153
     * @group 6613
154
     * @group 6614
155
     * @group 6616
156
     */
157
    public function testWillKeepNewItemsInDirtyCollectionAfterInitialization() : void
158
    {
159
        /** @var UnitOfWork|PHPUnit_Framework_MockObject_MockObject $unitOfWork */
160
        $unitOfWork = $this->createMock(UnitOfWork::class);
161
162
        $this->emMock->setUnitOfWork($unitOfWork);
163
164
        $newElement       = new stdClass();
165
        $persistedElement = new stdClass();
166
167
        $this->collection->add($newElement);
168
169
        self::assertFalse($this->collection->isInitialized());
170
        self::assertTrue($this->collection->isDirty());
171
172
        $unitOfWork
173
            ->expects(self::once())
174
            ->method('loadCollection')
175
            ->with($this->collection)
176
            ->willReturnCallback(static function (PersistentCollection $persistentCollection) use ($persistedElement) : void {
177
                $persistentCollection->unwrap()->add($persistedElement);
178
            });
179
180
        $this->collection->initialize();
181
182
        self::assertSame([$persistedElement, $newElement], $this->collection->toArray());
183
        self::assertTrue($this->collection->isInitialized());
184
        self::assertTrue($this->collection->isDirty());
185
    }
186
187
    /**
188
     * @group 6613
189
     * @group 6614
190
     * @group 6616
191
     */
192
    public function testWillDeDuplicateNewItemsThatWerePreviouslyPersistedInDirtyCollectionAfterInitialization() : void
193
    {
194
        /** @var UnitOfWork|PHPUnit_Framework_MockObject_MockObject $unitOfWork */
195
        $unitOfWork = $this->createMock(UnitOfWork::class);
196
197
        $this->emMock->setUnitOfWork($unitOfWork);
198
199
        $newElement                    = new stdClass();
200
        $newElementThatIsAlsoPersisted = new stdClass();
201
        $persistedElement              = new stdClass();
202
203
        $this->collection->add($newElementThatIsAlsoPersisted);
204
        $this->collection->add($newElement);
205
206
        self::assertFalse($this->collection->isInitialized());
207
        self::assertTrue($this->collection->isDirty());
208
209
        $unitOfWork
210
            ->expects(self::once())
211
            ->method('loadCollection')
212
            ->with($this->collection)
213
            ->willReturnCallback(static function (PersistentCollection $persistentCollection) use (
214
                $persistedElement,
215
                $newElementThatIsAlsoPersisted
216
            ) : void {
217
                $persistentCollection->unwrap()->add($newElementThatIsAlsoPersisted);
218
                $persistentCollection->unwrap()->add($persistedElement);
219
            });
220
221
        $this->collection->initialize();
222
223
        self::assertSame(
224
            [$newElementThatIsAlsoPersisted, $persistedElement, $newElement],
225
            $this->collection->toArray()
226
        );
227
        self::assertTrue($this->collection->isInitialized());
228
        self::assertTrue($this->collection->isDirty());
229
    }
230
231
    /**
232
     * @group 6613
233
     * @group 6614
234
     * @group 6616
235
     */
236
    public function testWillNotMarkCollectionAsDirtyAfterInitializationIfNoElementsWereAdded() : void
237
    {
238
        /** @var UnitOfWork|PHPUnit_Framework_MockObject_MockObject $unitOfWork */
239
        $unitOfWork = $this->createMock(UnitOfWork::class);
240
241
        $this->emMock->setUnitOfWork($unitOfWork);
242
243
        $newElementThatIsAlsoPersisted = new stdClass();
244
        $persistedElement              = new stdClass();
245
246
        $this->collection->add($newElementThatIsAlsoPersisted);
247
248
        self::assertFalse($this->collection->isInitialized());
249
        self::assertTrue($this->collection->isDirty());
250
251
        $unitOfWork
252
            ->expects(self::once())
253
            ->method('loadCollection')
254
            ->with($this->collection)
255
            ->willReturnCallback(static function (PersistentCollection $persistentCollection) use (
256
                $persistedElement,
257
                $newElementThatIsAlsoPersisted
258
            ) : void {
259
                $persistentCollection->unwrap()->add($newElementThatIsAlsoPersisted);
260
                $persistentCollection->unwrap()->add($persistedElement);
261
            });
262
263
        $this->collection->initialize();
264
265
        self::assertSame(
266
            [$newElementThatIsAlsoPersisted, $persistedElement],
267
            $this->collection->toArray()
268
        );
269
        self::assertTrue($this->collection->isInitialized());
270
        self::assertFalse($this->collection->isDirty());
271
    }
272
}
273