From 0ef9adba93ea9055250c9ec32f5042050c726ce8 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 11 Mar 2012 22:52:55 -0400 Subject: [PATCH] Move and rename pushDiff onto Hash. Its used internally in a number of places and diff() + merge() are not an resonable replacement. --- lib/Cake/Test/Case/Utility/HashTest.php | 102 ++++++++++++++++++++++++ lib/Cake/Utility/Hash.php | 44 +++++++--- 2 files changed, 136 insertions(+), 10 deletions(-) diff --git a/lib/Cake/Test/Case/Utility/HashTest.php b/lib/Cake/Test/Case/Utility/HashTest.php index 7061a76ce..d60aa95d0 100644 --- a/lib/Cake/Test/Case/Utility/HashTest.php +++ b/lib/Cake/Test/Case/Utility/HashTest.php @@ -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); + } + } diff --git a/lib/Cake/Utility/Hash.php b/lib/Cake/Utility/Hash.php index 6a2b7f465..022b375d5 100644 --- a/lib/Cake/Utility/Hash.php +++ b/lib/Cake/Utility/Hash.php @@ -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; } /**