APIv4 - Support FK field lookups in create/update/save actions
authorColeman Watts <coleman@civicrm.org>
Sun, 20 Jun 2021 20:16:05 +0000 (16:16 -0400)
committerColeman Watts <coleman@civicrm.org>
Mon, 21 Jun 2021 05:16:24 +0000 (01:16 -0400)
Civi/Api4/Generic/Traits/DAOActionTrait.php
tests/phpunit/api/v4/Action/FkJoinTest.php

index af611354480c2320c8082e248b86774715c7a329..76df9951a41d4b58eaaba7e34dd860be6bcaa49b 100644 (file)
@@ -164,6 +164,35 @@ trait DAOActionTrait {
     return $result;
   }
 
+  /**
+   * @inheritDoc
+   */
+  protected function formatWriteValues(&$record) {
+    $this->resolveFKValues($record);
+    parent::formatWriteValues($record);
+  }
+
+  /**
+   * Looks up an id based on some other property of an fk entity
+   *
+   * @param array $record
+   */
+  private function resolveFKValues(array &$record): void {
+    foreach ($record as $key => $value) {
+      if (substr_count($key, '.') !== 1) {
+        continue;
+      }
+      [$fieldName, $fkField] = explode('.', $key);
+      $field = $this->entityFields()[$fieldName] ?? NULL;
+      if (!$field || empty($field['fk_entity'])) {
+        continue;
+      }
+      $fkDao = CoreUtil::getBAOFromApiName($field['fk_entity']);
+      $record[$fieldName] = \CRM_Core_DAO::getFieldValue($fkDao, $value, 'id', $fkField);
+      unset($record[$key]);
+    }
+  }
+
   /**
    * @param array $params
    * @param int $entityId
index d02ac67c2872c525a49a23dc27fb77d502999913..efadad04754499b6fbb57678d1d8a2f4e03d4a79 100644 (file)
@@ -173,17 +173,18 @@ class FkJoinTest extends UnitTestCase {
       ->addValue('name', uniqid('join3'))
       ->execute()
       ->first()['name'];
-
+    // Create using pseudoconstant syntax (:name)
     $cid1 = Contact::create(FALSE)
       ->addValue('first_name', 'Aaa')
       ->addChain('tag1', EntityTag::create()->setValues(['entity_id' => '$id', 'tag_id:name' => $tag1]))
       ->addChain('tag2', EntityTag::create()->setValues(['entity_id' => '$id', 'tag_id:name' => $tag2]))
       ->execute()
       ->first()['id'];
+    // Create using fk syntax (.name)
     $cid2 = Contact::create(FALSE)
       ->addValue('first_name', 'Bbb')
-      ->addChain('tag1', EntityTag::create()->setValues(['entity_id' => '$id', 'tag_id:name' => $tag1]))
-      ->addChain('tag3', EntityTag::create()->setValues(['entity_id' => '$id', 'tag_id:name' => $tag3]))
+      ->addChain('tag1', EntityTag::create()->setValues(['entity_id' => '$id', 'tag_id.name' => $tag1]))
+      ->addChain('tag3', EntityTag::create()->setValues(['entity_id' => '$id', 'tag_id.name' => $tag3]))
       ->execute()
       ->first()['id'];
     $cid3 = Contact::create(FALSE)