diff --git a/lib/Cake/Test/Case/Utility/HashTest.php b/lib/Cake/Test/Case/Utility/HashTest.php index 18862d8fa..761ce626f 100644 --- a/lib/Cake/Test/Case/Utility/HashTest.php +++ b/lib/Cake/Test/Case/Utility/HashTest.php @@ -1990,4 +1990,50 @@ class HashTest extends CakeTestCase { $this->assertEquals($result, $array1+$array2); } +/** + * Tests Hash::expand + * + * @return void + */ + public function testExpand() { + $data = array('My', 'Array', 'To', 'Flatten'); + $flat = Hash::flatten($data); + $result = Hash::expand($flat); + $this->assertEqual($data, $result); + + $data = array( + '0.Post.id' => '1', '0.Post.author_id' => '1', '0.Post.title' => 'First Post', '0.Author.id' => '1', + '0.Author.user' => 'nate', '0.Author.password' => 'foo', '1.Post.id' => '2', '1.Post.author_id' => '3', + '1.Post.title' => 'Second Post', '1.Post.body' => 'Second Post Body', '1.Author.id' => '3', + '1.Author.user' => 'larry', '1.Author.password' => null + ); + $result = Hash::expand($data); + $expected = array( + array( + 'Post' => array('id' => '1', 'author_id' => '1', 'title' => 'First Post'), + 'Author' => array('id' => '1', 'user' => 'nate', 'password' => 'foo'), + ), + array( + 'Post' => array('id' => '2', 'author_id' => '3', 'title' => 'Second Post', 'body' => 'Second Post Body'), + 'Author' => array('id' => '3', 'user' => 'larry', 'password' => null), + ) + ); + $this->assertEqual($result, $expected); + + $data = array( + '0/Post/id' => 1, + '0/Post/name' => 'test post' + ); + $result = Hash::expand($data, '/'); + $expected = array( + array( + 'Post' => array( + 'id' => 1, + 'name' => 'test post' + ) + ) + ); + $this->assertEqual($result, $expected); + } + } diff --git a/lib/Cake/Utility/Hash.php b/lib/Cake/Utility/Hash.php index 83597078d..ec1689027 100644 --- a/lib/Cake/Utility/Hash.php +++ b/lib/Cake/Utility/Hash.php @@ -551,6 +551,36 @@ class Hash { return $result; } +/** + * Expand/unflattens an string to an array + * + * For example, unflattens an array that was collapsed with `Hash::flatten()` + * into a multi-dimensional array. So, `array('0.Foo.Bar' => 'Far')` becomes + * `array(array('Foo' => array('Bar' => 'Far')))`. + * + * @param array $data Flattened array + * @param string $separator The delimiter used + * @return array + */ + public static function expand($data, $separator = '.') { + $result = array(); + foreach ($data as $flat => $value) { + $keys = explode($separator, $flat); + $keys = array_reverse($keys); + $child = array( + $keys[0] => $value + ); + array_shift($keys); + foreach ($keys as $k) { + $child = array( + $k => $child + ); + } + $result = self::merge($result, $child); + } + return $result; + } + /** * This function can be thought of as a hybrid between PHP's `array_merge` and `array_merge_recursive`. *