CRM-13234 make profile api getfields complete for all built-in profiles
authoreileen <eileen@fuzion.co.nz>
Tue, 20 Aug 2013 12:17:14 +0000 (00:17 +1200)
committereileen <eileen@fuzion.co.nz>
Tue, 20 Aug 2013 12:17:14 +0000 (00:17 +1200)
Note that this fn has a lot of inconsistency to adjust for & this will require tweaking over time - however this is an new fn  / extension to the api so doesn't affect existing

api/v3/Profile.php
tests/phpunit/api/v3/ProfileTest.php

index 16c1b2aecea88b21b6a7891d7fd31be90fa4e3a0..70fb0297898679b63df26375b7208610fcb62ab7 100644 (file)
@@ -468,23 +468,32 @@ function _civicrm_api3_buildprofile_submitfields($profileID, $optionsBehaviour =
 
     $realFieldName = $field['field_name'];
     //see function notes
+    // as we build up a list of these we should be able to determine a generic approach
+    //
     $hardCodedEntityFields = array(
       'state_province' => 'state_province_id',
       'country' => 'country_id',
       'participant_status' => 'status_id',
       'gender' => 'gender_id',
+      'financial_type' => 'financial_type_id',
+      'soft_credit' => 'soft_credit_to',
+      'group' => 'group_id',
+      'tag' => 'tag_id',
     );
+
     if(array_key_exists($realFieldName, $hardCodedEntityFields)) {
       $realFieldName = $hardCodedEntityFields[$realFieldName];
     }
+
     $entities[$entity][$fieldName] = $realFieldName;
   }
 
   foreach ($entities as $entity => $entityFields) {
     $result = civicrm_api3($entity, 'getfields', array('action' => 'create'));
+    $entityGetFieldsResult = _civicrm_api3_profile_appendaliases($result['values'], $entity);
     foreach ($entityFields as $entityfield => $realName) {
-      $profileFields[$profileID][$entityfield] = $result['values'][$realName];
-      if($optionsBehaviour && !empty($result['values'][$realName]['pseudoconstant'])) {
+      $profileFields[$profileID][$entityfield] = $entityGetFieldsResult[$realName];
+      if($optionsBehaviour && !empty($entityGetFieldsResult[$realName]['pseudoconstant'])) {
         if($optionsBehaviour > 1  || !in_array($realName, array('state_province_id', 'county_id', 'country_id'))) {
           $options = civicrm_api3($entity, 'getoptions', array('field' => $realName));
           $profileFields[$profileID][$entityfield]['options'] = $options['values'];
@@ -527,8 +536,11 @@ function _civicrm_api3_map_profile_fields_to_entity(&$field) {
     $fieldName .= '-' . $field['location_type_id'];
     $entity = 'Phone';
   }
+  // @todo - sort this out!
   //here we do a hard-code list of known fields that don't map to where they are mapped to
-  // not a great solution but probably if we looked in the BAO we'd find a scary switch
+  // not a great solution but probably if we looked in the BAO we'd find a scary switch statement
+  // in a perfect world the uf_field table would hold the correct entity for each item
+  // & only the relationships between entities would need to be coded
   $hardCodedEntityMappings = array(
     'street_address' => 'Address',
     'street_number' => 'Address',
@@ -541,6 +553,18 @@ function _civicrm_api3_map_profile_fields_to_entity(&$field) {
     'state_province' => 'Address',
     'country' => 'Address',
     'county' => 'Address',
+    //note that in discussions about how to restructure the api we discussed making these membership
+    // fields into 'membership_payment' fields - which would entail declaring them in getfields
+    // & renaming them in existing profiles
+    'financial_type' => 'Contribution',
+    'total_amount' => 'Contribution',
+    'receive_date' => 'Contribution',
+    'payment_instrument' => 'Contribution',
+    'check_number' => 'Contribution',
+    'contribution_status_id' => 'Contribution',
+    'soft_credit' => 'Contribution',
+    'group' => 'GroupContact',
+    'tag' => 'EntityTag',
    );
   if(array_key_exists($fieldName, $hardCodedEntityMappings)) {
     $entity = $hardCodedEntityMappings[$fieldName];
@@ -557,4 +581,30 @@ function _civicrm_api3_profile_getProfileID($profileID) {
     $profileID = civicrm_api3('uf_group', 'getvalue', array('return' => 'id', 'name' => $profileID));
   }
   return $profileID;
+}
+
+/**
+ * helper function to add all aliases as keys to getfields response so we can look for keys within it
+ * since the relationship between profile fields & api / metadata based fields is a bit inconsistent
+ * @param array $values
+ *
+ * e.g getfields response incl 'membership_type_id' - with api.aliases = 'membership_type'
+ * returned array will include both as keys (with the same values)
+ */
+function _civicrm_api3_profile_appendaliases($values, $entity) {
+  foreach ($values as $field => $spec) {
+    if(!empty($spec['api.aliases'])) {
+      foreach ($spec['api.aliases'] as $alias) {
+        $values[$alias] = $spec;
+      }
+    }
+    if(!empty($spec['uniqueName'])) {
+      $values[$spec['uniqueName']] = $spec;
+    }
+  }
+  //special case on membership & contribution - can't see how to handle in a generic way
+  if(in_array($entity, array('Membership', 'Contribution'))) {
+    $values['send_receipt'] = array('title' => 'Send Receipt', 'type' => 16);
+  }
+  return $values;
 }
\ No newline at end of file
index 61f3ef99b18fd63882ca531b9e0f9725fc382359..01d9fb179f47857b026350a1b3a56eb97fe423bc 100644 (file)
@@ -287,7 +287,7 @@ class api_v3_ProfileTest extends CiviUnitTestCase {
     $this->assertFalse(array_key_exists('participant_status', $result['values']));
   }
   /**
-   * Check getfields works & gives us our fields
+   * Check getfields works & gives us our fields - partipant profile
    */
   function testGetFieldsParticipantProfile() {
     $result = $this->callAPISuccess('profile', 'getfields', array(
@@ -298,6 +298,36 @@ class api_v3_ProfileTest extends CiviUnitTestCase {
     $this->assertTrue(array_key_exists('participant_status', $result['values']));
     $this->assertEquals('Attended', $result['values']['participant_status']['options'][2]);
   }
+
+  /**
+   * Check getfields works & gives us our fields - membership_batch_entry
+   * (getting to the end with no e-notices is pretty good evidence it's working)
+   */
+  function testGetFieldsMembershipBatchProfile() {
+    $result = $this->callAPISuccess('profile', 'getfields', array(
+      'action' => 'submit',
+      'profile_id' => 'membership_batch_entry',
+      'get_options' => 'all')
+    );
+    $this->assertTrue(array_key_exists('total_amount', $result['values']));
+    $this->assertEquals(12, $result['values']['receive_date']['type']);
+  }
+
+  /**
+   * Check getfields works & gives us our fields - do them all
+   * (getting to the end with no e-notices is pretty good evidence it's working)
+   */
+  function testGetFieldsAllProfiles() {
+    $result = $this->callAPISuccess('uf_group', 'get', array('return' => 'id'));
+    $profileIDs = array_keys($result['values']);
+    foreach ($profileIDs as $profileID) {
+    $result = $this->callAPISuccess('profile', 'getfields', array(
+      'action' => 'submit',
+      'profile_id' => $profileID,
+      'get_options' => 'all')
+    );
+    }
+  }
   /////////////// test $this->callAPISuccess3_profile_set //////////////////
 
   /**