From e4a505797ddd54105631ad570c59447c7e6862bb Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 19 Feb 2012 23:34:51 -0500 Subject: [PATCH] Move combine() across. --- lib/Cake/Test/Case/Utility/Set2Test.php | 204 ++++++++++++++++++++++++ lib/Cake/Utility/Set2.php | 68 +++++++- 2 files changed, 269 insertions(+), 3 deletions(-) diff --git a/lib/Cake/Test/Case/Utility/Set2Test.php b/lib/Cake/Test/Case/Utility/Set2Test.php index 4112af170..1c092f938 100644 --- a/lib/Cake/Test/Case/Utility/Set2Test.php +++ b/lib/Cake/Test/Case/Utility/Set2Test.php @@ -116,6 +116,41 @@ class Set2Test extends CakeTestCase { ); } + public static function userData() { + return array( + array( + 'User' => array( + 'id' => 2, + 'group_id' => 1, + 'Data' => array( + 'user' => 'mariano.iglesias', + 'name' => 'Mariano Iglesias' + ) + ) + ), + array( + 'User' => array( + 'id' => 14, + 'group_id' => 2, + 'Data' => array( + 'user' => 'phpnut', + 'name' => 'Larry E. Masters' + ) + ) + ), + array( + 'User' => array( + 'id' => 25, + 'group_id' => 1, + 'Data' => array( + 'user' => 'gwoo', + 'name' => 'The Gwoo' + ) + ) + ) + ); + } + /** * Test get() * @@ -1074,4 +1109,173 @@ class Set2Test extends CakeTestCase { $this->assertTrue(Set2::check($set, 'My Index 1.First.Second.Third.Fourth')); $this->assertFalse(Set2::check($set, 'My Index 1.First.Seconds.Third.Fourth')); } + +/** + * testCombine method + * + * @return void + */ + public function testCombine() { + $result = Set2::combine(array(), '{n}.User.id', '{n}.User.Data'); + $this->assertTrue(empty($result)); + + $a = self::userData(); + + $result = Set2::combine($a, '{n}.User.id'); + $expected = array(2 => null, 14 => null, 25 => null); + $this->assertEquals($expected, $result); + + $result = Set2::combine($a, '{n}.User.id', '{n}.User.non-existant'); + $expected = array(2 => null, 14 => null, 25 => null); + $this->assertEquals($expected, $result); + + $result = Set2::combine($a, '{n}.User.id', '{n}.User.Data'); + $expected = array( + 2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'), + 14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters'), + 25 => array('user' => 'gwoo', 'name' => 'The Gwoo')); + $this->assertEquals($expected, $result); + + $result = Set2::combine($a, '{n}.User.id', '{n}.User.Data.name'); + $expected = array( + 2 => 'Mariano Iglesias', + 14 => 'Larry E. Masters', + 25 => 'The Gwoo'); + $this->assertEquals($expected, $result); + } + +/** + * test combine() with a group path. + * + * @return void + */ + public function testCombineWithGroupPath() { + $a = self::userData(); + + $result = Set2::combine($a, '{n}.User.id', '{n}.User.Data', '{n}.User.group_id'); + $expected = array( + 1 => array( + 2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'), + 25 => array('user' => 'gwoo', 'name' => 'The Gwoo') + ), + 2 => array( + 14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters') + ) + ); + $this->assertEquals($expected, $result); + + $result = Set2::combine($a, '{n}.User.id', '{n}.User.Data.name', '{n}.User.group_id'); + $expected = array( + 1 => array( + 2 => 'Mariano Iglesias', + 25 => 'The Gwoo' + ), + 2 => array( + 14 => 'Larry E. Masters' + ) + ); + $this->assertEquals($expected, $result); + + + $result = Set2::combine($a, '{n}.User.id', '{n}.User.Data', '{n}.User.group_id'); + $expected = array( + 1 => array( + 2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'), + 25 => array('user' => 'gwoo', 'name' => 'The Gwoo') + ), + 2 => array( + 14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters') + ) + ); + $this->assertEquals($expected, $result); + + $result = Set2::combine($a, '{n}.User.id', '{n}.User.Data.name', '{n}.User.group_id'); + $expected = array( + 1 => array( + 2 => 'Mariano Iglesias', + 25 => 'The Gwoo' + ), + 2 => array( + 14 => 'Larry E. Masters' + ) + ); + $this->assertEquals($expected, $result); + } + +/** + * Test combine with formatting rules. + * + * @return void + */ + public function testCombineWithFormatting() { + $this->markTestIncomplete('Not done, format() is not implemented'); + $a = self::userData(); + + $result = Set2::combine( + $a, + '{n}.User.id', + array('{0}: {1}', '{n}.User.Data.user', '{n}.User.Data.name'), + '{n}.User.group_id' + ); + $expected = array( + 1 => array( + 2 => 'mariano.iglesias: Mariano Iglesias', + 25 => 'gwoo: The Gwoo' + ), + 2 => array( + 14 => 'phpnut: Larry E. Masters' + ) + ); + $this->assertEquals($expected, $result); + + $result = Set2::combine( + $a, + array('{0}: {1}', + '{n}.User.Data.user', + '{n}.User.Data.name'), + '{n}.User.id' + ); + $expected = array( + 'mariano.iglesias: Mariano Iglesias' => 2, + 'phpnut: Larry E. Masters' => 14, + 'gwoo: The Gwoo' => 25 + ); + $this->assertEquals($expected, $result); + + $result = Set2::combine( + $a, + array('{1}: {0}', '{n}.User.Data.user', '{n}.User.Data.name'), + '{n}.User.id' + ); + $expected = array( + 'Mariano Iglesias: mariano.iglesias' => 2, + 'Larry E. Masters: phpnut' => 14, + 'The Gwoo: gwoo' => 25 + ); + $this->assertEquals($expected, $result); + + $result = Set2::combine( + $a, + array('%1$s: %2$d', '{n}.User.Data.user', '{n}.User.id'), + '{n}.User.Data.name' + ); + $expected = array( + 'mariano.iglesias: 2' => 'Mariano Iglesias', + 'phpnut: 14' => 'Larry E. Masters', + 'gwoo: 25' => 'The Gwoo' + ); + $this->assertEquals($expected, $result); + + $result = Set2::combine( + $a, + array('%2$d: %1$s', '{n}.User.Data.user', '{n}.User.id'), + '{n}.User.Data.name' + ); + $expected = array( + '2: mariano.iglesias' => 'Mariano Iglesias', + '14: phpnut' => 'Larry E. Masters', + '25: gwoo' => 'The Gwoo' + ); + $this->assertEquals($expected, $result); + } } diff --git a/lib/Cake/Utility/Set2.php b/lib/Cake/Utility/Set2.php index 64ab4c7a3..8466d836c 100644 --- a/lib/Cake/Utility/Set2.php +++ b/lib/Cake/Utility/Set2.php @@ -308,7 +308,69 @@ class Set2 { return $data; } - public static function combine(array $data, $keyPath, $valuePath = null) { + +/** + * Creates an associative array using `$keyPath` as the path to build its keys, and optionally + * `$valuePath` as path to get the values. If `$valuePath` is not specified, all values will be initialized + * to null (useful for Set::merge). You can optionally group the values by what is obtained when + * following the path specified in `$groupPath`. + * + * @param array $data Array from where to extract keys and values + * @param string $keyPath A dot-separated string. + * @param string $valuePath A dot-separated string. + * @param string $groupPath A dot-separated string. + * @return array Combined array + * @link http://book.cakephp.org/2.0/en/core-utility-libraries/set.html#Set::combine + */ + public static function combine(array $data, $keyPath, $valuePath = null, $groupPath = null) { + if (empty($data)) { + return array(); + } + + if (is_array($keyPath)) { + $format = array_shift($keyPath); + $keys = self::format($data, $format, $keyPath); + } else { + $keys = self::extract($data, $keyPath); + } + if (empty($keys)) { + return array(); + } + + if (!empty($valuePath) && is_array($valuePath)) { + $format = array_shift($valuePath); + $vals = self::format($data, $format, $valuePath); + } elseif (!empty($valuePath)) { + $vals = self::extract($data, $valuePath); + } + + $count = count($keys); + for ($i = 0; $i < $count; $i++) { + if (!isset($vals[$i])) { + $vals[$i] = null; + } + } + + if ($groupPath != null) { + $group = self::extract($data, $groupPath); + if (!empty($group)) { + $c = count($keys); + for ($i = 0; $i < $c; $i++) { + if (!isset($group[$i])) { + $group[$i] = 0; + } + if (!isset($out[$group[$i]])) { + $out[$group[$i]] = array(); + } + $out[$group[$i]][$keys[$i]] = $vals[$i]; + } + return $out; + } + } + if (empty($vals)) { + return array(); + } + return array_combine($keys, $vals); } @@ -380,10 +442,10 @@ class Set2 { public static function filter(array $data) { foreach ($data as $k => $v) { if (is_array($v)) { - $data[$k] = Set2::filter($v); + $data[$k] = self::filter($v); } } - return array_filter($data, array('Set2', '_filter')); + return array_filter($data, array('self', '_filter')); } /**