Improve APIv4 metadata for RelationshipCache and Bridge entities in general
authorColeman Watts <coleman@civicrm.org>
Thu, 3 Dec 2020 20:55:53 +0000 (15:55 -0500)
committerColeman Watts <coleman@civicrm.org>
Thu, 3 Dec 2020 20:55:53 +0000 (15:55 -0500)
These are the core changes needed toward geting joins supported by Search Kit

CRM/Contact/DAO/RelationshipCache.php
CRM/Core/DAO.php
Civi/Api4/Entity.php
Civi/Api4/Generic/AbstractEntity.php
Civi/Api4/Generic/DAOEntity.php
Civi/Api4/Generic/Traits/EntityBridge.php
Civi/Api4/GroupContact.php
Civi/Api4/RelationshipCache.php
Civi/Api4/Utils/ReflectionUtils.php
xml/schema/Contact/RelationshipCache.xml

index ba2d97d00223b82c07be6ee3dc6051e8580d5730..5701d5c3e67369f3bb6c9e897eda430d3203562b 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Contact/RelationshipCache.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:3bee16c8388728d3e391e9dd7c17abb8)
+ * (GenCodeChecksum:ba039fcadc13e48749f965343301ec1d)
  */
 
 /**
@@ -129,7 +129,7 @@ class CRM_Contact_DAO_RelationshipCache extends CRM_Core_DAO {
    *   Whether to return the plural version of the title.
    */
   public static function getEntityTitle($plural = FALSE) {
-    return $plural ? ts('Relationship Caches') : ts('Relationship Cache');
+    return $plural ? ts('Related Contacts') : ts('Related Contact');
   }
 
   /**
@@ -237,7 +237,7 @@ class CRM_Contact_DAO_RelationshipCache extends CRM_Core_DAO {
         'near_relation' => [
           'name' => 'near_relation',
           'type' => CRM_Utils_Type::T_STRING,
-          'title' => ts('Relationship Name (Near side)'),
+          'title' => ts('Relationship Name (to related contact)'),
           'description' => ts('name for relationship of near_contact to far_contact.'),
           'maxlength' => 64,
           'size' => CRM_Utils_Type::BIG,
@@ -271,7 +271,7 @@ class CRM_Contact_DAO_RelationshipCache extends CRM_Core_DAO {
         'far_relation' => [
           'name' => 'far_relation',
           'type' => CRM_Utils_Type::T_STRING,
-          'title' => ts('Relationship Name (Near side)'),
+          'title' => ts('Relationship Name (from related contact)'),
           'description' => ts('name for relationship of far_contact to near_contact.'),
           'maxlength' => 64,
           'size' => CRM_Utils_Type::BIG,
index 2d40afd073630aa17cb9f57357a46c63aeb96934..79457ed5d91d56ca822f49ef09128068c8692a7e 100644 (file)
@@ -530,8 +530,7 @@ class CRM_Core_DAO extends DB_DataObject {
    * Returns list of FK relationships.
    *
    *
-   * @return array
-   *   Array of CRM_Core_Reference_Interface
+   * @return CRM_Core_Reference_Basic[]
    */
   public static function getReferenceColumns() {
     return [];
index 8dec4cebaf213a462c297b2a2f256144c914f881..ac61fcf3892be89ddd6f20dcdcb7ed6de392423a 100644 (file)
@@ -98,6 +98,11 @@ class Entity extends Generic\AbstractEntity {
           'data_type' => 'Array',
           'description' => 'Any @see annotations from docblock',
         ],
+        [
+          'name' => 'bridge',
+          'data_type' => 'Array',
+          'description' => 'Connecting fields for EntityBridge types',
+        ],
       ];
     }))->setCheckPermissions($checkPermissions);
   }
