diff --git a/src/Patcher/ListPatcher.php b/src/Patcher/ListPatcher.php index 2deff09..d4e22e2 100644 --- a/src/Patcher/ListPatcher.php +++ b/src/Patcher/ListPatcher.php @@ -4,6 +4,7 @@ use Diff\DiffOp\Diff\Diff; use Diff\DiffOp\DiffOpAdd; +use Diff\DiffOp\DiffOpChange; use Diff\DiffOp\DiffOpRemove; /** @@ -41,6 +42,16 @@ public function patch( array $base, Diff $diff ) { foreach ( $diff as $diffOp ) { if ( $diffOp instanceof DiffOpAdd ) { $base[] = $diffOp->getNewValue(); + } elseif ( $diffOp instanceof DiffOpChange ) { + $key = array_search( $diffOp->getOldValue(), $base, true ); + + if ( $key === false ) { + $this->handleError( 'Cannot change an element in a list if it is not present' ); + continue; + } + + unset( $base[$key] ); + $base[] = $diffOp->getNewValue(); } elseif ( $diffOp instanceof DiffOpRemove ) { $key = array_search( $diffOp->getOldValue(), $base, true ); diff --git a/tests/phpunit/Patcher/ListPatcherTest.php b/tests/phpunit/Patcher/ListPatcherTest.php index 8fded3b..7a862c3 100644 --- a/tests/phpunit/Patcher/ListPatcherTest.php +++ b/tests/phpunit/Patcher/ListPatcherTest.php @@ -4,6 +4,7 @@ use Diff\DiffOp\Diff\Diff; use Diff\DiffOp\DiffOpAdd; +use Diff\DiffOp\DiffOpChange; use Diff\DiffOp\DiffOpRemove; use Diff\Patcher\ListPatcher; use Diff\Patcher\Patcher; @@ -67,6 +68,13 @@ public function patchProvider() { $argLists[] = array( $patcher, $base, $diff, $expected ); + $argLists[] = array( + new ListPatcher(), + array( 1 ), + new Diff( array( new DiffOpChange( 1, 2 ) ) ), + array( 2 ) + ); + $patcher = new ListPatcher(); $base = array( 0, 1, 2, 3, 4 ); $diff = new Diff( array( @@ -139,6 +147,13 @@ public function getApplicableDiffProvider() { $argLists[] = array( $diff, $currentObject, $expected, 'Empty diff should remain empty on non-empty base' ); + $argLists[] = array( + new Diff( array( new Diff( array( new DiffOpAdd( 1 ) ) ) ) ), + array(), + new Diff(), + 'Recursive diffs should be ignored by ListPatcher' + ); + $diff = new Diff( array( new DiffOpRemove( 9001 ), ), false ); @@ -149,6 +164,13 @@ public function getApplicableDiffProvider() { $argLists[] = array( $diff, $currentObject, $expected, 'Remove ops should be removed on empty base' ); + $argLists[] = array( + new Diff( array( new DiffOpChange( 1, 2 ) ) ), + array(), + new Diff(), + 'Change ops should be removed on empty base' + ); + $diff = new Diff( array( new DiffOpAdd( 42 ), new DiffOpRemove( 9001 ), @@ -201,6 +223,13 @@ public function getApplicableDiffProvider() { 'list diffs containing only add ops should be retained even when not in the base' ); + $argLists[] = array( + new Diff( array( new DiffOpChange( 1, 2 ) ) ), + array( 1 ), + new Diff( array( new DiffOpRemove( 1 ), new DiffOpAdd( 2 ) ) ), + 'Change ops with values present in the base should be retained in ListDiff' + ); + $diff = new Diff( array( new DiffOpRemove( 42 ), new DiffOpRemove( 9001 ),