Skip to content

Commit

Permalink
Merge pull request #663 from webimpress/hotfix/hydration-nested-entities
Browse files Browse the repository at this point in the history
Fixed hydration with nested entities
  • Loading branch information
TomHAnderson authored Jan 26, 2019
2 parents 216c2f2 + 33a9206 commit c8ce08e
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/DoctrineModule/Stdlib/Hydrator/DoctrineObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ protected function hydrateByValue(array $data, $object)

$object->$setter($this->hydrateValue($field, $value, $data));
}

$this->metadata = $metadata;
}

return $object;
Expand Down Expand Up @@ -375,6 +377,8 @@ protected function hydrateByReference(array $data, $object)
} else {
$reflProperty->setValue($object, $this->hydrateValue($field, $value, $data));
}

$this->metadata = $metadata;
}

return $object;
Expand Down
17 changes: 17 additions & 0 deletions tests/DoctrineModuleTest/Stdlib/Hydrator/Asset/OneToOneEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace DoctrineModuleTest\Stdlib\Hydrator\Asset;

use DateTime;

class OneToOneEntity
{
/**
Expand All @@ -14,6 +16,11 @@ class OneToOneEntity
*/
protected $toOne;

/**
* @var DateTime
*/
protected $createdAt;


public function setId($id)
{
Expand Down Expand Up @@ -45,4 +52,14 @@ public function getToOne($modifyValue = true)

return $this->toOne;
}

public function setCreatedAt(DateTime $createdAt)
{
$this->createdAt = $createdAt;
}

public function getCreatedAt()
{
return $this->createdAt;
}
}
118 changes: 117 additions & 1 deletion tests/DoctrineModuleTest/Stdlib/Hydrator/DoctrineObjectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

namespace DoctrineModuleTest\Stdlib\Hydrator;

