From d451690c9a2999cbaacbdd40ab79ab69e0eba006 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Thu, 24 Jun 2021 15:36:23 -0400 Subject: [PATCH] APIv4 - Don't assume the identifier field for a table is named 'id' APIv4 getInfo() now returns the name of the "id_field" for any entity. This modifies the selectQuery so that `get` actions rely on that metadata. --- Civi/Api4/CustomValue.php | 1 + Civi/Api4/Query/Api4SelectQuery.php | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Civi/Api4/CustomValue.php b/Civi/Api4/CustomValue.php index acb10d88d8..bd1705d065 100644 --- a/Civi/Api4/CustomValue.php +++ b/Civi/Api4/CustomValue.php @@ -142,6 +142,7 @@ class CustomValue { 'class' => __CLASS__, 'type' => ['CustomValue'], 'searchable' => 'secondary', + 'id_field' => 'id', 'see' => [ 'https://docs.civicrm.org/user/en/latest/organising-your-data/creating-custom-fields/#multiple-record-fieldsets', '\Civi\Api4\CustomGroup', diff --git a/Civi/Api4/Query/Api4SelectQuery.php b/Civi/Api4/Query/Api4SelectQuery.php index 052c0c0aa4..99940efefd 100644 --- a/Civi/Api4/Query/Api4SelectQuery.php +++ b/Civi/Api4/Query/Api4SelectQuery.php @@ -88,7 +88,8 @@ class Api4SelectQuery { $this->api = $apiGet; // Always select ID of main table unless grouping by something else - $this->forceSelectId = !$this->isAggregateQuery() || $this->getGroupBy() === ['id']; + $id = $this->getIdField($this->getEntity()); + $this->forceSelectId = !$this->isAggregateQuery() || $this->getGroupBy() === [$id]; // Build field lists foreach ($this->api->entityFields() as $field) { @@ -203,7 +204,8 @@ class Api4SelectQuery { } else { if ($this->forceSelectId) { - $select = array_merge(['id'], $select); + $id = $this->getIdField($this->getEntity()); + $select = array_merge([$id], $select); } // Expand the superstar 'custom.*' to select all fields in all custom groups @@ -228,8 +230,10 @@ class Api4SelectQuery { foreach ($wildFields as $wildField) { $pos = array_search($wildField, array_values($select)); // If the joined_entity.id isn't in the fieldspec already, autoJoinFK will attempt to add the entity. - $idField = substr($wildField, 0, strrpos($wildField, '.')) . '.id'; - $this->autoJoinFK($idField); + $fkField = substr($wildField, 0, strrpos($wildField, '.')); + $fkEntity = $this->getField($fkField)['fk_entity'] ?? NULL; + $id = $fkEntity ? $this->getIdField($fkEntity) : 'id'; + $this->autoJoinFK($fkField . ".$id"); $matches = $this->selectMatchingFields($wildField); array_splice($select, $pos, 1, $matches); } @@ -272,6 +276,14 @@ class Api4SelectQuery { return SelectUtil::getMatchingFields($pattern, array_keys($availableFields)); } + /** + * @param $entityName + * @return string + */ + private function getIdField($entityName) { + return CoreUtil::getApiClass($entityName)::getInfo()['id_field']; + } + /** * Add WHERE clause to query */ -- 2.25.1