Skip to content

Commit 7181089

Browse files
committed
API: Add ArrayLib::flatten($array, $preserveKeys)
1 parent 3b72432 commit 7181089

File tree

2 files changed

+104
-22
lines changed

2 files changed

+104
-22
lines changed

core/ArrayLib.php

+75-22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<?php
2+
23
/**
34
* Library of static methods for manipulating arrays.
5+
*
46
* @package framework
57
* @subpackage misc
68
*/
@@ -43,7 +45,10 @@ class ArrayLib {
4345
* @return array
4446
*/
4547
public static function invert($arr) {
46-
if(!$arr) return false;
48+
if(!$arr) {
49+
return false;
50+
}
51+
4752
$result = array();
4853

4954
foreach($arr as $columnName => $column) {
@@ -56,7 +61,7 @@ public static function invert($arr) {
5661
}
5762

5863
/**
59-
* Return an array where the keys are all equal to the values
64+
* Return an array where the keys are all equal to the values.
6065
*
6166
* @param $arr array
6267
* @return array
@@ -70,7 +75,8 @@ public static function valuekey($arr) {
7075
*/
7176
public static function array_values_recursive($arr) {
7277
$lst = array();
73-
foreach(array_keys($arr) as $k){
78+
79+
foreach(array_keys($arr) as $k) {
7480
$v = $arr[$k];
7581
if (is_scalar($v)) {
7682
$lst[] = $v;
@@ -80,92 +86,115 @@ public static function array_values_recursive($arr) {
8086
);
8187
}
8288
}
89+
8390
return $lst;
8491
}
8592

8693
/**
87-
* Filter an array by keys (useful for only allowing certain form-input to be saved).
94+
* Filter an array by keys (useful for only allowing certain form-input to
95+
* be saved).
8896
*
8997
* @param $arr array
9098
* @param $keys array
99+
*
91100
* @return array
92101
*/
93-
public static function filter_keys($arr, $keys)
94-
{
95-
foreach ($arr as $key => $v) {
96-
if (!in_array($key, $keys)) {
102+
public static function filter_keys($arr, $keys) {
103+
foreach($arr as $key => $v) {
104+
if(!in_array($key, $keys)) {
97105
unset($arr[$key]);
98106
}
99107
}
108+
100109
return $arr;
101110
}
102111

103112
/**
104-
* Determines if an array is associative by checking
105-
* for existing keys via array_key_exists().
113+
* Determines if an array is associative by checking for existing keys via
114+
* array_key_exists().
115+
*
106116
* @see http://nz.php.net/manual/en/function.is-array.php#76188
107117
*
108118
* @param array $arr
119+
*
109120
* @return boolean
110121
*/
111122
public static function is_associative($arr) {
112123
if(is_array($arr) && ! empty($arr)) {
113124
for($iterator = count($arr) - 1; $iterator; $iterator--) {
114-
if (!array_key_exists($iterator, $arr)) return true;
125+
if (!array_key_exists($iterator, $arr)) {
126+
return true;
127+
}
115128
}
129+
116130
return !array_key_exists(0, $arr);
117131
}
132+
118133
return false;
119134
}
120135

121136
/**
122137
* Recursively searches an array $haystack for the value(s) $needle.
138+
*
123139
* Assumes that all values in $needle (if $needle is an array) are at
124140
* the SAME level, not spread across multiple dimensions of the $haystack.
125141
*
126142
* @param mixed $needle
127143
* @param array $haystack
128144
* @param boolean $strict
145+
*
129146
* @return boolean
130147
*/
131148
public static function in_array_recursive($needle, $haystack, $strict = false) {
132-
if(!is_array($haystack)) return false; // Not an array, we've gone as far as we can down this branch
133-
134-
if(in_array($needle, $haystack, $strict)) return true; // Is it in this level of the array?
135-
else {
136-
foreach($haystack as $obj) { // It's not, loop over the rest of this array
137-
if(self::in_array_recursive($needle, $obj, $strict)) return true;
149+
if(!is_array($haystack)) {
150+
return false;
151+
}
152+
153+
if(in_array($needle, $haystack, $strict)) {
154+
return true;
155+
} else {
156+
foreach($haystack as $obj) {
157+
if(self::in_array_recursive($needle, $obj, $strict)) {
158+
return true;
159+
}
138160
}
139161
}
140162

141-
return false; // Never found $needle :(
163+
return false;
142164
}
143165

144166
/**
145167
* Recursively merges two or more arrays.
146168
*
147-
* Behaves similar to array_merge_recursive(), however it only merges values when both are arrays
148-
* rather than creating a new array with both values, as the PHP version does. The same behaviour
149-
* also occurs with numeric keys, to match that of what PHP does to generate $_REQUEST.
169+
* Behaves similar to array_merge_recursive(), however it only merges
170+
* values when both are arrays rather than creating a new array with
171+
* both values, as the PHP version does. The same behaviour also occurs
172+
* with numeric keys, to match that of what PHP does to generate $_REQUEST.
173+
*
174+
* @param array $array
150175
*
151-
* @param array $array, ...
152176
* @return array
153177
*/
154178
public static function array_merge_recursive($array) {
155179
$arrays = func_get_args();
156180
$merged = array();
181+
157182
if(count($arrays) == 1) {
158183
return $array;
159184
}
185+
160186
while ($arrays) {
161187
$array = array_shift($arrays);
188+
162189
if (!is_array($array)) {
163190
trigger_error('ArrayLib::array_merge_recursive() encountered a non array argument', E_USER_WARNING);
164191
return;
165192
}
193+
166194
if (!$array) {
167195
continue;
168196
}
197+
169198
foreach ($array as $key => $value) {
170199
if (is_array($value) && array_key_exists($key, $merged) && is_array($merged[$key])) {
171200
$merged[$key] = ArrayLib::array_merge_recursive($merged[$key], $value);
@@ -174,6 +203,30 @@ public static function array_merge_recursive($array) {
174203
}
175204
}
176205
}
206+
177207
return $merged;
178208
}
209+
210+
/**
211+
* Takes an multi dimension array and returns the flattened version.
212+
*
213+
* @param array $array
214+
* @param boolean $preserveKeys
215+
*
216+
* @return array
217+
*/
218+
public static function flatten($array, $preserveKeys = true, &$out = array()) {
219+
foreach($array as $key => $child) {
220+
if(is_array($child)) {
221+
$out = self::flatten($child, $preserveKeys, $out);
222+
} else if($preserveKeys) {
223+
$out[$key] = $child;
224+
} else {
225+
$out[] = $child;
226+
}
227+
}
228+
229+
return $out;
230+
}
179231
}
232+

tests/core/ArrayLibTest.php

+29
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
<?php
2+
23
/**
34
* @package framework
45
* @subpackage tests
56
*/
67
class ArrayLibTest extends SapphireTest {
8+
79
public function testInvert() {
810
$arr = array(
911
'row1' => array(
@@ -187,4 +189,31 @@ public function testArrayMergeRecursive() {
187189
'Numeric keys should behave like string keys'
188190
);
189191
}
192+
193+
public function testFlatten() {
194+
$options = array(
195+
'1' => 'one',
196+
'2' => 'two'
197+
);
198+
199+
$expected = $options;
200+
201+
$this->assertEquals($expected, ArrayLib::flatten($options));
202+
203+
$options = array(
204+
'1' => array(
205+
'2' => 'two',
206+
'3' => 'three'
207+
),
208+
'4' => 'four'
209+
);
210+
211+
$expected = array(
212+
'2' => 'two',
213+
'3' => 'three',
214+
'4' => 'four'
215+
);
216+
217+
$this->assertEquals($expected, ArrayLib::flatten($options));
218+
}
190219
}

0 commit comments

Comments
 (0)