Move and rename pushDiff onto Hash.

Its used internally in a number of places and diff() + merge()
are not an resonable replacement.
This commit is contained in:
mark_story 2012-03-11 22:52:55 -04:00
parent 19e0d8d946
commit 0ef9adba93
2 changed files with 136 additions and 10 deletions

View file

@ -1851,4 +1851,106 @@ class HashTest extends CakeTestCase {
}
$this->assertEquals($input, $result);
}
/**
* testMergeDiff method
*
* @return void
*/
public function testMergeDiff() {
$array1 = array(
'ModelOne' => array(
'id' => 1001,
'field_one' => 'a1.m1.f1',
'field_two' => 'a1.m1.f2'
)
);
$array2 = array(
'ModelTwo' => array(
'id' => 1002,
'field_one' => 'a2.m2.f1',
'field_two' => 'a2.m2.f2'
)
);
$result = Hash::mergeDiff($array1, $array2);
$this->assertEquals($result, $array1 + $array2);
$result = Hash::mergeDiff($array1, array());
$this->assertEquals($result, $array1);
$result = Hash::mergeDiff(array(), $array1);
$this->assertEquals($result, $array1);
$array3 = array(
'ModelOne' => array(
'id' => 1003,
'field_one' => 'a3.m1.f1',
'field_two' => 'a3.m1.f2',
'field_three' => 'a3.m1.f3'
)
);
$result = Hash::mergeDiff($array1, $array3);
$expected = array(
'ModelOne' => array(
'id' => 1001,
'field_one' => 'a1.m1.f1',
'field_two' => 'a1.m1.f2',
'field_three' => 'a3.m1.f3'
)
);
$this->assertEquals($expected, $result);
$array1 = array(
0 => array('ModelOne' => array('id' => 1001, 'field_one' => 's1.0.m1.f1', 'field_two' => 's1.0.m1.f2')),
1 => array('ModelTwo' => array('id' => 1002, 'field_one' => 's1.1.m2.f2', 'field_two' => 's1.1.m2.f2'))
);
$array2 = array(
0 => array('ModelOne' => array('id' => 1001, 'field_one' => 's2.0.m1.f1', 'field_two' => 's2.0.m1.f2')),
1 => array('ModelTwo' => array('id' => 1002, 'field_one' => 's2.1.m2.f2', 'field_two' => 's2.1.m2.f2'))
);
$result = Hash::mergeDiff($array1, $array2);
$this->assertEquals($result, $array1);
$array3 = array(
0 => array(
'ModelThree' => array(
'id' => 1003,
'field_one' => 's3.0.m3.f1',
'field_two' => 's3.0.m3.f2'
)
)
);
$result = Hash::mergeDiff($array1, $array3);
$expected = array(
0 => array(
'ModelOne' => array(
'id' => 1001,
'field_one' => 's1.0.m1.f1',
'field_two' => 's1.0.m1.f2'
),
'ModelThree' => array(
'id' => 1003,
'field_one' => 's3.0.m3.f1',
'field_two' => 's3.0.m3.f2'
)
),
1 => array(
'ModelTwo' => array(
'id' => 1002,
'field_one' => 's1.1.m2.f2',
'field_two' => 's1.1.m2.f2'
)
)
);
$this->assertEquals($expected, $result);
$result = Hash::mergeDiff($array1, null);
$this->assertEquals($result, $array1);
$result = Hash::mergeDiff($array1, $array2);
$this->assertEquals($result, $array1+$array2);
}
}

View file

@ -757,27 +757,51 @@ class Hash {
* and work on multi-dimensional arrays.
*
* @param mixed $data First value
* @param mixed $data2 Second value
* @return array Returns the key => value pairs that are not common in $data and $data2
* The expression for this function is ($data - $data2) + ($data2 - ($data - $data2))
* @param mixed $compare Second value
* @return array Returns the key => value pairs that are not common in $data and $compare
* The expression for this function is ($data - $compare) + ($compare - ($data - $compare))
* @link http://book.cakephp.org/2.0/en/core-utility-libraries/set.html#Set::diff
*/
public static function diff(array $data, $data2) {
public static function diff(array $data, $compare) {
if (empty($data)) {
return (array)$data2;
return (array)$compare;
}
if (empty($data2)) {
if (empty($compare)) {
return (array)$data;
}
$intersection = array_intersect_key($data, $data2);
$intersection = array_intersect_key($data, $compare);
while (($key = key($intersection)) !== null) {
if ($data[$key] == $data2[$key]) {
if ($data[$key] == $compare[$key]) {
unset($data[$key]);
unset($data2[$key]);
unset($compare[$key]);
}
next($intersection);
}
return $data + $data2;
return $data + $compare;
}
/**
* Merges the difference between $data and $push onto $data.
*
* @param array $data The data to append onto.
* @param array $compare The data to compare and append onto.
* @return array The merged array.
*/
public static function mergeDiff(array $data, $compare) {
if (empty($data) && !empty($compare)) {
return $compare;
}
if (empty($compare)) {
return $data;
}
foreach ($compare as $key => $value) {
if (!array_key_exists($key, $data)) {
$data[$key] = $value;
} elseif (is_array($value)) {
$data[$key] = self::mergeDiff($data[$key], $compare[$key]);
}
}
return $data;
}
/**