use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModuleTest\Stdlib\Hydrator\Asset\ByValueDifferentiatorEntity;
use DoctrineModuleTest\Stdlib\Hydrator\Asset\ContextStrategy;
use DoctrineModuleTest\Stdlib\Hydrator\Asset\SimpleEntity;
use PHPUnit\Framework\TestCase as BaseTestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use ReflectionClass;
use Doctrine\Common\Collections\ArrayCollection;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineObjectHydrator;
Expand Down Expand Up @@ -2646,7 +2650,8 @@ public function testOverrideDefaultStrategy()
/**
* https://github.com/doctrine/DoctrineModule/issues/639
*/
public function testStrategyWithArray() {
public function testStrategyWithArrayByValue()
{
$entity = new Asset\SimpleEntity();

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

$this->assertEquals('complex,value', $entity->getField());
}

public function testStrategyWithArrayByReference()
{
$entity = new Asset\SimpleEntity();

$data = ['field' => ['complex', 'value']];
$this->configureObjectManagerForSimpleEntity();
$this->hydratorByReference->addStrategy('field', new class implements StrategyInterface {
public function extract($value) : array
{
return explode(',', $value);
}

public function hydrate($value) : string
{
return implode(',', $value);
}

});

$this->hydratorByReference->hydrate($data, $entity);

$this->assertSame('complex,value', $entity->getField());
}

private function getObjectManagerForNestedHydration()
{
$oneToOneMetadata = $this->prophesize(ClassMetadata::class);
$oneToOneMetadata->getName()->willReturn(Asset\OneToOneEntity::class);
$oneToOneMetadata->getFieldNames()->willReturn(['id', 'toOne', 'createdAt']);
$oneToOneMetadata->getAssociationNames()->willReturn(['toOne']);
$oneToOneMetadata->getTypeOfField('id')->willReturn('integer');
$oneToOneMetadata->getTypeOfField('toOne')->willReturn(Asset\ByValueDifferentiatorEntity::class);
$oneToOneMetadata->getTypeOfField('createdAt')->willReturn('datetime');
$oneToOneMetadata->hasAssociation('id')->willReturn(false);
$oneToOneMetadata->hasAssociation('toOne')->willReturn(true);
$oneToOneMetadata->hasAssociation('createdAt')->willReturn(false);
$oneToOneMetadata->isSingleValuedAssociation('toOne')->willReturn(true);
$oneToOneMetadata->isCollectionValuedAssociation('toOne')->willReturn(false);
$oneToOneMetadata->getAssociationTargetClass('toOne')->willReturn(Asset\ByValueDifferentiatorEntity::class);
$oneToOneMetadata->getReflectionClass()->willReturn(new ReflectionClass(Asset\OneToOneEntity::class));
$oneToOneMetadata->getIdentifier()->willReturn(['id']);
$oneToOneMetadata->getIdentifierFieldNames(Argument::type(Asset\OneToOneEntity::class))->willReturn(['id']);

$byValueDifferentiatorEntity = $this->prophesize(ClassMetadata::class);
$byValueDifferentiatorEntity->getName()->willReturn(Asset\ByValueDifferentiatorEntity::class);
$byValueDifferentiatorEntity->getAssociationNames()->willReturn([]);
$byValueDifferentiatorEntity->getFieldNames()->willReturn(['id', 'field']);
$byValueDifferentiatorEntity->getTypeOfField('id')->willReturn('integer');
$byValueDifferentiatorEntity->getTypeOfField('field')->willReturn('string');
$byValueDifferentiatorEntity->hasAssociation(Argument::any())->willReturn(false);
$byValueDifferentiatorEntity->getIdentifier()->willReturn(['id']);
$byValueDifferentiatorEntity->getIdentifierFieldNames(Argument::type(Asset\ByValueDifferentiatorEntity::class))->willReturn(['id']);
$byValueDifferentiatorEntity->getReflectionClass()->willReturn(new ReflectionClass(Asset\ByValueDifferentiatorEntity::class));

$objectManager = $this->prophesize(ObjectManager::class);
$objectManager->getClassMetadata(Asset\OneToOneEntity::class)->will([$oneToOneMetadata, 'reveal']);
$objectManager->getClassMetadata(Asset\ByValueDifferentiatorEntity::class)->will([$byValueDifferentiatorEntity, 'reveal']);
$objectManager->find(Asset\OneToOneEntity::class, ['id' => 12])->willReturn(false);
$objectManager->find(Asset\ByValueDifferentiatorEntity::class, ['id' => 13])->willReturn(false);

return $objectManager->reveal();
}

public function testNestedHydrationByValue()
{
$objectManager = $this->getObjectManagerForNestedHydration();
$hydrator = new DoctrineObjectHydrator($objectManager, true);
$entity = new Asset\OneToOneEntity();

$data = [
'id' => 12,
'toOne' => [
'id' => 13,
'field' => 'value',
],
'createdAt' => '2019-01-24 12:00:00',
];

$hydrator->hydrate($data, $entity);

$this->assertSame(12, $entity->getId());
$this->assertInstanceOf(Asset\ByValueDifferentiatorEntity::class, $entity->getToOne(false));
$this->assertSame(13, $entity->getToOne(false)->getId());
$this->assertSame('Modified from setToOne setter', $entity->getToOne(false)->getField(false));
$this->assertSame('2019-01-24 12:00:00', $entity->getCreatedAt()->format('Y-m-d H:i:s'));
}

public function testNestedHydrationByReference()
{
$objectManager = $this->getObjectManagerForNestedHydration();
$hydrator = new DoctrineObjectHydrator($objectManager, false);
$entity = new Asset\OneToOneEntity();

$data = [
'id' => 12,
'toOne' => [
'id' => 13,
'field' => 'value',
],
'createdAt' => '2019-01-24 12:00:00',
];

$hydrator->hydrate($data, $entity);

$this->assertSame(12, $entity->getId());
$this->assertInstanceOf(Asset\ByValueDifferentiatorEntity::class, $entity->getToOne(false));
$this->assertSame(13, $entity->getToOne(false)->getId());
$this->assertSame('value', $entity->getToOne(false)->getField(false));
$this->assertSame('2019-01-24 12:00:00', $entity->getCreatedAt()->format('Y-m-d H:i:s'));
}
}

0 comments on commit c8ce08e

Please sign in to comment.