diff --git a/cake/libs/set.php b/cake/libs/set.php index 928e32a03..d99caa240 100644 --- a/cake/libs/set.php +++ b/cake/libs/set.php @@ -303,6 +303,50 @@ class Set extends Object { } return $return; } +/** + * Returns a series of values extracted from an array, formatted in a format string. + * + * @param array $data Source array from which to extract the data + * @param string $format Format string into which values will be inserted + * @param array $keys An array containing one or more Set::extract()-style key paths + * @return array An array of strings extracted from $keys and formatted with $format + * @access public + */ + function format($data, $format, $keys) { + $extracted = array(); + $count = count($keys); + + if (!$count) { + return; + } + + for ($i = 0; $i < $count; $i++) { + $extracted[] = Set::extract($data, $keys[$i]); + } + + if (preg_match_all('/\{([0-9]+)\}/msi', $format, $keys) && isset($keys[1])) { + $out = array(); + $keys = $keys[1]; + $data = $extracted; + $count = count($data[0]); + $format = preg_split('/\{([0-9]+)\}/msi', $format); + $count2 = count($format); + + for ($j = 0; $j < $count; $j++) { + $formatted = ''; + for ($i = 0; $i <= $count2; $i++) { + if (isset($format[$i])) { + $formatted .= $format[$i]; + } + if (isset($keys[$i]) && isset($data[$keys[$i]][$j])) { + $formatted .= $data[$keys[$i]][$j]; + } + } + $out[] = $formatted; + } + } + return $out; + } /** * Gets a value from an array or object that maps a given path. * The special {n}, as seen in the Model::generateList method, is taken care of here. diff --git a/cake/tests/cases/libs/set.test.php b/cake/tests/cases/libs/set.test.php index dd55342ae..76bb9cc1f 100644 --- a/cake/tests/cases/libs/set.test.php +++ b/cake/tests/cases/libs/set.test.php @@ -508,5 +508,51 @@ class SetTest extends UnitTestCase { $result = Set::reverse($map); $this->assertIdentical($result, $expected); } + + function testFormatting() { + $data = array( + array('Person' => array( + 'first_name' => 'Nate', + 'last_name' => 'Abele', + 'city' => 'Boston', + 'state' => 'MA', + 'something' => '42' + )), + array('Person' => array( + 'first_name' => 'Larry', + 'last_name' => 'Masters', + 'city' => 'Boondock', + 'state' => 'TN', + 'something' => '{0}' + )), + array('Person' => array( + 'first_name' => 'Garrett', + 'last_name' => 'Woodworth', + 'city' => 'Venice Beach', + 'state' => 'CA', + 'something' => '{1}' + )) + ); + + $result = Set::format($data, '{1}, {0}', array('{n}.Person.first_name', '{n}.Person.last_name')); + $expected = array('Abele, Nate', 'Masters, Larry', 'Woodworth, Garrett'); + $this->assertEqual($result, $expected); + + $result = Set::format($data, '{0}, {1}', array('{n}.Person.last_name', '{n}.Person.first_name')); + $this->assertEqual($result, $expected); + + $result = Set::format($data, '{0}, {1}', array('{n}.Person.city', '{n}.Person.state')); + $expected = array('Boston, MA', 'Boondock, TN', 'Venice Beach, CA'); + $this->assertEqual($result, $expected); + + $result = Set::format($data, '{{0}, {1}}', array('{n}.Person.city', '{n}.Person.state')); + $expected = array('{Boston, MA}', '{Boondock, TN}', '{Venice Beach, CA}'); + $this->assertEqual($result, $expected); + + $result = Set::format($data, '{{0}, {1}}', array('{n}.Person.something', '{n}.Person.something')); + $expected = array('{42, 42}', '{{0}, {0}}', '{{1}, {1}}'); + $this->assertEqual($result, $expected); + } } + ?> \ No newline at end of file