SearchKit - Fix handing of new EntityReference custom fields
authorColeman Watts <coleman@civicrm.org>
Sun, 26 Mar 2023 20:46:08 +0000 (16:46 -0400)
committerColeman Watts <coleman@civicrm.org>
Sun, 26 Mar 2023 20:46:15 +0000 (16:46 -0400)
Fixes the metadata for the new EntityReference custom fields to correctly display.

Removes redundant function SpecFormatter::customFieldHasOptions which was completely
identical to CRM_Core_BAO_CustomField::hasOptions except for one line which was incorrect.

Civi/Api4/Service/Spec/SpecFormatter.php
ext/search_kit/Civi/Search/Admin.php
tests/phpunit/api/v4/Custom/CustomEntityReferenceTest.php [new file with mode: 0644]

index 3b9ebb4e2225f48a1e8ba9465f5416e7562d2e5b..4f32c107729901cc28eb8bb6207a51ea8f2d4191 100644 (file)
@@ -48,7 +48,7 @@ class SpecFormatter {
       $field->setLabel($data['custom_group_id.title'] . ': ' . $data['label']);
       $field->setHelpPre($data['help_pre'] ?? NULL);
       $field->setHelpPost($data['help_post'] ?? NULL);
-      if (self::customFieldHasOptions($data)) {
+      if (\CRM_Core_BAO_CustomField::hasOptions($data)) {
         $field->setOptionsCallback([__CLASS__, 'getOptions']);
         $suffixes = ['label'];
         if (!empty($data['option_group_id'])) {
@@ -103,28 +103,6 @@ class SpecFormatter {
     return $field;
   }
 
-  /**
-   * Does this custom field have options
-   *
-   * @param array $field
-   * @return bool
-   */
-  private static function customFieldHasOptions($field) {
-    // This will include boolean fields with Yes/No options.
-    if (in_array($field['html_type'], ['Radio', 'CheckBox'])) {
-      return TRUE;
-    }
-    // Do this before the "Select" string search because date fields have a "Select Date" html_type
-    // and contactRef fields have an "Autocomplete-Select" html_type - contacts are an FK not an option list.
-    if (in_array($field['data_type'], ['ContactReference', 'Date'])) {
-      return FALSE;
-    }
-    if (strpos($field['html_type'], 'Select') !== FALSE) {
-      return TRUE;
-    }
-    return !empty($field['option_group_id']);
-  }
-
   /**
    * Get the data type from an array. Defaults to 'data_type' with fallback to
    * mapping for the integer value 'type'
index ee85568afd35e737fb4dda130a19e915dbeabc69..4967484f6f8d0b9861b8c98befe1c0dd3560c3d3 100644 (file)
@@ -191,9 +191,10 @@ class Admin {
         foreach (array_reverse($entity['fields'], TRUE) as $index => $field) {
           if (!empty($field['fk_entity']) && !$field['options'] && !empty($schema[$field['fk_entity']]['label_field'])) {
             $isCustom = strpos($field['name'], '.');
-            // Custom fields: append "Contact ID" to original field label
+            // Custom fields: append "Contact ID" etc. to original field label
             if ($isCustom) {
-              $entity['fields'][$index]['label'] .= ' ' . E::ts('Contact ID');
+              $idField = array_column($schema[$field['fk_entity']]['fields'], NULL, 'name')['id'];
+              $entity['fields'][$index]['label'] .= ' ' . $idField['title'];
             }
             // DAO fields: use title instead of label since it represents the id (title usually ends in ID but label does not)
             else {
diff --git a/tests/phpunit/api/v4/Custom/CustomEntityReferenceTest.php b/tests/phpunit/api/v4/Custom/CustomEntityReferenceTest.php
new file mode 100644 (file)
index 0000000..dda892c
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * @package CRM
+ * @copyright CiviCRM LLC https://civicrm.org/licensing
+ */
+
+namespace api\v4\Custom;
+
+use Civi\Api4\Contact;
+use Civi\Api4\CustomGroup;
+use Civi\Api4\CustomField;
+
+/**
+ * @group headless
+ */
+class CustomEntityReferenceTest extends CustomTestBase {
+
+  /**
+   * Ensure custom fields of type EntityReference show up correctly in getFields metadata.
+   */
+  public function testEntityReferenceCustomField() {
+    CustomGroup::create()->setValues([
+      'title' => 'EntityRefFields',
+      'extends' => 'Individual',
+    ])->execute();
+    CustomField::create()->setValues([
+      'label' => 'TestActivityReference',
+      'custom_group_id.name' => 'EntityRefFields',
+      'html_type' => 'Autocomplete-Select',
+      'data_type' => 'EntityReference',
+      'fk_entity' => 'Activity',
+    ])->execute();
+    $spec = Contact::getFields(FALSE)
+      ->addWhere('name', '=', 'EntityRefFields.TestActivityReference')
+      ->execute()->single();
+    $this->assertNull($spec['suffixes']);
+    $this->assertEquals('EntityRef', $spec['input_type']);
+    $this->assertEquals('Activity', $spec['fk_entity']);
+  }
+
+}