Skip to content
This repository has been archived by the owner on Jan 24, 2020. It is now read-only.

Commit

Permalink
Hydrator ignores private/protected getter/setter
Browse files Browse the repository at this point in the history
If the entity had a getter/setter which was private or protected the hydrator tried to call it anyway
and thus threw an exception. We now silently ignore them if there are not callable.

This allow for entities that have "read-only" fields which are set internally (such as timestamp).
  • Loading branch information
PowerKiKi committed Apr 22, 2016
1 parent ebd26ad commit 6c2f70a
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/DoctrineModule/Stdlib/Hydrator/DoctrineObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ protected function hydrateByValue(array $data, $object)
$target = $metadata->getAssociationTargetClass($field);

if ($metadata->isSingleValuedAssociation($field)) {
if (! method_exists($object, $setter)) {
if (! is_callable([$object, $setter])) {
continue;
}

Expand All @@ -275,7 +275,7 @@ protected function hydrateByValue(array $data, $object)
$this->toMany($object, $field, $target, $value);
}
} else {
if (! method_exists($object, $setter)) {
if (! is_callable([$object, $setter])) {
continue;
}

Expand Down Expand Up @@ -438,7 +438,7 @@ protected function toMany($object, $collectionName, $target, $values)
switch (gettype($value)) {
case 'object':
$getter = 'get' . ucfirst($field);
if (method_exists($value, $getter)) {
if (is_callable([$value, $getter])) {
$find[$field] = $value->$getter();
} elseif (property_exists($value, $field)) {
$find[$field] = $value->$field;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace DoctrineModuleTest\Stdlib\Hydrator\Asset;

class SimplePrivateEntity
{
private function setPrivate($value)
{
throw new \Exception('Should never be called');
}

private function getPrivate()
{
throw new \Exception('Should never be called');
}

protected function setProtected($value)
{
throw new \Exception('Should never be called');
}

protected function getProtected()
{
throw new \Exception('Should never be called');
}
}
67 changes: 67 additions & 0 deletions tests/DoctrineModuleTest/Stdlib/Hydrator/DoctrineObjectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2518,4 +2518,71 @@ public function testHydrateByValueUsesNamingStrategy()
$entity = $this->hydratorByValue->hydrate(array('camel_case' => $name), new NamingStrategyEntity());
$this->assertEquals($name, $entity->getCamelCase());
}

public function configureObjectManagerForSimplePrivateEntity()
{
$refl = new ReflectionClass('DoctrineModuleTest\Stdlib\Hydrator\Asset\SimplePrivateEntity');

$this
->metadata
->expects($this->any())
->method('getName')
->will($this->returnValue('DoctrineModuleTest\Stdlib\Hydrator\Asset\SimplePrivateEntity'));
$this
->metadata
->expects($this->any())
->method('getAssociationNames')
->will($this->returnValue(array()));

$this
->metadata
->expects($this->any())
->method('getFieldNames')
->will($this->returnValue(array('private', 'protected')));

$this
->metadata
->expects($this->any())
->method('getTypeOfField')
->with($this->logicalOr($this->equalTo('private'), $this->equalTo('protected')))
->will($this->returnValue('integer'));

$this
->metadata
->expects($this->any())
->method('hasAssociation')
->will($this->returnValue(false));

$this
->metadata
->expects($this->any())
->method('getIdentifierFieldNames')
->will($this->returnValue(array('private')));

$this
->metadata
->expects($this->any())
->method('getReflectionClass')
->will($this->returnValue($refl));

$this->hydratorByValue = new DoctrineObjectHydrator(
$this->objectManager,
true
);
$this->hydratorByReference = new DoctrineObjectHydrator(
$this->objectManager,
false
);
}

public function testCannotHydratePrivateByValue()
{
$entity = new Asset\SimplePrivateEntity();
$this->configureObjectManagerForSimplePrivateEntity();
$data = array('private' => 123, 'protected' => 456);

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

$this->assertInstanceOf('DoctrineModuleTest\Stdlib\Hydrator\Asset\SimplePrivateEntity', $entity);
}
}

0 comments on commit 6c2f70a

Please sign in to comment.