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
Bug
introduced
by
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
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 |