entity_reference_uuid-8.x-1.x-dev/src/EntityReferenceUuidEntityViewsTrait.php
src/EntityReferenceUuidEntityViewsTrait.php
<?php namespace Drupal\entity_reference_uuid; use Drupal\Core\Entity\ContentEntityType; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\Sql\SqlEntityStorageInterface; use Drupal\Core\Field\FieldDefinitionInterface; /** * Trait to add views relationships for entity_reference_uuid base fields. * * This trait is intended to be used in a subclass of * \Drupal\views\EntityViewsData. */ trait EntityReferenceUuidEntityViewsTrait { /** * Processes the views data for an entity reference UUID field. * * @param string $table * The table the language field is added to. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The field definition. * @param array $views_field * The views field data. * @param string $field_column_name * The field column being processed. * * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ protected function processViewsDataForEntityReferenceUuid($table, FieldDefinitionInterface $field_definition, array &$views_field, $field_column_name) { if ($target_entity_type_id = $field_definition->getItemDefinition()->getSetting('target_type')) { $target_entity_type = $this->getEntityTypeManager()->getDefinition($target_entity_type_id); if ($target_entity_type instanceof ContentEntityType) { $views_field['relationship'] = [ 'base' => $this->getViewsTableForEntityType($target_entity_type), 'base field' => $target_entity_type->getKey('id'), 'entity base table' => $target_entity_type->getBaseTable(), 'entity uuid field' => $target_entity_type->getKey('uuid'), 'label' => $target_entity_type->getLabel(), 'title' => $target_entity_type->getLabel(), 'id' => 'entity_standard_uuid', ]; $views_field['field']['id'] = 'field'; $views_field['argument']['id'] = 'string'; $views_field['filter']['id'] = 'equality'; $views_field['sort']['id'] = 'standard'; $views_field['field']['click sortable'] = FALSE; } } } /** * Helper to be called from getViewsData() in subclass of EntityViewsData. * * @param array $data * The Views data. * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type * The entity type whose base fields we are checking. * @param \Drupal\Core\Entity\Sql\SqlEntityStorageInterface $storage * The entity storage. * * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException * * @see \Drupal\views\EntityViewsData::getViewsData() */ protected function addReverseEntityReferenceUuid(array &$data, EntityTypeInterface $entity_type, SqlEntityStorageInterface $storage) { $entity_type_id = $entity_type->id(); $base_table = $entity_type->getBaseTable() ?: $entity_type_id; $revisionable = $entity_type->isRevisionable(); $revision_table = ''; if ($revisionable) { $revision_table = $entity_type->getRevisionTable() ?: $entity_type_id . '_revision'; } $translatable = $entity_type->isTranslatable(); $data_table = ''; if ($translatable) { $data_table = $entity_type->getDataTable() ?: $entity_type_id . '_field_data'; } // Load all typed data definitions of all fields. This should cover each of // the entity base, revision, data tables. $field_definitions = \Drupal::service('entity_field.manager')->getBaseFieldDefinitions($entity_type_id); /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */ if ($table_mapping = $storage->getTableMapping($field_definitions)) { // Iterate over each table we have so far and collect field data for each. // Based on whether the field is in the field_definitions provided by the // entity manager. // @todo We should better just rely on information coming from the entity // storage. // @todo https://www.drupal.org/node/2337511 foreach ($table_mapping->getTableNames() as $table) { foreach ($table_mapping->getFieldNames($table) as $field_name) { $field_type = $field_definitions[$field_name]->getType(); if ($field_type === 'entity_reference_uuid' && $table !== $revision_table) { $args = []; $target_entity_type_id = $field_definitions[$field_name]->getItemDefinition()->getSetting('target_type'); $target_entity_type = $this->getEntityTypeManager()->getDefinition($target_entity_type_id); // The line below is technically wrong since the UUID is not copied // to the data table, but we use hook_views_data_alter() to make it // appear to be present. $target_base_table = $target_entity_type->getDataTable() ?: $target_entity_type->getBaseTable(); // Provide a reverse relationship for the entity type that is // referenced by the field. $args['@entity'] = $entity_type->getLabel(); $args['@label'] = $target_entity_type->getSingularLabel(); $args['@field_name'] = $field_name; $pseudo_field_name = 'reverse__' . $entity_type_id . '__' . $field_name; $data[$target_base_table][$pseudo_field_name]['relationship'] = [ 'title' => t('@entity using @field_name', $args), 'label' => t('@field_name', ['@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_uuid', 'base' => $entity_type->getDataTable() ?: $entity_type->getBaseTable(), 'entity base table' => $entity_type->getBaseTable(), 'entity_type' => $entity_type_id, 'base field' => $entity_type->getKey('id'), 'target base' => $target_base_table, 'target entity base table' => $target_entity_type->getBaseTable(), 'target entity uuid field' => $target_entity_type->getKey('uuid'), 'target entity base field' => $target_entity_type->getKey('id'), 'field_name' => $field_name, 'field table' => $data_table ?: $base_table, 'field field' => $field_name, ]; // @todo Do we need to add the entity status as join extra? } } } } } /** * Don't fail if this trait is used someplace unexpected. * * @return \Drupal\Core\Entity\EntityTypeManagerInterface * The default entityTypeManager. */ protected function getEntityTypeManager() { return $this->entityTypeManager ?? \Drupal::entityTypeManager(); } /** * {@inheritdoc} * * @see \Drupal\views\EntityViewsData::getViewsTableForEntityType */ public function getViewsTableForEntityType(EntityTypeInterface $entity_type) { return $entity_type->getDataTable() ?: $entity_type->getBaseTable(); } }