Skip to content

Commit c8ce08e

Browse files
authored
Merge pull request #663 from webimpress/hotfix/hydration-nested-entities
Fixed hydration with nested entities
2 parents 216c2f2 + 33a9206 commit c8ce08e

File tree

3 files changed

+138
-1
lines changed

3 files changed

+138
-1
lines changed

src/DoctrineModule/Stdlib/Hydrator/DoctrineObject.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,8 @@ protected function hydrateByValue(array $data, $object)
328328

329329
$object->$setter($this->hydrateValue($field, $value, $data));
330330
}
331+
332+
$this->metadata = $metadata;
331333
}
332334

333335
return $object;
@@ -375,6 +377,8 @@ protected function hydrateByReference(array $data, $object)
375377
} else {
376378
$reflProperty->setValue($object, $this->hydrateValue($field, $value, $data));
377379
}
380+
381+
$this->metadata = $metadata;
378382
}
379383

380384
return $object;

tests/DoctrineModuleTest/Stdlib/Hydrator/Asset/OneToOneEntity.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace DoctrineModuleTest\Stdlib\Hydrator\Asset;
44

5+
use DateTime;
6+
57
class OneToOneEntity
68
{
79
/**
@@ -14,6 +16,11 @@ class OneToOneEntity
1416
*/
1517
protected $toOne;
1618

19+
/**
20+
* @var DateTime
21+
*/
22+
protected $createdAt;
23+
1724

1825
public function setId($id)
1926
{
@@ -45,4 +52,14 @@ public function getToOne($modifyValue = true)
4552

4653
return $this->toOne;
4754
}
55+
56+
public function setCreatedAt(DateTime $createdAt)
57+
{
58+
$this->createdAt = $createdAt;
59+
}
60+
61+
public function getCreatedAt()
62+
{
63+
return $this->createdAt;
64+
}
4865
}

tests/DoctrineModuleTest/Stdlib/Hydrator/DoctrineObjectTest.php

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22

33
namespace DoctrineModuleTest\Stdlib\Hydrator;
44

