Add contact type to schema to allow GetFields filtering
authorColeman Watts <coleman@civicrm.org>
Sun, 29 Dec 2019 02:17:12 +0000 (21:17 -0500)
committerColeman Watts <coleman@civicrm.org>
Mon, 30 Dec 2019 02:58:18 +0000 (21:58 -0500)
CRM/Contact/DAO/Contact.php
CRM/Core/CodeGen/Specification.php
Civi/Api4/Service/Spec/Provider/ContactCreationSpecProvider.php
Civi/Api4/Service/Spec/SpecGatherer.php
tests/phpunit/api/v4/Action/GetExtraFieldsTest.php
xml/schema/Contact/Contact.xml
xml/templates/dao.tpl

index 3c14834a791def875d13779030264536a0b22c2d..99405af76c360a4f6485ce5a69667a1e4ec3740b 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Contact/Contact.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:b72765d873639076299753a8c4e676d5)
+ * (GenCodeChecksum:773bf2fc16c1af3c283f6ecc7098e927)
  */
 
 /**
@@ -434,6 +434,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'size' => CRM_Utils_Type::BIG,
           'where' => 'civicrm_contact.contact_type',
           'export' => TRUE,
+          'contactType' => NULL,
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -847,6 +848,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'headerPattern' => '/^first|(f(irst\s)?name)$/i',
           'dataPattern' => '/^\w+$/',
           'export' => TRUE,
+          'contactType' => 'Individual',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -867,6 +869,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'headerPattern' => '/^middle|(m(iddle\s)?name)$/i',
           'dataPattern' => '/^\w+$/',
           'export' => TRUE,
+          'contactType' => 'Individual',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -887,6 +890,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'headerPattern' => '/^last|(l(ast\s)?name)$/i',
           'dataPattern' => '/^\w+(\s\w+)?+$/',
           'export' => TRUE,
+          'contactType' => 'Individual',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -905,6 +909,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'headerPattern' => '/^(prefix|title)/i',
           'dataPattern' => '/^(mr|ms|mrs|sir|dr)\.?$/i',
           'export' => TRUE,
+          'contactType' => 'Individual',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -927,6 +932,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'headerPattern' => '/^suffix$/i',
           'dataPattern' => '/^(sr|jr)\.?|i{2,}$/',
           'export' => TRUE,
+          'contactType' => 'Individual',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -950,6 +956,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'where' => 'civicrm_contact.formal_title',
           'headerPattern' => '/^title/i',
           'export' => TRUE,
+          'contactType' => 'Individual',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -1141,6 +1148,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'headerPattern' => '/^job|(j(ob\s)?title)$/i',
           'dataPattern' => '//',
           'export' => TRUE,
+          'contactType' => 'Individual',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -1158,6 +1166,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'where' => 'civicrm_contact.gender_id',
           'headerPattern' => '/^gender$/i',
           'export' => TRUE,
+          'contactType' => 'Individual',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -1180,6 +1189,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'headerPattern' => '/^birth|(b(irth\s)?date)|D(\W*)O(\W*)B(\W*)$/i',
           'dataPattern' => '/\d{4}-?\d{2}-?\d{2}/',
           'export' => TRUE,
+          'contactType' => 'Individual',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -1197,6 +1207,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'where' => 'civicrm_contact.is_deceased',
           'headerPattern' => '/i(s\s)?d(eceased)$/i',
           'export' => TRUE,
+          'contactType' => 'Individual',
           'default' => '0',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
@@ -1215,6 +1226,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'where' => 'civicrm_contact.deceased_date',
           'headerPattern' => '/^deceased|(d(eceased\s)?date)$/i',
           'export' => TRUE,
+          'contactType' => 'Individual',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -1236,6 +1248,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'headerPattern' => '/^household|(h(ousehold\s)?name)$/i',
           'dataPattern' => '/^\w+$/',
           'export' => TRUE,
+          'contactType' => 'Household',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -1250,6 +1263,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'title' => ts('Household Primary Contact ID'),
           'description' => ts('Optional FK to Primary Contact for this household.'),
           'where' => 'civicrm_contact.primary_contact_id',
+          'contactType' => 'Household',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -1268,6 +1282,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'headerPattern' => '/^organization|(o(rganization\s)?name)$/i',
           'dataPattern' => '/^\w+$/',
           'export' => TRUE,
+          'contactType' => 'Organization',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -1287,6 +1302,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'where' => 'civicrm_contact.sic_code',
           'headerPattern' => '/^sic|(s(ic\s)?code)$/i',
           'export' => TRUE,
+          'contactType' => 'Organization',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
@@ -1323,6 +1339,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO {
           'description' => ts('OPTIONAL FK to civicrm_contact record.'),
           'where' => 'civicrm_contact.employer_id',
           'export' => TRUE,
+          'contactType' => 'Individual',
           'table_name' => 'civicrm_contact',
           'entity' => 'Contact',
           'bao' => 'CRM_Contact_BAO_Contact',
index 17bfc45a5571a95fd14dacc9e83c4ce0b46bdb22..5ee9bb2025a874820291dca3a28246e7f73f6c04 100644 (file)
@@ -371,6 +371,7 @@ class CRM_Core_CodeGen_Specification {
     $field['uniqueTitle'] = $this->value('uniqueTitle', $fieldXML);
     $field['serialize'] = $this->value('serialize', $fieldXML);
     $field['html'] = $this->value('html', $fieldXML);
+    $field['contactType'] = $this->value('contactType', $fieldXML);
     if (isset($fieldXML->permission)) {
       $field['permission'] = trim($this->value('permission', $fieldXML));
       $field['permission'] = $field['permission'] ? array_filter(array_map('trim', explode(',', $field['permission']))) : [];
index 4810d03d0582da6c0246c64b3dff5a9a9268a2a1..1f77f16d2dc0a1202954a943455ad9c096842ab3 100644 (file)
@@ -29,8 +29,10 @@ class ContactCreationSpecProvider implements Generic\SpecProviderInterface {
    * @param \Civi\Api4\Service\Spec\RequestSpec $spec
    */
   public function modifySpec(RequestSpec $spec) {
-    $spec->getFieldByName('contact_type')
-      ->setDefaultValue('Individual');
+    $contactTypeField = $spec->getFieldByName('contact_type');
+    if ($contactTypeField) {
+      $contactTypeField->setDefaultValue('Individual');
+    }
 
     $spec->getFieldByName('is_opt_out')->setRequired(FALSE);
     $spec->getFieldByName('is_deleted')->setRequired(FALSE);
index d10c95ecf1cb2d8e69559cb33df95da3ba3d8859..0edb4e8c6a5885ac25396e756b2aa7d02d672586 100644 (file)
@@ -56,7 +56,7 @@ class SpecGatherer {
 
     // Real entities
     if (strpos($entity, 'Custom_') !== 0) {
-      $this->addDAOFields($entity, $action, $specification);
+      $this->addDAOFields($entity, $action, $specification, $values);
       if ($includeCustom && array_key_exists($entity, \CRM_Core_SelectValues::customGroupExtends())) {
         $this->addCustomFields($entity, $specification, $values);
       }
@@ -93,14 +93,18 @@ class SpecGatherer {
    * @param string $entity
    * @param string $action
    * @param \Civi\Api4\Service\Spec\RequestSpec $specification
+   * @param array $values
    */
-  private function addDAOFields($entity, $action, RequestSpec $specification) {
+  private function addDAOFields($entity, $action, RequestSpec $specification, $values = []) {
     $DAOFields = $this->getDAOFields($entity);
 
     foreach ($DAOFields as $DAOField) {
       if ($DAOField['name'] == 'id' && $action == 'create') {
         continue;
       }
+      if (array_key_exists('contactType', $DAOField) && !empty($values['contact_type']) && $DAOField['contactType'] != $values['contact_type']) {
+        continue;
+      }
       if ($action !== 'create' || isset($DAOField['default'])) {
         $DAOField['required'] = FALSE;
       }
index adab653b86a3ae94ff2b0611cfef3317336ab7d5..60126b16de6b44ce767b834d5f19852919f6d744 100644 (file)
@@ -29,17 +29,26 @@ use Civi\Api4\Contact;
  */
 class GetExtraFieldsTest extends UnitTestCase {
 
-  public function testBAOFieldsWillBeReturned() {
-    $returnedFields = Contact::getFields()
-      ->execute()
-      ->getArrayCopy();
+  public function testGetFieldsByContactType() {
+    $getFields = Contact::getFields()->setCheckPermissions(FALSE)->addSelect('name')->setIncludeCustom(FALSE);
 
-    $baseFields = \CRM_Contact_BAO_Contact::fields();
-    $baseFieldNames = array_column($baseFields, 'name');
-    $returnedFieldNames = array_column($returnedFields, 'name');
-    $notReturned = array_diff($baseFieldNames, $returnedFieldNames);
+    $baseFields = array_column(\CRM_Contact_BAO_Contact::fields(), 'name');
+    $returnedFields = $getFields->execute()->column('name');
+    $notReturned = array_diff($baseFields, $returnedFields);
 
+    // With no contact_type specified, all fields should be returned
     $this->assertEmpty($notReturned);
+
+    $individualFields = $getFields->setValues(['contact_type' => 'Individual'])->execute()->column('name');
+    $this->assertNotContains('sic_code', $individualFields);
+    $this->assertNotContains('contact_type', $individualFields);
+    $this->assertContains('first_name', $individualFields);
+
+    $organizationFields = $getFields->setValues(['contact_type' => 'Organization'])->execute()->column('name');
+    $this->assertContains('sic_code', $organizationFields);
+    $this->assertNotContains('contact_type', $organizationFields);
+    $this->assertNotContains('first_name', $organizationFields);
+    $this->assertNotContains('household_name', $organizationFields);
   }
 
 }
index 7facb329ca523a274ade049479c90615043d2030..262358eaf1c91d046e68cde06deb0f114e8a0ca2 100644 (file)
@@ -39,6 +39,7 @@
     </html>
     <add>1.1</add>
     <change>3.1</change>
+    <contactType>null</contactType>
   </field>
   <index>
     <name>index_contact_type</name>
     <fulltext/>
     <comment>First Name.</comment>
     <add>1.1</add>
+    <contactType>Individual</contactType>
   </field>
   <index>
     <name>index_first_name</name>
     <fulltext/>
     <comment>Middle Name.</comment>
     <add>1.1</add>
+    <contactType>Individual</contactType>
   </field>
   <field>
     <name>last_name</name>
     <comment>Last Name.</comment>
     <fulltext/>
     <add>1.1</add>
+    <contactType>Individual</contactType>
   </field>
   <index>
     <name>index_last_name</name>
     <dataPattern>/^(mr|ms|mrs|sir|dr)\.?$/i</dataPattern>
     <import>true</import>
     <add>1.2</add>
+    <contactType>Individual</contactType>
   </field>
   <index>
     <name>UI_prefix</name>
     <headerPattern>/^suffix$/i</headerPattern>
     <dataPattern>/^(sr|jr)\.?|i{2,}$/</dataPattern>
     <add>1.2</add>
+    <contactType>Individual</contactType>
   </field>
   <index>
     <name>UI_suffix</name>
     <headerPattern>/^title/i</headerPattern>
     <comment>Formal (academic or similar) title in front of name. (Prof., Dr. etc.)</comment>
     <add>4.5</add>
+    <contactType>Individual</contactType>
   </field>
   <field>
     <name>communication_style_id</name>
     <dataPattern>//</dataPattern>
     <comment>Job Title</comment>
     <add>1.1</add>
+    <contactType>Individual</contactType>
   </field>
   <field>
     <name>gender_id</name>
     <comment>FK to gender ID</comment>
     <import>true</import>
     <add>1.2</add>
+    <contactType>Individual</contactType>
   </field>
   <index>
     <name>UI_gender</name>
       <type>Select Date</type>
       <formatType>birth</formatType>
     </html>
+    <contactType>Individual</contactType>
   </field>
   <field>
     <name>is_deceased</name>
     <html>
       <type>CheckBox</type>
     </html>
+    <contactType>Individual</contactType>
   </field>
   <index>
     <name>index_is_deceased</name>
       <type>Select Date</type>
       <formatType>birth</formatType>
     </html>
+    <contactType>Individual</contactType>
   </field>
   <field>
     <name>mail_to_household_id</name>
     <comment>Household Name.</comment>
     <fulltext/>
     <add>1.1</add>
+    <contactType>Household</contactType>
   </field>
   <index>
     <name>index_household_name</name>
     <title>Household Primary Contact ID</title>
     <comment>Optional FK to Primary Contact for this household.</comment>
     <add>1.1</add>
+    <contactType>Household</contactType>
   </field>
   <foreignKey>
     <name>primary_contact_id</name>
     <comment>Organization Name.</comment>
     <fulltext/>
     <add>1.1</add>
+    <contactType>Organization</contactType>
   </field>
   <index>
     <name>index_organization_name</name>
     <html>
       <type>Text</type>
     </html>
+    <contactType>Organization</contactType>
   </field>
   <field>
     <name>user_unique_id</name>
     <html>
       <type>EntityRef</type>
     </html>
+    <contactType>Individual</contactType>
   </field>
   <foreignKey>
     <name>employer_id</name>
index 6718b8541fdf8585ed84ace6e46328d3d2c51977..ac6b477ec3f292522942041013e0c9beea0d4d62 100644 (file)
@@ -124,7 +124,9 @@ class {$table.className} extends CRM_Core_DAO {ldelim}
 {if $field.export}
                       'export'    => {$field.export|strtoupper},
 {/if} {* field.export *}
-
+{if $field.contactType}
+                      'contactType' => {if $field.contactType == 'null'}NULL{else}'{$field.contactType}'{/if},
+{/if}
 {if $field.rule}
                       'rule'      => '{$field.rule}',
 {/if} {* field.rule *}