*/
class CRM_Utils_Array {
+ /**
+ * Cast a value to an array.
+ *
+ * This is similar to PHP's `(array)`, but it also converts iterators.
+ *
+ * @param mixed $value
+ * @return array
+ */
+ public static function cast($value) {
+ if (is_array($value)) {
+ return $value;
+ }
+ if ($value instanceof CRM_Utils_LazyArray || $value instanceof ArrayObject) {
+ // iterator_to_array() would work here, but getArrayCopy() doesn't require actual iterations.
+ return $value->getArrayCopy();
+ }
+ if (is_iterable($value)) {
+ return iterator_to_array($value);
+ }
+ if (is_scalar($value)) {
+ return [$value];
+ }
+ throw new \RuntimeException(sprintf("Cannot cast %s to array", gettype($value)));
+ }
+
/**
* Returns $list[$key] if such element exists, or a default value otherwise.
*
return $newRows;
}
+ /**
+ * Rotate a matrix, converting from row-oriented array to a column-oriented array.
+ *
+ * @param iterable $rows
+ * Ex: [['a'=>10,'b'=>'11'], ['a'=>20,'b'=>21]]
+ * Formula: [scalar $rowId => [scalar $colId => mixed $value]]
+ * @param bool $unique
+ * Only return unique values.
+ * @return array
+ * Ex: ['a'=>[10,20], 'b'=>[11,21]]
+ * Formula: [scalar $colId => [scalar $rowId => mixed $value]]
+ * Note: In unique mode, the $rowId is not meaningful.
+ */
+ public static function asColumns(iterable $rows, bool $unique = FALSE) {
+ $columns = [];
+ foreach ($rows as $rowKey => $row) {
+ foreach ($row as $columnKey => $value) {
+ if (FALSE === $unique) {
+ $columns[$columnKey][$rowKey] = $value;
+ }
+ elseif (!in_array($value, $columns[$columnKey] ?? [])) {
+ $columns[$columnKey][] = $value;
+ }
+ }
+ }
+ return $columns;
+ }
+
/**
* Rewrite the keys in an array.
*
return TRUE;
}
+ /**
+ * Remove a key from an array.
+ *
+ * This is a helper for when the calling function does not know how many layers deep
+ * the path array is so cannot easily check.
+ *
+ * @param array $values
+ * @param array $path
+ * @param bool $cleanup
+ * If removed item leaves behind an empty array, should you remove the empty array?
+ * @return bool
+ * TRUE if anything has been removed. FALSE if no changes were required.
+ */
+ public static function pathUnset(&$values, $path, $cleanup = FALSE) {
+ if (count($path) === 1) {
+ if (isset($values[$path[0]])) {
+ unset($values[$path[0]]);
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+ }
+ else {
+ $next = array_shift($path);
+ $r = static::pathUnset($values[$next], $path, $cleanup);
+ if ($cleanup && $values[$next] === []) {
+ $r = TRUE;
+ unset($values[$next]);
+ }
+ return $r;
+ }
+ }
+
/**
* Set a single value in an array tree.
*
$r[$last] = $value;
}
+ /**
+ * Move an item in an array-tree (if it exists).
+ *
+ * @param array $values
+ * Data-tree
+ * @param string[] $src
+ * Old path for the existing item
+ * @param string[] $dest
+ * New path
+ * @param bool $cleanup
+ * @return int
+ * Number of items moved (0 or 1).
+ */
+ public static function pathMove(&$values, $src, $dest, $cleanup = FALSE) {
+ if (!static::pathIsset($values, $src)) {
+ return 0;
+ }
+ else {
+ $value = static::pathGet($values, $src);
+ static::pathSet($values, $dest, $value);
+ static::pathUnset($values, $src, $cleanup);
+ return 1;
+ }
+ }
+
/**
* Convert a simple dictionary into separate key+value records.
*