diff --git a/includes/common.inc b/includes/common.inc index f6171cf..a83feb2 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -6462,6 +6462,66 @@ function element_set_attributes(array &$element, array $map) { } /** + * Computes the difference between arrays. + * + * This is just a wrapper around array_diff_assoc(). The only reason Drupal + * provides this function is in since PHP 5.4 casting of arrays to strings + * throws a notice. If you want to use array_diff_assoc() as it was up to PHP + * 5.3, then use this function but consider the consequences -- it should be + * rare to use this function. + * + * @param array $array1 + * The array to compare from. + * @param array $array2 + * The array to compare to. + * + * @return array + * Returns an array containing all the values from array1 that are not present + * in array2. + */ +function drupal_array_diff_assoc($array1, $array2) { + return @array_diff_assoc($array1, $array2); +} + +/** + * Recursively computes the difference of arrays with additional index check. + * + * This is a version of array_diff_assoc() that supports multidimensional + * arrays. + * + * @param array $array1 + * The array to compare from. + * @param array $array2 + * The array to compare to. + * + * @return array + * Returns an array containing all the values from array1 that are not present + * in array2. + */ +function array_diff_assoc_recursive($array1, $array2) { + $difference = array(); + + foreach ($array1 as $key => $value) { + if (is_array($value)) { + if (!array_key_exists($key, $array2) && !is_array($array2[$key])) { + $difference[$key] = $value; + } + else { + $new_diff = array_diff_assoc_recursive($value, $array2[$key]); + if (!empty($new_diff)) { + $difference[$key] = $new_diff; + } + } + } + elseif (!array_key_exists($key, $array2) || $array2[$key] !== $value) { + $difference[$key] = $value; + } + } + + return $difference; +} + +/** * Sets a value in a nested array with variable depth. * * This helper function should be used when the depth of the array element you diff --git a/modules/simpletest/tests/common.test b/modules/simpletest/tests/common.test index cc46069..d9a221f 100644 --- a/modules/simpletest/tests/common.test +++ b/modules/simpletest/tests/common.test @@ -2630,3 +2630,82 @@ class FeedIconTest extends DrupalWebTestCase { } } + +/** + * Test utility functionality in utility.inc. + */ +class ArrayRecursiveUnitTest extends DrupalUnitTestCase { + + /** + * Array to use for testing. + * + * @var array + */ + protected $array1; + + /** + * Array to use for testing. + * + * @var array + */ + protected $array2; + + public static function getInfo() { + return array( + 'name' => 'Array diff assoc tests', + 'description' => 'Tests that the array_diff_assoc_recursive function works.', + 'group' => 'System', + ); + } + + function setUp() { + parent::setUp(); + + $this->array1 = array( + 'same' => 'yes', + 'different' => 'no', + 'array_empty_diff' => array(), + 'null' => NULL, + 'int_diff' => 1, + 'array_diff' => array('same' => 'same', 'array' => array('same' => 'same')), + 'new' => 'new', + ); + $this->array2 = array( + 'same' => 'yes', + 'different' => 'yes', + 'array_empty_diff' => array(), + 'null' => NULL, + 'int_diff' => '1', + 'array_diff' => array('same' => 'different', 'array' => array('same' => 'same')), + ); + } + + /** + * Tests function drupal_array_diff_assoc. + */ + public function testArrayDiffAssoc() { + $expected = array( + 'different' => 'no', + 'new' => 'new', + ); + + $this->assertIdentical(drupal_array_diff_assoc($this->array1, $this->array2), $expected); + } + + + /** + * Tests function array_diff_assoc_recursive. + */ + public function testArrayDiffAssocRecursive() { + $expected = array( + 'different' => 'no', + 'int_diff' => 1, + // The 'array' key should not be returned, as it's the same. + 'array_diff' => array('same' => 'same'), + 'new' => 'new', + ); + + $this->assertIdentical(array_diff_assoc_recursive($this->array1, $this->array2), $expected); + } +} +