$v) { $array[$k] = $v; } } return $array; } public static function mergeDiff($array1, $array2) { return array_merge($array1, array_diff_key($array2, $array1)); } public static function diffRecursive($array1, $array2) { foreach ($array1 as $key => $value) { if (is_array($value)) { if (@!is_array($array2[$key])) { $difference[$key] = $value; } else { $new_diff = Qs_Array::diffRecursive($value, $array2[$key]); if (!empty($new_diff)) { $difference[$key] = $new_diff; } } } elseif ($value != @$array2[$key]) { $difference[$key] = $value; } } return !isset($difference) ? array() : $difference; } public static function mergeRecursive($firstArray, $secondArray) { if (is_array($firstArray) && is_array($secondArray)) { foreach ($secondArray as $key => $value) { if (isset($firstArray[$key])) { $firstArray[$key] = Qs_Array::mergeRecursive($firstArray[$key], $value); } else { $firstArray[$key] = $value; } } } else { $firstArray = $secondArray; } return $firstArray; } /** * Array sorting * * $data, multidim array * $keys, array(array(key => col1, sort => desc), array(key => col2, type => numeric)) * * @param array $data * @param array $keys * @return array */ public static function multisort($data, $keys) { // List As Columns $cols = array(); foreach ($data as $key => $row) { foreach ($keys as $k){ $cols[$k['key']][$key] = $row[$k['key']]; } } // List original keys $idkeys = array_keys($data); // Sort Expression $i = 0; $sort = ''; foreach ($keys as $k) { if ($i > 0) { $sort .= ', '; } $sort .= '$cols[\'' . $k['key'] . '\']'; if (isset($k['sort'])) { $sort .= ', SORT_' . strtoupper($k['sort']); } if (isset($k['type'])) { $sort .= ', SORT_' . strtoupper($k['type']); } $i++; } $sort .= ', $idkeys'; // Sort Funct $sort = 'array_multisort(' . $sort . ');'; eval($sort); // Rebuild Full Array foreach($idkeys as $idkey) { $result[$idkey] = $data[$idkey]; } return $result; } public static function get($array, $field, $default = null) { if (false !== $field && null !== $field) { if (is_string($field)) { $field = str_replace(']', '', $field); $parts = explode('[', $field); } elseif (is_array($field)) { $parts = $field; } else { throw new Qs_Exception('Qs_Array::get. Invalid second argument type ' . gettype($field)); } while (null !== ($name = array_shift($parts))) { if (!array_key_exists($name, $array)) { return $default; } $array = $array[$name]; } } return $array; } public static function set(&$array, $field, $value) { if (false !== $field) { if (is_array($field)) { $parts = $field; } else { $field = str_replace(']', '', $field); $parts = explode('[', $field); } if (null !== ($name = array_shift($parts))) { if (empty($parts)) { $array[$name] = $value; } elseif (!array_key_exists($name, $array) || !is_array($array[$name])) { $array[$name] = array(); } Qs_Array::set($array[$name], $parts, $value); } } else { $array = $value; } } public static function remove(&$array, $field) { if (false !== $field) { if (is_array($field)) { $parts = $field; } else { $field = str_replace(']', '', $field); $parts = explode('[', $field); } if (($name = array_shift($parts))) { if (empty($parts)) { unset($array[$name]); } elseif (array_key_exists($name, $array)) { Qs_Array::remove($array[$name], $parts); } } } else { unset($array); } } public static function excludeArray($array1, $array2) { foreach ($array2 as $keyName) { if (is_array($keyName)) { $array1 = Qs_Array::excludeArray($array1, $keyName); } elseif (array_key_exists($keyName, $array1)) { unset($array1[$keyName]); } } return $array1; } public static function excludeKey() { $args = func_get_args(); return call_user_func_array('Qs_Array::exclude', $args); } /** * @static * @deprecated function deprecated in Release 3.0. Use excludeKey * @return bool|mixed */ public static function exclude() { if (func_num_args() < 2) { return false; } $args = func_get_args(); $array = array_shift($args); $array = Qs_Array::excludeArray($array, $args); return $array; } public static function excludeValue() { if (func_num_args() < 2) { return false; } $args = func_get_args(); $array = array_shift($args); $array = Qs_Array::excludeValues($array, $args); return $array; } public static function excludeValues(array $array, array $values) { foreach ($values as $value) { if (false !== ($index = array_search($value, $array))) { unset($array[$index]); } } return $array; } public static function collapse(array $array, $belongsTo = '') { $result = array(); foreach ($array as $key => $value) { $itemBelongsTo = $belongsTo . (empty($belongsTo) ? $key : '[' . $key . ']'); if (is_array($value)) { $result = array_merge($result, Qs_Array::collapse($value, $itemBelongsTo)); } else { $result[$itemBelongsTo] = $value; } } return $result; } public static function expand(array $array) { $result = array(); foreach ($array as $key => $value) { Qs_Array::set($result, $key, $value); } return $result; } /** * Swap 2 elements in array preserving keys * * @param array $array * @param array $key1 * @param array $key2 * @return array */ public static function swap($array, $key1, $key2) { if (!is_array($array) || empty($array) || !array_key_exists($key1, $array) || !array_key_exists($key2, $array) ) { return $array; } $value1 = $array[$key1]; $value2 = $array[$key2]; $result = array(); foreach($array as $key => $value) { if ((string) $key == (string) $key1) { $key = $key2; $value = $value2; } else if ((string) $key == (string) $key2) { $key = $key1; $value = $value1; } $result[$key] = $value; } return $result; } /** * Move an element inside an array preserving keys * $relpos should be like -1, +2... * * @param array $array * @param array $key * @param array $relpos * @return array */ public static function move($array, $key, $relpos) { if (!is_array($array) || empty($array) || !array_key_exists($key, $array) || !$relpos) { return $array; } $from = Qs_Array::keyPos($key, $array); if ($from === false) { return $array; } $to = $from + $relpos + ($relpos > 0 ? 1 : 0); $length = count($array); if ($to >= $length) { $val = $array[$key]; unset($array[$key]); $array[$key] = $val; } else { if ($to < 0) { $to = 0; } $new = array(); $x = 0; foreach ($array as $i => $v) { if ($x++ == $to) { $new[$key] = $array[$key]; } if ($i !== $key) { $new[$i]=$v; } } $array = $new; } return $array; } /** * Get a key position in array * * @param array $key * @param array $array * @return integer */ public static function keyPos($key, $array) { $position = 0; foreach ($array as $i => $v) { if ($key === $i) { return $position; } $position++; } return false; } /** * Return key by position * * @param array $key * @param array $array * @return integer */ public static function keyByPos($position, $array) { $x = 0; foreach ($array as $i => $v) { if ($position == $x++) { return $i; } } return false; } public static function implodeLast($separator, $lastSeparator, $array) { $arraySize = count($array); $separators = array(); if ($arraySize > 2) { $separators = array_fill(0, $arraySize - 2, $separator); } $separators[] = $lastSeparator; return Qs_Array::implode($separators, $array); } public static function implode() { $countArguments = func_num_args(); $arguments = func_get_args(); if ($countArguments == 2 && is_array($arguments[0])) { $string = ''; $separators = array_values($arguments[0]); $elements = array_values($arguments[1]); $countSepatarots = count($separators); $countElements = count($elements); $html = ''; for ($i = 0; $i < $countElements; $i++) { $string .= (0 == $i ? '' : $separators[($i - 1) % $countSepatarots]) . $elements[$i]; } return $string; } return call_user_func_array('implode', $arguments); } /** * Convert associated array to indexed array with associated items * @static * @param array $array Associated array * @param string $keyName * @param string $valueName * @return array Indexed array */ public static function assocToIndex(array $array, $keyName, $valueName) { $result = array(); foreach ($array as $key => $value) { $result[] = array($keyName => $key, $valueName => $value); } return $result; } /** * Return array containing values from $source specified by $map ([$destination] => $source) * * Example: * * $values = array('map', 'class' => 'Qs_Array', 'framework' => 'qsf2', 'ver' => array(2, 0)); * $map = array( * 'function' => 0, * 'class', * 'framework' => array('source' => 'framework', 'callback' => 'strtoupper'), * 'version' => 'ver[0]', * ); * $result = Qs_Array::map($values, $map); * // Return: array('function' => 'map', 'class' => 'Qs_Array', 'framework' => 'QSF2', 'version' => 2) * * @static * @param array $values Source array * @param array $map Array of pairs ([$destination] => string|array $source). * @return array */ public static function map($values, $map) { $result = array(); foreach ($map as $destination => $source) { $sourceKey = null; $callback = null; if (is_array($source)) { $sourceKey = (isset($source['source'])) ? $source['source'] : $destination; $callback = (isset($source['callback']) && is_callable($source['callback'])) ? $source['callback'] : null; } else { $sourceKey = $source; $destination = is_int($destination) ? $sourceKey : $destination; } if (is_array($sourceKey) || (is_string($sourceKey) && false !== strpos($sourceKey, '['))) { $value = self::get($values, $sourceKey, null); } else { $value = array_key_exists($sourceKey, $values) ? $values[$sourceKey] : null; } $result[$destination] = (isset($value) && isset($callback)) ? call_user_func($callback, $value) : $value; } return $result; } /** * Extract value from tree * @static * @param array $tree * @param string $valueField * @return array */ public static function treeValues(array $tree, $valueField = 'value') { $result = array(); self::_treeValues($tree, $valueField, $result); return $result; } /** * @internal * @static * @param array $tree * @param string $valueField * @param array $result * @return void */ protected static function _treeValues(array $tree, $valueField, array &$result) { foreach ((array) $tree as $node) { if (array_key_exists($valueField, $node)) { $result[] = $node[$valueField]; } if (!empty($node['sub'])) { self::_treeValues($node['sub'], $valueField, $result); } } return; } /** * Build tree from the array according to $idField and $parentIdFiled * @param array $list Two level array with source values * @param array $fields Field what will be copied to each node using Qs_Array::map() * @param string $idField * @param string $parentIdField * @return array */ public static function buildTree(array $list, $fields = array('id', 'title'), $idField = 'id', $parentIdField = 'idParent') { $result = array(); self::_buildNodeSub($list, $result, 0, $fields, $idField, $parentIdField); return $result; } protected static function _buildNodeSub(array &$list, array &$parentSub, $parentId = 0, $fields, $idField, $parentIdField) { foreach ($list as $key => $page) { if ($parentId == $page[$parentIdField]) { $node = self::map($page, $fields); unset($list[$key]); $node['sub'] = array(); self::_buildNodeSub($list, $node['sub'], $page[$idField], $fields, $idField, $parentIdField); if (empty($node['sub'])) { unset($node['sub']); } $parentSub[$page[$idField]] = $node; } } return; } }