You are here

civicrm_entity_reference_field.module in CiviCRM Entity 7.2

Provide CiviCRM entity reference field type

File

modules/civicrm_entity_reference_field/civicrm_entity_reference_field.module
View source
<?php

/**
 * @file
 * Provide CiviCRM entity reference field type
 */

/**
 * Implements hook_field_info().
 *
 * @return array
 */
function civicrm_entity_reference_field_field_info() {
  return array(
    'civicrm_entity_reference' => array(
      'label' => t('CiviCRM Entity Reference'),
      'description' => t('This field references CiviCRM entities by querying configured entity by a column name from a value on the host entity.'),
      'settings' => array(
        'target_entity_type' => 'address',
        'target_id_column' => 'contact_id',
        'host_source_id' => 'id',
      ),
      'instance_settings' => array(),
      'default_widget' => 'civicrm_entity_reference_default_widget',
      'default_formatter' => 'civicrm_entity_reference_default_formatter',
    ),
  );
}

/**
 * Implements hook_form_FORMID_alter().
 *
 * form id : field_ui_field_edit_form
 *
 * Alter Field Settings form to set cardinality to Unlimited, and disable the select widget
 *
 * Check the "delete reference" inline entity form option if that is the widget
 *
 * @param $form
 * @param $form_state
 */
function civicrm_entity_reference_field_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
  if ($form['#field']['type'] == 'civicrm_entity_reference') {

    // field settings mods
    // Commenting our for now, for cases like location block on events, there is only one value, maybe it doesn't make sense to force 'Unlimited'

    //$form['field']['cardinality']['#default_value'] = -1;

    //$form['field']['cardinality']['#disabled'] = TRUE;
    if ($form['instance']['widget']['type']['#value'] == 'inline_entity_form_single' || $form['instance']['widget']['type']['#value'] == 'inline_entity_form') {

      // Its going to delete the referenced entity so we just set this value to 1 and disable the checkbox to avoid confusion
      // UPDATE: OR not? Cases like Events that have location blocks, don't need to delete the location block when deleting the event?

      //$form['instance']['widget']['settings']['type_settings']['delete_references']['#default_value'] = 1;

      //$form['instance']['widget']['settings']['type_settings']['delete_references']['#disabled'] = TRUE;

      // Does it make sense to have the "add existing entities?" functionality, disabling it for now
      if (isset($form['instance']['widget']['settings']['type_settings']['allow_existing'])) {
        $form['instance']['widget']['settings']['type_settings']['allow_existing']['#default_value'] = 0;
        $form['instance']['widget']['settings']['type_settings']['allow_existing']['#disabled'] = TRUE;
      }
    }
  }
}

/**
 * Implements hook_form_FORMID_alter().
 *
 * form id : field_ui_field_overview_form
 *
 * Only allow creation of civicrm_entity_reference field  for civicrm entities
 *
 * @param $form
 * @param $form_state
 */
function civicrm_entity_reference_field_form_field_ui_field_overview_form_alter(&$form, &$form_state) {
  $civicrm_entities = array_keys(_civicrm_entity_enabled_entities());
  if (!in_array($form['#entity_type'], $civicrm_entities)) {
    unset($form['fields']['_add_new_field']['type']['#options']['civicrm_entity_reference']);
    foreach ($form['fields']['_add_existing_field']['field_name']['#options'] as $field_name => $description) {
      if (strpos($description, 'CiviCRM Entity Reference:') !== FALSE) {
        unset($form['fields']['_add_existing_field']['field_name']['#options'][$field_name]);
      }
    }
  }
}

/**
 * Implements hook_field_settings_form().
 *
 * @param $field
 * @param $instance
 * @param $has_data
 */
