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

Commit

Permalink
Merge branch 'hotfix/65'
Browse files Browse the repository at this point in the history
Close #65
  • Loading branch information
weierophinney committed Sep 20, 2017
2 parents 9a4bc55 + 2907ec9 commit c7cf9a3
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 7 deletions.
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ All notable changes to this project will be documented in this file, in reverse

- Nothing.

### Changed

- Nothing.

### Deprecated

- Nothing.
Expand All @@ -18,7 +22,12 @@ All notable changes to this project will be documented in this file, in reverse

### Fixed

- Nothing.
- [#65](https://github.com/zendframework/zend-hydrator/pull/65) fixes the
hydration behavior of the `ArraySerializable` hydrator when using
`exchangeArray()`. Previously, the method would clear any existing values from
the instance, which is problematic when a partial update is provided as values
not in the update would disappear. The class now pulls the original values,
and recursively merges the replacement with those values.

## 2.2.2 - 2017-05-17

Expand Down
23 changes: 17 additions & 6 deletions src/ArraySerializable.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

namespace Zend\Hydrator;

use Zend\Stdlib\ArrayUtils;

class ArraySerializable extends AbstractHydrator
{
/**
Expand Down Expand Up @@ -68,14 +70,23 @@ public function hydrate(array $data, $object)
}

if (is_callable([$object, 'exchangeArray'])) {
// Ensure any previously populated values not in the replacement
// remain following population.
if (is_callable([$object, 'getArrayCopy'])) {
$original = $object->getArrayCopy($object);
$replacement = ArrayUtils::merge($original, $replacement);
}
$object->exchangeArray($replacement);
} elseif (is_callable([$object, 'populate'])) {
return $object;
}

if (is_callable([$object, 'populate'])) {
$object->populate($replacement);
} else {
throw new Exception\BadMethodCallException(
sprintf('%s expects the provided object to implement exchangeArray() or populate()', __METHOD__)
);
return $object;
}
return $object;

throw new Exception\BadMethodCallException(
sprintf('%s expects the provided object to implement exchangeArray() or populate()', __METHOD__)
);
}
}
38 changes: 38 additions & 0 deletions test/ArraySerializableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,42 @@ public function testCanHydrateToArraySerializableObject()

$this->assertSame($data, $object->getArrayCopy());
}

/**
* Verifies that when an object already has properties,
* these properties are preserved when it's hydrated with new data
* existing properties should get overwritten
*/
public function testWillPreserveOriginalPropsAtHydration()
{
$original = new ArraySerializableAsset();

$data = [
'bar' => 'foo1'
];

$expected = array_merge($original->getArrayCopy(), $data);

$actual = $this->hydrator->hydrate($data, $original);

$this->assertSame($expected, $actual->getArrayCopy());
}

/**
* To preserve backwards compatibility, if getArrayCopy() is not implemented
* by the to-be hydrated object, simply exchange the array
*/
public function testWillReplaceArrayIfNoGetArrayCopy()
{
$original = new \ZendTest\Hydrator\TestAsset\ArraySerializableNoGetArrayCopy();

$data = [
'bar' => 'foo1'
];

$expected = $data;

$actual = $this->hydrator->hydrate($data, $original);
$this->assertSame($expected, $actual->getData());
}
}
44 changes: 44 additions & 0 deletions test/TestAsset/ArraySerializableNoGetArrayCopy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace ZendTest\Hydrator\TestAsset;

class ArraySerializableNoGetArrayCopy
{
protected $data = [];

public function __construct()
{
$this->data = [
"foo" => "bar",
"bar" => "foo",
"blubb" => "baz",
"quo" => "blubb"
];
}

/**
* Exchange internal values from provided array
*
* @param array $array
* @return void
*/
public function exchangeArray(array $array)
{
$this->data = $array;
}

/**
* Returns the internal data
*/
public function getData()
{
return $this->data;
}
}

0 comments on commit c7cf9a3

Please sign in to comment.