CiviCRM Entity - Customizing and Adding Entity Types

CiviCRM Entity is a Drupal module that exposed CiviCRM API entities and actions as Drupal entity types. By installing the module over 40 CiviCRM entities are exposed to Drupal.  This is great, but not all API entities are exposed by this module yet, and often developers write their own custom APIs.  There are also times when you may want to customize the settings for how CiviCRM Entity integrates the API with Drupal. CiviCRM Entity is extendable, and by implementing one hook, you easily expose other API entities or alter the settings for already exposed entities.  In this blog article we will show you how to do this in detail.

CiviCRM Entity ships with an civicrm_entity.api.php file documenting this hook.  The hook is hook_civicrm_entity_supported_info(), but despite its name, this hook acts like a standard Drupal _alter() hook.

You can set or alter:

  • The name of the API entity
  • The property of the entity that is used for the entity label
  • Specifiy the permissions that are necessary to view, edit, create, or delete an entity via the Drupal native forms
  • Specifiy a callback function to use to determine user access for the various operations
  • Specify a theme template file to use for rendering the page view of the entity
  • Set some metadata for Display Suite formatters for properties

All the settings for all the currently exposed entities for examples of the settings are in the function civicrm_entity_supported_entities_info().

Altering Exposed Entity Settings

It is probable that the most common case for altering the settings of an entity type exposed out of the box will be setting permissions necessary to access the view page, and the add/edit/delete forms. We have used this setting alteration to allow users to add or edit events, that have no access to the CiviCRM backend. Lets say you have a user role, "Editor", and this role is permissioned to edit and create Drupal content. We want to allow these users who have 'Administer content' permission, and no CiviCRM permissions, to add and edit CiviCRM Events. By default this would normally require the 'Edit all Events' permission.

So we just implement a hook in a custom module, in this case my module name is civicrm_custom

function civicrm_custom_civicrm_entity_supported_info(&$civicrm_entity_info) {
  $civicrm_entity_info['civicrm_event']['permissions']['edit'] = array('administer nodes');
  $civicrm_entity_info['civicrm_event']['permissions']['update'] = array('administer nodes');
  $civicrm_entity_info['civicrm_event']['permissions']['create'] = array('administer nodes');
}

Each item of the permissions array accepts an array of permission machine names, so you can specifiy multiple permissions that are necessary to use the forms. Note that if you remove or don't set a permission for an operation, and dont' specifiy a callback then CiviCRM Entity defaults to 'administer CiviCRM' permission necessary to access.

It works great with a callback function too, so we can do it like this:

/**
 * Implements hook_civicrm_entity_supported_info().
 */
function civicrm_custom_civicrm_entity_supported_info(&$civicrm_entity_info) {
  $civicrm_entity_info['civicrm_event']['permissions']['access callback'] = 'civicrm_custom_my_event_access_handler';
}
 
/**
 * @param $op
 * the operation access is requested for
 * @param $entity_type
 * The entity type
 * @param $entity
 * the entity object
 * @param $account
 * The user object of the user requesting access
 * @param $permission
 * The array of permissions that is set via the supported info metadata (would include any updates from hook_civicrm_entity_supported_info())
 */
function civicrm_custom_my_event_access_handler($op, $entity_type, $entity, $account, $permissions) {
  // if $op is view, check if the user has 'view event info' permissions
  if($op == 'view') {
    return user_access('view event info', $account);
  }
  // For all other ops, check for the role with rid 4 (editor) or 3 (administrator)
  else {
    return (user_has_role(4, $account) || user_has_role(3, $account));
  }
}

Exposing a new API entity

We have developed an API extension for Counties for deployment with some of our CiviCRM 4.6 sites. We have had cause to use the Drupal Entity API with this, and for using the Entity Reference field type to reference counties. Below is a sample hook implemenation for integrating the County API as a Drupal entity type.

/**
 * Implements hook_civicrm_entity_supported_info().
 */
function civicrm_custom_civicrm_entity_supported_info(&$civicrm_entity_info) {
  // 'civicrm_county' is the table where the counties are stored
  $civicrm_entity_info['civicrm_county'] = array(
    'civicrm entity name' => 'county', // the api entity name
    'label property' => 'name', // name is the property we want to use for the entity label
    'permissions' => array(
      'view' => array('view all contacts'),
      'edit' => array('edit all contacts'),
      'update' => array('edit all contacts'),
      'create' => array('edit all contacts'),
      'delete' => array('delete contacts'),
    ),
  );
}

I hope you can see that altering the exposure settings for the current entity types, and adding exposure for custom API entites is pretty easy, and there are some powerful options for permissions with Drupal based forms. 

Enjoy creating your CiviCRM API integrations!

Tags: