Same name and namespace in other branches
  1. 8.9.x core/modules/views/src/EntityViewsData.php \Drupal\views\EntityViewsData::getViewsData()
  2. 9 core/modules/views/src/EntityViewsData.php \Drupal\views\EntityViewsData::getViewsData()

Returns views data for the entity type.

Return value

array Views data in the format of hook_views_data().

Overrides EntityViewsDataInterface::getViewsData

8 calls to EntityViewsData::getViewsData()
BlockContentViewsData::getViewsData in core/modules/block_content/src/BlockContentViewsData.php
Returns views data for the entity type.
CommentViewsData::getViewsData in core/modules/comment/src/CommentViewsData.php
Returns views data for the entity type.
EntityTestViewsData::getViewsData in core/modules/system/tests/modules/entity_test/src/EntityTestViewsData.php
Returns views data for the entity type.
FileViewsData::getViewsData in core/modules/file/src/FileViewsData.php
Returns views data for the entity type.
MediaViewsData::getViewsData in core/modules/media/src/MediaViewsData.php
Returns views data for the entity type.

... See full list

8 methods override EntityViewsData::getViewsData()
BlockContentViewsData::getViewsData in core/modules/block_content/src/BlockContentViewsData.php
Returns views data for the entity type.
CommentViewsData::getViewsData in core/modules/comment/src/CommentViewsData.php
Returns views data for the entity type.
EntityTestViewsData::getViewsData in core/modules/system/tests/modules/entity_test/src/EntityTestViewsData.php
Returns views data for the entity type.
FileViewsData::getViewsData in core/modules/file/src/FileViewsData.php
Returns views data for the entity type.
MediaViewsData::getViewsData in core/modules/media/src/MediaViewsData.php
Returns views data for the entity type.

... See full list

File

core/modules/views/src/EntityViewsData.php, line 130

Class

EntityViewsData
Provides generic views integration for entities.

Namespace

Drupal\views

Code

