diff --git b/entityreference.module a/entityreference.module index 810f992..15fc262 100644 --- b/entityreference.module +++ a/entityreference.module @@ -245,16 +245,29 @@ function entityreference_field_validate($entity_type, $entity, $field, $instance function entityreference_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) { if (!empty($field['settings']['handler_settings']['lock_revision'])) { $dest_entity_type = $field['settings']['target_type']; + $original_items = array(); if (isset($entity->original)) { $original_items = field_get_items($entity_type, $entity->original, $field['field_name']); } else { $ids = entity_extract_ids($entity_type, $entity); - $original = entity_load_unchanged($entity_type, $ids[0]); - $original_items = field_get_items($entity_type, $original, $field['field_name']); + if ($ids[0]) { + $original = entity_load_unchanged($entity_type, $ids[0]); + if ($original) { + $original_items = field_get_items($entity_type, $original, $field['field_name']); + } + } } foreach ($items as $key => $val) { - $ref_entity = entity_load_single($dest_entity_type, $val['target_id']); + // If the revision id is explicitly set, load the revision. + $ref_entity = FALSE; + if (isset($val['revision_id']) && $val['revision_id']) { + $ref_entity = entity_revision_load($dest_entity_type, $val['revision_id']); + } + // If the was not set or couldn't be loaded. + if (!$ref_entity) { + $ref_entity = entity_load_single($dest_entity_type, $val['target_id']); + } $ref_ids = entity_extract_ids($dest_entity_type, $ref_entity); // find the original item, which does not have the same delta per se. $original_revision = FALSE; @@ -700,12 +713,61 @@ function entityreference_field_property_callback(&$info, $entity_type, $field, $ // Then apply the default. entity_metadata_field_default_property_callback($info, $entity_type, $field, $instance, $field_type); + // If the entity reference is locked to a revision, load that revision, not + // the current one. + if (!empty($field['settings']['handler_settings']['lock_revision'])) { + $name = $field['field_name']; + $property = &$info[$entity_type]['bundles'][$instance['bundle']]['properties'][$name]; + $property['getter callback'] = 'entityreference_metadata_field_get_revision_data'; + $property['setter callback'] = 'entityreference_metadata_field_set_revision_data'; + } + // Invoke the behaviors to allow them to change the properties. foreach (entityreference_get_behavior_handlers($field, $instance) as $handler) { $handler->property_info_alter($info, $entity_type, $field, $instance, $field_type); } } +function entityreference_metadata_field_get_revision_data($entity, array $options, $name, $entity_type, $info){ + $field = field_info_field($name); + $langcode = isset($options['language']) ? $options['language']->language : LANGUAGE_NONE; + $langcode = entity_metadata_field_get_language($entity_type, $entity, $field, $langcode, TRUE); + $values = array(); + if (isset($entity->{$name}[$langcode])) { + foreach ($entity->{$name}[$langcode] as $delta => $data) { + if (isset($data['revision_id'])) { + $values[$delta] = array('id' => $data['target_id'], 'vid' => $data['revision_id']); + } + else { + $values[$delta] = $data['target_id']; + } + } + } + // For an empty single-valued field, we have to return NULL. + return $field['cardinality'] == 1 ? ($values ? reset($values) : NULL) : $values; +} + +function entityreference_metadata_field_set_revision_data($entity, $name, $value, $langcode, $entity_type, $info) { + $field = field_info_field($name); + $langcode = entity_metadata_field_get_language($entity_type, $entity, $field, $langcode); + $values = $field['cardinality'] == 1 ? array($value) : (array) $value; + + $items = array(); + foreach ($values as $delta => $value) { + if (isset($value) && is_array($value)) { + $items[$delta]['target_id'] = $value['id']; + $items[$delta]['revision_id'] = $value['vid']; + } + else { + $items[$delta]['target_id'] = $value; + } + } + $entity->{$name}[$langcode] = $items; + // Empty the static field language cache, so the field system picks up any + // possible new languages. + drupal_static_reset('field_language'); +} + /** * Implements hook_field_widget_info(). */ @@ -1226,10 +1288,12 @@ function entityreference_field_formatter_prepare_view($entity_type, $entities, $ // We need to load the revisions one by-one. foreach ($revision_ids as $revision_id) { $entity = entity_revision_load($target_type, $revision_id); - list($id) = entity_extract_ids($target_type, $entity); - // Use the revision-ID in the key. - $identifier = $id . ':' . $revision_id; - $target_entities[$identifier] = $entity; + if ($entity) { + list($id) = entity_extract_ids($target_type, $entity); + // Use the revision-ID in the key. + $identifier = $id . ':' . $revision_id; + $target_entities[$identifier] = $entity; + } } } @@ -1240,12 +1304,12 @@ function entityreference_field_formatter_prepare_view($entity_type, $entities, $ foreach ($items[$id] as $delta => $item) { // Check whether the referenced entity could be loaded. $identifier = !empty($item['revision_id']) ? $item['target_id'] . ':' . $item['revision_id'] : $item['target_id']; - if (!isset($target_entities[$identifier])) { + if (isset($target_entities[$identifier])) { // Replace the instance value with the term data. - $items[$id][$delta]['entity'] = $target_entities[$item[$identifier]]; + $items[$id][$delta]['entity'] = $target_entities[$identifier]; // Check whether the user has access to the referenced entity. - $has_view_access = (entity_access('view', $field['settings']['target_type'], $target_entities[$item[$identifier]]) !== FALSE); - $has_update_access = (entity_access('update', $field['settings']['target_type'], $target_entities[$item[$identifier]]) !== FALSE); + $has_view_access = (entity_access('view', $field['settings']['target_type'], $target_entities[$identifier]) !== FALSE); + $has_update_access = (entity_access('update', $field['settings']['target_type'], $target_entities[$identifier]) !== FALSE); $items[$id][$delta]['access'] = ($has_view_access || $has_update_access); } // Otherwise, unset the instance value, since the entity does not exist. diff --git b/plugins/selection/EntityReference_SelectionHandler_Generic.class.php a/plugins/selection/EntityReference_SelectionHandler_Generic.class.php index 012367f..839add1 100644 --- b/plugins/selection/EntityReference_SelectionHandler_Generic.class.php +++ a/plugins/selection/EntityReference_SelectionHandler_Generic.class.php @@ -149,12 +149,12 @@ class EntityReference_SelectionHandler_Generic implements EntityReference_Select ); } - // Provide an option to lock the entity reference to the latest revision if + // Provide an option to lock the entity reference to the current revision if // the entity supports it. if (!empty($entity_info['revision table'])) { $form['lock_revision'] = array( '#type' => 'checkbox', - '#title' => t('Lock the field to the most current revision'), + '#title' => t('Lock the field to the revision of the entity at the time it was referenced.'), '#default_value' => !empty($field['settings']['handler_settings']['lock_revision']) ? TRUE : FALSE, '#description' => t('When this is enabled, the reference will track the latest revision to that entity when this field is saved. This, combined with e.g. the Workbench Moderation module, can be used to provide limited workflow functionality around the referenced content.', array('!url' => 'http://drupal.org/project/workbench_moderation')) ); diff --git b/plugins/selection/EntityReference_SelectionHandler_Views.class.php a/plugins/selection/EntityReference_SelectionHandler_Views.class.php index 059c1e2..60e569c 100644 --- b/plugins/selection/EntityReference_SelectionHandler_Views.class.php +++ a/plugins/selection/EntityReference_SelectionHandler_Views.class.php @@ -74,7 +74,7 @@ class EntityReference_SelectionHandler_Views implements EntityReference_Selectio if (!empty($entity_info['revision table'])) { $form['lock_revision'] = array( '#type' => 'checkbox', - '#title' => t('Lock the field to the most current revision'), + '#title' => t('Lock the field to the revision of the entity at the time it was referenced.'), '#default_value' => !empty($field['settings']['handler_settings']['lock_revision']) ? TRUE : FALSE, '#description' => t('When this is enabled, the reference will track the latest revision to that entity when this field is saved. This, combined with e.g. the Workbench Moderation module, can be used to provide limited workflow functionality around the referenced content.', array('!url' => 'http://drupal.org/project/workbench_moderation')) ); diff --git b/views/entityreference.views.inc a/views/entityreference.views.inc index baa7034..f79be4b 100644 --- b/views/entityreference.views.inc +++ a/views/entityreference.views.inc @@ -30,6 +30,26 @@ function entityreference_field_views_data($field) { 'help' => t('A bridge to the @entity entity that is referenced via !field_name', $parameters), ); } + + if (isset($field['settings']['handler_settings']['lock_revision']) && $field['settings']['handler_settings']['lock_revision'] && isset($entity_info['revision table'])) { + $entity = $entity_info['label']; + if ($entity == t('Node')) { + $entity = t('Content'); + } + $entity .= ' ' . t('Revision'); + + $field_name = $field['field_name'] . '_revision_id'; + $parameters = array('@entity' => $entity, '!field_name' => $field['field_name']); + $data[$table_name][$field_name]['relationship'] = array( + 'handler' => 'views_handler_relationship', + 'base' => $entity_info['revision table'], + 'base field' => $entity_info['entity keys']['revision'], + 'label' => t('@entity entity revision referenced from !field_name', $parameters), + 'group' => t('Entity Reference'), + 'title' => t('Referenced Entity Revision'), + 'help' => t('A bridge to the @entity entity revision that is referenced via !field_name', $parameters), + ); + } } // Invoke the behaviors to allow them to change the properties.