* array( * 'row1' => array( * 'col1' =>'val1', * 'col2' => 'val2' * ), * 'row2' => array( * 'col1' => 'val3', * 'col2' => 'val4' * ) * ) * * * After: * * array( * 'col1' => array( * 'row1' => 'val1', * 'row2' => 'val3', * ), * 'col2' => array( * 'row1' => 'val2', * 'row2' => 'val4', * ), * ) * * * @param array $arr * @return array */ public static function invert($arr) { if (!$arr) { return []; } $result = array(); foreach ($arr as $columnName => $column) { foreach ($column as $rowName => $cell) { $result[$rowName][$columnName] = $cell; } } return $result; } /** * Return an array where the keys are all equal to the values. * * @param $arr array * @return array */ public static function valuekey($arr) { return array_combine($arr, $arr); } /** * @todo Improve documentation * * @param array $arr * @return array */ public static function array_values_recursive($arr) { $lst = array(); foreach (array_keys($arr) as $k) { $v = $arr[$k]; if (is_scalar($v)) { $lst[] = $v; } elseif (is_array($v)) { $lst = array_merge($lst, self::array_values_recursive($v) ); } } return $lst; } /** * Filter an array by keys (useful for only allowing certain form-input to * be saved). * * @param $arr array * @param $keys array * * @return array */ public static function filter_keys($arr, $keys) { foreach ($arr as $key => $v) { if (!in_array($key, $keys)) { unset($arr[$key]); } } return $arr; } /** * Determines if an array is associative by checking for existing keys via * array_key_exists(). * * @see http://nz.php.net/manual/en/function.is-array.php#76188 * * @param array $arr * * @return boolean */ public static function is_associative($arr) { if (is_array($arr) && !empty($arr)) { for ($iterator = count($arr) - 1; $iterator; $iterator--) { if (!array_key_exists($iterator, $arr)) { return true; } } return !array_key_exists(0, $arr); } return false; } /** * Recursively searches an array $haystack for the value(s) $needle. * * Assumes that all values in $needle (if $needle is an array) are at * the SAME level, not spread across multiple dimensions of the $haystack. * * @param mixed $needle * @param array $haystack * @param boolean $strict * * @return boolean */ public static function in_array_recursive($needle, $haystack, $strict = false) { if (!is_array($haystack)) { return false; } if (in_array($needle, $haystack, $strict)) { return true; } else { foreach ($haystack as $obj) { if (self::in_array_recursive($needle, $obj, $strict)) { return true; } } } return false; } /** * Similar to array_map, but recurses when arrays are encountered. * * Actually only one array argument is supported. * * @param $f callback to apply * @param $array array * @return array */ public static function array_map_recursive($f, $array) { $applyOrRecurse = function ($v) use ($f) { return is_array($v) ? ArrayLib::array_map_recursive($f, $v) : call_user_func($f, $v); }; return array_map($applyOrRecurse, $array); } /** * Recursively merges two or more arrays. * * Behaves similar to array_merge_recursive(), however it only merges * values when both are arrays rather than creating a new array with * both values, as the PHP version does. The same behaviour also occurs * with numeric keys, to match that of what PHP does to generate $_REQUEST. * * @param array $array * * @return array */ public static function array_merge_recursive($array) { $arrays = func_get_args(); $merged = array(); if (count($arrays) == 1) { return $array; } while ($arrays) { $array = array_shift($arrays); if (!is_array($array)) { trigger_error('SilverStripe\ORM\ArrayLib::array_merge_recursive() encountered a non array argument', E_USER_WARNING); return []; } if (!$array) { continue; } foreach ($array as $key => $value) { if (is_array($value) && array_key_exists($key, $merged) && is_array($merged[$key])) { $merged[$key] = ArrayLib::array_merge_recursive($merged[$key], $value); } else { $merged[$key] = $value; } } } return $merged; } /** * Takes an multi dimension array and returns the flattened version. * * @param array $array * @param boolean $preserveKeys * @param array $out * @return array */ public static function flatten($array, $preserveKeys = true, &$out = array()) { foreach ($array as $key => $child) { if (is_array($child)) { $out = self::flatten($child, $preserveKeys, $out); } else { if ($preserveKeys) { $out[$key] = $child; } else { $out[] = $child; } } } return $out; } }