Merge pull request #6492 from eileenmcnaughton/CRM-17020
[civicrm-core.git] / CRM / Utils / Array.php
index 9471cb0fa2f0b86f6e0040fc4a8bcd5397b2e357..d82ff2df4c3263a8f2e020f1964812e595a08f07 100644 (file)
@@ -3,7 +3,7 @@
  +--------------------------------------------------------------------+
  | CiviCRM version 4.6                                                |
  +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2014                                |
+ | Copyright CiviCRM LLC (c) 2004-2015                                |
  +--------------------------------------------------------------------+
  | This file is a part of CiviCRM.                                    |
  |                                                                    |
@@ -29,7 +29,7 @@
  * Provides a collection of static methods for array manipulation.
  *
  * @package CRM
- * @copyright CiviCRM LLC (c) 2004-2014
+ * @copyright CiviCRM LLC (c) 2004-2015
  */
 class CRM_Utils_Array {
 
@@ -639,6 +639,10 @@ class CRM_Utils_Array {
     if (is_array($values)) {
       return $values;
     }
+    // Empty string -> empty array
+    if ($values === '') {
+      return array();
+    }
     return explode($delim, trim((string) $values, $delim));
   }
 
@@ -831,4 +835,133 @@ class CRM_Utils_Array {
     return $output;
   }
 
+  /**
+   * Diff multidimensional arrays
+   * ( array_diff does not support multidimensional array)
+   *
+   * @param array $array1
+   * @param array $array2
+   * @return array
+   */
+  public static function multiArrayDiff($array1, $array2) {
+    $arrayDiff = array();
+    foreach ($array1 as $mKey => $mValue) {
+      if (array_key_exists($mKey, $array2)) {
+        if (is_array($mValue)) {
+          $recursiveDiff = self::multiArrayDiff($mValue, $array2[$mKey]);
+          if (count($recursiveDiff)) {
+            $arrayDiff[$mKey] = $recursiveDiff;
+          }
+        }
+        else {
+          if ($mValue != $array2[$mKey]) {
+            $arrayDiff[$mKey] = $mValue;
+          }
+        }
+      }
+      else {
+        $arrayDiff[$mKey] = $mValue;
+      }
+    }
+    return $arrayDiff;
+  }
+
+  /**
+   * Given a 2-dimensional matrix, create a new matrix with a restricted list of columns.
+   *
+   * @param array $matrix
+   *   All matrix data, as a list of rows.
+   * @param array $columns
+   *   List of column names.
+   * @return array
+   */
+  public static function filterColumns($matrix, $columns) {
+    $newRows = array();
+    foreach ($matrix as $pos => $oldRow) {
+      $newRow = array();
+      foreach ($columns as $column) {
+        $newRow[$column] = CRM_Utils_Array::value($column, $oldRow);
+      }
+      $newRows[$pos] = $newRow;
+    }
+    return $newRows;
+  }
+
+  /**
+   * Rewrite the keys in an array by filtering through a function.
+   *
+   * @param array $array
+   * @param callable $func
+   *   Function($key, $value). Returns the new key.
+   * @return array
+   */
+  public static function rekey($array, $func) {
+    $result = array();
+    foreach ($array as $key => $value) {
+      $newKey = $func($key, $value);
+      $result[$newKey] = $value;
+    }
+    return $result;
+  }
+
+  /**
+   * Copy all properties of $other into $array (recursively).
+   *
+   * @param array|ArrayAccess $array
+   * @param array $other
+   */
+  public static function extend(&$array, $other) {
+    foreach ($other as $key => $value) {
+      if (is_array($value)) {
+        self::extend($array[$key], $value);
+      }
+      else {
+        $array[$key] = $value;
+      }
+    }
+  }
+
+  /**
+   * Get a single value from an array-tre.
+   *
+   * @param array $arr
+   *   Ex: array('foo'=>array('bar'=>123)).
+   * @param array $pathParts
+   *   Ex: array('foo',bar').
+   * @return mixed|NULL
+   *   Ex 123.
+   */
+  public static function pathGet($arr, $pathParts) {
+    $r = $arr;
+    foreach ($pathParts as $part) {
+      if (!isset($r[$part])) {
+        return NULL;
+      }
+      $r = $r[$part];
+    }
+    return $r;
+  }
+
+  /**
+   * Set a single value in an array tree.
+   *
+   * @param array $arr
+   *   Ex: array('foo'=>array('bar'=>123)).
+   * @param array $pathParts
+   *   Ex: array('foo',bar').
+   * @param $value
+   *   Ex: 456.
+   */
+  public static function pathSet(&$arr, $pathParts, $value) {
+    $r = &$arr;
+    $last = array_pop($pathParts);
+    foreach ($pathParts as $part) {
+      if (!isset($r[$part])) {
+        $r[$part] = array();
+      }
+      $r = &$r[$part];
+    }
+    $r[$last] = $value;
+  }
+
 }