From b2c28789e80a97badd14145fda39b545d83ca3ef Mon Sep 17 00:00:00 2001 From: dontub Date: Fri, 17 Jan 2020 21:11:47 +0000 Subject: [PATCH] Fix deep copying of ArrayObject in PHP 7.4 (#145) --- src/DeepCopy/DeepCopy.php | 5 +- .../TypeFilter/Spl/ArrayObjectFilter.php | 36 ++++++++++++++ tests/DeepCopyTest/DeepCopyTest.php | 14 ++++++ .../TypeFilter/Spl/ArrayObjectFilterTest.php | 48 +++++++++++++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/DeepCopy/TypeFilter/Spl/ArrayObjectFilter.php create mode 100644 tests/DeepCopyTest/TypeFilter/Spl/ArrayObjectFilterTest.php diff --git a/src/DeepCopy/DeepCopy.php b/src/DeepCopy/DeepCopy.php index 09a209e..15e5c68 100644 --- a/src/DeepCopy/DeepCopy.php +++ b/src/DeepCopy/DeepCopy.php @@ -2,19 +2,21 @@ namespace DeepCopy; +use ArrayObject; use DateInterval; use DateTimeInterface; use DateTimeZone; use DeepCopy\Exception\CloneException; use DeepCopy\Filter\Filter; use DeepCopy\Matcher\Matcher; +use DeepCopy\Reflection\ReflectionHelper; use DeepCopy\TypeFilter\Date\DateIntervalFilter; +use DeepCopy\TypeFilter\Spl\ArrayObjectFilter; use DeepCopy\TypeFilter\Spl\SplDoublyLinkedListFilter; use DeepCopy\TypeFilter\TypeFilter; use DeepCopy\TypeMatcher\TypeMatcher; use ReflectionObject; use ReflectionProperty; -use DeepCopy\Reflection\ReflectionHelper; use SplDoublyLinkedList; /** @@ -59,6 +61,7 @@ public function __construct($useCloneMethod = false) { $this->useCloneMethod = $useCloneMethod; + $this->addTypeFilter(new ArrayObjectFilter($this), new TypeMatcher(ArrayObject::class)); $this->addTypeFilter(new DateIntervalFilter(), new TypeMatcher(DateInterval::class)); $this->addTypeFilter(new SplDoublyLinkedListFilter($this), new TypeMatcher(SplDoublyLinkedList::class)); } diff --git a/src/DeepCopy/TypeFilter/Spl/ArrayObjectFilter.php b/src/DeepCopy/TypeFilter/Spl/ArrayObjectFilter.php new file mode 100644 index 0000000..dbc25a5 --- /dev/null +++ b/src/DeepCopy/TypeFilter/Spl/ArrayObjectFilter.php @@ -0,0 +1,36 @@ +copier = $copier; + } + + /** + * {@inheritdoc} + */ + public function apply($arrayObject) + { + return new ArrayObject( + $this->copier->copy($arrayObject->getArrayCopy()), + $arrayObject->getFlags(), + $arrayObject->getIteratorClass() + ); + } +} + diff --git a/tests/DeepCopyTest/DeepCopyTest.php b/tests/DeepCopyTest/DeepCopyTest.php index a6f92a5..4a9e924 100644 --- a/tests/DeepCopyTest/DeepCopyTest.php +++ b/tests/DeepCopyTest/DeepCopyTest.php @@ -2,6 +2,7 @@ namespace DeepCopyTest; +use ArrayObject; use DateInterval; use DateTime; use DateTimeImmutable; @@ -24,6 +25,7 @@ use DeepCopy\TypeFilter\ShallowCopyFilter; use DeepCopy\TypeMatcher\TypeMatcher; use PHPUnit\Framework\TestCase; +use RecursiveArrayIterator; use SplDoublyLinkedList; use stdClass; use function DeepCopy\deep_copy; @@ -385,6 +387,18 @@ public function test_it_uses_the_first_filter_matching_for_copying_object_proper $this->assertNull($copy->getAProp()->cloned); } + public function test_it_can_deep_copy_an_array_object() + { + $foo = new f003\Foo('foo'); + $foo->setProp('bar'); + $object = new ArrayObject(['foo' => $foo, \ArrayObject::ARRAY_AS_PROPS, \RecursiveArrayIterator::class]); + + $copy = deep_copy($object); + + $this->assertEqualButNotSame($object, $copy); + $this->assertEqualButNotSame($foo, $copy['foo']); + } + /** * @ticket https://github.com/myclabs/DeepCopy/pull/49 */ diff --git a/tests/DeepCopyTest/TypeFilter/Spl/ArrayObjectFilterTest.php b/tests/DeepCopyTest/TypeFilter/Spl/ArrayObjectFilterTest.php new file mode 100644 index 0000000..b16449a --- /dev/null +++ b/tests/DeepCopyTest/TypeFilter/Spl/ArrayObjectFilterTest.php @@ -0,0 +1,48 @@ + + * + * @covers \DeepCopy\TypeFilter\Spl\ArrayObjectFilter + */ +final class ArrayObjectFilterTest extends TestCase +{ + /** + * @var ArrayObjectFilter + */ + private $arrayObjectFilter; + + /** + * @var DeepCopy|ObjectProphecy + */ + private $copierProphecy; + + protected function setUp(): void + { + $this->copierProphecy = $this->prophesize(DeepCopy::class); + $this->arrayObjectFilter = new ArrayObjectFilter( + $this->copierProphecy->reveal() + ); + } + + public function test_it_deep_copies_an_array_object(): void + { + $arrayObject = new ArrayObject(['foo' => 'bar'], ArrayObject::ARRAY_AS_PROPS, RecursiveArrayIterator::class); + $this->copierProphecy->copy(['foo' => 'bar'])->willReturn(['copy' => 'bar']); + + /** @var \ArrayObject $newArrayObject */ + $newArrayObject = $this->arrayObjectFilter->apply($arrayObject); + $this->assertSame(['copy' => 'bar'], $newArrayObject->getArrayCopy()); + $this->assertSame(ArrayObject::ARRAY_AS_PROPS, $newArrayObject->getFlags()); + $this->assertSame(RecursiveArrayIterator::class, $newArrayObject->getIteratorClass()); + } +}