File: /www/exchange0old/exchange/Bin/Array.php
<?php
/**
* dev-rc - Array.php
*
* Initial version by: MisterX
* Initial version created on: 04.03.2016
*/
class Bin_Array {
/**
* Retrieve a single key from an array. If the key does not exist in the
* array, the default value will be returned instead.
*
* // Get the value "username" from $_POST, if it exists
* $username = Bin_Array::get($_POST, 'username');
*
* // Get the value "sorting" from $_GET, if it exists
* $sorting = Bin_Array::get($_GET, 'sorting');
*
* @param array $array array to extract from
* @param string $key key name
* @param mixed $default default value
* @return mixed
*/
public static function get($array, $key, $default = null) {
if (!is_array($array)) {
return $default;
}
if (isset($array[$key])) {
return $array[$key];
}
return array_key_exists($key,$array) ? $array[$key] : $default;
}
/**
* Overwrites an array with values from input arrays.
* Keys that do not exist in the first array will not be added!
*
* $a1 = array('name' => 'john', 'mood' => 'happy', 'food' => 'bacon');
* $a2 = array('name' => 'jack', 'food' => 'tacos', 'drink' => 'beer');
*
* // Overwrite the values of $a1 with $a2
* $array = Bin_Array::overwrite($a1, $a2);
*
* // The output of $array will now be:
* array('name' => 'jack', 'mood' => 'happy', 'food' => 'tacos')
*
* @param array $array1 master array
* @param array $array2 input arrays that will overwrite existing values
* @return array
*/
public static function overwrite($array1, $array2)
{
foreach (array_intersect_key($array2, $array1) as $key => $value) {
$array1[$key] = $value;
}
if (func_num_args() > 2) {
foreach (array_slice(func_get_args(), 2) as $array2) {
foreach (array_intersect_key($array2, $array1) as $key => $value) {
$array1[$key] = $value;
}
}
}
return $array1;
}
/**
* Retrieves multiple paths from an array. If the path does not exist in the
* array, the default value will be added instead.
*
* // Get the values "username", "password" from $_POST
* $auth = Bin_Array::extract($_POST, array('username', 'password'));
*
*
* @param array $array array to extract paths from
* @param array $keys list of path
* @param mixed $default default value
* @return array
*/
public static function extract($array, array $keys, $default = NULL) {
$found = array();
foreach ($keys as $key) {
$found[$key] = self::get($array, $key, $default);
}
return $found;
}
public static function map_recursive($func, $array) {
foreach ($array as $key => $val) {
if (is_array($array[$key])) {
$array[$key] = self::map_recursive($func, $array[$key]);
} else {
$array[$key] = call_user_func($func, $val);
}
}
return $array;
}
/**
* Gets a value from an array using a dot separated path.
*
* // Get the value of $array['foo']['bar']
* $value = Arr::path($array, 'foo.bar');
*
* Using a wildcard "*" will search intermediate arrays and return an array.
*
* // Get the values of "color" in theme
* $colors = Arr::path($array, 'theme.*.color');
*
* // Using an array of keys
* $colors = Arr::path($array, array('theme', '*', 'color'));
*
* @param array $array array to search
* @param mixed $path key path string (delimiter separated) or array of keys
* @param mixed $default default value if the path is not set
* @param string $delimiter key path delimiter
* @return mixed
*/
public static function path($array, $path, $default = null, $delimiter = null) {
if (!self::isArray($array)) {
// This is not an array!
return $default;
}
if (is_array($path)) {
// The path has already been separated into keys
$keys = $path;
} else {
if (array_key_exists($path, $array)) {
// No need to do extra processing
return $array[$path];
}
if ($delimiter === null) {
// Use the default delimiter
$delimiter = '.';
}
// Remove starting delimiters and spaces
$path = ltrim($path, "{$delimiter} ");
// Remove ending delimiters, spaces, and wildcards
$path = rtrim($path, "{$delimiter} *");
// Split the keys by delimiter
$keys = explode($delimiter, $path);
}
do {
$key = array_shift($keys);
if (ctype_digit($key)) {
// Make the key an integer
$key = (int) $key;
}
if (isset($array[$key])) {
if ($keys) {
if (self::isArray($array[$key])) {
// Dig down into the next part of the path
$array = $array[$key];
} else {
// Unable to dig deeper
break;
}
} else {
// Found the path requested
return $array[$key];
}
} elseif ($key === '*') {
// Handle wildcards
$values = array();
foreach ($array as $arr) {
if ($value = self::path($arr, implode('.', $keys))) {
$values[] = $value;
}
}
if ($values) {
// Found the values requested
return $values;
} else {
// Unable to dig deeper
break;
}
} else {
// Unable to dig deeper
break;
}
}
while ($keys);
// Unable to find the value requested
return $default;
}
/**
* Test if a value is an array with an additional check for array-like objects.
* @param mixed $value value to check
* @return boolean
*/
public static function isArray($value) {
if (is_array($value)) {
// Definitely an array
return true;
} else {
// Possibly a Traversable object, functionally the same as an array
return (is_object($value) && $value instanceof Traversable);
}
}
/**
* Return the first element in an array passing a given truth test.
*
* @param array $array
* @param mixed $default
* @return mixed
*/
public static function first($array, $default = null) {
return empty($array) ? $default : reset($array);
}
/**
* Retrieves muliple single-key values from a list of arrays.
*
* // Get all of the "id" values from a result
* $ids = Bin_Arr::pluck($result, 'id');
*
* [!!] A list of arrays is an array that contains arrays, eg: array(array $a, array $b, array $c, ...)
*
* @param array $array list of arrays to check
* @param string $key key to pluck
* @return array
*/
public static function pluck($array, $key) {
$values = array();
foreach ($array as $row)
{
$itemValue = self::data_get($row, $key);
// Found a value in this row
$values[] = $itemValue;
}
return $values;
}
protected function data_get($target, $key, $default = null) {
if (is_null($key)) {
return $target;
}
$key = is_array($key) ? $key : explode('.', $key);
while (($segment = array_shift($key)) !== null) {
if (self::accessible($target) && self::exists($target, $segment)) {
$target = $target[$segment];
} elseif (is_object($target) && isset($target->{$segment})) {
$target = $target->{$segment};
} else {
return $default;
}
}
return $target;
}
public static function accessible($value) {
return is_array($value) || $value instanceof ArrayAccess;
}
public static function exists($array, $key) {
if ($array instanceof ArrayAccess) {
return $array->offsetExists($key);
}
return array_key_exists($key, $array);
}
}