Uploaded image for project: 'CiviCRM'
  1. CiviCRM
  2. CRM-6163

API will NEVER add custom data to custom fields

    Details

    • Type: Bug
    • Status: Done/Fixed
    • Priority: Major
    • Resolution: Cannot Reproduce
    • Affects Version/s: 3.1.4
    • Fix Version/s: None
    • Component/s: CiviCRM API
    • Labels:
      None

      Description

      Looking at the docs, the original v1 civicrm_contact_add function would add information to custom fields when you created or updated a contact by supplying the field name = value as part of the $params array (ex: $params['mycustomfieldname']='mydata').

      As of at least 3.1.4 (this is my first install and the version I am using) the newer api v2 functions civicrm_contact_create & civivcrm_contact_update as well as the deprecated v1 function civicrm_contact_add will never add custom data to custom fields... so unless of course there is a specific way to format the array with the custom data that you want inserted/updated, then the wiki documentation on how to do it (for civicrm_contact_add) no longer works.

      I am making the assumption (never assume so correct me if I am wrong) that using custom fields from within CiviCRM itself (not the API) is functioning correctly (although I have seen the odd post about issues with custom field data sometimes not saving), and since CiviCRM and the API both use this same code then we cannot modify these underlying functions to 'fix' the api but will probably need to re-write the api itself to use these functions as they have been modified. But anyways I will show you the problem(s) and then perhaps a suggested course of action can put forth!

      Now we have to do some backtracking thru a few functions and files to see the problem...

      Start by looking at /api/v2/Contact.php in the civicrm_contact_update function around line 146 you will see this:
      $customValue = civicrm_contact_check_custom_params( $params, $csType );
      if ( $customValue ) {
      return $customValue;
      }
      _civicrm_custom_format_params( $params, $values, $params['contact_type'], $entityId );

      So lets start by looking at the civicrm_contact_check_custom_params function which is down around line 585 of same file and you will see that it requires CRM/Core/BAO/CustomField.php and then calls the two functions CRM_Core_BAO_CustomField::getFields and CRM_Core_BAO_CustomField::getKeyID

      Looking first at getKeyID function in CRM/Core/BAO/CustomField.php we notice that it using preg_match it appears to look for keys that start with "custom_". Did previous versions of CiviCRM give all custom field names a name that starts with custom?
      Ok let's assume that it actually found match in the preg_match (which I don't think it ever would >this is ISSUE#1) ... the preg_match would put the match into the $match array as $match[0] since $match is empty at this point, but then the return statement tells it to send back $match[1] . So (from the api perspective anyways) $match[1] will ALWAYS be empty even if there was a match (>this is ISSUE#2).

      Ok so now looking at getFields function in CRM/Core/BAO/CustomField.php we see that it will look for custom fields in the database and it returns an array of the form (this example would be if it found only 2 custom fields):
      [0]=>([label]=>'something', [groupTitle]=>'somethingelse', etc..), [1]=>([label]=>'something', [groupTitle]=>'somethingelse', etc..)

      So ISSUE #3 is the fact that in each child array, which contains info about each custom field from the custom_field and custom_group tables, does not actually get the column_name information so there would be no way for it to match on the custom field name of mycustomfield that you supplied in the original $params ($params['mycustomfieldname']='mydata').

      Now go back and look at the civicrm_contact_check_custom_params function in /api/v2/Contact.php at about line 590 it says:
      if ( !array_key_exists($customFieldID, $customFields)) {

      Since the getFields returns an array of the form [$key]=>($childkey=>data) for each custom field ISSUE #4 is that array_key_exists only looks at parent keys and does NOT check sub-arrays for child keys. So if getFields actually got the custom field name (column_name) from the custom_field/group tables (which it does not), then array_key_exists would never find a match anyways because the main $keys that it searches are just numbers from 0 to whatever.

      Now I am not sure if any of the above issues affect anything else in CiviCRM that uses custom fields, but certainly there is now no longer anyway (that I can see) to add information to custom fields thru the api ... civicrm_contact_add is broken (and deprecated) and civicrm_contact_create/_update don't do it either (did they ever?).

      So for now the following code in /api/v2/Contact.php in the civicrm_contact_update function around line 146 is just a waste of time:
      $customValue = civicrm_contact_check_custom_params( $params, $csType );
      if ( $customValue ) {
      return $customValue;
      }
      _civicrm_custom_format_params( $params, $values, $params['contact_type'], $entityId );

        Attachments

          Activity

            People

            • Assignee:
              lobo Donald A. Lobo
              Reporter:
              jsherk jsherk (Inactive)
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: