silverstripe-framework/ORM/ArrayLib.php

265 lines
5.2 KiB
PHP
Raw Normal View History

<?php
namespace SilverStripe\ORM;
/**
* Library of static methods for manipulating arrays.
*/
class ArrayLib
{
2014-08-15 08:53:05 +02:00
/**
* Inverses the first and second level keys of an associative
* array, keying the result by the second level, and combines
* all first level entries within them.
2014-08-15 08:53:05 +02:00
*
* Before:
* <example>
* array(
* 'row1' => array(
* 'col1' =>'val1',
* 'col2' => 'val2'
* ),
* 'row2' => array(
* 'col1' => 'val3',
* 'col2' => 'val4'
* )
* )
* </example>
2014-08-15 08:53:05 +02:00
*
* After:
* <example>
* array(
* 'col1' => array(
* 'row1' => 'val1',
* 'row2' => 'val3',
* ),
* 'col2' => array(
* 'row1' => 'val2',
* 'row2' => 'val4',
* ),
* )
* </example>
2014-08-15 08:53:05 +02:00
*
* @param array $arr
* @return array
*/
public static function invert($arr)
{
if (!$arr) {
return [];
}
$result = array();
2014-08-15 08:53:05 +02:00
foreach ($arr as $columnName => $column) {
foreach ($column as $rowName => $cell) {
$result[$rowName][$columnName] = $cell;
}
}
2014-08-15 08:53:05 +02:00
return $result;
}
2014-08-15 08:53:05 +02:00
/**
* Return an array where the keys are all equal to the values.
2014-08-15 08:53:05 +02:00
*
* @param $arr array
* @return array
*/
public static function valuekey($arr)
{
return array_combine($arr, $arr);
}
2014-08-15 08:53:05 +02:00
/**
* @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;
}
2014-08-15 08:53:05 +02:00
/**
2014-08-15 08:53:05 +02:00
* Filter an array by keys (useful for only allowing certain form-input to
* be saved).
2014-08-15 08:53:05 +02:00
*
* @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;
}
2014-08-15 08:53:05 +02:00
/**
2014-08-15 08:53:05 +02:00
* 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.
*
2014-08-15 08:53:05 +02:00
* 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)) {
2014-08-15 08:53:05 +02:00
return false;
}
if (in_array($needle, $haystack, $strict)) {
return true;
} else {
foreach ($haystack as $obj) {
if (self::in_array_recursive($needle, $obj, $strict)) {
2014-08-15 08:53:05 +02:00
return true;
}
}
}
2014-08-15 08:53:05 +02:00
return false;
}
2014-08-15 08:53:05 +02:00
/**
* 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.
*
2014-08-15 08:53:05 +02:00
* 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();
2014-08-15 08:53:05 +02:00
if (count($arrays) == 1) {
return $array;
}
while ($arrays) {
$array = array_shift($arrays);
2014-08-15 08:53:05 +02:00
if (!is_array($array)) {
trigger_error('SilverStripe\ORM\ArrayLib::array_merge_recursive() encountered a non array argument',
E_USER_WARNING);
return [];
}
if (!$array) {
continue;
}
2014-08-15 08:53:05 +02:00
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;
}
2014-08-15 08:53:05 +02:00
/**
* Takes an multi dimension array and returns the flattened version.
*
* @param array $array
* @param boolean $preserveKeys
* @param array $out
* @return array
2014-08-15 08:53:05 +02:00
*/
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;
}
}
2014-08-15 08:53:05 +02:00