You are here

function diff_entity_fields_diff in Diff 7.3

Internal callback to handle fieldable entities.

Field comparison is handled for core modules, but is expandable to any other fields if the module defines MODULE_field_diff_view().

Parameters

object $old_entity: The older entity entity revision.

object $new_entity: The newer entity entity revision.

array $context: An associative array containing:

  • entity_type: The entity type; e.g., 'node' or 'user'.
  • old_entity: The older entity.
  • new_entity: The newer entity.
  • view_mode: The view mode to use. Defaults to FALSE.

string $default_langcode: (optional) Language code to force comparison in.

Return value

array An associative array of values keyed by the field name and delta value.

1 call to diff_entity_fields_diff()
diff_entity_diff in ./diff.diff.inc
Implements hook_entity_diff().

File

./diff.diff.inc, line 50
Includes the hooks defined by diff_hook_info().

Code

function diff_entity_fields_diff($old_entity, $new_entity, $context, $default_langcode = NULL) {
  $result = array();
  $entity_type = $context['entity_type'];
  $view_mode = $context['view_mode'];
  $field_context = $context;
  $actual_mode = FALSE;
  list(, , $bundle_name) = entity_extract_ids($entity_type, $new_entity);
  $instances = field_info_instances($entity_type, $bundle_name);

  // Some fields piggy back the display settings, so we need to fake these by
  // ensuring that the field mode is always set.
  if (empty($view_mode)) {
    $actual_mode = 'diff_standard';
    $field_context['custom_settings'] = FALSE;
  }
  $view_mode_settings = field_view_mode_settings($entity_type, $bundle_name);
  $actual_mode = !empty($view_mode_settings[$view_mode]['custom_settings']) ? $view_mode : 'default';
  if (!isset($field_context['custom_settings'])) {
    $field_context['custom_settings'] = $actual_mode && $actual_mode == $view_mode;
  }
  $field_context['old_entity'] = $old_entity;
  $field_context['new_entity'] = $new_entity;
  $field_context['bundle_name'] = $bundle_name;
  foreach ($instances as $instance) {

    // Any view mode is supported in relation to hiding fields, but only if
    // selected (todo see if this is a valid option).
    if ($actual_mode && $instance['display'][$actual_mode]['type'] == 'hidden') {
      continue;
    }
    $field_name = $instance['field_name'];
    $field = field_info_field($field_name);
    $field_context['field'] = $field;
    $field_context['instance'] = $instance;
    $field_context['display'] = $instance['display'][$actual_mode];

    // We provide a loose check on the field access.
    if (field_access('view', $field, $entity_type) || field_access('edit', $field, $entity_type)) {
      $langcode = $default_langcode ? $default_langcode : field_language($entity_type, $new_entity, $field_name);
      $field_context['language'] = $langcode;
      $field_context['field'] = $field;
      $field_context['instance'] = $instance;
      $old_items = array();
      if (!empty($old_entity->{$field_name}[$langcode])) {
        $old_items = $old_entity->{$field_name}[$langcode];
      }
      $new_items = array();
      if (!empty($new_entity->{$field_name}[$langcode])) {
        $new_items = $new_entity->{$field_name}[$langcode];
      }

      // Load files containing the field callbacks.
      _diff_autoload($field);
      $field_context['settings'] = diff_get_field_settings($field_context);

      // Reference fields can optionally prepare objects in bulk to reduce
      // overheads related to multiple database calls. If a field considers
      // that the delta values is meaningless, they can order and rearrange
      // to provide cleaner results.
      $func = $field['module'] . '_field_diff_view_prepare';
      if (function_exists($func)) {
        $func($old_items, $new_items, $field_context);
      }

      // Allow other modules to act safely on behalf of the core field module.
      drupal_alter('field_diff_view_prepare', $old_items, $new_items, $field_context);

      // These functions compiles the items into comparable arrays of strings.
      $func = $field['module'] . '_field_diff_view';
      if (!function_exists($func)) {
        $func = 'diff_field_diff_view';
      }

      // Copy the static ID cache to ensure this is the same for each comparison.
      $original_html_ids = drupal_static('drupal_html_id');
      $html_ids =& drupal_static('drupal_html_id');

      // These callbacks should be independent of revision.
      $old_context = $field_context;
      $old_context['entity'] = $old_entity;
      $old_values = $func($old_items, $old_context);

      // Restores the ID cache to the original.
      $html_ids = $original_html_ids;
      $new_context = $field_context;
      $new_context['entity'] = $new_entity;
      $new_values = $func($new_items, $new_context);

      // Allow other modules to act safely on behalf of the core field module.
      drupal_alter('field_diff_view', $old_values, $old_items, $old_context);
      drupal_alter('field_diff_view', $new_values, $new_items, $new_context);
      $max = max(array(
        count($old_values),
        count($new_values),
      ));
      if ($max) {
        $result[$field_name] = array(
          '#name' => $instance['label'],
          '#old' => array(),
          '#new' => array(),
          '#settings' => $field_context['settings'],
        );
        for ($delta = 0; $delta < $max; $delta++) {
          if (isset($old_values[$delta])) {
            $result[$field_name]['#old'][] = is_array($old_values[$delta]) ? implode("\n", $old_values[$delta]) : $old_values[$delta];
          }
          if (isset($new_values[$delta])) {
            $result[$field_name]['#new'][] = is_array($new_values[$delta]) ? implode("\n", $new_values[$delta]) : $new_values[$delta];
          }
        }
        $result[$field_name]['#old'] = implode("\n", $result[$field_name]['#old']);
        $result[$field_name]['#new'] = implode("\n", $result[$field_name]['#new']);
        if ($actual_mode) {
          $result[$field_name]['#weight'] = $instance['display'][$actual_mode]['weight'];
        }
      }
    }
  }
  return $result;
}