diff --git a/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php b/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php index 44cef23070..6148832d82 100644 --- a/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php +++ b/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php @@ -218,7 +218,7 @@ public function executeInserts(array $options = []): void $this->class->reflFields[$this->class->versionField]->setValue($document, $nextVersion); } - $data[$versionMapping['name']] = $type->convertPHPToDatabaseValue($nextVersion); + $data[$versionMapping['name']] = $type->convertToDatabaseValue($nextVersion); } $inserts[] = $data; @@ -296,7 +296,7 @@ private function executeUpsert(object $document, array $options): void $this->class->reflFields[$this->class->versionField]->setValue($document, $nextVersion); } - $data['$set'][$versionMapping['name']] = $type->convertPHPToDatabaseValue($nextVersion); + $data['$set'][$versionMapping['name']] = $type->convertToDatabaseValue($nextVersion); } foreach (array_keys($criteria) as $field) { @@ -377,8 +377,8 @@ public function update(object $document, array $options = []): void $type = Type::getType($versionMapping['type']); assert($type instanceof Versionable); $nextVersion = $type->getNextVersion($currentVersion); - $update['$set'][$versionMapping['name']] = Type::convertPHPToDatabaseValue($nextVersion); - $query[$versionMapping['name']] = Type::convertPHPToDatabaseValue($currentVersion); + $update['$set'][$versionMapping['name']] = $type->convertToDatabaseValue($nextVersion); + $query[$versionMapping['name']] = $type->convertToDatabaseValue($currentVersion); } if (! empty($update)) { diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Functional/Ticket/GH2789Test.php b/tests/Doctrine/ODM/MongoDB/Tests/Functional/Ticket/GH2789Test.php new file mode 100644 index 0000000000..bae9c72e30 --- /dev/null +++ b/tests/Doctrine/ODM/MongoDB/Tests/Functional/Ticket/GH2789Test.php @@ -0,0 +1,88 @@ +dm->persist($doc); + $this->dm->flush(); + + $documents = $this->dm->getDocumentCollection(GH2789VersionedUuid::class)->find()->toArray(); + self::assertCount(1, $documents); + self::assertEquals(new Binary('1', 142), $documents[0]['version'], 'The version field should be stored using the custom type'); + + $doc->message = 'new message'; + $this->dm->persist($doc); + $this->dm->flush(); + + $documents = $this->dm->getDocumentCollection(GH2789VersionedUuid::class)->find()->toArray(); + self::assertCount(1, $documents); + self::assertEquals(new Binary('2', 142), $documents[0]['version'], 'The version field should be incremented and stored using the custom type'); + } +} + +#[ODM\Document(collection: 'gh2789_versioned_uuid')] +class GH2789VersionedUuid +{ + #[ODM\Id] + public string $id; + + #[ODM\Version] + #[ODM\Field(type: GH2789CustomType::class)] + public int $version; + + public function __construct( + #[ODM\Field(type: 'string')] + public string $message, + ) { + } +} + +/** + * Custom type that stores an integer as a MongoDB Binary subtype 142. + */ +class GH2789CustomType extends Type implements Versionable +{ + public function convertToPHPValue($value): int + { + assert($value instanceof Binary); + + return (int) $value->getData(); + } + + public function convertToDatabaseValue($value): Binary + { + assert(is_int($value)); + + return new Binary((string) $value, 142); + } + + public function getNextVersion($current): int + { + if ($current === null) { + return 1; + } + + assert(is_int($current)); + + return $current + 1; + } +}