From 4b953f95e2a6d8e565bf224a2deb560bb7af7204 Mon Sep 17 00:00:00 2001 From: colemanw Date: Wed, 3 Jan 2024 09:15:00 -0500 Subject: [PATCH] APIv4 - Add fk_column to getFields metadata Before: getFields contained incomplete info about foreign keys, so trying to map the schema was unnecessarily difficult. After: No need to use extra DAO methods like getReferenceColumns() to find out about FKs. All the info is returned by getFields. --- Civi/Api4/Generic/DAOGetFieldsAction.php | 5 ++++ Civi/Api4/Service/Spec/SpecFormatter.php | 3 +++ Civi/Schema/Traits/DataTypeSpecTrait.php | 25 +++++++++++++++++++ tests/phpunit/api/v4/Action/GetFieldsTest.php | 1 + .../v4/Custom/CustomEntityReferenceTest.php | 1 + 5 files changed, 35 insertions(+) diff --git a/Civi/Api4/Generic/DAOGetFieldsAction.php b/Civi/Api4/Generic/DAOGetFieldsAction.php index 8b4a5655ff..251724dc33 100644 --- a/Civi/Api4/Generic/DAOGetFieldsAction.php +++ b/Civi/Api4/Generic/DAOGetFieldsAction.php @@ -130,6 +130,11 @@ class DAOGetFieldsAction extends BasicGetFieldsAction { public function fields() { $fields = parent::fields(); + $fields[] = [ + 'name' => 'fk_column', + 'data_type' => 'String', + 'description' => 'Name of fk_entity column this field references.', + ]; $fields[] = [ 'name' => 'dfk_entities', 'description' => 'List of possible entity types this field could be referencing.', diff --git a/Civi/Api4/Service/Spec/SpecFormatter.php b/Civi/Api4/Service/Spec/SpecFormatter.php index 47506d54aa..b13d1f4b92 100644 --- a/Civi/Api4/Service/Spec/SpecFormatter.php +++ b/Civi/Api4/Service/Spec/SpecFormatter.php @@ -117,6 +117,9 @@ class SpecFormatter { elseif (($data['html']['type'] ?? NULL) === 'EntityRef' && !empty($data['pseudoconstant']['table'])) { $field->setFkEntity(CoreUtil::getApiNameFromTableName($data['pseudoconstant']['table'])); } + if (!empty($data['FKColumnName'])) { + $field->setFkColumn($data['FKColumnName']); + } return $field; } diff --git a/Civi/Schema/Traits/DataTypeSpecTrait.php b/Civi/Schema/Traits/DataTypeSpecTrait.php index 1c4b9bef1c..1ffe6c3881 100644 --- a/Civi/Schema/Traits/DataTypeSpecTrait.php +++ b/Civi/Schema/Traits/DataTypeSpecTrait.php @@ -41,6 +41,11 @@ trait DataTypeSpecTrait { */ public $fkEntity; + /** + * @var string + */ + public $fkColumn; + /** * @var string */ @@ -98,7 +103,27 @@ trait DataTypeSpecTrait { */ public function setFkEntity($fkEntity) { $this->fkEntity = $fkEntity; + // If the field has a FK Entity, then FK Column also must be set. + if ($fkEntity) { + // Ensure a sensible default if not already set. + $this->fkColumn ??= 'id'; + } + return $this; + } + /** + * @return string|null + */ + public function getFkColumn(): ?string { + return $this->fkColumn; + } + + /** + * @param string $fkColumn + * @return $this + */ + public function setFkColumn($fkColumn) { + $this->fkColumn = $fkColumn; return $this; } diff --git a/tests/phpunit/api/v4/Action/GetFieldsTest.php b/tests/phpunit/api/v4/Action/GetFieldsTest.php index 8aeab52cc8..587bf52b7e 100644 --- a/tests/phpunit/api/v4/Action/GetFieldsTest.php +++ b/tests/phpunit/api/v4/Action/GetFieldsTest.php @@ -253,6 +253,7 @@ class GetFieldsTest extends Api4TestBase implements TransactionalInterface { // fk_entity should be specific to specified entity_table, but dfk_entities should still contain all values $this->assertEquals('Activity', $tagFields['entity_id']['fk_entity']); $this->assertContains('Contact', $tagFields['entity_id']['dfk_entities']); + $this->assertEquals('id', $tagFields['entity_id']['fk_column']); $tagFields = EntityTag::getFields(FALSE) ->addValue('entity_table:name', 'Contact') diff --git a/tests/phpunit/api/v4/Custom/CustomEntityReferenceTest.php b/tests/phpunit/api/v4/Custom/CustomEntityReferenceTest.php index be9594b931..da05c6d412 100644 --- a/tests/phpunit/api/v4/Custom/CustomEntityReferenceTest.php +++ b/tests/phpunit/api/v4/Custom/CustomEntityReferenceTest.php @@ -58,6 +58,7 @@ class CustomEntityReferenceTest extends CustomTestBase { $this->assertNull($spec['suffixes']); $this->assertEquals('EntityRef', $spec['input_type']); $this->assertEquals('Activity', $spec['fk_entity']); + $this->assertEquals('id', $spec['fk_column']); $this->assertEquals($subject, $spec['input_attrs']['filter']['subject']); // Check results $activities = $this->saveTestRecords('Activity', [ -- 2.25.1