-
-
Notifications
You must be signed in to change notification settings - Fork 506
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make PersistentCollectionInterface
and PersistentCollection
generic
#2324
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,7 +85,8 @@ | |
* version?: bool, | ||
* lock?: bool, | ||
* inherited?: string, | ||
* declared?: class-string | ||
* declared?: class-string, | ||
* prime?: list<string> | ||
* } | ||
* @psalm-type FieldMapping = array{ | ||
* type: string, | ||
|
@@ -99,7 +100,6 @@ | |
* isOwningSide: bool, | ||
* isInverseSide: bool, | ||
* strategy?: string, | ||
* notSaved?: bool, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is duplicated |
||
* association?: int, | ||
* id?: bool, | ||
* collectionClass?: class-string, | ||
|
@@ -124,7 +124,8 @@ | |
* lock?: bool, | ||
* notSaved?: bool, | ||
* inherited?: string, | ||
* declared?: class-string | ||
* declared?: class-string, | ||
* prime?: list<string> | ||
* } | ||
* @psalm-type AssociationFieldMapping = array{ | ||
* type: string, | ||
|
@@ -162,7 +163,8 @@ | |
* lock?: bool, | ||
* notSaved?: bool, | ||
* inherited?: string, | ||
* declared?: class-string | ||
* declared?: class-string, | ||
* prime?: list<string> | ||
* } | ||
* @psalm-type IndexKeys = array<string, mixed> | ||
* @psalm-type IndexOptions = array<string, mixed> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
use Closure; | ||
use Doctrine\Common\Collections\Collection as BaseCollection; | ||
use Doctrine\ODM\MongoDB\DocumentManager; | ||
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; | ||
use Doctrine\ODM\MongoDB\MongoDBException; | ||
use Doctrine\ODM\MongoDB\UnitOfWork; | ||
use Doctrine\ODM\MongoDB\Utility\CollectionHelper; | ||
|
@@ -21,25 +22,32 @@ | |
|
||
/** | ||
* Trait with methods needed to implement PersistentCollectionInterface. | ||
* | ||
* @psalm-import-type FieldMapping from ClassMetadata | ||
* @template TKey of array-key | ||
* @template T of object | ||
*/ | ||
trait PersistentCollectionTrait | ||
{ | ||
/** | ||
* A snapshot of the collection at the moment it was fetched from the database. | ||
* This is used to create a diff of the collection at commit time. | ||
* | ||
* @var array | ||
* @var array<TKey, T> | ||
*/ | ||
private $snapshot = []; | ||
|
||
/** | ||
* Collection's owning entity | ||
* Collection's owning document | ||
* | ||
* @var object|null | ||
*/ | ||
private $owner; | ||
|
||
/** @var array|null */ | ||
/** | ||
* @var array|null | ||
* @psalm-var FieldMapping|null | ||
*/ | ||
private $mapping; | ||
|
||
/** | ||
|
@@ -60,7 +68,7 @@ trait PersistentCollectionTrait | |
/** | ||
* The wrapped Collection instance. | ||
* | ||
* @var BaseCollection | ||
* @var BaseCollection<TKey, T> | ||
*/ | ||
private $coll; | ||
|
||
|
@@ -130,6 +138,7 @@ public function initialize() | |
return; | ||
} | ||
|
||
/** @psalm-var array<TKey, T> $newObjects */ | ||
$newObjects = []; | ||
|
||
if ($this->isDirty) { | ||
|
@@ -164,7 +173,7 @@ public function initialize() | |
/** | ||
* Marks this collection as changed/dirty. | ||
*/ | ||
private function changed() | ||
private function changed(): void | ||
{ | ||
if ($this->isDirty) { | ||
return; | ||
|
@@ -681,7 +690,7 @@ public function unwrap() | |
* 2. New collection is not dirty, if reused on other document nothing | ||
* changes. | ||
* 3. Snapshot leads to invalid diffs being generated. | ||
* 4. Lazy loading grabs entities from old owner object. | ||
* 4. Lazy loading grabs documents from old owner object. | ||
* 5. New collection is connected to old owner and leads to duplicate keys. | ||
*/ | ||
public function __clone() | ||
|
@@ -730,11 +739,10 @@ private function doAdd($value, $arrayAccess) | |
* Actual logic for removing element by its key. | ||
* | ||
* @param mixed $offset | ||
* @param bool $arrayAccess | ||
* | ||
* @return bool | ||
* @return bool|T|null | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we can return the result of |
||
*/ | ||
private function doRemove($offset, $arrayAccess) | ||
private function doRemove($offset, bool $arrayAccess) | ||
{ | ||
$this->initialize(); | ||
if ($arrayAccess) { | ||
|
@@ -758,9 +766,8 @@ private function doRemove($offset, $arrayAccess) | |
* | ||
* @param mixed $offset | ||
* @param mixed $value | ||
* @param bool $arrayAccess | ||
*/ | ||
private function doSet($offset, $value, $arrayAccess) | ||
private function doSet($offset, $value, bool $arrayAccess): void | ||
{ | ||
$arrayAccess ? $this->coll->offsetSet($offset, $value) : $this->coll->set($offset, $value); | ||
|
||
|
@@ -777,10 +784,8 @@ private function doSet($offset, $value, $arrayAccess) | |
* | ||
* Embedded documents are automatically considered as "orphan removal enabled" because they might have references | ||
* that require to trigger cascade remove operations. | ||
* | ||
* @return bool | ||
*/ | ||
private function isOrphanRemovalEnabled() | ||
private function isOrphanRemovalEnabled(): bool | ||
{ | ||
if ($this->mapping === null) { | ||
return false; | ||
|
@@ -795,10 +800,8 @@ private function isOrphanRemovalEnabled() | |
|
||
/** | ||
* Checks whether collection owner needs to be scheduled for dirty change in case the collection is modified. | ||
* | ||
* @return bool | ||
*/ | ||
private function needsSchedulingForSynchronization() | ||
private function needsSchedulingForSynchronization(): bool | ||
{ | ||
return $this->owner && $this->dm && ! empty($this->mapping['isOwningSide']) | ||
&& $this->dm->getClassMetadata(get_class($this->owner))->isChangeTrackingNotify(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -228,3 +228,27 @@ parameters: | |
message: "#^Method Doctrine\\\\ODM\\\\MongoDB\\\\Tests\\\\SchemaManagerTest\\:\\:writeOptions\\(\\) should return PHPUnit\\\\Framework\\\\Constraint\\\\Constraint but returns PHPUnit\\\\Framework\\\\Constraint\\\\ArraySubset\\.$#" | ||
count: 1 | ||
path: tests/Doctrine/ODM/MongoDB/Tests/SchemaManagerTest.php | ||
|
||
# import type in PHPStan does not work, see https://github.com/phpstan/phpstan/issues/5091 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All these issues being ignored are because in PHPStan, apparently importing type aliases from a trait does not work: phpstan/phpstan#5091 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Subscribed to that issue 👍 |
||
- | ||
message: "#^Access to offset '.+' on an unknown class Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\\\FieldMapping\\.$#" | ||
count: 12 | ||
path: lib/Doctrine/ODM/MongoDB/PersistentCollection.php | ||
|
||
# import type in PHPStan does not work, see https://github.com/phpstan/phpstan/issues/5091 | ||
- | ||
message: "#^Method Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\:\\:getMapping\\(\\) should return array\\('type' \\=\\> string, 'fieldName' \\=\\> string, 'name' \\=\\> string, 'isCascadeRemove' \\=\\> bool, 'isCascadePersist' \\=\\> bool, 'isCascadeRefresh' \\=\\> bool, 'isCascadeMerge' \\=\\> bool, 'isCascadeDetach' \\=\\> bool, \\.\\.\\.\\) but returns Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\\\FieldMapping\\|null\\.$#" | ||
count: 1 | ||
path: lib/Doctrine/ODM/MongoDB/PersistentCollection.php | ||
|
||
# import type in PHPStan does not work, see https://github.com/phpstan/phpstan/issues/5091 | ||
- | ||
message: "#^Property Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\:\\:\\$mapping has unknown class Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\\\FieldMapping as its type\\.$#" | ||
count: 1 | ||
path: lib/Doctrine/ODM/MongoDB/PersistentCollection.php | ||
|
||
# import type in PHPStan does not work, see https://github.com/phpstan/phpstan/issues/5091 | ||
- | ||
message: "#^Property Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\<TKey of \\(int\\|string\\),T of object\\>\\:\\:\\$mapping \\(Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\\\FieldMapping\\|null\\) does not accept array\\<string, array\\<int\\|string, mixed\\>\\|bool\\|int\\|string\\|null\\>\\.$#" | ||
count: 1 | ||
path: lib/Doctrine/ODM/MongoDB/PersistentCollection.php |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,7 +42,19 @@ public function testExceptionForGetTypeClassWithoutDocumentManager() | |
$unserialized = unserialize($serialized); | ||
assert($unserialized instanceof PersistentCollection); | ||
|
||
$unserialized->setOwner($owner, ['targetDocument' => stdClass::class]); | ||
$unserialized->setOwner($owner, [ | ||
'type' => ClassMetadata::ONE, | ||
'name' => 'name', | ||
'fieldName' => 'fieldName', | ||
'isCascadeRemove' => false, | ||
'isCascadePersist' => false, | ||
'isCascadeRefresh' => false, | ||
'isCascadeMerge' => false, | ||
'isCascadeDetach' => false, | ||
'isOwningSide' => false, | ||
'isInverseSide' => false, | ||
'targetDocument' => stdClass::class, | ||
]); | ||
Comment on lines
+45
to
+57
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is to create a valid |
||
$this->expectException(MongoDBException::class); | ||
$this->expectExceptionMessage( | ||
'No DocumentManager is associated with this PersistentCollection, ' . | ||
|
@@ -274,9 +286,10 @@ public function testOffsetExistsIsForwarded() | |
public function testOffsetGetIsForwarded() | ||
{ | ||
$collection = $this->getMockCollection(); | ||
$collection->expects($this->once())->method('offsetGet')->willReturn(2); | ||
$object = new stdClass(); | ||
$collection->expects($this->once())->method('offsetGet')->willReturn($object); | ||
$pcoll = new PersistentCollection($collection, $this->dm, $this->uow); | ||
$this->assertSame(2, $pcoll[0]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These changes in tests are because |
||
$this->assertSame($object, $pcoll[0]); | ||
} | ||
|
||
public function testOffsetUnsetIsForwarded() | ||
|
@@ -302,12 +315,12 @@ public function testOffsetSetIsForwarded() | |
$collection = $this->getMockCollection(); | ||
$collection->expects($this->exactly(2))->method('offsetSet'); | ||
$pcoll = new PersistentCollection($collection, $this->dm, $this->uow); | ||
$pcoll[] = 1; | ||
$pcoll[1] = 2; | ||
$pcoll[] = new stdClass(); | ||
$pcoll[1] = new stdClass(); | ||
$collection->expects($this->once())->method('add'); | ||
$pcoll->add(3); | ||
$pcoll->add(new stdClass()); | ||
$collection->expects($this->once())->method('set'); | ||
$pcoll->set(3, 4); | ||
$pcoll->set(3, new stdClass()); | ||
} | ||
|
||
public function testIsEmptyIsForwardedWhenCollectionIsInitialized() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing one, I used
list<string>
because of:mongodb-odm/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php
Lines 494 to 497 in f033c43