From d290014d6cace5667c68a73078815c51c85aa425 Mon Sep 17 00:00:00 2001 From: colemanw Date: Wed, 5 Aug 2026 13:07:30 -0400 Subject: [PATCH] SearchKit - Fix deep joins to custom fields. Fixes dev/core#6676 --- ext/search_kit/ang/crmSearchAdmin.module.js | 4 +- .../api/v4/Custom/ContactCustomJoinTest.php | 83 +++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/ext/search_kit/ang/crmSearchAdmin.module.js b/ext/search_kit/ang/crmSearchAdmin.module.js index 76267adc91ac..582ac052855b 100644 --- a/ext/search_kit/ang/crmSearchAdmin.module.js +++ b/ext/search_kit/ang/crmSearchAdmin.module.js @@ -236,9 +236,9 @@ if (Array.isArray(condition)) { condition.forEach((ref, side) => { if (side !== 1 && typeof ref === 'string') { - if (ref.includes('.')) { + if (ref.includes(join.alias + '.')) { condition[side] = ref.replace(join.alias + '.', alias + '.'); - } else if (prefix.length && !ref.includes('"') && !ref.includes("'")) { + } else if (prefix.length && !ref.startsWith(prefix + '.') && !ref.includes('"') && !ref.includes("'")) { condition[side] = prefix + '.' + ref; } } diff --git a/tests/phpunit/api/v4/Custom/ContactCustomJoinTest.php b/tests/phpunit/api/v4/Custom/ContactCustomJoinTest.php index bdfa6b9c2c34..ab91c1f5752a 100644 --- a/tests/phpunit/api/v4/Custom/ContactCustomJoinTest.php +++ b/tests/phpunit/api/v4/Custom/ContactCustomJoinTest.php @@ -157,4 +157,87 @@ public function testJoinWithCustomFieldComparedToCoreFieldInOnClause(): void { $this->assertNull($result[2]['activity.id']); } + /** + * Tests custom entityRef field on joined entity in explicit join clause. + */ + public function testJoinWithCustomFieldOnJoinedEntity(): void { + $this->createTestRecord('CustomGroup', [ + 'name' => 'Activity_fields', + 'title' => 'Activity_fields', + 'extends' => 'Activity', + 'extends_entity_column_value:name' => ['Meeting'], + ]); + $this->createTestRecord('CustomField', [ + 'name' => 'Org', + 'label' => 'Org', + 'custom_group_id.name' => 'Activity_fields', + 'html_type' => 'EntityRef', + 'data_type' => 'EntityReference', + 'fk_entity' => 'Organization', + ]); + $org = $this->createTestRecord('Contact', [ + 'contact_type' => 'Organization', + 'organization_name' => 'Test Organization', + ]); + $target = $this->createTestRecord('Contact', [ + 'contact_type' => 'Individual', + 'first_name' => 'Test', + 'last_name' => 'Target', + ]); + $this->createTestRecord('Activity', [ + 'activity_type_id:name' => 'Meeting', + 'subject' => 'Test Meeting', + 'target_contact_id' => [$target['id']], + 'Activity_fields.Org' => $org['id'], + ]); + + $result = civicrm_api4('Contact', 'get', [ + 'checkPermissions' => FALSE, + 'select' => [ + 'id', + 'Contact_ActivityContact_Activity_01.subject', + 'Contact_ActivityContact_Activity_01_Activity_Organization_Org_01.organization_name', + ], + 'where' => [ + ['id', '=', $target['id']], + ], + 'join' => [ + [ + 'Activity AS Contact_ActivityContact_Activity_01', + 'INNER', + 'ActivityContact', + [ + 'id', + '=', + 'Contact_ActivityContact_Activity_01.contact_id', + ], + [ + 'Contact_ActivityContact_Activity_01.record_type_id:name', + '=', + '"Activity Targets"', + ], + [ + 'Contact_ActivityContact_Activity_01.activity_type_id:name', + '=', + '"Meeting"', + ], + ], + [ + 'Organization AS Contact_ActivityContact_Activity_01_Activity_Organization_Org_01', + 'INNER', + [ + 'Contact_ActivityContact_Activity_01.Activity_fields.Org', + '=', + 'Contact_ActivityContact_Activity_01_Activity_Organization_Org_01.id', + ], + ], + ], + ]); + + $this->assertCount(1, $result); + $this->assertEquals($target['id'], $result[0]['id']); + $this->assertSame('Test Meeting', $result[0]['Contact_ActivityContact_Activity_01.subject']); + $this->assertSame('Test Organization', $result[0]['Contact_ActivityContact_Activity_01_Activity_Organization_Org_01.organization_name']); + } + }