diff --git a/core/lib/Drupal/Component/Utility/diffArray.php b/core/lib/Drupal/Component/Utility/diffArray.php new file mode 100644 index 0000000..20738ae --- /dev/null +++ b/core/lib/Drupal/Component/Utility/diffArray.php @@ -0,0 +1,88 @@ + value1 and key => value2 the same if (string) $value1 === + * (string) $value2. + * + * @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. + */ + public static function diffAssoc(array $array1, array $array2) { + $difference = array(); + + foreach ($array1 as $key => $value) { + if (!array_key_exists($key, $array2) || ((string) $array2[$key] !== (string) $value)) { + $difference[$key] = $value; + } + } + + return $difference; + } + + /** + * Recursively computes the difference of arrays with additional index check. + * + * This function is the same as array_diff_assoc() but multidimensional arrays + * do not throw notices. Note that as the comparison is made by (string) + * $value1 === (string) $value2 every array element is considered equal. This + * is, again, the same as array_diff_assoc() the only reason Drupal provides + * this function is since PHP 5.4 this 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. + */ + public static function diffAssocRecursive(array $array1, array $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 = static::diffAssocRecursive($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; + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/diffArrayUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/diffArrayUnitTest.php new file mode 100644 index 0000000..02e85bb --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Common/diffArrayUnitTest.php @@ -0,0 +1,89 @@ + 'diffArray functionality', + 'description' => 'Tests the diffArray helper class.', + '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 diffArray::diffAssoc(). + */ + public function testDiffAssoc() { + $expected = array( + 'different' => 'no', + 'new' => 'new', + ); + + $this->assertIdentical(diffArray::diffAssoc($this->array1, $this->array2), $expected); + } + + /** + * Tests diffArray::diffAssocRecursive(). + */ + public function testDiffAssocRecursive() { + $expected = array( + 'different' => 'no', + 'int_diff' => 1, + // The 'array' key should no be returned as it's the same. + 'array_diff' => array('same' => 'same'), + 'new' => 'new', + ); + + $this->assertIdentical(diffArray::diffAssocRecursive($this->array1, $this->array2), $expected); + } + +}