function civicrm_entity_reference_field_field_settings_form($field, $instance, $has_data) {
  $defaults = field_info_field_settings($field['type']);
  $settings = array_merge($defaults, $field['settings']);
  $host_entity_type = $instance['entity_type'];
  $civicrm_entities = _civicrm_entity_enabled_entities();
  $entities = array();
  foreach ($civicrm_entities as $drupal_name => $civicrm_name) {
    $entities[$civicrm_name] = ucwords(str_replace('_', ' ', $civicrm_name));
  }
  $form['target_entity_type'] = array(
    '#type' => 'select',
    '#title' => t('Target Entity Type'),
    '#default_value' => $settings['target_entity_type'],
    '#description' => t('Target entity type for this reference field.'),
    '#options' => $entities,
    '#ajax' => array(
      'event' => 'change',
      'wrapper' => 'target-id-column-wrapper',
      'callback' => 'civicrm_entity_reference_field_target_entity_type_ajax_callback',
      'method' => 'replace',
    ),
  );
  $target_id_column_options = _civicrm_entity_reference_field_get_target_id_column_options($settings['target_entity_type']);
  $form['target_id_column'] = array(
    '#type' => 'select',
    '#title' => t('Target ID Join Column'),
    '#default_value' => $settings['target_id_column'],
    '#description' => t('The column of the targeted entity type to use to query against'),
    '#options' => $target_id_column_options,
    '#prefix' => '<div id="target-id-column-wrapper">',
    '#suffix' => '</div>',
    '#validated' => TRUE,
  );
  $form['host_source_id'] = array(
    '#type' => 'select',
    '#title' => t('Host Source Column'),
    '#default_value' => $settings['host_source_id'],
    '#description' => t('Host Entity property which value is used query target entity table.'),
    // want to automate choices for this setting in the future
    '#options' => array(
      'id' => 'ID',
      'loc_block_id' => 'Location Block ID (CiviCRM Event Entity)',
      'address_id' => 'Address ID (Location Block Entity)',
      'email_id' => 'Email ID (Location Block Entity)',
      'phone_id' => 'Phone ID (Location Block Entity)',
      'im_id' => 'Instant Messaging ID (Location Block Entity)',
      'uf_group_id' => 'UFGroup ID (UFJoin Entity)',
      'contact_id' => 'Contact ID (Grant Entity)',
    ),
  );
  return $form;
}

/**
 * Ajax callback for the field settings Target Entity Type select field change
 *
 * Update Target ID Join Column options
 *
 * @param $form
 * @param $form_state
 * @return mixed
 */
function civicrm_entity_reference_field_target_entity_type_ajax_callback(&$form, &$form_state) {
  $entity_type = $form_state['values']['field']['settings']['target_entity_type'];
  $target_id_column_options = _civicrm_entity_reference_field_get_target_id_column_options($entity_type);
  $form['field']['settings']['target_id_column']['#options'] = $target_id_column_options;
  $form['field']['settings']['target_id_column']['#default_value'] = 'id';
  return $form['field']['settings']['target_id_column'];
}

/**
 * @param $entity_type
 * @return array
 */
function _civicrm_entity_reference_field_get_target_id_column_options($entity_type) {
  $options = array();
  if (!civicrm_initialize()) {
    return;
  }
  $result = civicrm_api3($entity_type, 'getfields', array(
    'api_action' => "create",
  ));
  foreach ($result['values'] as $prop => $data) {
    if (strpos($prop, 'id') !== FALSE) {
      $options[$prop] = $data['title'];
    }
  }
  return $options;
}

/**
 * Implements hook_field_load().
 *
 * @param $entity_type
 * @param $entities
 * @param $field
 * @param $instances
 * @param $langcode
 * @param $items
 * @param $age
 */
