REF - Extract CRM_Utils_Array::filterByPrefix
authorColeman Watts <coleman@civicrm.org>
Thu, 25 Aug 2022 12:58:33 +0000 (08:58 -0400)
committerColeman Watts <coleman@civicrm.org>
Thu, 25 Aug 2022 13:16:59 +0000 (09:16 -0400)
CRM/Utils/Array.php
Civi/Api4/Action/Contact/ContactSaveTrait.php
Civi/Api4/Utils/FormattingUtil.php
ext/afform/core/Civi/Api4/Action/Afform/GetOptions.php
ext/search_kit/Civi/Api4/Action/SearchDisplay/AbstractRunAction.php

index 45649a167dc8f09c33f32b547f09a735866d0e3e..cf03d320b0f851774600f647f62bbdc0fd7119bc 100644 (file)
@@ -1384,7 +1384,7 @@ class CRM_Utils_Array {
    * @param string $prefix
    * @return array
    */
-  public static function prefixKeys(array $collection, string $prefix) {
+  public static function prefixKeys(array $collection, string $prefix): array {
     $result = [];
     foreach ($collection as $key => $value) {
       $result[$prefix . $key] = $value;
@@ -1392,4 +1392,21 @@ class CRM_Utils_Array {
     return $result;
   }
 
+  /**
+   * Removes all items from an array whose keys have a given prefix, and returns them unprefixed.
+   *
+   * @param array $collection
+   * @param string $prefix
+   */
+  public static function filterByPrefix(array &$collection, string $prefix): array {
+    $filtered = [];
+    foreach (array_keys($collection) as $key) {
+      if (!$prefix || strpos($key, $prefix) === 0) {
+        $filtered[substr($key, strlen($prefix))] = $collection[$key];
+        unset($collection[$key]);
+      }
+    }
+    return $filtered;
+  }
+
 }
index 3fcc920a254b5a80556be5ec9deb38a7844e425e..4dadbe0603b7fe6095846e157546db20ba7fb897 100644 (file)
@@ -13,7 +13,6 @@
 namespace Civi\Api4\Action\Contact;
 
 use Civi\Api4\Utils\CoreUtil;
-use Civi\Api4\Utils\FormattingUtil;
 
 /**
  * Code shared by Contact create/update/save actions
@@ -58,7 +57,7 @@ trait ContactSaveTrait {
     foreach (['Address', 'Email', 'Phone', 'IM'] as $entity) {
       foreach (['primary', 'billing'] as $type) {
         $prefix = strtolower($entity) . '_' . $type . '.';
-        $item = FormattingUtil::filterByPrefix($params, $prefix . '*', '*');
+        $item = \CRM_Utils_Array::filterByPrefix($params, $prefix);
         // Not allowed to update by id or alter primary or billing flags
         unset($item['id'], $item['is_primary'], $item['is_billing']);
         if ($item) {
index 2079d929fe4b2fcf9a9955a67cacc55f28d320d1..3e92ddd2e023dbf8a56c062e82073d18827f0b72 100644 (file)
@@ -261,7 +261,7 @@ class FormattingUtil {
     // Use BAO::buildOptions if possible
     if ($baoName) {
       $fieldName = empty($field['custom_field_id']) ? $field['name'] : 'custom_' . $field['custom_field_id'];
-      $options = $baoName::buildOptions($fieldName, $context, self::filterByPrefix($params, $fieldPath, $field['name']));
+      $options = $baoName::buildOptions($fieldName, $context, self::filterByPath($params, $fieldPath, $field['name']));
     }
     // Fallback for option lists that exist in the api but not the BAO
     if (!isset($options) || $options === FALSE) {
@@ -308,7 +308,7 @@ class FormattingUtil {
    * @param mixed $value
    */
   private static function applyFormatters(array $result, string $fieldPath, array $field, &$value) {
-    $row = self::filterByPrefix($result, $fieldPath, $field['name']);
+    $row = self::filterByPath($result, $fieldPath, $field['name']);
 
     foreach ($field['output_formatters'] as $formatter) {
       $formatter($value, $row, $field);
@@ -382,8 +382,7 @@ class FormattingUtil {
    * Given a field belonging to either the main entity or a joined entity,
    * and a values array of [path => value], this returns all values which share the same root path.
    *
-   * Works by filtering array keys to only include those with the same prefix as a given field,
-   * stripping them of that prefix.
+   * Note: Unlike CRM_Utils_Array::filterByPrefix this does not mutate the original array.
    *
    * Ex:
    * ```
@@ -409,15 +408,9 @@ class FormattingUtil {
    * @param string $fieldName
    * @return array
    */
-  public static function filterByPrefix(array $values, string $fieldPath, string $fieldName): array {
-    $filtered = [];
+  public static function filterByPath(array $values, string $fieldPath, string $fieldName): array {
     $prefix = substr($fieldPath, 0, strpos($fieldPath, $fieldName));
-    foreach ($values as $key => $val) {
-      if (!$prefix || strpos($key, $prefix) === 0) {
-        $filtered[substr($key, strlen($prefix))] = $val;
-      }
-    }
-    return $filtered;
+    return \CRM_Utils_Array::filterByPrefix($values, $prefix);
   }
 
 }
index a9726940726bfc946200601f66bf3c6103f68d9e..7251d2eb2e07b3bec471125d962ac3d6bddb687e 100644 (file)
@@ -87,7 +87,7 @@ class GetOptions extends AbstractProcessor {
       'where' => [['name', '=', $fieldName]],
       'select' => ['options'],
       'loadOptions' => ['id', 'label'],
-      'values' => FormattingUtil::filterByPrefix($this->values, $this->fieldName, $fieldName),
+      'values' => FormattingUtil::filterByPath($this->values, $this->fieldName, $fieldName),
     ], 0)['options'] ?: [];
   }
 
index 69526ce04fa5a18276773cefcff3174c9734d6d6..6d417c4baf7f454c0d97b2b8dddf364882c0a362 100644 (file)
@@ -560,7 +560,7 @@ abstract class AbstractRunAction extends \Civi\Api4\Generic\AbstractAction {
       $editable['value'] = $data[$editable['value_path']];
       // Ensure field is appropriate to this entity sub-type
       $field = $this->getField($column['key']);
-      $entityValues = FormattingUtil::filterByPrefix($data, $editable['id_path'], $editable['id_key']);
+      $entityValues = FormattingUtil::filterByPath($data, $editable['id_path'], $editable['id_key']);
       if (!$this->fieldBelongsToEntity($editable['entity'], $field['name'], $entityValues)) {
         return NULL;
       }