In one of our recent project I have used CiViCRM with Drupal. I have to build a CRM profile edit page inside Drupal. In past we had created similar functionality in one another project but that was implemented by direct CiViCRM database read/write operation. But in this project I've implement this using the CiViCRM API. I faced some problem and it was taking much time to figure out the right way to do this in some case. So I'm sharing this experience with all hoping that it may save some time if in case you need the same functionality.

How you will read the CRM profile data?

You need to initialize the API first.

<?php if (!civicrm_initialize()) {
         return;
    }
?>

If you don't know the CRM contact ID then you have to get it by the Drupal user ID.

<?php
   
global $user;
   
$params = array(
       
'uf_id' => $user->uid,
       
'version' => 3,
    );
   
$UFMatch = civicrm_api('UFMatch', 'Get', $params);
   
$UFMatch_id = $UFMatch['id'];
   
$contact_id = $UFMatch['values'][$UFMatch_id]['contact_id'];
?>

Now you have the contact ID of CRM profile. So you can call the API to get profile data.

<?php $params = array(
       
'contact_id' => $contact_id,
       
'version' => 3,
    );
   
// Get Contact details for the user.
   
$contact = civicrm_api('contact', 'get', $params);
?>

But you will not get the data/values for custom fields in this way. So you need to call API in a different way to get all the custom values.

<?php $params = array(
       
'version' => 3,
       
'sequential' => 1,
       
'entity_id' => $contact_id,
    );
   
$custom_values = civicrm_api('CustomValue', 'get', $params);
?>

You will get all custom values in this array and can traverse by custom field ID - 1 as array index starts from 0.

<?php $custom_values['values'][0]['latest']; // You will get value for custom_1 field
?>

When you have all the data you can generate your profile update form in Drupal. I am skipping this part.

How to call API to update a CRM profile after the form submission?

Default fields and all simple text custom fields can be updated in one API call.

<?php $params = array(
       
'first_name' => $form_state['values']['first_name'],
       
'last_name' => $form_state['values']['last_name'],
       
'contact_type' => 'Individual',
       
'version' => 3,
       
'job_title' => $form_state['values']['job_title'],
       
'contact_id' => $form_state['values']['contact_id'],
       
'organization_name' => $form_state['values']['organization_name'],
       
'custom_2' => $form_state['values']['language'],
       
'custom_14' => $form_state['values']['professional_publications_1'],
       
'custom_15' => $form_state['values']['professional_publications_2'],
       
'custom_16' => $form_state['values']['professional_publications_3'],
       
'custom_26' => $form_state['values']['years_in_this_position'],
    );
?>

You can update/delete profile picture in the same API call. CiViCRM keeps the path the profile picture in its 'Image_URL' field. So you can just set/unset this field depending on your action.

<?php if ($form_state['values']['picture_delete'] == 1) { // If you just want to remove the existing profile picture
       
if (isset($form_state['values']['old_image_url'])) {
       
$params['image_URL'] = '';
        }
    } else if(isset(
$form_state['values']['picture'])){
       
$params['image_URL'] = $path_to_your_profile_picture;
    }
?>

Finally call the API by passing the above parameter array.

<?php $result = civicrm_api('contact', 'create', $params);
?>

But updating multi select dropdown values or other type of fields are not so simple. So it was time consuming for me to figure it out. We have a multi select list for 'Area of Interest' field. So we have updated this as follows.

<?php $params = array(
       
'id' => $form_state['values']['contact_id'],
       
'entity_id' => $form_state['values']['contact_id'],
       
'custom_3' => $form_state['values']['areas_of_interest'], //Array of the data values
       
'version' => 3,
    );
civicrm_api('CustomValue', 'Create', $params);
?>

Updating address field is also different as it is a group of fields.

<?php $params = array(
       
'version' => 3,
       
'sequential' => 1,
       
'street_address' => $form_state['values']['street_address'],
       
'country_id' => $form_state['values']['country_id'],
       
'contact_id' => $contact_id,
       
'location_type_id' => 1, // It defines which type of address - Home, Billing, Main etc
   
);
    if (
$form_state['values']['address_id'] > 0) {  // If there is a address and need to update , then set ID
       
$params['id'] = $form_state['values']['address_id'];
    }
   
$result = civicrm_api('Address', 'create', $params);
?>

Updating phone fields.

<?php $params = array(
           
'version' => 3,
           
'sequential' => 1,
           
'phone' => $form_state['values']['phone'],
           
'contact_id' => $contact_id,
           
'phone_type_id' => 1,
        );
        if (
$form_state['values']['phone_id'] > 0) {
           
$params['id'] = $form_state['values']['phone_id'];
        }

       

$result = civicrm_api('Phone', 'create', $params);
?>

File is a separate entity so if you have custom file field then you have to create a file entity and then you have to insert that file ID in your custom field value.

<?php $file = $form_state['values']['professional_cv']; // This is file input field
       
$fparams = array(
           
'version' => 3,
           
'sequential' => 1,
           
'uri' => $file->filename,
           
'mime_type' => $file->filemime,
        );   
       
$result = civicrm_api('File', 'create', $fparams);
?>

Now the file Entity has been created. So you have to update the custom field value by the newly created file ID. I couldn't do this using the API so lastly for saving time I did this by direct database query. I will figure out the this when I will get time for this :).

<?php $sql = "UPDATE civicrm_value_individual_member_information_1 SET `professional_cv_8` = '".$result['id']."' WHERE entity_id = ".$contact_id;
       
CRM_Core_DAO::executeQuery($sql);
?>

Hope this may help you in some case. Thank You.

Comments

jilani's picture

Thanks for the nice article... I want to add something here

You can get CiviCRM Contact Id from CiviCRM session, that means you don't need to API call to get the contact id

<?php
    $session
=& CRM_Core_Session::singleton( );
   
$civicrm_contact_id = $session->get( 'userID' ); // this will return civicrm contact id
?>

Add new comment