function civicrm_entity_reference_field_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
  if (!civicrm_initialize()) {
    return;
  }
  foreach ($entities as $id => $entity) {
    if (!empty($entity->{$field['settings']['host_source_id']})) {
      try {
        $params = array(
          $field['settings']['target_id_column'] => $entity->{$field['settings']['host_source_id']},
        );
        $is_primary_entities = array(
          'address',
          'phone',
          'email',
          'im',
        );
        if (in_array($field['settings']['target_entity_type'], $is_primary_entities)) {
          $params['options'] = array(
            'sort' => 'is_primary DESC',
          );
        }
        $result = civicrm_api3($field['settings']['target_entity_type'], 'get', $params);
      } catch (CiviCRM_API3_Exception $e) {
        $error = $e
          ->getMessage();
        drupal_set_message($error, 'error');
        continue;
      }
      if ($result['count']) {
        $delta = 0;
        foreach ($result['values'] as $target_id => $data) {
          $items[$id][$delta]['target_id'] = $target_id;
          $delta += 1;
        }
      }
    }
  }
}

/**
 * Implements hook_field_insert().
 *
 * @param $entity_type
 * @param $entity
 * @param $field
 * @param $instance
 * @param $langcode
 * @param $items
 */
function civicrm_entity_reference_field_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
  foreach ($items as $delta => $item) {
    unset($items[$delta]);
  }
}

/**
 * Implements hook_field_update().
 *
 * @param $entity_type
 * @param $entity
 * @param $field
 * @param $instance
 * @param $langcode
 * @param $items
 */
function civicrm_entity_reference_field_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) {
  foreach ($items as $delta => $item) {
    unset($items[$delta]);
  }
}

/**
 * Implements hook_field_widget_info().
 */
function civicrm_entity_reference_field_field_widget_info() {
  return array(
    'civicrm_entity_reference_default_widget' => array(
      'label' => t('CiviCRM Entity Reference Default Widget'),
      'field types' => array(
        'civicrm_entity_reference',
      ),
      'settings' => array(),
      'behaviors' => array(
        'multiple values' => FIELD_BEHAVIOR_DEFAULT,
        'default value' => FIELD_BEHAVIOR_DEFAULT,
      ),
    ),
  );
}

/**
 * Implements hook_field_widget_info_alter().
 *
 * @param $info
 */
function civicrm_entity_reference_field_field_widget_info_alter(&$info) {
  $info['inline_entity_form']['field types'][] = 'civicrm_entity_reference';
  $info['inline_entity_form_single']['field types'][] = 'civicrm_entity_reference';
}

/**
 * Implements hook_inline_entity_form_settings_alter().
 *
 * @param $settings
 * @param $field
 * @param $instance
 */
function civicrm_entity_reference_field_inline_entity_form_settings_alter(&$settings, $field, $instance) {
  if ($field['type'] == 'civicrm_entity_reference') {
    $settings['entity_type'] = 'civicrm_' . $field['settings']['target_entity_type'];
    $settings['column'] = 'target_id';
    $settings['bundles'] = array(
      'civicrm_' . $field['settings']['target_entity_type'],
    );
  }
}

/**
 * Implements hook_field_is_empty().
 *
 * @param $item
 * @param $field
 * @return bool
 */
function civicrm_entity_reference_field_field_is_empty($item, $field) {
  if (!isset($item['target_id']) || !is_numeric($item['target_id'])) {
    return TRUE;
  }
  return FALSE;
}

/**
 * Implements hook_field_widget_form().
 */
function civicrm_entity_reference_field_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  $orig_element = $element;
  switch ($instance['widget']['type']) {
    case 'civicrm_entity_reference_default_widget':
      $widget = array();
      $widget = $orig_element + array(
        '#type' => 'textfield',
        '#default_value' => isset($items[$delta]['target_id']) ? $items[$delta]['target_id'] : NULL,
      );
      $widget['#title'] = t('Target ID');
      $widget['#weight'] = 0;
      $element['target_id'] = $widget;
      break;
  }
  return $element;
}

/**
 * Implements hook_field_formatter_info().
 */
