Daniel Werner has submitted this change and it was merged. Change subject: Implemented StrategicArrayComparer ......................................................................
Implemented StrategicArrayComparer Change-Id: Ib1f3f4c2a1e3f28fa142429cb64d115c4706fabd --- M RELEASE-NOTES.md M src/ArrayComparer/ArrayComparer.php M src/ArrayComparer/NativeArrayComparer.php M src/ArrayComparer/StrategicArrayComparer.php M src/ArrayComparer/StrictArrayComparer.php M src/differ/CallbackListDiffer.php M tests/phpunit/ArrayComparer/NativeArrayComparerTest.php M tests/phpunit/ArrayComparer/StrategicArrayComparerTest.php M tests/phpunit/ArrayComparer/StrictArrayComparerTest.php 9 files changed, 225 insertions(+), 26 deletions(-) Approvals: Daniel Werner: Looks good to me, approved diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index f1c82cc..01e3a08 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -4,6 +4,13 @@ ## Version 0.8 (dev) +#### Additions + +* Added Diff\ArrayComparer\ArrayComparer interface +* Added NativeArrayComparer, ArrayComparer adapter for array_diff +* Added StrictArrayComparer, containing the "strict mode" logic from ListDiffer +* Added StrategicArrayComparer, implementation of ArrayComparer that takes a ValueComparer as strategy + #### Improvements * MapPatcher will now report conflicts for remove operations that specify a value to be removed diff --git a/src/ArrayComparer/ArrayComparer.php b/src/ArrayComparer/ArrayComparer.php index 8fbab4c..99c6ab9 100644 --- a/src/ArrayComparer/ArrayComparer.php +++ b/src/ArrayComparer/ArrayComparer.php @@ -6,7 +6,7 @@ * Interface for objects that can compute the difference between two arrays * in similar fashion to PHPs native array_diff. * - * @since 0.7 + * @since 0.8 * * @file * @ingroup Diff @@ -19,7 +19,9 @@ /** * Returns an array containing all the entries from arrayOne that are not present in arrayTwo. * - * @since 0.7 + * Implementations are allowed to hold quantity into account or to disregard it. + * + * @since 0.8 * * @param array $firstArray * @param array $secondArray diff --git a/src/ArrayComparer/NativeArrayComparer.php b/src/ArrayComparer/NativeArrayComparer.php index 798e873..c5ef04f 100644 --- a/src/ArrayComparer/NativeArrayComparer.php +++ b/src/ArrayComparer/NativeArrayComparer.php @@ -5,7 +5,7 @@ /** * Adapter for PHPs native array_diff method. * - * @since 0.7 + * @since 0.8 * * @file * @ingroup Diff @@ -20,7 +20,7 @@ * * Uses @see array_diff. * - * @since 0.7 + * @since 0.8 * * @param array $arrayOne * @param array $arrayTwo diff --git a/src/ArrayComparer/StrategicArrayComparer.php b/src/ArrayComparer/StrategicArrayComparer.php index 39c6d32..fbf0977 100644 --- a/src/ArrayComparer/StrategicArrayComparer.php +++ b/src/ArrayComparer/StrategicArrayComparer.php @@ -8,7 +8,9 @@ * Computes the difference between two arrays by comparing elements with * a ValueComparer. * - * @since 0.7 + * Quantity matters: [42, 42] and [42] are different + * + * @since 0.8 * * @file * @ingroup Diff @@ -27,7 +29,7 @@ /** * @see ArrayComparer::diffArrays * - * @since 0.7 + * @since 0.8 * * @param array $arrayOne * @param array $arrayTwo @@ -35,7 +37,40 @@ * @return array */ public function diffArrays( array $arrayOne, array $arrayTwo ) { - return array(); // TODO: implement + $notInTwo = array(); + + foreach ( $arrayOne as $element ) { + $valueOffset = $this->arraySearch( $element, $arrayTwo ); + + if ( $valueOffset === false ) { + $notInTwo[] = $element; + continue; + } + + unset( $arrayTwo[$valueOffset] ); + } + + return $notInTwo; + } + + /** + * @since 0.8 + * + * @param string|int $needle + * @param array $haystack + * + * @return bool|int|string + */ + protected function arraySearch( $needle, array $haystack ) { + foreach ( $haystack as $valueOffset => $thing ) { + $areEqual = $this->valueComparer->valuesAreEqual( $needle, $thing ); + + if ( $areEqual ) { + return $valueOffset; + } + } + + return false; } } diff --git a/src/ArrayComparer/StrictArrayComparer.php b/src/ArrayComparer/StrictArrayComparer.php index 785bce8..6d3e2c3 100644 --- a/src/ArrayComparer/StrictArrayComparer.php +++ b/src/ArrayComparer/StrictArrayComparer.php @@ -5,7 +5,15 @@ /** * Strict variant of PHPs array_diff method. * - * @since 0.7 + * Similar to @see array_diff with the following differences: + * + * - Strict comparison for arrays: ['42'] and [42] are different + * - Quantity matters: [42, 42] and [42] are different + * - Arrays and objects are compared properly: [[1]] and [[2]] are different + * - Naive support for objects by using non-strict comparison + * - Only works with two arrays (array_diff can take more) + * + * @since 0.8 * * @file * @ingroup Diff @@ -18,15 +26,7 @@ /** * @see ArrayComparer::diffArrays * - * Similar to @see array_diff with the following differences: - * - * - Strict comparison for arrays: ['42'] and [42] are different - * - Quantity matters: [42, 42] and [42] are different - * - Arrays and objects are compared properly: [[1]] and [[2]] are different - * - Naive support for objects by using non-strict comparison - * - Only works with two arrays (array_diff can take more) - * - * @since 0.7 + * @since 0.8 * * @param array $arrayOne * @param array $arrayTwo diff --git a/src/differ/CallbackListDiffer.php b/src/differ/CallbackListDiffer.php index 9f5dc28..e8f9e11 100644 --- a/src/differ/CallbackListDiffer.php +++ b/src/differ/CallbackListDiffer.php @@ -101,6 +101,7 @@ $areEqual = call_user_func_array( $this->comparisonCallback, array( $needle, $thing ) ); if ( !is_bool( $areEqual ) ) { + // TODO: throw a more specific exception type throw new Exception( 'Comparison callback returned a non-boolean value' ); } diff --git a/tests/phpunit/ArrayComparer/NativeArrayComparerTest.php b/tests/phpunit/ArrayComparer/NativeArrayComparerTest.php index 5b5de97..cdbd68e 100644 --- a/tests/phpunit/ArrayComparer/NativeArrayComparerTest.php +++ b/tests/phpunit/ArrayComparer/NativeArrayComparerTest.php @@ -9,7 +9,7 @@ * @covers Diff\ArrayComparer\NativeArrayComparer * * @file - * @since 0.7 + * @since 0.8 * * @ingroup DiffTest * diff --git a/tests/phpunit/ArrayComparer/StrategicArrayComparerTest.php b/tests/phpunit/ArrayComparer/StrategicArrayComparerTest.php index 9d3b400..b457c0f 100644 --- a/tests/phpunit/ArrayComparer/StrategicArrayComparerTest.php +++ b/tests/phpunit/ArrayComparer/StrategicArrayComparerTest.php @@ -2,6 +2,7 @@ namespace Diff\Tests\ArrayComparer; +use Diff\ArrayComparer\ArrayComparer; use Diff\ArrayComparer\StrategicArrayComparer; use Diff\Tests\DiffTestCase; @@ -9,7 +10,7 @@ * @covers Diff\ArrayComparer\StrategicArrayComparer * * @file - * @since 0.7 + * @since 0.8 * * @ingroup DiffTest * @@ -25,26 +26,179 @@ $this->assertTrue( true ); } - public function testDiffArrays() { + public function testDiffArraysWithComparerThatAlwaysReturnsTrue() { + $valueComparer = $this->getMock( 'Diff\Comparer\ValueComparer' ); + + $valueComparer->expects( $this->any() ) + ->method( 'valuesAreEqual' ) + ->will( $this->returnValue( true ) ); + + $arrayComparer = new StrategicArrayComparer( $valueComparer ); + + $this->assertNoDifference( + $arrayComparer, + array( 0, 2, 4 ), + array( 1, 2, 9 ) + ); + + $this->assertNoDifference( + $arrayComparer, + array( 1, 2, 3 ), + array( 1, 2, 3 ) + ); + + $this->assertNoDifference( + $arrayComparer, + array( 'bah' ), + array( 'foo', 'bar', 'baz' ) + ); + + $this->assertNoDifference( + $arrayComparer, + array(), + array( 'foo', 'bar', 'baz' ) + ); + + $this->assertNoDifference( + $arrayComparer, + array(), + array() + ); + } + + protected function assertNoDifference( ArrayComparer $arrayComparer, array $arrayOne, array $arrayTwo ) { + $this->assertEquals( + array(), + $arrayComparer->diffArrays( + $arrayOne, + $arrayTwo + ) + ); + } + + public function testDiffArraysWithComparerThatAlwaysReturnsFalse() { + $valueComparer = $this->getMock( 'Diff\Comparer\ValueComparer' ); + + $valueComparer->expects( $this->any() ) + ->method( 'valuesAreEqual' ) + ->will( $this->returnValue( false ) ); + + $arrayComparer = new StrategicArrayComparer( $valueComparer ); + + $this->assertAllDifferent( + $arrayComparer, + array(), + array() + ); + + $this->assertAllDifferent( + $arrayComparer, + array( 1, 2, 3 ), + array() + ); + + $this->assertAllDifferent( + $arrayComparer, + array( 1, 2, 3 ), + array( 1, 2, 3 ) + ); + + $this->assertAllDifferent( + $arrayComparer, + array(), + array( 1, 2, 3 ) + ); + } + + protected function assertAllDifferent( ArrayComparer $arrayComparer, array $arrayOne, array $arrayTwo ) { + $this->assertEquals( + $arrayOne, + $arrayComparer->diffArrays( + $arrayOne, + $arrayTwo + ) + ); + } + + public function testQuantityMattersWithReturnTrue() { + $valueComparer = $this->getMock( 'Diff\Comparer\ValueComparer' ); + + $valueComparer->expects( $this->any() ) + ->method( 'valuesAreEqual' ) + ->will( $this->returnValue( true ) ); + + $arrayComparer = new StrategicArrayComparer( $valueComparer ); + + $this->assertEquals( + array( 1, 1, 1 ), + $arrayComparer->diffArrays( + array( 1, 1, 1, 1 ), + array( 1 ) + ) + ); + + $this->assertEquals( + array( 1 ), + $arrayComparer->diffArrays( + array( 1, 1, 1, 1 ), + array( 1, 1, 1 ) + ) + ); + } + + public function testQuantityMattersWithSimpleComparison() { $valueComparer = $this->getMock( 'Diff\Comparer\ValueComparer' ); $valueComparer->expects( $this->any() ) ->method( 'valuesAreEqual' ) ->will( $this->returnCallback( function( $firstValue, $secondValue ) { - return true; + return $firstValue == $secondValue; } ) ); $arrayComparer = new StrategicArrayComparer( $valueComparer ); $this->assertEquals( - array(), + array( 1, 2, 5 ), $arrayComparer->diffArrays( - array( 0, 2, 4 ), - array( 1, 2, 9 ) + array( 1, 1, 2, 3, 2, 5 ), + array( 1, 2, 3, 4 ) ) ); - // TODO: implement + $this->assertEquals( + array( 1 ), + $arrayComparer->diffArrays( + array( 1, 1, 1, 2, 2, 3 ), + array( 1, 1, 2, 2, 3, 3, 3 ) + ) + ); + + $this->assertEquals( + array( 1 ), + $arrayComparer->diffArrays( + array( 3, 1, 2, 1, 1, 2 ), + array( 1, 3, 3, 2, 2, 3, 1 ) + ) + ); + } + + public function testValueComparerGetsCalledWithCorrectValues() { + $valueComparer = $this->getMock( 'Diff\Comparer\ValueComparer' ); + + $valueComparer->expects( $this->once() ) + ->method( 'valuesAreEqual' ) + ->with( + $this->equalTo( 1 ), + $this->equalTo( 2 ) + ) + ->will( $this->returnValue( true ) ); + + $arrayComparer = new StrategicArrayComparer( $valueComparer ); + + $arrayComparer->diffArrays( + array( 1 ), + array( 2 ) + ); } } diff --git a/tests/phpunit/ArrayComparer/StrictArrayComparerTest.php b/tests/phpunit/ArrayComparer/StrictArrayComparerTest.php index c1f065b..35cd54b 100644 --- a/tests/phpunit/ArrayComparer/StrictArrayComparerTest.php +++ b/tests/phpunit/ArrayComparer/StrictArrayComparerTest.php @@ -9,7 +9,7 @@ * @covers Diff\ArrayComparer\StrictArrayComparer * * @file - * @since 0.7 + * @since 0.8 * * @ingroup DiffTest * -- To view, visit https://gerrit.wikimedia.org/r/77247 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ib1f3f4c2a1e3f28fa142429cb64d115c4706fabd Gerrit-PatchSet: 6 Gerrit-Project: mediawiki/extensions/Diff Gerrit-Branch: master Gerrit-Owner: Jeroen De Dauw <jeroended...@gmail.com> Gerrit-Reviewer: Daniel Werner <daniel.wer...@wikimedia.de> Gerrit-Reviewer: Jeroen De Dauw <jeroended...@gmail.com> Gerrit-Reviewer: jenkins-bot _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits