From b192a823a03bbd201b60c82f86abca63c978ac80 Mon Sep 17 00:00:00 2001 From: colemanw Date: Tue, 3 Oct 2023 19:22:39 -0400 Subject: [PATCH] APIv4 - Fix autocomplete for Individual,Household,Organization entities --- CRM/Core/DAO/AllCoreTables.php | 2 +- Civi/Api4/Service/Schema/SchemaMapBuilder.php | 14 ++++- .../v4/Custom/CustomEntityReferenceTest.php | 61 +++++++++++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/CRM/Core/DAO/AllCoreTables.php b/CRM/Core/DAO/AllCoreTables.php index 4c22ee769b..ba28171ba9 100644 --- a/CRM/Core/DAO/AllCoreTables.php +++ b/CRM/Core/DAO/AllCoreTables.php @@ -358,7 +358,7 @@ class CRM_Core_DAO_AllCoreTables { * * @param string $briefName * - * @return FALSE|string + * @return string */ public static function getTableForEntityName($briefName): string { self::init(); diff --git a/Civi/Api4/Service/Schema/SchemaMapBuilder.php b/Civi/Api4/Service/Schema/SchemaMapBuilder.php index dc388ae4e8..576b96ec6e 100644 --- a/Civi/Api4/Service/Schema/SchemaMapBuilder.php +++ b/Civi/Api4/Service/Schema/SchemaMapBuilder.php @@ -16,6 +16,7 @@ use Civi\Api4\Entity; use Civi\Api4\Event\SchemaMapBuildEvent; use Civi\Api4\Service\Schema\Joinable\CustomGroupJoinable; use Civi\Api4\Service\Schema\Joinable\Joinable; +use Civi\Api4\Utils\CoreUtil; use Civi\Core\Service\AutoService; use Civi\Core\CiviEventDispatcherInterface; use CRM_Core_DAO_AllCoreTables as AllCoreTables; @@ -142,7 +143,7 @@ class SchemaMapBuilder extends AutoService { } if ($fieldData->data_type === 'EntityReference' && isset($fieldData->fk_entity)) { - $targetTable = AllCoreTables::getTableForEntityName($fieldData->fk_entity); + $targetTable = self::getTableName($fieldData->fk_entity); $joinable = new Joinable($targetTable, 'id', $fieldData->name); $customTable->addTableLink($fieldData->column_name, $joinable); } @@ -162,4 +163,15 @@ class SchemaMapBuilder extends AutoService { } } + /** + * @param string $entityName + * @return string + */ + private static function getTableName(string $entityName) { + if (CoreUtil::isContact($entityName)) { + return 'civicrm_contact'; + } + return AllCoreTables::getTableForEntityName($entityName); + } + } diff --git a/tests/phpunit/api/v4/Custom/CustomEntityReferenceTest.php b/tests/phpunit/api/v4/Custom/CustomEntityReferenceTest.php index 3f34c1c0cc..be9594b931 100644 --- a/tests/phpunit/api/v4/Custom/CustomEntityReferenceTest.php +++ b/tests/phpunit/api/v4/Custom/CustomEntityReferenceTest.php @@ -21,6 +21,8 @@ use Civi\Api4\Activity; use Civi\Api4\Contact; use Civi\Api4\CustomGroup; use Civi\Api4\CustomField; +use Civi\Api4\Individual; +use Civi\Api4\Organization; /** * @group headless @@ -44,6 +46,11 @@ class CustomEntityReferenceTest extends CustomTestBase { 'fk_entity' => 'Activity', 'filter' => "subject=$subject", ])->execute()->single(); + // Spec should only exist for Individuals + $spec = Organization::getFields(FALSE) + ->addWhere('name', '=', 'EntityRefFields.TestActivityReference') + ->execute()->first(); + $this->assertNull($spec); // Check metadata $spec = Contact::getFields(FALSE) ->addWhere('name', '=', 'EntityRefFields.TestActivityReference') @@ -71,4 +78,58 @@ class CustomEntityReferenceTest extends CustomTestBase { $this->assertGreaterThan(2, $result->countFetched()); } + /** + * Ensure custom fields of type EntityReference correctly apply filters + */ + public function testEntityReferenceCustomFieldByContactType(): void { + CustomGroup::create()->setValues([ + 'title' => 'EntityRefFields', + 'extends' => 'Individual', + ])->execute(); + CustomField::create()->setValues([ + 'label' => 'TestOrgRef', + 'custom_group_id.name' => 'EntityRefFields', + 'html_type' => 'Autocomplete-Select', + 'data_type' => 'EntityReference', + 'fk_entity' => 'Organization', + ])->execute()->single(); + // Check metadata + $spec = Individual::getFields(FALSE) + ->addWhere('name', '=', 'EntityRefFields.TestOrgRef') + ->execute()->single(); + $this->assertNull($spec['suffixes']); + $this->assertEquals('EntityRef', $spec['input_type']); + $this->assertEquals('Organization', $spec['fk_entity']); + // Check results + $contacts = $this->saveTestRecords('Contact', [ + 'records' => [ + ['contact_type' => 'Organization'], + ['contact_type' => 'Individual'], + ['contact_type' => 'Household'], + ], + ])->indexBy('contact_type')->column('id'); + // Autocomplete by id + $result = (array) Organization::autocomplete(FALSE) + ->setFieldName("Contact.EntityRefFields.TestOrgRef") + ->setInput((string) $contacts['Organization']) + ->execute(); + $this->assertCount(1, $result); + // Autocomplete by id + $result = (array) Organization::autocomplete(FALSE) + ->setFieldName("Contact.EntityRefFields.TestOrgRef") + ->setInput((string) $contacts['Individual']) + ->execute(); + $this->assertCount(0, $result); + // Autocomplete by id + $result = (array) Organization::autocomplete(FALSE) + ->setFieldName("Contact.EntityRefFields.TestOrgRef") + ->setInput((string) $contacts['Household']) + ->execute(); + $this->assertCount(0, $result); + // No field specified + $result = Contact::autocomplete(FALSE) + ->execute(); + $this->assertGreaterThan(2, $result->countFetched()); + } + } -- 2.25.1