diff --git a/src/Construction/DoctrineObjectConstructor.php b/src/Construction/DoctrineObjectConstructor.php index 2eddf5824..31d5f8703 100644 --- a/src/Construction/DoctrineObjectConstructor.php +++ b/src/Construction/DoctrineObjectConstructor.php @@ -89,6 +89,12 @@ public function construct(DeserializationVisitorInterface $visitor, ClassMetadat $identifierList[$name] = $data[$dataName]; } + if (empty($identifierList)) { + // $classMetadataFactory->isTransient() fails on embeddable class with file metadata driver + // https://github.com/doctrine/persistence/issues/37 + return $this->fallbackConstructor->construct($visitor, $metadata, $data, $type, $context); + } + // Entity update, load it from database $object = $objectManager->find($metadata->name, $identifierList); diff --git a/tests/Fixtures/Doctrine/XmlMapping/JMS.Serializer.Tests.Fixtures.Doctrine.Embeddable.BlogPostSeo.dcm.xml b/tests/Fixtures/Doctrine/XmlMapping/JMS.Serializer.Tests.Fixtures.Doctrine.Embeddable.BlogPostSeo.dcm.xml new file mode 100644 index 000000000..87cce5a0d --- /dev/null +++ b/tests/Fixtures/Doctrine/XmlMapping/JMS.Serializer.Tests.Fixtures.Doctrine.Embeddable.BlogPostSeo.dcm.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/Serializer/Doctrine/ObjectConstructorTest.php b/tests/Serializer/Doctrine/ObjectConstructorTest.php index 07b5fc235..a5614468e 100644 --- a/tests/Serializer/Doctrine/ObjectConstructorTest.php +++ b/tests/Serializer/Doctrine/ObjectConstructorTest.php @@ -14,9 +14,11 @@ use Doctrine\ORM\Configuration; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\Driver\AnnotationDriver; +use Doctrine\ORM\Mapping\Driver\XmlDriver; use Doctrine\ORM\ORMException; use Doctrine\ORM\Tools\SchemaTool; use Doctrine\ORM\UnitOfWork; +use Doctrine\ORM\Version as ORMVersion; use JMS\Serializer\Builder\CallbackDriverFactory; use JMS\Serializer\Builder\DefaultDriverFactory; use JMS\Serializer\Construction\DoctrineObjectConstructor; @@ -29,6 +31,7 @@ use JMS\Serializer\Serializer; use JMS\Serializer\SerializerBuilder; use JMS\Serializer\SerializerInterface; +use JMS\Serializer\Tests\Fixtures\Doctrine\Embeddable\BlogPostSeo; use JMS\Serializer\Tests\Fixtures\Doctrine\Entity\Author; use JMS\Serializer\Tests\Fixtures\Doctrine\IdentityFields\Server; use JMS\Serializer\Tests\Fixtures\DoctrinePHPCR\Author as DoctrinePHPCRAuthor; @@ -212,6 +215,40 @@ public function testNamingForIdentifierColumnIsConsidered() ); } + public function testFallbackOnEmbeddableClassWithXmlDriver() + { + if (ORMVersion::compare('2.5') >= 0) { + $this->markTestSkipped('Not using Doctrine ORM >= 2.5 with Embedded entities'); + } + + $fallback = $this->getMockBuilder(ObjectConstructorInterface::class)->getMock(); + $fallback->expects($this->once())->method('construct'); + + $connection = $this->createConnection(); + $entityManager = $this->createXmlEntityManager($connection); + + $this->registry = $registry = new SimpleBaseManagerRegistry( + static function ($id) use ($connection, $entityManager) { + switch ($id) { + case 'default_connection': + return $connection; + + case 'default_manager': + return $entityManager; + + default: + throw new \RuntimeException(sprintf('Unknown service id "%s".', $id)); + } + } + ); + + $type = ['name' => BlogPostSeo::class, 'params' => []]; + $class = new ClassMetadata(BlogPostSeo::class); + + $constructor = new DoctrineObjectConstructor($this->registry, $fallback, DoctrineObjectConstructor::ON_MISSING_FALLBACK); + $constructor->construct($this->visitor, $class, ['metaTitle' => 'test'], $type, $this->context); + } + protected function setUp() { $this->visitor = $this->getMockBuilder(DeserializationVisitorInterface::class)->getMock(); @@ -265,13 +302,16 @@ private function createConnection() ]); } - private function createEntityManager(Connection $con) + private function createEntityManager(Connection $con, ?Configuration $cfg = null) { - $cfg = new Configuration(); - $cfg->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader(), [ - __DIR__ . '/../../Fixtures/Doctrine/Entity', - __DIR__ . '/../../Fixtures/Doctrine/IdentityFields', - ])); + if (!$cfg) { + $cfg = new Configuration(); + $cfg->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader(), [ + __DIR__ . '/../../Fixtures/Doctrine/Entity', + __DIR__ . '/../../Fixtures/Doctrine/IdentityFields', + ])); + } + $cfg->setAutoGenerateProxyClasses(true); $cfg->setProxyNamespace('JMS\Serializer\DoctrineProxy'); $cfg->setProxyDir(sys_get_temp_dir() . '/serializer-test-proxies'); @@ -279,6 +319,21 @@ private function createEntityManager(Connection $con) return EntityManager::create($con, $cfg); } + /** + * @param Connection $con + * + * @return EntityManager + */ + private function createXmlEntityManager(Connection $con) + { + $cfg = new Configuration(); + $cfg->setMetadataDriverImpl(new XmlDriver([ + __DIR__ . '/../../Fixtures/Doctrine/XmlMapping', + ])); + + return $this->createEntityManager($con, $cfg); + } + /** * @return SerializerInterface */