Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Move merge() into Set2.

  • Loading branch information...
commit e736ea3af98bb4b6f0f33f6b30567f1d3af48d0f 1 parent 51f45c0
@markstory markstory authored
Showing with 227 additions and 3 deletions.
  1. +171 −0 lib/Cake/Test/Case/Utility/Set2Test.php
  2. +56 −3 lib/Cake/Utility/Set2.php
View
171 lib/Cake/Test/Case/Utility/Set2Test.php
@@ -276,4 +276,175 @@ public function testFlatten() {
$this->assertEquals($expected, $result);
}
+/**
+ * Test diff();
+ *
+ * @return void
+ */
+ public function testDiff() {
+ $a = array(
+ 0 => array('name' => 'main'),
+ 1 => array('name' => 'about')
+ );
+ $b = array(
+ 0 => array('name' => 'main'),
+ 1 => array('name' => 'about'),
+ 2 => array('name' => 'contact')
+ );
+
+ $result = Set2::diff($a, array());
+ $expected = $a;
+ $this->assertEquals($expected, $result);
+
+ $result = Set2::diff(array(), $b);
+ $expected = $b;
+ $this->assertEquals($expected, $result);
+
+ $result = Set2::diff($a, $b);
+ $expected = array(
+ 2 => array('name' => 'contact')
+ );
+ $this->assertEquals($expected, $result);
+
+
+ $b = array(
+ 0 => array('name' => 'me'),
+ 1 => array('name' => 'about')
+ );
+
+ $result = Set2::diff($a, $b);
+ $expected = array(
+ 0 => array('name' => 'main')
+ );
+ $this->assertEquals($expected, $result);
+
+ $a = array();
+ $b = array('name' => 'bob', 'address' => 'home');
+ $result = Set2::diff($a, $b);
+ $this->assertEquals($result, $b);
+
+
+ $a = array('name' => 'bob', 'address' => 'home');
+ $b = array();
+ $result = Set2::diff($a, $b);
+ $this->assertEquals($result, $a);
+
+ $a = array('key' => true, 'another' => false, 'name' => 'me');
+ $b = array('key' => 1, 'another' => 0);
+ $expected = array('name' => 'me');
+ $result = Set2::diff($a, $b);
+ $this->assertEquals($expected, $result);
+
+ $a = array('key' => 'value', 'another' => null, 'name' => 'me');
+ $b = array('key' => 'differentValue', 'another' => null);
+ $expected = array('key' => 'value', 'name' => 'me');
+ $result = Set2::diff($a, $b);
+ $this->assertEquals($expected, $result);
+
+ $a = array('key' => 'value', 'another' => null, 'name' => 'me');
+ $b = array('key' => 'differentValue', 'another' => 'value');
+ $expected = array('key' => 'value', 'another' => null, 'name' => 'me');
+ $result = Set2::diff($a, $b);
+ $this->assertEquals($expected, $result);
+
+ $a = array('key' => 'value', 'another' => null, 'name' => 'me');
+ $b = array('key' => 'differentValue', 'another' => 'value');
+ $expected = array('key' => 'differentValue', 'another' => 'value', 'name' => 'me');
+ $result = Set2::diff($b, $a);
+ $this->assertEquals($expected, $result);
+
+ $a = array('key' => 'value', 'another' => null, 'name' => 'me');
+ $b = array(0 => 'differentValue', 1 => 'value');
+ $expected = $a + $b;
+ $result = Set2::diff($a, $b);
+ $this->assertEquals($expected, $result);
+ }
+
+/**
+ * Test merge()
+ *
+ * @return void
+ */
+ public function testMerge() {
+ $result = Set2::merge(array('foo'), array('bar'));
+ $this->assertEquals($result, array('foo', 'bar'));
+
+ $result = Set2::merge(array('foo'), array('user' => 'bob', 'no-bar'), 'bar');
+ $this->assertEquals($result, array('foo', 'user' => 'bob', 'no-bar', 'bar'));
+
+ $a = array('foo', 'foo2');
+ $b = array('bar', 'bar2');
+ $expected = array('foo', 'foo2', 'bar', 'bar2');
+ $this->assertEquals($expected, Set2::merge($a, $b));
+
+ $a = array('foo' => 'bar', 'bar' => 'foo');
+ $b = array('foo' => 'no-bar', 'bar' => 'no-foo');
+ $expected = array('foo' => 'no-bar', 'bar' => 'no-foo');
+ $this->assertEquals($expected, Set2::merge($a, $b));
+
+ $a = array('users' => array('bob', 'jim'));
+ $b = array('users' => array('lisa', 'tina'));
+ $expected = array('users' => array('bob', 'jim', 'lisa', 'tina'));
+ $this->assertEquals($expected, Set2::merge($a, $b));
+
+ $a = array('users' => array('jim', 'bob'));
+ $b = array('users' => 'none');
+ $expected = array('users' => 'none');
+ $this->assertEquals($expected, Set2::merge($a, $b));
+
+ $a = array('users' => array('lisa' => array('id' => 5, 'pw' => 'secret')), 'cakephp');
+ $b = array('users' => array('lisa' => array('pw' => 'new-pass', 'age' => 23)), 'ice-cream');
+ $expected = array(
+ 'users' => array('lisa' => array('id' => 5, 'pw' => 'new-pass', 'age' => 23)),
+ 'cakephp',
+ 'ice-cream'
+ );
+ $result = Set2::merge($a, $b);
+ $this->assertEquals($expected, $result);
+
+ $c = array(
+ 'users' => array('lisa' => array('pw' => 'you-will-never-guess', 'age' => 25, 'pet' => 'dog')),
+ 'chocolate'
+ );
+ $expected = array(
+ 'users' => array('lisa' => array('id' => 5, 'pw' => 'you-will-never-guess', 'age' => 25, 'pet' => 'dog')),
+ 'cakephp',
+ 'ice-cream',
+ 'chocolate'
+ );
+ $this->assertEquals($expected, Set2::merge($a, $b, $c));
+
+ $this->assertEquals($expected, Set2::merge($a, $b, array(), $c));
+
+ $a = array(
+ 'Tree',
+ 'CounterCache',
+ 'Upload' => array(
+ 'folder' => 'products',
+ 'fields' => array('image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id')
+ )
+ );
+ $b = array(
+ 'Cacheable' => array('enabled' => false),
+ 'Limit',
+ 'Bindable',
+ 'Validator',
+ 'Transactional'
+ );
+ $expected = array(
+ 'Tree',
+ 'CounterCache',
+ 'Upload' => array(
+ 'folder' => 'products',
+ 'fields' => array('image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id')
+ ),
+ 'Cacheable' => array('enabled' => false),
+ 'Limit',
+ 'Bindable',
+ 'Validator',
+ 'Transactional'
+ );
+ $this->assertEquals(Set2::merge($a, $b), $expected);
+ }
+
}
View
59 lib/Cake/Utility/Set2.php
@@ -85,7 +85,7 @@ public static function filter(array $data) {
/**
* Collapses a multi-dimensional array into a single dimension, using a delimited array path for
* each array element's key, i.e. array(array('Foo' => array('Bar' => 'Far'))) becomes
- * array('0.Foo.Bar' => 'Far').
+ * array('0.Foo.Bar' => 'Far').)
*
* @param array $data Array to flatten
* @param string $separator String used to separate array key elements in a path, defaults to '.'
@@ -120,8 +120,36 @@ public static function flatten(array $data, $separator = '.') {
return $result;
}
+/**
+ * This function can be thought of as a hybrid between PHP's `array_merge` and `array_merge_recursive`.
+ *
+ * The difference between this method and the built-in ones, is that if an array key contains another array, then
+ * Set2::merge() will behave in a recursive fashion (unlike `array_merge`). But it will not act recursively for
+ * keys that contain scalar values (unlike `array_merge_recursive`).
+ *
+ * Note: This function will work with an unlimited amount of arguments and typecasts non-array parameters into arrays.
+ *
+ * @param array $data Array to be merged
+ * @param mixed $merge Array to merge with. The argument and all trailing arguments will be array cast when merged
+ * @return array Merged array
+ * @link http://book.cakephp.org/2.0/en/core-utility-libraries/set.html#Set::merge
+ */
public static function merge(array $data, $merge) {
-
+ $args = func_get_args();
+ $return = current($args);
+
+ while (($arg = next($args)) !== false) {
+ foreach ((array)$arg as $key => $val) {
+ if (!empty($return[$key]) && is_array($return[$key]) && is_array($val)) {
+ $return[$key] = self::merge($return[$key], $val);
+ } elseif (is_int($key)) {
+ $return[] = $val;
+ } else {
+ $return[$key] = $val;
+ }
+ }
+ }
+ return $return;
}
/**
@@ -183,8 +211,33 @@ public static function sort(array $data, $path, $dir) {
}
+/**
+ * Computes the difference between two complex arrays.
+ * This method differs from the built-in array_diff() in that it will preserve keys
+ * and work on multi-dimensional arrays.
+ *
+ * @param mixed $data First value
+ * @param mixed $data2 Second value
+ * @return array Returns the key => value pairs that are not common in $data and $data2
+ * The expression for this function is ($data - $data2) + ($data2 - ($data - $data2))
+ * @link http://book.cakephp.org/2.0/en/core-utility-libraries/set.html#Set::diff
+ */
public static function diff(array $data, $data2) {
-
+ if (empty($data)) {
+ return (array)$data2;
+ }
+ if (empty($data2)) {
+ return (array)$data;
+ }
+ $intersection = array_intersect_key($data, $data2);
+ while (($key = key($intersection)) !== null) {
+ if ($data[$key] == $data2[$key]) {
+ unset($data[$key]);
+ unset($data2[$key]);
+ }
+ next($intersection);
+ }
+ return $data + $data2;
}
public static function normalize(array $data, $assoc = true) {
Please sign in to comment.
Something went wrong with that request. Please try again.