function civicrm_entity_reference_field_field_formatter_info() {
  return array(
    'civicrm_entity_reference_default_formatter' => array(
      // Machine name of the formatter
      'label' => t('Referenced ID'),
      'field types' => array(
        'civicrm_entity_reference',
      ),
      'settings' => array(),
    ),
    'civicrm_entity_reference_entity_label_formatter' => array(
      // Machine name of the formatter
      'label' => t('Label'),
      'field types' => array(
        'civicrm_entity_reference',
      ),
      'settings' => array(
        // Array of the settings we'll create
        'link_to_entity' => 0,
      ),
    ),
    'civicrm_entity_reference_entity_formatter' => array(
      // Machine name of the formatter
      'label' => t('Rendered Entity'),
      'field types' => array(
        'civicrm_entity_reference',
      ),
      'settings' => array(
        // Array of the settings we'll create
        'view_mode' => 'default',
      ),
    ),
  );
}

/**
 * Implements hook_field_formatter_settings_form().
 *
 * @param $field
 * @param $instance
 * @param $view_mode
 * @param $form
 * @param $form_state
 * @return array
 */
function civicrm_entity_reference_field_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  if ($field['type'] == 'civicrm_entity_reference') {
    $display = $instance['display'][$view_mode];
    $settings = $display['settings'];
    $target_entity_type = 'civicrm_' . $field['settings']['target_entity_type'];
    $modes = field_view_mode_settings($target_entity_type, $target_entity_type);
    $view_modes = array(
      'default' => 'default',
    );
    foreach ($modes as $key => $data) {
      $view_modes[$key] = $key;
    }
    $element = array();
    $element['view_mode'] = array(
      '#type' => 'select',
      '#title' => t('View mode'),
      '#description' => 'Target Entity: civicrm_' . $field['settings']['target_entity_type'] . ', Select the view mode to render the entity as.',
      '#options' => $view_modes,
      '#default_value' => isset($settings['view_mode']) ? $settings['view_mode'] : 'default',
    );
    $element['link_to_entity'] = array(
      '#type' => 'checkbox',
      '#title' => t('Output as link to entity'),
      '#default_value' => isset($settings['link_to_entity']) ? $settings['link_to_entity'] : 'default',
      '#return_value' => 1,
    );
    if ($display['type'] == 'civicrm_entity_reference_entity_formatter') {
      $element['link_to_entity']['#access'] = FALSE;
    }
    elseif ($display['type'] == 'civicrm_entity_reference_entity_label_formatter') {
      $element['view_mode']['#access'] = FALSE;
    }
    return $element;
  }
}

/**
 * Implements hook_field_formatter_settings_summary().
 *
 * @param $field
 * @param $instance
 * @param $view_mode
 * @return string
 */
function civicrm_entity_reference_field_field_formatter_settings_summary($field, $instance, $view_mode) {
  if ($field['type'] == 'civicrm_entity_reference') {
    $display = $instance['display'][$view_mode];
    $settings = $display['settings'];
    $summary = '';
    if ($display['type'] == 'civicrm_entity_reference_entity_formatter') {
      $summary = t('Target Entity @entity_type Rendered as : @data', array(
        '@entity_type' => 'civicrm_' . $field['settings']['target_entity_type'],
        '@data' => isset($settings['view_mode']) ? $settings['view_mode'] : 'default',
      ));
    }
    elseif ($display['type'] == 'civicrm_entity_reference_entity_label_formatter') {
      $summary = t('Display @entity_type label as @data', array(
        '@entity_type' => 'civicrm_' . $field['settings']['target_entity_type'],
        '@data' => !empty($settings['link_to_entity']) ? 'link' : 'plain text.',
      ));
    }
    return $summary;
  }
}

/**
 * Implement hook_field_formatter_prepare_view().
 *
 * @param $entity_type
 * @param $entities
 * @param $field
 * @param $instances
 * @param $langcode
 * @param $items
 * @param $displays
 */