index d4e775ecefe1bae7729d89c2ae6fc98bbb1aa548..1c69eae15ebe17285c55669bda2accebbf2bf85a 100644 (file)
@@ -86,7 +86,9 @@ abstract class AbstractEntity {
    * @return string
    */
   protected static function getEntityTitle($plural = FALSE) {
-    return static::getEntityName();
+    $name = static::getEntityName();
+    $dao = \CRM_Core_DAO_AllCoreTables::getFullName($name);
+    return $dao ? $dao::getEntityTitle($plural) : ($plural ? \CRM_Utils_String::pluralize($name) : $name);
   }
 
   /**
@@ -136,6 +138,13 @@ abstract class AbstractEntity {
       'type' => [self::stripNamespace(get_parent_class(static::class))],
       'paths' => static::getEntityPaths(),
     ];
+    // Add info for entities with a corresponding DAO
+    $dao = \CRM_Core_DAO_AllCoreTables::getFullName($info['name']);
+    if ($dao) {
+      $info['paths'] = $dao::getEntityPaths();
+      $info['icon'] = $dao::$_icon;
+      $info['dao'] = $dao;
+    }
     foreach (ReflectionUtils::getTraits(static::class) as $trait) {
       $info['type'][] = self::stripNamespace($trait);
     }
index fa035259386816c624e111d4fb52999dabc23e1d..ad34c1a7538b3a4b19667d9428a03ba380c03406 100644 (file)
@@ -90,29 +90,4 @@ abstract class DAOEntity extends AbstractEntity {
       ->setCheckPermissions($checkPermissions);
   }
 
-  /**
-   * @param bool $plural
-   *   Whether to return a plural title.
-   * @return string
-   */
-  protected static function getEntityTitle($plural = FALSE) {
-    $name = static::getEntityName();
-    $dao = \CRM_Core_DAO_AllCoreTables::getFullName($name);
-    return $dao ? $dao::getEntityTitle($plural) : $name;
-  }
-
-  /**
-   * @return array
-   */
-  public static function getInfo() {
-    $info = parent::getInfo();
-    $dao = \CRM_Core_DAO_AllCoreTables::getFullName($info['name']);
-    if ($dao) {
-      $info['paths'] = $dao::getEntityPaths();
-      $info['icon'] = $dao::$_icon;
-      $info['dao'] = $dao;
-    }
-    return $info;
-  }
-
 }
index 49b17680cd4e35725245305c4d0464d632023d2a..ff0d4120d21186b77fe6170d8a444cc6942b5b4e 100644 (file)
@@ -20,4 +20,24 @@ namespace Civi\Api4\Generic\Traits;
  */
 trait EntityBridge {
 
+  /**
+   * Adds "bridge" info, which should specify an array of two field names from this entity
+   *
+   * This automatic function can be overridden by annotating the APIv4 entity like
+   * `@bridge contact_id group_id`
+   *
+   * @return array
+   */
+  public static function getInfo() {
+    $info = parent::getInfo();
+    if (!empty($info['dao']) && empty($info['bridge'])) {
+      foreach (($info['dao'])::fields() as $field) {
+        if (!empty($field['FKClassName']) || $field['name'] === 'entity_id') {
+          $info['bridge'][] = $field['name'];
+        }
+      }
+    }
+    return $info;
+  }
+
 }
index 808c1a92fd3c67b6fd9236425dadd9bf1f05be7d..086fb9b273944e42e338861a95196716d4ec3631 100644 (file)
@@ -24,8 +24,9 @@ namespace Civi\Api4;
  * A contact can either be "Added" "Removed" or "Pending" in a group.
  * CiviCRM only considers them to be "in" a group if their status is "Added".
  *
+ * @bridge group_id contact_id
  * @see \Civi\Api4\Group
- *
+ * @searchable false
  * @package Civi\Api4
  */
 class GroupContact extends Generic\DAOEntity {
index a206cd2c277641d96b0dd8241f163f6c9ed752dd..4c6281c3a87792ef763b45c9d25cc3e277b4bbf7 100644 (file)
@@ -23,7 +23,7 @@ namespace Civi\Api4;
  * RelationshipCache - readonly table to facilitate joining and finding contacts by relationship.
  *
  * @see \Civi\Api4\Relationship
- *
+ * @bridge near_contact_id far_contact_id
  * @package Civi\Api4
  */
 class RelationshipCache extends Generic\AbstractEntity {
index cb7ddb01dc5b61e4b61acf1fbb25de507367b7c7..ce3f709a2c352a1ae25ccc8cd832ae22f89c8f8c 100644 (file)
@@ -98,6 +98,9 @@ class ReflectionUtils {
         elseif ($key == 'searchable') {
           $info[$key] = strtolower($words[0]) !== 'false';
         }
+        elseif ($key == 'bridge') {
+          $info[$key] = $words;
+        }
         elseif ($key == 'param' && $words) {
           $type = $words[0][0] !== '$' ? explode('|', array_shift($words)) : NULL;
           $param = rtrim(array_shift($words), '-:()/');
index dd6c2c401a7d7cdbfd04a6ca146f8e85ba019e1b..7de6ac766e4daa34c5bb6be15564b3fefc0750da 100644 (file)
@@ -8,7 +8,7 @@
   <add>5.29</add>
   <log>false</log>
   <icon>fa-handshake-o</icon>
-
+  <title>Related Contact</title>
   <field>
     <name>id</name>
     <type>int unsigned</type>
@@ -89,7 +89,7 @@
   <field>
     <name>near_relation</name>
     <type>varchar</type>
-    <title>Relationship Name (Near side)</title>
+    <title>Relationship Name (to related contact)</title>
     <length>64</length>
     <comment>name for relationship of near_contact to far_contact.</comment>
     <add>5.29</add>
   <field>
     <name>far_relation</name>
     <type>varchar</type>
-    <title>Relationship Name (Near side)</title>
+    <title>Relationship Name (from related contact)</title>
     <length>64</length>
     <comment>name for relationship of far_contact to near_contact.</comment>
     <add>5.29</add>