public function getViewsData() {
  $data = [];
  $base_table = $this->entityType
    ->getBaseTable() ?: $this->entityType
    ->id();
  $views_revision_base_table = NULL;
  $revisionable = $this->entityType
    ->isRevisionable();
  $entity_id_key = $this->entityType
    ->getKey('id');
  $entity_keys = $this->entityType
    ->getKeys();
  $revision_table = '';
  if ($revisionable) {
    $revision_table = $this->entityType
      ->getRevisionTable() ?: $this->entityType
      ->id() . '_revision';
  }
  $translatable = $this->entityType
    ->isTranslatable();
  $data_table = '';
  if ($translatable) {
    $data_table = $this->entityType
      ->getDataTable() ?: $this->entityType
      ->id() . '_field_data';
  }

  // Some entity types do not have a revision data table defined, but still
  // have a revision table name set in
  // \Drupal\Core\Entity\Sql\SqlContentEntityStorage::initTableLayout() so we
  // apply the same kind of logic.
  $revision_data_table = '';
  if ($revisionable && $translatable) {
    $revision_data_table = $this->entityType
      ->getRevisionDataTable() ?: $this->entityType
      ->id() . '_field_revision';
  }
  $entity_revision_key = $this->entityType
    ->getKey('revision');
  $revision_field = $entity_revision_key;

  // Setup base information of the views data.
  $data[$base_table]['table']['group'] = $this->entityType
    ->getLabel();
  $data[$base_table]['table']['provider'] = $this->entityType
    ->getProvider();
  $views_base_table = $base_table;
  if ($data_table) {
    $views_base_table = $data_table;
  }
  $data[$views_base_table]['table']['base'] = [
    'field' => $entity_id_key,
    'title' => $this->entityType
      ->getLabel(),
    'cache_contexts' => $this->entityType
      ->getListCacheContexts(),
    'access query tag' => $this->entityType
      ->id() . '_access',
  ];
  $data[$base_table]['table']['entity revision'] = FALSE;
  if ($label_key = $this->entityType
    ->getKey('label')) {
    if ($data_table) {
      $data[$views_base_table]['table']['base']['defaults'] = [
        'field' => $label_key,
        'table' => $data_table,
      ];
    }
    else {
      $data[$views_base_table]['table']['base']['defaults'] = [
        'field' => $label_key,
      ];
    }
  }

  // Entity types must implement a list_builder in order to use Views'
  // entity operations field.
  if ($this->entityType
    ->hasListBuilderClass()) {
    $data[$base_table]['operations'] = [
      'field' => [
        'title' => $this
          ->t('Operations links'),
        'help' => $this
          ->t('Provides links to perform entity operations.'),
        'id' => 'entity_operations',
      ],
    ];
    if ($revision_table) {
      $data[$revision_table]['operations'] = [
        'field' => [
          'title' => $this
            ->t('Operations links'),
          'help' => $this
            ->t('Provides links to perform entity operations.'),
          'id' => 'entity_operations',
        ],
      ];
    }
  }
  if ($this->entityType
    ->hasViewBuilderClass()) {
    $data[$base_table]['rendered_entity'] = [
      'field' => [
        'title' => $this
          ->t('Rendered entity'),
        'help' => $this
          ->t('Renders an entity in a view mode.'),
        'id' => 'rendered_entity',
      ],
    ];
  }

  // Setup relations to the revisions/property data.
  if ($data_table) {
    $data[$base_table]['table']['join'][$data_table] = [
      'left_field' => $entity_id_key,
      'field' => $entity_id_key,
      'type' => 'INNER',
    ];
    $data[$data_table]['table']['group'] = $this->entityType
      ->getLabel();
    $data[$data_table]['table']['provider'] = $this->entityType
      ->getProvider();
    $data[$data_table]['table']['entity revision'] = FALSE;
  }
  if ($revision_table) {
    $data[$revision_table]['table']['group'] = $this
      ->t('@entity_type revision', [
      '@entity_type' => $this->entityType
        ->getLabel(),
    ]);
    $data[$revision_table]['table']['provider'] = $this->entityType
      ->getProvider();
    $data[$revision_table]['table']['entity revision'] = TRUE;
    $views_revision_base_table = $revision_table;
    if ($revision_data_table) {
      $views_revision_base_table = $revision_data_table;
    }
    $data[$views_revision_base_table]['table']['entity revision'] = TRUE;
    $data[$views_revision_base_table]['table']['base'] = [
      'field' => $revision_field,
      'title' => $this
        ->t('@entity_type revisions', [
        '@entity_type' => $this->entityType
          ->getLabel(),
      ]),
    ];

    // Join the revision table to the base table.
    $data[$views_revision_base_table]['table']['join'][$views_base_table] = [
      'left_field' => $revision_field,
      'field' => $revision_field,
      'type' => 'INNER',
    ];
    if ($revision_data_table) {
      $data[$revision_data_table]['table']['group'] = $this
        ->t('@entity_type revision', [
        '@entity_type' => $this->entityType
          ->getLabel(),
      ]);
      $data[$revision_data_table]['table']['entity revision'] = TRUE;
      $data[$revision_table]['table']['join'][$revision_data_table] = [
        'left_field' => $revision_field,
        'field' => $revision_field,
        'type' => 'INNER',
      ];
    }

    // Add a filter for showing only the latest revisions of an entity.
    $data[$revision_table]['latest_revision'] = [
      'title' => $this
        ->t('Is Latest Revision'),
      'help' => $this
        ->t('Restrict the view to only revisions that are the latest revision of their entity.'),
      'filter' => [
        'id' => 'latest_revision',
      ],
    ];
    if ($this->entityType
      ->isTranslatable()) {
      $data[$revision_table]['latest_translation_affected_revision'] = [
        'title' => $this
          ->t('Is Latest Translation Affected Revision'),
        'help' => $this
          ->t('Restrict the view to only revisions that are the latest translation affected revision of their entity.'),
        'filter' => [
          'id' => 'latest_translation_affected_revision',
        ],
      ];
    }

    // Add a relationship from the revision table back to the main table.
    $entity_type_label = $this->entityType
      ->getLabel();
    $data[$views_revision_base_table][$entity_id_key]['relationship'] = [
      'id' => 'standard',
      'base' => $views_base_table,
      'base field' => $entity_id_key,
      'title' => $entity_type_label,
      'help' => $this
        ->t('Get the actual @label from a @label revision', [
        '@label' => $entity_type_label,
      ]),
    ];
    $data[$views_revision_base_table][$entity_revision_key]['relationship'] = [
      'id' => 'standard',
      'base' => $views_base_table,
      'base field' => $entity_revision_key,
      'title' => $this
        ->t('@label revision', [
        '@label' => $entity_type_label,
      ]),
      'help' => $this
        ->t('Get the actual @label from a @label revision', [
        '@label' => $entity_type_label,
      ]),
    ];
    if ($translatable) {
      $extra = [
        'field' => $entity_keys['langcode'],
        'left_field' => $entity_keys['langcode'],
      ];
      $data[$views_revision_base_table][$entity_id_key]['relationship']['extra'][] = $extra;
      $data[$views_revision_base_table][$entity_revision_key]['relationship']['extra'][] = $extra;
      $data[$revision_table]['table']['join'][$views_base_table]['left_field'] = $entity_revision_key;
      $data[$revision_table]['table']['join'][$views_base_table]['field'] = $entity_revision_key;
    }
  }
  $this
    ->addEntityLinks($data[$base_table]);
  if ($views_revision_base_table) {
    $this
      ->addEntityLinks($data[$views_revision_base_table]);
  }

  // Load all typed data definitions of all fields. This should cover each of
  // the entity base, revision, data tables.
  $field_definitions = $this->entityFieldManager
    ->getBaseFieldDefinitions($this->entityType
    ->id());

  /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
  $table_mapping = $this->storage
    ->getTableMapping($field_definitions);

  // Fetch all fields that can appear in both the base table and the data
  // table.
  $duplicate_fields = array_intersect_key($entity_keys, array_flip([
    'id',
    'revision',
    'bundle',
  ]));

  // 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 field 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) {

      // To avoid confusing duplication in the user interface, for fields
      // that are on both base and data tables, only add them on the data
      // table (same for revision vs. revision data).
      if ($data_table && ($table === $base_table || $table === $revision_table) && in_array($field_name, $duplicate_fields)) {
        continue;
      }
      $this
        ->mapFieldDefinition($table, $field_name, $field_definitions[$field_name], $table_mapping, $data[$table]);
    }
  }
  foreach ($field_definitions as $field_definition) {
    if ($table_mapping
      ->requiresDedicatedTableStorage($field_definition
      ->getFieldStorageDefinition())) {
      $table = $table_mapping
        ->getDedicatedDataTableName($field_definition
        ->getFieldStorageDefinition());
      $data[$table]['table']['group'] = $this->entityType
        ->getLabel();
      $data[$table]['table']['provider'] = $this->entityType
        ->getProvider();
      $data[$table]['table']['join'][$views_base_table] = [
        'left_field' => $entity_id_key,
        'field' => 'entity_id',
        'extra' => [
          [
            'field' => 'deleted',
            'value' => 0,
            'numeric' => TRUE,
          ],
        ],
      ];
      if ($revisionable) {
        $revision_table = $table_mapping
          ->getDedicatedRevisionTableName($field_definition
          ->getFieldStorageDefinition());
        $data[$revision_table]['table']['group'] = $this
          ->t('@entity_type revision', [
          '@entity_type' => $this->entityType
            ->getLabel(),
        ]);
        $data[$revision_table]['table']['provider'] = $this->entityType
          ->getProvider();
        $data[$revision_table]['table']['join'][$views_revision_base_table] = [
          'left_field' => $revision_field,
          'field' => 'entity_id',
          'extra' => [
            [
              'field' => 'deleted',
              'value' => 0,
              'numeric' => TRUE,
            ],
          ],
        ];
      }
    }
  }
  if ($uid_key = $entity_keys['uid'] ?? '') {
    $data[$data_table][$uid_key]['filter']['id'] = 'user_name';
  }
  if ($revision_table && ($revision_uid_key = $this->entityType
    ->getRevisionMetadataKeys()['revision_user'] ?? '')) {
    $data[$revision_table][$revision_uid_key]['filter']['id'] = 'user_name';
  }

  // Add the entity type key to each table generated.
  $entity_type_id = $this->entityType
    ->id();
  array_walk($data, function (&$table_data) use ($entity_type_id) {
    $table_data['table']['entity type'] = $entity_type_id;
  });
  return $data;
}