function civicrm_entity_reference_field_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) {

  // this function borrowed pretty much straight from the entityreference module :)
  $target_ids = array();
  $target_entity_type = 'civicrm_' . $field['settings']['target_entity_type'];

  // Collect every possible entity attached to any of the entities.
  foreach ($entities as $id => $entity) {
    foreach ($items[$id] as $delta => $item) {
      if (isset($item['target_id'])) {
        $target_ids[] = $item['target_id'];
      }
    }
  }
  if ($target_ids) {
    try {
      $target_entities = entity_load($target_entity_type, $target_ids);
    } catch (Exception $e) {
      return;
    }
  }
  else {
    $target_entities = array();
  }

  // Iterate through the fieldable entities again to attach the loaded data.
  foreach ($entities as $id => $entity) {
    $rekey = FALSE;
    foreach ($items[$id] as $delta => $item) {

      // Check whether the referenced entity could be loaded.
      if (isset($target_entities[$item['target_id']])) {

        // Replace the instance value with the term data.
        $items[$id][$delta]['entity'] = $target_entities[$item['target_id']];

        // Check whether the user has access to the referenced entity.
        $has_view_access = entity_access('view', $target_entity_type, $target_entities[$item['target_id']]) !== FALSE;
        $has_update_access = entity_access('update', $target_entity_type, $target_entities[$item['target_id']]) !== FALSE;
        $items[$id][$delta]['access'] = $has_view_access || $has_update_access;
      }
      else {
        unset($items[$id][$delta]);
        $rekey = TRUE;
      }
    }
    if ($rekey) {

      // Rekey the items array.
      $items[$id] = array_values($items[$id]);
    }
  }
}

/**
 * Implements hook_field_formatter_view().
 */
function civicrm_entity_reference_field_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array();
  $settings = $display['settings'];

  // Rebuild the items list to contain only those with access.
  foreach ($items as $key => $item) {
    if (empty($item['access'])) {
      unset($items[$key]);
    }
  }
  switch ($display['type']) {
    case 'civicrm_entity_reference_default_formatter':
      foreach ($items as $delta => $item) {
        $element[$delta] = array(
          '#markup' => $item['target_id'],
        );
      }
      break;
    case 'civicrm_entity_reference_entity_formatter':
      $target_entity_type = 'civicrm_' . $field['settings']['target_entity_type'];
      foreach ($items as $delta => $item) {
        static $depth = 0;
        $depth++;
        if ($depth > 20) {
          throw new EntityReferenceRecursiveRenderingException(t('Recursive rendering detected when rendering entity @entity_type(@entity_id). Aborting rendering.', array(
            '@entity_type' => $entity_type,
            '@entity_id' => $item['target_id'],
          )));
        }
        $entity_to_render = $item['entity'];
        unset($entity_to_render->content);
        if ($target_entity_type == 'civicrm_contact') {

          //for some reason the is_deleted column of the contact record is coming to the entity

          // as contact_is_deleted ...special handling to have the page value set properly
          $entity_to_render->is_deleted = $entity_to_render->contact_is_deleted;
        }
        $view_mode = isset($settings['view_mode']) ? $settings['view_mode'] : 'default';
        $content = entity_view($target_entity_type, array(
          $item['target_id'] => $entity_to_render,
        ), $view_mode, $langcode, FALSE);
        $depth = 0;
        $element[$delta] = $content;
      }
      break;
    case 'civicrm_entity_reference_entity_label_formatter':
      $target_entity_type = 'civicrm_' . $field['settings']['target_entity_type'];
      foreach ($items as $delta => $item) {
        $output_as_link = !empty($settings['link_to_entity']) ? 1 : 0;
        $entity_text = entity_label($target_entity_type, $item['entity']);
        $entity_path = '/' . str_replace('_', '-', $target_entity_type) . '/' . $item['target_id'];
        if (empty($entity_text)) {
          $entity_text = ucwords(str_replace('_', ' ', $target_entity_type)) . 'id:' . $item['target_id'];
        }
        if ($output_as_link) {
          $element[$delta] = array(
            '#markup' => l($entity_text, $entity_path),
          );
        }
        else {
          $element[$delta] = array(
            '#markup' => $entity_text,
          );
        }
      }
      break;
  }
  return $element;
}

