APIv4 - Fix entity name on custom groups in schemaMapper
authorColeman Watts <coleman@civicrm.org>
Fri, 29 May 2020 18:32:45 +0000 (14:32 -0400)
committerColeman Watts <coleman@civicrm.org>
Mon, 1 Jun 2020 05:18:10 +0000 (01:18 -0400)
Only multi-record groups are considered an api "entity", so for other groups the entity should be null.

Civi/Api4/Action/Entity/GetLinks.php
Civi/Api4/Query/Api4SelectQuery.php
Civi/Api4/Service/Schema/Joinable/CustomGroupJoinable.php
Civi/Api4/Service/Schema/SchemaMapBuilder.php

index e841c566aca2ebb0d541681b29047add928aac4c..5a4bc69785b2cda6c3ef6b95d37f505a6b2e3d7e 100644 (file)
@@ -40,9 +40,7 @@ class GetLinks extends \Civi\Api4\Generic\BasicGetAction {
           'links' => [],
         ];
         foreach ($table->getTableLinks() as $link) {
-          $link = $link->toArray();
-          $link['entity'] = CoreUtil::getApiNameFromTableName($link['targetTable']);
-          $item['links'][] = $link;
+          $item['links'][] = $link->toArray();
         }
         $result[] = $item;
       }
index 9dffe7a734959810dd1e817973aa6aa884e7f8e6..5378454474eecb40b022e83fd8e0fde41df2a290 100644 (file)
@@ -518,9 +518,8 @@ class Api4SelectQuery extends SelectQuery {
     }
     $prefix = $pathArray ? implode('.', $pathArray) . '.' : '';
     // Cache field info for retrieval by $this->getField()
-    $joinEntity = $lastLink->getEntity();
     foreach ($lastLink->getEntityFields() as $fieldObject) {
-      $fieldArray = ['entity' => $joinEntity] + $fieldObject->toArray();
+      $fieldArray = $fieldObject->toArray();
       $fieldArray['sql_name'] = '`' . $lastLink->getAlias() . '`.`' . $fieldArray['column_name'] . '`';
       $fieldArray['is_custom'] = $isCustom;
       $fieldArray['is_join'] = TRUE;
index fd5ab30f9ddf9652bec69dfab6b2758422c730e2..464cd911f431dd8fbf5f772bf008f21affe50003 100644 (file)
@@ -41,15 +41,17 @@ class CustomGroupJoinable extends Joinable {
    * @param $targetTable
    * @param $alias
    * @param bool $isMultiRecord
-   * @param string $entity
    * @param string $columns
    */
-  public function __construct($targetTable, $alias, $isMultiRecord, $entity, $columns) {
-    $this->entity = $entity;
+  public function __construct($targetTable, $alias, $isMultiRecord, $columns) {
     $this->columns = $columns;
     parent::__construct($targetTable, 'entity_id', $alias);
     $this->joinType = $isMultiRecord ?
       self::JOIN_TYPE_ONE_TO_MANY : self::JOIN_TYPE_ONE_TO_ONE;
+    // Only multi-record groups are considered an api "entity"
+    if (!$isMultiRecord) {
+      $this->entity = NULL;
+    }
   }
 
   /**
@@ -59,11 +61,11 @@ class CustomGroupJoinable extends Joinable {
     if (!$this->entityFields) {
       $fields = CustomField::get()
         ->setCheckPermissions(FALSE)
-        ->setSelect(['custom_group.name', '*'])
+        ->setSelect(['custom_group.name', 'custom_group.extends', '*'])
         ->addWhere('custom_group.table_name', '=', $this->getTargetTable())
         ->execute();
       foreach ($fields as $field) {
-        $this->entityFields[] = \Civi\Api4\Service\Spec\SpecFormatter::arrayToField($field, $this->getEntity());
+        $this->entityFields[] = \Civi\Api4\Service\Spec\SpecFormatter::arrayToField($field, $this->getEntityFromExtends($field['custom_group.extends']));
       }
     }
     return $this->entityFields;
@@ -92,4 +94,25 @@ class CustomGroupJoinable extends Joinable {
     return $this->columns[$fieldName];
   }
 
+  /**
+   * Translate custom_group.extends to entity name.
+   *
+   * Custom_group.extends pretty much maps 1-1 with entity names, except for a couple oddballs.
+   * @see \CRM_Core_SelectValues::customGroupExtends
+   *
+   * @param $extends
+   * @return string
+   * @throws \API_Exception
+   * @throws \Civi\API\Exception\UnauthorizedException
+   */
+  private function getEntityFromExtends($extends) {
+    if (strpos($extends, 'Participant') === 0) {
+      return 'Participant';
+    }
+    if ($extends === 'Contact' || in_array($extends, \CRM_Contact_BAO_ContactType::basicTypes(TRUE))) {
+      return 'Contact';
+    }
+    return $extends;
+  }
+
 }
index b6393755e0ae6bf0c85a760737b0de05f0399a4c..afecc01056ade66658293062293a826477856fba 100644 (file)
@@ -111,7 +111,7 @@ class SchemaMapBuilder {
         $target = $map->getTableByName($link->getTargetTable());
         $tableName = $link->getBaseTable();
         // Exclude custom field tables
-        if (strpos($link->getTargetTable(), 'civicrm_value_') !== 0) {
+        if (strpos($link->getTargetTable(), 'civicrm_value_') !== 0 && strpos($link->getBaseTable(), 'civicrm_value_') !== 0) {
           $plural = str_replace('civicrm_', '', $this->getPlural($tableName));
           $joinable = new Joinable($tableName, $link->getBaseColumn(), $plural);
           $joinable->setJoinType($joinable::JOIN_TYPE_ONE_TO_MANY);
@@ -190,7 +190,7 @@ class SchemaMapBuilder {
     }
 
     foreach ($links as $alias => $link) {
-      $joinable = new CustomGroupJoinable($link['tableName'], $alias, $link['isMultiple'], $entity, $link['columns']);
+      $joinable = new CustomGroupJoinable($link['tableName'], $alias, $link['isMultiple'], $link['columns']);
       $baseTable->addTableLink('id', $joinable);
     }
   }