diff --git a/docroot/sites/all/modules/contrib/entityreference/entityreference.install b/docroot/sites/all/modules/contrib/entityreference/entityreference.install index 4e248ef..2f79947 100644 --- a/docroot/sites/all/modules/contrib/entityreference/entityreference.install +++ b/docroot/sites/all/modules/contrib/entityreference/entityreference.install @@ -18,11 +18,17 @@ function entityreference_field_schema($field) { $schema = array( 'columns' => array( 'target_id' => array( - 'description' => 'The id of the target entity.', + 'description' => 'The ID of the target entity.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, ), + 'revision_id' => array( + 'description' => 'The revision ID of the target entity.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => FALSE, + ), ), 'indexes' => array( 'target_id' => array('target_id'), @@ -161,4 +167,34 @@ function entityreference_update_7002() { 'not null' => TRUE, )); } -} \ No newline at end of file +} + +/** + * Add "revision-id" to the field schema. + */ +function entityreference_update_7003() { + if (!module_exists('field_sql_storage')) { + return; + } + foreach (field_info_fields() as $field_name => $field) { + if ($field['type'] != 'entityreference' || $field['storage']['type'] !== 'field_sql_storage') { + // Not an entity reference field. + continue; + } + + // Add the new column. + $field = field_info_field($field_name); + $table_name = _field_sql_storage_tablename($field); + $revision_name = _field_sql_storage_revision_tablename($field); + + $spec = array( + 'description' => 'The revision ID of the target entity.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => FALSE, + ); + + db_add_field($table_name, $field_name . '_revision_id', $spec); + db_add_field($revision_name, $field_name . '_revision_id', $spec); + } +} diff --git a/docroot/sites/all/modules/contrib/entityreference/entityreference.module b/docroot/sites/all/modules/contrib/entityreference/entityreference.module index bdcb562..2c7c5c7 100644 --- a/docroot/sites/all/modules/contrib/entityreference/entityreference.module +++ b/docroot/sites/all/modules/contrib/entityreference/entityreference.module @@ -243,6 +243,25 @@ function entityreference_field_validate($entity_type, $entity, $field, $instance * Adds the target type to the field data structure when saving. */ function entityreference_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) { + $dest_entity_type = $field['settings']['target_type']; + foreach ($items as $key => $val) { + + // 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); + + if (isset($ref_ids[1]) && is_numeric($ref_ids[1])) { + $items[$key]['revision_id'] = $ref_ids[1]; + } + } + // Invoke the behaviors. foreach (entityreference_get_behavior_handlers($field, $instance) as $handler) { $handler->presave($entity_type, $entity, $field, $instance, $langcode, $items); @@ -672,12 +691,58 @@ 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); + // Load revision, not the current one. + $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(). */ @@ -1172,42 +1237,67 @@ function entityreference_field_formatter_settings_summary($field, $instance, $vi */ function entityreference_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) { $target_ids = array(); + $revision_ids = array(); // 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'])) { + if (!empty($item['revision_id'])) { + $revision_ids[] = $item['revision_id']; + } + elseif (!empty($item['target_id'])) { $target_ids[] = $item['target_id']; } } } + $target_type = $field['settings']['target_type']; + + $target_entities = array(); + if ($target_ids) { - $target_entities = entity_load($field['settings']['target_type'], $target_ids); + $target_entities = entity_load($target_type, $target_ids); } - else { - $target_entities = array(); + + if ($revision_ids) { + // We need to load the revisions one by-one. + foreach ($revision_ids as $revision_id) { + $entity = entity_revision_load($target_type, $revision_id); + 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; + } + } } - // Iterate through the fieldable entities again to attach the loaded data. + // 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']])) { + $identifier = !empty($item['revision_id']) ? $item['target_id'] . ':' . $item['revision_id'] : $item['target_id']; + if (isset($target_entities[$identifier])) { // Replace the instance value with the term data. - $items[$id][$delta]['entity'] = $target_entities[$item['target_id']]; + $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['target_id']]) !== FALSE); - $has_update_access = (entity_access('update', $field['settings']['target_type'], $target_entities[$item['target_id']]) !== 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. else { unset($items[$id][$delta]); $rekey = TRUE; + unset($items[$id][$delta]); + continue; } + + $entity = $target_entities[$identifier]; + $items[$id][$delta]['entity'] = $entity; + $items[$id][$delta]['access'] = entity_access('view', $target_type, $entity); } if ($rekey) { diff --git a/docroot/sites/all/modules/contrib/entityreference/views/entityreference.views.inc b/docroot/sites/all/modules/contrib/entityreference/views/entityreference.views.inc index baa7034..f79be4b 100644 --- a/docroot/sites/all/modules/contrib/entityreference/views/entityreference.views.inc +++ b/docroot/sites/all/modules/contrib/entityreference/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.