/**
 * Implements hook_civicrm_post().
 *
 * Clear specific entity field cache for entities that have fields of type civicrm_reference_field and target new or deleted entity
 *
 * This won't work for every entity. For example new Notes do not cause this hook to fire. :(
 *
 * @param $op
 * @param $objectName
 * @param $objectId
 * @param $objectRef
 */
function civicrm_entity_reference_field_civicrm_post($op, $objectName, $objectId, &$objectRef) {
  if ($op == 'create' || $op == 'delete' || $op == 'edit') {
    $civicrm_entity_reference_fields = db_select('field_config', 'fc')
      ->fields('fc', array(
      'field_name',
      'id',
    ))
      ->condition('type', 'civicrm_entity_reference')
      ->execute();
    while ($record = $civicrm_entity_reference_fields
      ->fetchAssoc()) {
      $field = field_info_field_by_id($record['id']);
      $civicrm_entity_type = ltrim(strtolower(preg_replace('/[A-Z]/', '_$0', $objectName)), '_');
      if ($field['settings']['target_entity_type'] == $civicrm_entity_type) {
        $instances = db_select('field_config_instance', 'fi')
          ->fields('fi', array(
          'id',
          'entity_type',
        ))
          ->condition('field_id', $record['id'])
          ->execute();
        while ($instance = $instances
          ->fetchAssoc()) {

          //clear the cache of entity
          if (!empty($field['settings']['target_id_column']) && isset($objectRef->{$field['settings']['target_id_column']})) {
            cache_clear_all('field:' . $instance['entity_type'] . ':' . $objectRef->{$field['settings']['target_id_column']}, 'cache_field');
          }
        }
      }
    }
  }
}

/**
 * Implements hook_field_widget_form_alter().
 *
 * For CiviCRM Entity Add forms
 *
 * Unset field form for Inline Entity Form -- Single on entity create.
 * Disable widget buttons for Inline Entity Form -- Multiple on entity create.
 * Disable widget for default widget.
 *
 * @param $element
 * @param $form_state
 * @param $context
 */
function civicrm_entity_reference_field_field_widget_form_alter(&$element, &$form_state, $context) {
  if ($context['field']['type'] == 'civicrm_entity_reference') {
    if ($context['instance']['widget']['type'] == 'inline_entity_form_single') {
      if (!empty($form_state['op']) && $form_state['op'] == 'create' || !empty($element['form']['#op']) && $element['form']['#op'] == 'add') {
        $field = $context['field']['settings']['target_id_column'];
        if ($element['#entity_type'] == 'civicrm_contact' && array_key_exists($field, $element['form'])) {
          $element['form'][$field]['#required'] = FALSE;
          $element['form'][$field]['#disabled'] = TRUE;
        }
        else {
          unset($element['form']);
        }
      }
    }
    elseif ($context['instance']['widget']['type'] == 'inline_entity_form') {
      if (!empty($form_state['op']) && $form_state['op'] == 'create' || !empty($context['form']['#op']) && $context['form']['#op'] == 'add') {
        $element['actions']['ief_add']['#disabled'] = TRUE;
      }
    }
    elseif ($context['instance']['widget']['type'] == 'civicrm_entity_reference_default_widget') {
      if ($form_state['op'] == 'create') {
        $element['#disabled'] = TRUE;
      }
    }
  }
}

/**
 * Implements hook_inline_entity_form_entity_form_alter().
 *
 * @param $entity_form
 * @param $form_state
 */
