diff --git a/entity_reference_revisions.views.inc b/entity_reference_revisions.views.inc index 9d351b3..5b6a266 100644 --- a/entity_reference_revisions.views.inc +++ b/entity_reference_revisions.views.inc @@ -13,60 +13,76 @@ use Drupal\field\FieldStorageConfigInterface; function entity_reference_revisions_field_views_data(FieldStorageConfigInterface $field_storage) { $data = views_field_default_views_data($field_storage); $entity_manager = \Drupal::entityTypeManager(); + + // Add a relationship to the target entity type. + $target_entity_type_id = $field_storage->getSetting('target_type'); + $target_entity_type = $entity_manager->getDefinition($target_entity_type_id); + $entity_type_id = $field_storage->getTargetEntityTypeId(); + $entity_type = $entity_manager->getDefinition($entity_type_id); + $field_name = $field_storage->getName(); + /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */ + $table_mapping = $entity_manager->getStorage($entity_type_id)->getTableMapping(); + foreach ($data as $table_name => $table_data) { - // Add a relationship to the target entity type. - $target_entity_type_id = $field_storage->getSetting('target_type'); - $target_entity_type = $entity_manager->getDefinition($target_entity_type_id); - $entity_type_id = $field_storage->getTargetEntityTypeId(); - $entity_type = $entity_manager->getDefinition($entity_type_id); - $target_base_table = $target_entity_type->getDataTable() ?: $target_entity_type->getBaseTable(); - $field_name = $field_storage->getName(); + foreach (['id' => 'id', 'revision' => 'revision_id'] as $key => $column) { + if ($key == 'id' || !$target_entity_type->isRevisionable()) { + $target_base_table = $target_entity_type->getDataTable() ?: $target_entity_type->getBaseTable(); + } else { + $target_base_table = $target_entity_type->getRevisionDataTable() ?: $target_entity_type->getRevisionTable(); + } + + // Provide a relationship for the entity type with the entity reference + // revisions field. + $args = array( + '@label' => $target_entity_type->getLabel(), + '@field_name' => $field_name, + ); + $data[$table_name][$field_name . '_target_' . $column]['relationship'] = array( + 'title' => $key == 'id' ? t('@label referenced from @field_name', $args) : t('@label revision referenced from @field_name', $args), + 'label' => $key == 'id' ? t('@field_name: @label', $args) : t('@field_name: @label revision', $args), + 'group' => $entity_type->getLabel(), + 'help' => t('Appears in: @bundles.', array('@bundles' => implode(', ', $field_storage->getBundles()))), + 'id' => 'standard', + 'base' => $target_base_table, + 'entity type' => $target_entity_type_id, + 'base field' => $target_entity_type->getKey($key), + 'relationship field' => $field_name . '_target_' . $column, + ); - // Provide a relationship for the entity type with the entity reference - // revisions field. - $args = array( - '@label' => $target_entity_type->getLabel(), - '@field_name' => $field_name, - ); - $data[$table_name][$field_name]['relationship'] = array( - 'title' => t('@label referenced from @field_name', $args), - 'label' => t('@field_name: @label', $args), - 'group' => $entity_type->getLabel(), - 'help' => t('Appears in: @bundles.', array('@bundles' => implode(', ', $field_storage->getBundles()))), - 'id' => 'standard', - 'base' => $target_base_table, - 'entity type' => $target_entity_type_id, - 'base field' => $target_entity_type->getKey('revision'), - 'relationship field' => $field_name . '_target_revision_id', - ); + if ($key == 'id' || !$entity_type->isRevisionable()) { + $base_table = $entity_type->getDataTable() ?: $entity_type->getBaseTable(); + } + else { + $base_table = $entity_type->getRevisionDataTable() ?: $entity_type->getRevisionTable(); + } - // Provide a reverse relationship for the entity type that is referenced by - // the field. - $args['@entity'] = $entity_type->getLabel(); - $args['@label'] = $target_entity_type->getLowercaseLabel(); - $pseudo_field_name = 'reverse__' . $entity_type_id . '__' . $field_name; - /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */ - $table_mapping = $entity_manager->getStorage($entity_type_id)->getTableMapping(); - $data[$target_base_table][$pseudo_field_name]['relationship'] = array( - 'title' => t('@entity using @field_name', $args), - 'label' => t('@field_name', array('@field_name' => $field_name)), - 'group' => $target_entity_type->getLabel(), - 'help' => t('Relate each @entity with a @field_name set to the @label.', $args), - 'id' => 'entity_reverse', - 'base' => $entity_type->getDataTable() ?: $entity_type->getBaseTable(), - 'entity_type' => $entity_type_id, - 'base field' => $entity_type->getKey('revision'), - 'field_name' => $field_name, - 'field table' => $table_mapping->getDedicatedDataTableName($field_storage), - 'field field' => $field_name . '_target_revision_id', - 'join_extra' => array( - array( - 'field' => 'deleted', - 'value' => 0, - 'numeric' => TRUE, + // Provide a reverse relationship for the entity type that is referenced by + // the field. + $args['@entity'] = $entity_type->getLabel(); + $args['@label'] = $target_entity_type->getLowercaseLabel(); + $pseudo_field_name = 'reverse__' . $entity_type_id . '__' . $field_name . '_target_' . $column; + $data[$target_base_table][$pseudo_field_name]['relationship'] = array( + 'title' => $key == 'id' ? t('@entity using @field_name', $args) : t('@entity revision using @field_name', $args), + 'label' => $key == 'id' ? t('@field_name', array('@field_name' => $field_name)) : t('@field_name revision', array('@field_name' => $field_name)), + 'group' => $target_entity_type->getLabel(), + 'help' => $key == 'id' ? t('Relate each @entity with a @field_name set to the @label.', $args) : t('Relate each @entity revision with a @field_name set to the @label.', $args), + 'id' => $key == 'id' ? 'entity_reverse' : 'entity_reference_revisions', + 'base' => $base_table, + 'entity_type' => $entity_type_id, + 'base field' => $entity_type->getKey($key), + 'revision' => $key == 'revision', + 'field_name' => $field_name, + 'field table' => $key == 'id' ? $table_mapping->getDedicatedDataTableName($field_storage) : $table_mapping->getDedicatedRevisionTableName($field_storage), + 'field field' => $field_name . '_target_' . $column, + 'join_extra' => array( + array( + 'field' => 'deleted', + 'value' => 0, + 'numeric' => TRUE, + ), ), - ), - ); + ); + } } return $data; diff --git a/src/Plugin/views/relationship/EntityReferenceRevisions.php b/src/Plugin/views/relationship/EntityReferenceRevisions.php new file mode 100644 index 0000000..4215ff0 --- /dev/null +++ b/src/Plugin/views/relationship/EntityReferenceRevisions.php @@ -0,0 +1,107 @@ +joinManager = $join_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('plugin.manager.views.join') + ); + } + + /** + * Called to implement a relationship in a query. + */ + public function query() { + $this->ensureMyTable(); + // First, relate our base table to the current base table to the + // field, using the base table's id field to the field's column. + $views_data = Views::viewsData()->get($this->table); + $left_field = $views_data['table']['base']['field']; + + $first = array( + 'left_table' => $this->tableAlias, + 'left_field' => $left_field, + 'table' => $this->definition['field table'], + 'field' => $this->definition['field field'], + 'adjusted' => TRUE + ); + if (!empty($this->options['required'])) { + $first['type'] = 'INNER'; + } + + if (!empty($this->definition['join_extra'])) { + $first['extra'] = $this->definition['join_extra']; + } + + if (!empty($def['join_id'])) { + $id = $def['join_id']; + } + else { + $id = 'standard'; + } + $first_join = $this->joinManager->createInstance($id, $first); + + + $this->first_alias = $this->query->addTable($this->definition['field table'], $this->relationship, $first_join); + + // Second, relate the field table to the entity specified using + // the entity id on the field table and the entity's id field. + $second = array( + 'left_table' => $this->first_alias, + 'left_field' => !empty($this->definition['revision']) ? 'revision_id' : 'entity_id', + 'table' => $this->definition['base'], + 'field' => $this->definition['base field'], + 'adjusted' => TRUE + ); + + if (!empty($this->options['required'])) { + $second['type'] = 'INNER'; + } + + if (!empty($def['join_id'])) { + $id = $def['join_id']; + } + else { + $id = 'standard'; + } + $second_join = $this->joinManager->createInstance($id, $second); + $second_join->adjusted = TRUE; + + // use a short alias for this: + $alias = $this->definition['field_name'] . '_' . $this->table; + + $this->alias = $this->query->addRelationship($alias, $second_join, $this->definition['base'], $this->relationship); + } + +}