From 66eabe462ad86b344684d4837e0fac4473889907 Mon Sep 17 00:00:00 2001
From: mark_story <mark@mark-story.com>
Date: Sun, 18 Mar 2012 19:00:25 -0400
Subject: [PATCH] Copy Set::expand into Hash class.

---
 lib/Cake/Test/Case/Utility/HashTest.php | 46 +++++++++++++++++++++++++
 lib/Cake/Utility/Hash.php               | 30 ++++++++++++++++
 2 files changed, 76 insertions(+)

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`.
  *