mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2025-01-18 18:46:17 +00:00
Adding new Set::merge() and Set class test case, thanks Felix
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@4779 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
parent
1c6c32981e
commit
ac904cd4d4
2 changed files with 202 additions and 18 deletions
|
@ -60,23 +60,67 @@ class Set extends Object {
|
|||
function &get() {
|
||||
return $this->value;
|
||||
}
|
||||
/**
|
||||
* Merges the contents of the array object with $array
|
||||
*
|
||||
* @param mixed $array An array, another Set object, or a value to be appended
|
||||
* @return array
|
||||
* @access public
|
||||
*/
|
||||
function merge($array = null, $array2 = null) {
|
||||
if ($array2 !== null && is_array($array2)) {
|
||||
return array_merge_recursive($array, $array2);
|
||||
}
|
||||
|
||||
if(!isset($this->value)) {
|
||||
$this->value = array();
|
||||
/**
|
||||
* This function can be thought of as a hybrid between PHP's array_merge and array_merge_recursive. The difference
|
||||
* to the two is that if an array key contains another array then the function behaves recursive (unlike array_merge)
|
||||
* but does not do if for keys containing strings (unlike array_merge_recursive). See the unit test for more information.
|
||||
*
|
||||
* Note: This function will work with an unlimited amount of arguments and typecasts non-array parameters into arrays.
|
||||
*
|
||||
* @param array $arr1
|
||||
* @param array $arr2
|
||||
* @return array
|
||||
*/
|
||||
function merge($arr1, $arr2 = null) {
|
||||
// Get all arguments that were passed to the function
|
||||
$args = func_get_args();
|
||||
|
||||
// If $this is a Set class
|
||||
if (is_a($this, 'set')) {
|
||||
// Get the call stack
|
||||
$backtrace = debug_backtrace();
|
||||
// And the previous call
|
||||
$previousCall = low($backtrace[1]['class'].'::'.$backtrace[1]['function']);
|
||||
// If this is not a recursive call
|
||||
if ($previousCall != 'set::merge') {
|
||||
// Reference this Set's value as our resulting $r array
|
||||
$r =& $this->value;
|
||||
// And push an empty args at the beginning of the $args array which will be discarded later on
|
||||
array_unshift($args, null);
|
||||
}
|
||||
}
|
||||
$this->value = array_merge_recursive($this->value, Set::__array($array));
|
||||
return $this->value;
|
||||
|
||||
// If $r has not been set yet
|
||||
if (!isset($r)) {
|
||||
// Tpecast the first argument into an array and use it as our resulting $r array
|
||||
$r = (array)current($args);
|
||||
}
|
||||
|
||||
// Loop through all $args we were given
|
||||
while(($arg = next($args)) !== false) {
|
||||
// If a Set object was passed in
|
||||
if (is_a($arg, 'set')) {
|
||||
// Use it's value for the merging
|
||||
$arg = $arg->get();
|
||||
}
|
||||
// Loop through all $key / $val pairs of our current $arg
|
||||
foreach ((array)$arg as $key => $val) {
|
||||
// If the current $key holds an array and the current $arg and all previous ones ($r)
|
||||
if (is_array($val) && isset($r[$key]) && is_array($r[$key])) {
|
||||
// Go for recursive merging
|
||||
$r[$key] = Set::merge($r[$key], $val);
|
||||
} elseif (is_int($key)) {
|
||||
// If it's a numerical index go for auto-incremeting
|
||||
$r[] = $val;
|
||||
} else {
|
||||
// And in case of an associative one do an overwrite
|
||||
$r[$key] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return the merged array
|
||||
return $r;
|
||||
}
|
||||
/**
|
||||
* Pushes the differences in $array2 onto the end of $array
|
||||
|
@ -117,7 +161,7 @@ class Set extends Object {
|
|||
if (is_array($class)) {
|
||||
$val = $class;
|
||||
$class = $tmp;
|
||||
} elseif (is_a($this, 'set') || is_a($this, 'Set')) {
|
||||
} elseif (is_a($this, 'set')) {
|
||||
$val = $this->get();
|
||||
}
|
||||
|
||||
|
@ -129,10 +173,10 @@ class Set extends Object {
|
|||
function __array($array) {
|
||||
if ($array == null) {
|
||||
$array = $this->value;
|
||||
} elseif (is_object($array) && (is_a($array, 'set') || is_a($array, 'Set'))) {
|
||||
} elseif (is_object($array) && (is_a($array, 'set'))) {
|
||||
$array = $array->get();
|
||||
} elseif (is_object($array)) {
|
||||
// Throw an error
|
||||
$array = get_object_vars($array);
|
||||
} elseif (!is_array($array)) {
|
||||
$array = array($array);
|
||||
}
|
||||
|
|
140
cake/tests/cases/libs/set.test.php
Executable file
140
cake/tests/cases/libs/set.test.php
Executable file
|
@ -0,0 +1,140 @@
|
|||
<?php
|
||||
|
||||
// Include the class to be tested
|
||||
uses('set');
|
||||
|
||||
/**
|
||||
* UnitTestCase for the Set class
|
||||
*
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs
|
||||
*/
|
||||
class SetTest extends UnitTestCase {
|
||||
|
||||
function testMerge() {
|
||||
// Test that passing in just 1 array returns it "as-is"
|
||||
$r = Set::merge(array('foo'));
|
||||
$this->assertIdentical($r, array('foo'));
|
||||
|
||||
// Test that passing in a non-array turns it into one
|
||||
$r = Set::merge('foo');
|
||||
$this->assertIdentical($r, array('foo'));
|
||||
|
||||
// Test that this works for 2 strings as well
|
||||
$r = Set::merge('foo', 'bar');
|
||||
$this->assertIdentical($r, array('foo', 'bar'));
|
||||
|
||||
// Test that this works for arguments of mixed types as well
|
||||
$r = Set::merge('foo', array('user' => 'bob', 'no-bar'), 'bar');
|
||||
$this->assertIdentical($r, array('foo', 'user' => 'bob', 'no-bar', 'bar'));
|
||||
|
||||
// Test merging two simple numerical indexed arrays
|
||||
$a = array('foo', 'foo2');
|
||||
$b = array('bar', 'bar2');
|
||||
$this->assertIdentical(Set::merge($a, $b), array('foo', 'foo2', 'bar', 'bar2'));
|
||||
|
||||
// Test merging two simple associative arrays
|
||||
$a = array('foo' => 'bar', 'bar' => 'foo');
|
||||
$b = array('foo' => 'no-bar', 'bar' => 'no-foo');
|
||||
$this->assertIdentical(Set::merge($a, $b), array('foo' => 'no-bar', 'bar' => 'no-foo'));
|
||||
|
||||
// Test merging two simple nested arrays
|
||||
$a = array('users' => array('bob', 'jim'));
|
||||
$b = array('users' => array('lisa', 'tina'));
|
||||
$this->assertIdentical(Set::merge($a, $b), array(
|
||||
'users' => array('bob', 'jim', 'lisa', 'tina')
|
||||
));
|
||||
|
||||
// Test that merging an key holding a string over an array one causes an overwrite
|
||||
$a = array('users' => array('jim', 'bob'));
|
||||
$b = array('users' => 'none');
|
||||
$this->assertIdentical(Set::merge($a, $b), array('users' => 'none'));
|
||||
|
||||
// Test merging two somewhat complex nested arrays
|
||||
$a = array(
|
||||
'users' => array(
|
||||
'lisa' => array(
|
||||
'id' => 5,
|
||||
'pw' => 'secret'
|
||||
)
|
||||
),
|
||||
'cakephp'
|
||||
);
|
||||
$b = array(
|
||||
'users' => array(
|
||||
'lisa' => array(
|
||||
'pw' => 'new-pass',
|
||||
'age' => 23
|
||||
)
|
||||
),
|
||||
'ice-cream'
|
||||
);
|
||||
$this->assertIdentical(Set::merge($a, $b), array(
|
||||
'users' => array(
|
||||
'lisa' => array(
|
||||
'id' => 5,
|
||||
'pw' => 'new-pass',
|
||||
'age' => 23
|
||||
)
|
||||
),
|
||||
'cakephp',
|
||||
'ice-cream'
|
||||
));
|
||||
|
||||
// And now go for the ultimate tripple-play ; )
|
||||
$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->assertIdentical(Set::merge($a, $b, $c), $expected);
|
||||
|
||||
// Test that passing in an empty array does not mess things up
|
||||
$this->assertIdentical(Set::merge($a, $b, array(), $c), $expected);
|
||||
|
||||
// Create a new Set instance from the $a array
|
||||
$Set =& new Set($a);
|
||||
// Merge $b, an empty array and $c over it
|
||||
$r = $Set->merge($b, array(), $c);
|
||||
// And test that it produces the same result as a static call would
|
||||
$this->assertIdentical($r, $expected);
|
||||
// And also updates it's own value property
|
||||
$this->assertIdentical($Set->value, $expected);
|
||||
|
||||
// Let the garbage collector eat the Set instance
|
||||
unset($Set);
|
||||
|
||||
$Set =& new Set();
|
||||
|
||||
$SetA =& new Set($a);
|
||||
$SetB =& new Set($b);
|
||||
$SetC =& new Set($c);
|
||||
|
||||
$r = $Set->merge($SetA, $SetB, $SetC);
|
||||
// And test that it produces the same result as a static call would
|
||||
$this->assertIdentical($r, $expected);
|
||||
// And also updates it's own value property
|
||||
$this->assertIdentical($Set->value, $expected);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
Loading…
Add table
Reference in a new issue