From b2eb1882a4f5cfc2a0f7d74ce487c4528bbfb88d Mon Sep 17 00:00:00 2001 From: jperras Date: Wed, 23 Sep 2009 21:03:09 -0400 Subject: [PATCH] Adding convenience method Set::apply(). --- cake/libs/set.php | 34 ++++++++++++++++++++ cake/tests/cases/libs/set.test.php | 50 ++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/cake/libs/set.php b/cake/libs/set.php index e50895da187..fbf4cd61478 100644 --- a/cake/libs/set.php +++ b/cake/libs/set.php @@ -1137,6 +1137,40 @@ function sort($data, $path, $dir) { return $sorted; } +/** + * Allows the application of a callback method to elements of an + * array extracted by a Set::extract() compatible path. + * + * @param string $path A Set-compatible path to the array value + * @param array $data + * @param mixed $callback Callback method to be applied to extracted data. + * See http://ca2.php.net/manual/en/language.pseudo-types.php#language.types.callback for examples + * of callback formats. + * @param array $options + * @return mixed Result of the callback when applied to extracted data + * + */ + function apply($path, $data, $callback, $options = array()) { + $defaults = array('type' => 'pass'); + $options = array_merge($defaults, $options); + + $extracted = Set::extract($path, $data); + + if ($options['type'] === 'map') { + $result = array_map($callback, &$extracted); + + } elseif ($options['type'] === 'reduce') { + $result = array_reduce(&$extracted, $callback); + + } elseif ($options['type'] === 'pass') { + $result = call_user_func_array($callback, array($extracted)); + } else { + return null; + } + + return $result; + } + /** * Deprecated, Set class should be called statically * diff --git a/cake/tests/cases/libs/set.test.php b/cake/tests/cases/libs/set.test.php index 1b7da9a22e2..993692bbb7b 100644 --- a/cake/tests/cases/libs/set.test.php +++ b/cake/tests/cases/libs/set.test.php @@ -2402,6 +2402,56 @@ function testPushDiff() { $this->assertIdentical($result, $array1+$array2); } +/** + * testSetApply method + * @access public + * @return void + * + */ + function testApply() { + $data = array( + array('Movie' => array('id' => 1, 'title' => 'movie 3', 'rating' => 5)), + array('Movie' => array('id' => 1, 'title' => 'movie 1', 'rating' => 1)), + array('Movie' => array('id' => 1, 'title' => 'movie 2', 'rating' => 3)) + ); + + $result = Set::apply('/Movie/rating', $data, 'array_sum'); + $expected = 9; + $this->assertEqual($result, $expected); + + $result = Set::apply('/Movie/rating', $data, 'array_product'); + $expected = 15; + $this->assertEqual($result, $expected); + + $result = Set::apply('/Movie/title', $data, 'ucfirst', array('type' => 'map')); + $expected = array('Movie 3', 'Movie 1', 'Movie 2'); + $this->assertEqual($result, $expected); + + $result = Set::apply('/Movie/title', $data, 'strtoupper', array('type' => 'map')); + $expected = array('MOVIE 3', 'MOVIE 1', 'MOVIE 2'); + $this->assertEqual($result, $expected); + + $result = Set::apply('/Movie/rating', $data, array('self', '_method'), array('type' => 'reduce')); + $expected = 9; + $this->assertEqual($result, $expected); + + $result = Set::apply('/Movie/rating', $data, 'strtoupper', array('type' => 'non existing type')); + $expected = null; + $this->assertEqual($result, $expected); + + } + +/** + * Helper method to test Set::apply() + * + * @access protected + * @return void + */ + function _method($val1, $val2) { + $val1 += $val2; + return $val1; + } + /** * testXmlSetReverse method *