function civicrm_entity_reference_field_inline_entity_form_entity_form_alter(&$entity_form, &$form_state) {
  $ief_id = $entity_form['#ief_id'];
  $host_entity_type = $form_state['inline_entity_form'][$ief_id]['instance']['entity_type'];
  $field_info = array();
  foreach ($entity_form['#parents'] as $key => $parent) {
    if (strpos($parent, 'field_') === 0) {
      $field = field_info_field($parent);
      $instances = db_select('field_config_instance', 'fi')
        ->fields('fi', array(
        'id',
      ))
        ->condition('field_id', $field['id'])
        ->condition('entity_type', $host_entity_type)
        ->condition('bundle', $host_entity_type)
        ->execute();
      if ($instances
        ->rowCount()) {
        $field_name = $parent;
        $field_info = $field;
      }
    }
  }
  if (!empty($field_info) && $field_info['type'] == 'civicrm_entity_reference') {

    // Generally you want to set the target_id_column to the host_id_prop
    $target_id_column = isset($field_info['settings']['target_id_column']) ? $field_info['settings']['target_id_column'] : '';
    $host_id_prop = isset($field_info['settings']['host_source_id']) ? $field_info['settings']['host_source_id'] : '';

    // this doesn't handle a field that is nested on an entityreference field that is on say a node....
    // this handles the 'multi' widget
    if (isset($form_state['complete form'][$host_id_prop]['#default_value']) && isset($entity_form[$target_id_column]) && is_array($entity_form[$target_id_column])) {
      if ($entity_form['#op'] == 'add' || $entity_form['#op'] == 'create') {
        $entity_form[$target_id_column]['#default_value'] = $form_state['complete form'][$host_id_prop]['#default_value'];
      }
      $entity_form[$target_id_column]['#disabled'] = TRUE;
    }
    elseif (isset($form_state['field'][$field_name][LANGUAGE_NONE]['instance']['entity_type'])) {
      $host_entity_type = $form_state['field'][$field_name][LANGUAGE_NONE]['instance']['entity_type'];
      if (isset($form_state[$host_entity_type]->{$host_id_prop})) {
        if ($entity_form['#op'] == 'add' || $entity_form['#op'] == 'create') {
          $entity_form[$target_id_column]['#default_value'] = $form_state[$host_entity_type]->{$host_id_prop};
        }
        $entity_form[$target_id_column]['#disabled'] = TRUE;
      }
    }

    //temporary ... necessary to disable target_id_column when civicrm_entity_reference field is embedded on a entityreference field which is embedded on a node
    if (!empty($entity_form[$target_id_column]['#default_value'])) {
      $entity_form[$target_id_column]['#disabled'] = TRUE;
    }

    // special handling of address fields on location blocks, because in this case the contact_id is not required
    $contact_id_entities = array(
      'civicrm_address',
      'civicrm_email',
      'civicrm_phone',
      'civicrm_im',
    );
    if ($host_entity_type == 'civicrm_loc_block' && in_array($entity_form['#entity_type'], $contact_id_entities)) {
      $entity_form['contact_id']['#required'] = FALSE;
      $entity_form['contact_id']['#default_value'] = 1;
      $entity_form['contact_id']['#disabled'] = TRUE;
      $entity_form['contact_id']['#description'] = t('The value of 1 for this field is only a placeholder and will be set to NULL on save.');
    }
  }
}

/**
 * Implements hook_entity_presave().
 *
 * We needed this because sometimes you need to back fill a value before save
 *
 * For example, if you put a civicrm entity reference field which targets the location block, on a event entity, you have to make sure the event gets a value for the location_block_id
 * Another example is that the location block address_id property needs to be set after the address is saved (considering if you have an civicrm_entity_reference field on the location block form, targeting address
 *
 * More cases of this type may crop up and we'll better understand how to automate as time passes and experience hits us over the head
 *
 * @param $entity
 * @param $type
 */
