Merge pull request #15309 from totten/master-api4
[civicrm-core.git] / Civi / Api4 / Utils / ArrayInsertionUtil.php
1 <?php
2
3 namespace Civi\Api4\Utils;
4
5 use CRM_Utils_Array as UtilsArray;
6
7 class ArrayInsertionUtil {
8
9 /**
10 * If the values to be inserted contain a key _parent_id they will only be
11 * inserted if the parent node ID matches their ID
12 *
13 * @param $array
14 * The array to insert the value in
15 * @param array $parts
16 * Path to insertion point with structure:
17 * [[ name => is_multiple ], ..]
18 * @param mixed $values
19 * The value to be inserted
20 */
21 public static function insert(&$array, $parts, $values) {
22 $key = key($parts);
23 $isMulti = array_shift($parts);
24 if (!isset($array[$key])) {
25 $array[$key] = $isMulti ? [] : NULL;
26 }
27 if (empty($parts)) {
28 $values = self::filterValues($array, $isMulti, $values);
29 $array[$key] = $values;
30 }
31 else {
32 if ($isMulti) {
33 foreach ($array[$key] as &$subArray) {
34 self::insert($subArray, $parts, $values);
35 }
36 }
37 else {
38 self::insert($array[$key], $parts, $values);
39 }
40 }
41 }
42
43 /**
44 * @param $parentArray
45 * @param $isMulti
46 * @param $values
47 *
48 * @return array|mixed
49 */
50 private static function filterValues($parentArray, $isMulti, $values) {
51 $parentID = UtilsArray::value('id', $parentArray);
52
53 if ($parentID) {
54 $values = array_filter($values, function ($value) use ($parentID) {
55 return UtilsArray::value('_parent_id', $value) == $parentID;
56 });
57 }
58
59 $unsets = ['_parent_id', '_base_id'];
60 array_walk($values, function (&$value) use ($unsets) {
61 foreach ($unsets as $unset) {
62 if (isset($value[$unset])) {
63 unset($value[$unset]);
64 }
65 }
66 });
67
68 if (!$isMulti) {
69 $values = array_shift($values);
70 }
71 return $values;
72 }
73
74 }