You are here

field_property.module in Field property 7

Allows fields to be properties and have the same value across all revisions.

File

field_property.module
View source
<?php

/**
 * @file
 * Allows fields to be properties and have the same value across all revisions.
 */
function field_property_entity_type_has_revisions($entity_type) {
  $info = entity_get_info($entity_type);
  return !empty($info['entity keys']['revision']) && !empty($info['revision table']);
}

/**
 * Implements hook_form_alter().
 */
function field_property_form_field_ui_field_edit_form_alter(&$form, $form_state) {
  $instance = $form['#instance'];
  $form['instance']['is_property'] = array(
    '#type' => 'checkbox',
    '#title' => t('Revision-less field'),
    // @todo Description
    '#default_value' => !empty($instance['is_property']),
    '#weight' => -9,
    '#access' => field_property_entity_type_has_revisions($instance['entity_type']),
  );
}

/**
 * Implements hook_field_attach_update().
 */
function field_property_field_attach_update($entity_type, $entity) {
  if (!field_property_entity_type_has_revisions($entity_type)) {
    return;
  }
  $revision_ids = field_property_get_all_entity_revision_ids($entity_type, $entity, TRUE);
  if (empty($revision_ids)) {
    return;
  }
  $info = entity_get_info($entity_type);
  list(, , $bundle) = entity_extract_ids($entity_type, $entity);

  // Collect the storage backends used by the remaining fields in the entities.
  $storages = array();
  foreach (field_info_instances($entity_type, $bundle) as $instance) {
    if (empty($instance['is_property'])) {

      // Only care about fields that are properties.
      continue;
    }
    $field = field_info_field_by_id($instance['field_id']);
    $field_id = $field['id'];
    $field_name = $field['field_name'];

    // Leave the field untouched if $entity comes with no $field_name property,
    // but empty the field if it comes as a NULL value or an empty array.
    // Function property_exists() is slower, so we catch the more frequent
    // cases where it's an empty array with the faster isset().
    if (isset($entity->{$field_name}) || property_exists($entity, $field_name)) {

      // Collect the storage backend if the field has not been written yet.
      if (!isset($skip_fields[$field_id])) {
        $storages[$field['storage']['type']][$field_id] = $field_id;
      }
    }
  }

  // Field storage backends save any remaining unsaved fields.
  foreach ($storages as $storage => $fields) {

    // Save for each revision.
    foreach ($revision_ids as $revision_id) {

      // Create a cloned revision object based on the entity.
      $revision = clone $entity;
      $revision->{$info['entity keys']['revision']} = $revision_id;
      $storage_info = field_info_storage_types($storage);
      module_invoke($storage_info['module'], 'field_storage_write', $entity_type, $revision, FIELD_STORAGE_UPDATE, $fields);
    }
  }
}

/**
 * Return an array of all the revision IDs of a given entity.
 */
function field_property_get_all_entity_revision_ids($entity_type, $entity, $exclude_current_revision_id = FALSE) {
  $info = entity_get_info($entity_type);
  if (empty($info['entity keys']['id']) || empty($info['entity keys']['revision']) || empty($info['revision table'])) {
    return array();
  }
  list($entity_id, $revision_id) = entity_extract_ids($entity_type, $entity);
  $id_key = $info['entity keys']['id'];
  $revision_key = $info['entity keys']['revision'];
  $query = db_select($info['revision table'], 'revision');
  $query
    ->addField('revision', $revision_key);
  $query
    ->condition('revision.' . $id_key, $entity_id);
  if ($exclude_current_revision_id) {
    $query
      ->condition('revision.' . $revision_key, $revision_id, '<>');
  }
  return $query
    ->execute()
    ->fetchCol();
}

/**
 * Implements hook_field_widget_form_alter().
 */
function field_property_field_widget_form_alter(&$element, &$form_state, $context) {
  if (!empty($context['instance']['is_property'])) {
    $text = t("This field is synchonized across all revisions.");
    if (isset($element['#description'])) {
      $element['#description'] .= ' ' . $text;
    }
    else {
      $element['#description'] = $text;
    }
  }
}

Functions

Namesort descending Description
field_property_entity_type_has_revisions @file Allows fields to be properties and have the same value across all revisions.
field_property_field_attach_update Implements hook_field_attach_update().
field_property_field_widget_form_alter Implements hook_field_widget_form_alter().
field_property_form_field_ui_field_edit_form_alter Implements hook_form_alter().
field_property_get_all_entity_revision_ids Return an array of all the revision IDs of a given entity.