function civicrm_entity_reference_field_entity_presave($entity, $type) {
  if ($type == 'civicrm_loc_block' || $type == 'civicrm_event') {
    foreach ($entity as $key => $value) {
      if (strpos($key, 'field_') === 0) {
        $field = field_info_field($key);
        if ($field['type'] == 'civicrm_entity_reference') {
          if ($type == 'civicrm_loc_block') {
            switch ($field['settings']['target_entity_type']) {
              case 'address':
                $entity->{$field['settings']['host_source_id']} = $entity->{$key}[LANGUAGE_NONE][0]['target_id'];

                // VIA the API you cannot save/create an address without a contact id, we fool it in this special case by in the form setting the id to 1, then undoing it with sql directly
                // it ain't pretty but it works
                db_update('civicrm_address')
                  ->fields(array(
                  'contact_id' => NULL,
                ))
                  ->condition('id', $entity->{$key}[LANGUAGE_NONE][0]['target_id'])
                  ->execute();
                break;
              case 'email':
                $entity->{$field['settings']['host_source_id']} = $entity->{$key}[LANGUAGE_NONE][0]['target_id'];
                db_update('civicrm_email')
                  ->fields(array(
                  'contact_id' => NULL,
                ))
                  ->condition('id', $entity->{$key}[LANGUAGE_NONE][0]['target_id'])
                  ->execute();
                break;
              case 'phone':
                $entity->{$field['settings']['host_source_id']} = $entity->{$key}[LANGUAGE_NONE][0]['target_id'];
                db_update('civicrm_phone')
                  ->fields(array(
                  'contact_id' => NULL,
                ))
                  ->condition('id', $entity->{$key}[LANGUAGE_NONE][0]['target_id'])
                  ->execute();
                break;
              case 'im':
                $entity->{$field['settings']['host_source_id']} = $entity->{$key}[LANGUAGE_NONE][0]['target_id'];
                db_update('civicrm_im')
                  ->fields(array(
                  'contact_id' => NULL,
                ))
                  ->condition('id', $entity->{$key}[LANGUAGE_NONE][0]['target_id'])
                  ->execute();
                break;
            }
          }
          elseif ($type == 'civicrm_event' && $field['settings']['target_entity_type'] == 'loc_block') {
            $entity->{$field['settings']['host_source_id']} = $entity->{$key}[LANGUAGE_NONE][0]['target_id'];
          }
        }
      }
    }
  }
}

Functions

Namesort descending Description
civicrm_entity_reference_field_civicrm_post Implements hook_civicrm_post().
civicrm_entity_reference_field_entity_presave Implements hook_entity_presave().
civicrm_entity_reference_field_field_formatter_info Implements hook_field_formatter_info().
civicrm_entity_reference_field_field_formatter_prepare_view Implement hook_field_formatter_prepare_view().
civicrm_entity_reference_field_field_formatter_settings_form Implements hook_field_formatter_settings_form().
civicrm_entity_reference_field_field_formatter_settings_summary Implements hook_field_formatter_settings_summary().
civicrm_entity_reference_field_field_formatter_view Implements hook_field_formatter_view().
civicrm_entity_reference_field_field_info Implements hook_field_info().
civicrm_entity_reference_field_field_insert Implements hook_field_insert().
civicrm_entity_reference_field_field_is_empty Implements hook_field_is_empty().
civicrm_entity_reference_field_field_load Implements hook_field_load().
civicrm_entity_reference_field_field_settings_form Implements hook_field_settings_form().
civicrm_entity_reference_field_field_update Implements hook_field_update().
civicrm_entity_reference_field_field_widget_form Implements hook_field_widget_form().
civicrm_entity_reference_field_field_widget_form_alter Implements hook_field_widget_form_alter().
civicrm_entity_reference_field_field_widget_info Implements hook_field_widget_info().
civicrm_entity_reference_field_field_widget_info_alter Implements hook_field_widget_info_alter().
civicrm_entity_reference_field_form_field_ui_field_edit_form_alter Implements hook_form_FORMID_alter().
civicrm_entity_reference_field_form_field_ui_field_overview_form_alter Implements hook_form_FORMID_alter().
civicrm_entity_reference_field_inline_entity_form_entity_form_alter Implements hook_inline_entity_form_entity_form_alter().
civicrm_entity_reference_field_inline_entity_form_settings_alter Implements hook_inline_entity_form_settings_alter().
civicrm_entity_reference_field_target_entity_type_ajax_callback Ajax callback for the field settings Target Entity Type select field change
_civicrm_entity_reference_field_get_target_id_column_options