5+
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
6+
use Doctrine\Common\Persistence\ObjectManager;
57
use DoctrineModuleTest\Stdlib\Hydrator\Asset\ByValueDifferentiatorEntity;
68
use DoctrineModuleTest\Stdlib\Hydrator\Asset\ContextStrategy;
79
use DoctrineModuleTest\Stdlib\Hydrator\Asset\SimpleEntity;
810
use PHPUnit\Framework\TestCase as BaseTestCase;
11+
use Prophecy\Argument;
12+
use Prophecy\Prophecy\ObjectProphecy;
913
use ReflectionClass;
1014
use Doctrine\Common\Collections\ArrayCollection;
1115
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineObjectHydrator;
@@ -2646,7 +2650,8 @@ public function testOverrideDefaultStrategy()
26462650
/**
26472651
* https://github.com/doctrine/DoctrineModule/issues/639
26482652
*/
2649-
public function testStrategyWithArray() {
2653+
public function testStrategyWithArrayByValue()
2654+
{
26502655
$entity = new Asset\SimpleEntity();
26512656

26522657
$data = ['field' => ['complex', 'value']];
@@ -2668,4 +2673,115 @@ public function hydrate($value) : string
26682673

26692674
$this->assertEquals('complex,value', $entity->getField());
26702675
}
2676+
2677+
public function testStrategyWithArrayByReference()
2678+
{
2679+
$entity = new Asset\SimpleEntity();
2680+
2681+
$data = ['field' => ['complex', 'value']];
2682+
$this->configureObjectManagerForSimpleEntity();
2683+
$this->hydratorByReference->addStrategy('field', new class implements StrategyInterface {
2684+
public function extract($value) : array
2685+
{
2686+
return explode(',', $value);
2687+
}
2688+
2689+
public function hydrate($value) : string
2690+
{
2691+
return implode(',', $value);
2692+
}
2693+
2694+
});
2695+
2696+
$this->hydratorByReference->hydrate($data, $entity);
2697+
2698+
$this->assertSame('complex,value', $entity->getField());
2699+
}
2700+
2701+
private function getObjectManagerForNestedHydration()
2702+
{
2703+
$oneToOneMetadata = $this->prophesize(ClassMetadata::class);
2704+
$oneToOneMetadata->getName()->willReturn(Asset\OneToOneEntity::class);
2705+
$oneToOneMetadata->getFieldNames()->willReturn(['id', 'toOne', 'createdAt']);
2706+
$oneToOneMetadata->getAssociationNames()->willReturn(['toOne']);
2707+
$oneToOneMetadata->getTypeOfField('id')->willReturn('integer');
2708+
$oneToOneMetadata->getTypeOfField('toOne')->willReturn(Asset\ByValueDifferentiatorEntity::class);
2709+
$oneToOneMetadata->getTypeOfField('createdAt')->willReturn('datetime');
2710+
$oneToOneMetadata->hasAssociation('id')->willReturn(false);
2711+
$oneToOneMetadata->hasAssociation('toOne')->willReturn(true);
2712+
$oneToOneMetadata->hasAssociation('createdAt')->willReturn(false);
2713+
$oneToOneMetadata->isSingleValuedAssociation('toOne')->willReturn(true);
2714+
$oneToOneMetadata->isCollectionValuedAssociation('toOne')->willReturn(false);
2715+
$oneToOneMetadata->getAssociationTargetClass('toOne')->willReturn(Asset\ByValueDifferentiatorEntity::class);
2716+
$oneToOneMetadata->getReflectionClass()->willReturn(new ReflectionClass(Asset\OneToOneEntity::class));
2717+
$oneToOneMetadata->getIdentifier()->willReturn(['id']);
2718+
$oneToOneMetadata->getIdentifierFieldNames(Argument::type(Asset\OneToOneEntity::class))->willReturn(['id']);
2719+
2720+
$byValueDifferentiatorEntity = $this->prophesize(ClassMetadata::class);
2721+
$byValueDifferentiatorEntity->getName()->willReturn(Asset\ByValueDifferentiatorEntity::class);
2722+
$byValueDifferentiatorEntity->getAssociationNames()->willReturn([]);
2723+
$byValueDifferentiatorEntity->getFieldNames()->willReturn(['id', 'field']);
2724+
$byValueDifferentiatorEntity->getTypeOfField('id')->willReturn('integer');
2725+
$byValueDifferentiatorEntity->getTypeOfField('field')->willReturn('string');
2726+
$byValueDifferentiatorEntity->hasAssociation(Argument::any())->willReturn(false);
2727+
$byValueDifferentiatorEntity->getIdentifier()->willReturn(['id']);
2728+
$byValueDifferentiatorEntity->getIdentifierFieldNames(Argument::type(Asset\ByValueDifferentiatorEntity::class))->willReturn(['id']);
2729+
$byValueDifferentiatorEntity->getReflectionClass()->willReturn(new ReflectionClass(Asset\ByValueDifferentiatorEntity::class));
2730+
2731+
$objectManager = $this->prophesize(ObjectManager::class);
2732+
$objectManager->getClassMetadata(Asset\OneToOneEntity::class)->will([$oneToOneMetadata, 'reveal']);
2733+
$objectManager->getClassMetadata(Asset\ByValueDifferentiatorEntity::class)->will([$byValueDifferentiatorEntity, 'reveal']);
2734+
$objectManager->find(Asset\OneToOneEntity::class, ['id' => 12])->willReturn(false);
2735+
$objectManager->find(Asset\ByValueDifferentiatorEntity::class, ['id' => 13])->willReturn(false);
2736+
2737+
return $objectManager->reveal();
2738+
}
2739+
2740+
public function testNestedHydrationByValue()
2741+
{
2742+
$objectManager = $this->getObjectManagerForNestedHydration();
2743+
$hydrator = new DoctrineObjectHydrator($objectManager, true);
2744+
$entity = new Asset\OneToOneEntity();
2745+
2746+
$data = [
2747+
'id' => 12,
2748+
'toOne' => [
2749+
'id' => 13,
2750+
'field' => 'value',
2751+
],
2752+
'createdAt' => '2019-01-24 12:00:00',
2753+
];
2754+
2755+
$hydrator->hydrate($data, $entity);
2756+
2757+
$this->assertSame(12, $entity->getId());
2758+
$this->assertInstanceOf(Asset\ByValueDifferentiatorEntity::class, $entity->getToOne(false));
2759+
$this->assertSame(13, $entity->getToOne(false)->getId());
2760+
$this->assertSame('Modified from setToOne setter', $entity->getToOne(false)->getField(false));
2761+
$this->assertSame('2019-01-24 12:00:00', $entity->getCreatedAt()->format('Y-m-d H:i:s'));
2762+
}
2763+
2764+
public function testNestedHydrationByReference()
2765+
{
2766+
$objectManager = $this->getObjectManagerForNestedHydration();
2767+
$hydrator = new DoctrineObjectHydrator($objectManager, false);
2768+
$entity = new Asset\OneToOneEntity();
2769+
2770+
$data = [
2771+
'id' => 12,
2772+
'toOne' => [
2773+
'id' => 13,
2774+
'field' => 'value',
2775+
],
2776+
'createdAt' => '2019-01-24 12:00:00',
2777+
];
2778+
2779+
$hydrator->hydrate($data, $entity);
2780+
2781+
$this->assertSame(12, $entity->getId());
2782+
$this->assertInstanceOf(Asset\ByValueDifferentiatorEntity::class, $entity->getToOne(false));
2783+
$this->assertSame(13, $entity->getToOne(false)->getId());
2784+
$this->assertSame('value', $entity->getToOne(false)->getField(false));
2785+
$this->assertSame('2019-01-24 12:00:00', $entity->getCreatedAt()->format('Y-m-d H:i:s'));
2786+
}
26712787
}

0 commit comments

Comments
 (0)