EntityViewsData.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. <?php
  2. namespace Drupal\views;
  3. use Drupal\Core\Entity\ContentEntityType;
  4. use Drupal\Core\Entity\EntityHandlerInterface;
  5. use Drupal\Core\Entity\EntityManagerInterface;
  6. use Drupal\Core\Entity\EntityTypeInterface;
  7. use Drupal\Core\Entity\Sql\SqlEntityStorageInterface;
  8. use Drupal\Core\Entity\Sql\TableMappingInterface;
  9. use Drupal\Core\Extension\ModuleHandlerInterface;
  10. use Drupal\Core\Field\FieldDefinitionInterface;
  11. use Drupal\Core\StringTranslation\StringTranslationTrait;
  12. use Drupal\Core\StringTranslation\TranslationInterface;
  13. use Symfony\Component\DependencyInjection\Container;
  14. use Symfony\Component\DependencyInjection\ContainerInterface;
  15. /**
  16. * Provides generic views integration for entities.
  17. */
  18. class EntityViewsData implements EntityHandlerInterface, EntityViewsDataInterface {
  19. use StringTranslationTrait;
  20. /**
  21. * Entity type for this views data handler instance.
  22. *
  23. * @var \Drupal\Core\Entity\EntityTypeInterface
  24. */
  25. protected $entityType;
  26. /**
  27. * The storage used for this entity type.
  28. *
  29. * @var \Drupal\Core\Entity\Sql\SqlEntityStorageInterface
  30. */
  31. protected $storage;
  32. /**
  33. * The module handler.
  34. *
  35. * @var \Drupal\Core\Extension\ModuleHandlerInterface
  36. */
  37. protected $moduleHandler;
  38. /**
  39. * The translation manager.
  40. *
  41. * @var \Drupal\Core\StringTranslation\TranslationInterface
  42. */
  43. protected $translationManager;
  44. /**
  45. * The field storage definitions for all base fields of the entity type.
  46. *
  47. * @var \Drupal\Core\Field\FieldStorageDefinitionInterface[]
  48. */
  49. protected $fieldStorageDefinitions;
  50. /**
  51. * The entity manager.
  52. *
  53. * @var \Drupal\Core\Entity\EntityManagerInterface
  54. */
  55. protected $entityManager;
  56. /**
  57. * Constructs an EntityViewsData object.
  58. *
  59. * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
  60. * The entity type to provide views integration for.
  61. * @param \Drupal\Core\Entity\Sql\SqlEntityStorageInterface $storage_controller
  62. * The storage handler used for this entity type.
  63. * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
  64. * The entity manager.
  65. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
  66. * The module handler.
  67. * @param \Drupal\Core\StringTranslation\TranslationInterface $translation_manager
  68. * The translation manager.
  69. */
  70. public function __construct(EntityTypeInterface $entity_type, SqlEntityStorageInterface $storage_controller, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, TranslationInterface $translation_manager) {
  71. $this->entityType = $entity_type;
  72. $this->entityManager = $entity_manager;
  73. $this->storage = $storage_controller;
  74. $this->moduleHandler = $module_handler;
  75. $this->setStringTranslation($translation_manager);
  76. }
  77. /**
  78. * {@inheritdoc}
  79. */
  80. public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
  81. return new static(
  82. $entity_type,
  83. $container->get('entity.manager')->getStorage($entity_type->id()),
  84. $container->get('entity.manager'),
  85. $container->get('module_handler'),
  86. $container->get('string_translation'),
  87. $container->get('typed_data_manager')
  88. );
  89. }
  90. /**
  91. * Gets the field storage definitions.
  92. *
  93. * @return \Drupal\Core\Field\FieldStorageDefinitionInterface[]
  94. */
  95. protected function getFieldStorageDefinitions() {
  96. if (!isset($this->fieldStorageDefinitions)) {
  97. $this->fieldStorageDefinitions = $this->entityManager->getFieldStorageDefinitions($this->entityType->id());
  98. }
  99. return $this->fieldStorageDefinitions;
  100. }
  101. /**
  102. * {@inheritdoc}
  103. */
  104. public function getViewsData() {
  105. $data = [];
  106. $base_table = $this->entityType->getBaseTable() ?: $this->entityType->id();
  107. $views_revision_base_table = NULL;
  108. $revisionable = $this->entityType->isRevisionable();
  109. $base_field = $this->entityType->getKey('id');
  110. $revision_table = '';
  111. if ($revisionable) {
  112. $revision_table = $this->entityType->getRevisionTable() ?: $this->entityType->id() . '_revision';
  113. }
  114. $translatable = $this->entityType->isTranslatable();
  115. $data_table = '';
  116. if ($translatable) {
  117. $data_table = $this->entityType->getDataTable() ?: $this->entityType->id() . '_field_data';
  118. }
  119. // Some entity types do not have a revision data table defined, but still
  120. // have a revision table name set in
  121. // \Drupal\Core\Entity\Sql\SqlContentEntityStorage::initTableLayout() so we
  122. // apply the same kind of logic.
  123. $revision_data_table = '';
  124. if ($revisionable && $translatable) {
  125. $revision_data_table = $this->entityType->getRevisionDataTable() ?: $this->entityType->id() . '_field_revision';
  126. }
  127. $revision_field = $this->entityType->getKey('revision');
  128. // Setup base information of the views data.
  129. $data[$base_table]['table']['group'] = $this->entityType->getLabel();
  130. $data[$base_table]['table']['provider'] = $this->entityType->getProvider();
  131. $views_base_table = $base_table;
  132. if ($data_table) {
  133. $views_base_table = $data_table;
  134. }
  135. $data[$views_base_table]['table']['base'] = [
  136. 'field' => $base_field,
  137. 'title' => $this->entityType->getLabel(),
  138. 'cache_contexts' => $this->entityType->getListCacheContexts(),
  139. ];
  140. $data[$base_table]['table']['entity revision'] = FALSE;
  141. if ($label_key = $this->entityType->getKey('label')) {
  142. if ($data_table) {
  143. $data[$views_base_table]['table']['base']['defaults'] = [
  144. 'field' => $label_key,
  145. 'table' => $data_table,
  146. ];
  147. }
  148. else {
  149. $data[$views_base_table]['table']['base']['defaults'] = [
  150. 'field' => $label_key,
  151. ];
  152. }
  153. }
  154. // Entity types must implement a list_builder in order to use Views'
  155. // entity operations field.
  156. if ($this->entityType->hasListBuilderClass()) {
  157. $data[$base_table]['operations'] = [
  158. 'field' => [
  159. 'title' => $this->t('Operations links'),
  160. 'help' => $this->t('Provides links to perform entity operations.'),
  161. 'id' => 'entity_operations',
  162. ],
  163. ];
  164. $data[$revision_table]['operations'] = [
  165. 'field' => [
  166. 'title' => $this->t('Operations links'),
  167. 'help' => $this->t('Provides links to perform entity operations.'),
  168. 'id' => 'entity_operations',
  169. ],
  170. ];
  171. }
  172. if ($this->entityType->hasViewBuilderClass()) {
  173. $data[$base_table]['rendered_entity'] = [
  174. 'field' => [
  175. 'title' => $this->t('Rendered entity'),
  176. 'help' => $this->t('Renders an entity in a view mode.'),
  177. 'id' => 'rendered_entity',
  178. ],
  179. ];
  180. }
  181. // Setup relations to the revisions/property data.
  182. if ($data_table) {
  183. $data[$base_table]['table']['join'][$data_table] = [
  184. 'left_field' => $base_field,
  185. 'field' => $base_field,
  186. 'type' => 'INNER',
  187. ];
  188. $data[$data_table]['table']['group'] = $this->entityType->getLabel();
  189. $data[$data_table]['table']['provider'] = $this->entityType->getProvider();
  190. $data[$data_table]['table']['entity revision'] = FALSE;
  191. }
  192. if ($revision_table) {
  193. $data[$revision_table]['table']['group'] = $this->t('@entity_type revision', ['@entity_type' => $this->entityType->getLabel()]);
  194. $data[$revision_table]['table']['provider'] = $this->entityType->getProvider();
  195. $views_revision_base_table = $revision_table;
  196. if ($revision_data_table) {
  197. $views_revision_base_table = $revision_data_table;
  198. }
  199. $data[$views_revision_base_table]['table']['entity revision'] = TRUE;
  200. $data[$views_revision_base_table]['table']['base'] = [
  201. 'field' => $revision_field,
  202. 'title' => $this->t('@entity_type revisions', ['@entity_type' => $this->entityType->getLabel()]),
  203. ];
  204. // Join the revision table to the base table.
  205. $data[$views_revision_base_table]['table']['join'][$views_base_table] = [
  206. 'left_field' => $revision_field,
  207. 'field' => $revision_field,
  208. 'type' => 'INNER',
  209. ];
  210. if ($revision_data_table) {
  211. $data[$revision_data_table]['table']['group'] = $this->t('@entity_type revision', ['@entity_type' => $this->entityType->getLabel()]);
  212. $data[$revision_data_table]['table']['entity revision'] = TRUE;
  213. $data[$revision_table]['table']['join'][$revision_data_table] = [
  214. 'left_field' => $revision_field,
  215. 'field' => $revision_field,
  216. 'type' => 'INNER',
  217. ];
  218. }
  219. // Add a filter for showing only the latest revisions of an entity.
  220. $data[$revision_table]['latest_revision'] = [
  221. 'title' => $this->t('Is Latest Revision'),
  222. 'help' => $this->t('Restrict the view to only revisions that are the latest revision of their entity.'),
  223. 'filter' => ['id' => 'latest_revision'],
  224. ];
  225. }
  226. $this->addEntityLinks($data[$base_table]);
  227. if ($views_revision_base_table) {
  228. $this->addEntityLinks($data[$views_revision_base_table]);
  229. }
  230. // Load all typed data definitions of all fields. This should cover each of
  231. // the entity base, revision, data tables.
  232. $field_definitions = $this->entityManager->getBaseFieldDefinitions($this->entityType->id());
  233. /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
  234. if ($table_mapping = $this->storage->getTableMapping($field_definitions)) {
  235. // Fetch all fields that can appear in both the base table and the data
  236. // table.
  237. $entity_keys = $this->entityType->getKeys();
  238. $duplicate_fields = array_intersect_key($entity_keys, array_flip(['id', 'revision', 'bundle']));
  239. // Iterate over each table we have so far and collect field data for each.
  240. // Based on whether the field is in the field_definitions provided by the
  241. // entity manager.
  242. // @todo We should better just rely on information coming from the entity
  243. // storage.
  244. // @todo https://www.drupal.org/node/2337511
  245. foreach ($table_mapping->getTableNames() as $table) {
  246. foreach ($table_mapping->getFieldNames($table) as $field_name) {
  247. // To avoid confusing duplication in the user interface, for fields
  248. // that are on both base and data tables, only add them on the data
  249. // table (same for revision vs. revision data).
  250. if ($data_table && ($table === $base_table || $table === $revision_table) && in_array($field_name, $duplicate_fields)) {
  251. continue;
  252. }
  253. $this->mapFieldDefinition($table, $field_name, $field_definitions[$field_name], $table_mapping, $data[$table]);
  254. }
  255. }
  256. foreach ($field_definitions as $field_definition) {
  257. if ($table_mapping->requiresDedicatedTableStorage($field_definition->getFieldStorageDefinition())) {
  258. $table = $table_mapping->getDedicatedDataTableName($field_definition->getFieldStorageDefinition());
  259. $data[$table]['table']['group'] = $this->entityType->getLabel();
  260. $data[$table]['table']['provider'] = $this->entityType->getProvider();
  261. $data[$table]['table']['join'][$views_base_table] = [
  262. 'left_field' => $base_field,
  263. 'field' => 'entity_id',
  264. 'extra' => [
  265. ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE],
  266. ],
  267. ];
  268. if ($revisionable) {
  269. $revision_table = $table_mapping->getDedicatedRevisionTableName($field_definition->getFieldStorageDefinition());
  270. $data[$revision_table]['table']['group'] = $this->t('@entity_type revision', ['@entity_type' => $this->entityType->getLabel()]);
  271. $data[$revision_table]['table']['provider'] = $this->entityType->getProvider();
  272. $data[$revision_table]['table']['join'][$views_revision_base_table] = [
  273. 'left_field' => $revision_field,
  274. 'field' => 'entity_id',
  275. 'extra' => [
  276. ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE],
  277. ],
  278. ];
  279. }
  280. }
  281. }
  282. }
  283. // Add the entity type key to each table generated.
  284. $entity_type_id = $this->entityType->id();
  285. array_walk($data, function (&$table_data) use ($entity_type_id) {
  286. $table_data['table']['entity type'] = $entity_type_id;
  287. });
  288. return $data;
  289. }
  290. /**
  291. * Sets the entity links in case corresponding link templates exist.
  292. *
  293. * @param array $data
  294. * The views data of the base table.
  295. */
  296. protected function addEntityLinks(array &$data) {
  297. $entity_type_id = $this->entityType->id();
  298. $t_arguments = ['@entity_type_label' => $this->entityType->getLabel()];
  299. if ($this->entityType->hasLinkTemplate('canonical')) {
  300. $data['view_' . $entity_type_id] = [
  301. 'field' => [
  302. 'title' => $this->t('Link to @entity_type_label', $t_arguments),
  303. 'help' => $this->t('Provide a view link to the @entity_type_label.', $t_arguments),
  304. 'id' => 'entity_link',
  305. ],
  306. ];
  307. }
  308. if ($this->entityType->hasLinkTemplate('edit-form')) {
  309. $data['edit_' . $entity_type_id] = [
  310. 'field' => [
  311. 'title' => $this->t('Link to edit @entity_type_label', $t_arguments),
  312. 'help' => $this->t('Provide an edit link to the @entity_type_label.', $t_arguments),
  313. 'id' => 'entity_link_edit',
  314. ],
  315. ];
  316. }
  317. if ($this->entityType->hasLinkTemplate('delete-form')) {
  318. $data['delete_' . $entity_type_id] = [
  319. 'field' => [
  320. 'title' => $this->t('Link to delete @entity_type_label', $t_arguments),
  321. 'help' => $this->t('Provide a delete link to the @entity_type_label.', $t_arguments),
  322. 'id' => 'entity_link_delete',
  323. ],
  324. ];
  325. }
  326. }
  327. /**
  328. * Puts the views data for a single field onto the views data.
  329. *
  330. * @param string $table
  331. * The table of the field to handle.
  332. * @param string $field_name
  333. * The name of the field to handle.
  334. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
  335. * The field definition defined in Entity::baseFieldDefinitions()
  336. * @param \Drupal\Core\Entity\Sql\TableMappingInterface $table_mapping
  337. * The table mapping information
  338. * @param array $table_data
  339. * A reference to a specific entity table (for example data_table) inside
  340. * the views data.
  341. */
  342. protected function mapFieldDefinition($table, $field_name, FieldDefinitionInterface $field_definition, TableMappingInterface $table_mapping, &$table_data) {
  343. // Create a dummy instance to retrieve property definitions.
  344. $field_column_mapping = $table_mapping->getColumnNames($field_name);
  345. $field_schema = $this->getFieldStorageDefinitions()[$field_name]->getSchema();
  346. $field_definition_type = $field_definition->getType();
  347. // Add all properties to views table data. We need an entry for each
  348. // column of each field, with the first one given special treatment.
  349. // @todo Introduce concept of the "main" column for a field, rather than
  350. // assuming the first one is the main column. See also what the
  351. // mapSingleFieldViewsData() method does with $first.
  352. $first = TRUE;
  353. foreach ($field_column_mapping as $field_column_name => $schema_field_name) {
  354. $table_data[$schema_field_name] = $this->mapSingleFieldViewsData($table, $field_name, $field_definition_type, $field_column_name, $field_schema['columns'][$field_column_name]['type'], $first, $field_definition);
  355. $table_data[$schema_field_name]['entity field'] = $field_name;
  356. $first = FALSE;
  357. }
  358. }
  359. /**
  360. * Provides the views data for a given data type and schema field.
  361. *
  362. * @param string $table
  363. * The table of the field to handle.
  364. * @param string $field_name
  365. * The machine name of the field being processed.
  366. * @param string $field_type
  367. * The type of field being handled.
  368. * @param string $column_name
  369. * For fields containing multiple columns, the column name being processed.
  370. * @param string $column_type
  371. * Within the field, the column type being handled.
  372. * @param bool $first
  373. * TRUE if this is the first column within the field.
  374. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
  375. * The field definition.
  376. *
  377. * @return array
  378. * The modified views data field definition.
  379. */
  380. protected function mapSingleFieldViewsData($table, $field_name, $field_type, $column_name, $column_type, $first, FieldDefinitionInterface $field_definition) {
  381. $views_field = [];
  382. // Provide a nicer, less verbose label for the first column within a field.
  383. // @todo Introduce concept of the "main" column for a field, rather than
  384. // assuming the first one is the main column.
  385. if ($first) {
  386. $views_field['title'] = $field_definition->getLabel();
  387. }
  388. else {
  389. $views_field['title'] = $field_definition->getLabel() . " ($column_name)";
  390. }
  391. if ($description = $field_definition->getDescription()) {
  392. $views_field['help'] = $description;
  393. }
  394. // Set up the field, sort, argument, and filters, based on
  395. // the column and/or field data type.
  396. // @todo Allow field types to customize this.
  397. // @see https://www.drupal.org/node/2337515
  398. switch ($field_type) {
  399. // Special case a few field types.
  400. case 'timestamp':
  401. case 'created':
  402. case 'changed':
  403. $views_field['field']['id'] = 'field';
  404. $views_field['argument']['id'] = 'date';
  405. $views_field['filter']['id'] = 'date';
  406. $views_field['sort']['id'] = 'date';
  407. break;
  408. case 'language':
  409. $views_field['field']['id'] = 'field';
  410. $views_field['argument']['id'] = 'language';
  411. $views_field['filter']['id'] = 'language';
  412. $views_field['sort']['id'] = 'standard';
  413. break;
  414. case 'boolean':
  415. $views_field['field']['id'] = 'field';
  416. $views_field['argument']['id'] = 'numeric';
  417. $views_field['filter']['id'] = 'boolean';
  418. $views_field['sort']['id'] = 'standard';
  419. break;
  420. case 'uri':
  421. // Let's render URIs as URIs by default, not links.
  422. $views_field['field']['id'] = 'field';
  423. $views_field['field']['default_formatter'] = 'string';
  424. $views_field['argument']['id'] = 'string';
  425. $views_field['filter']['id'] = 'string';
  426. $views_field['sort']['id'] = 'standard';
  427. break;
  428. case 'text':
  429. case 'text_with_summary':
  430. // Treat these three long text fields the same.
  431. $field_type = 'text_long';
  432. // Intentional fall-through here to the default processing!
  433. default:
  434. // For most fields, the field type is generic enough to just use
  435. // the column type to determine the filters etc.
  436. switch ($column_type) {
  437. case 'int':
  438. case 'integer':
  439. case 'smallint':
  440. case 'tinyint':
  441. case 'mediumint':
  442. case 'float':
  443. case 'double':
  444. case 'decimal':
  445. $views_field['field']['id'] = 'field';
  446. $views_field['argument']['id'] = 'numeric';
  447. $views_field['filter']['id'] = 'numeric';
  448. $views_field['sort']['id'] = 'standard';
  449. break;
  450. case 'char':
  451. case 'string':
  452. case 'varchar':
  453. case 'varchar_ascii':
  454. case 'tinytext':
  455. case 'text':
  456. case 'mediumtext':
  457. case 'longtext':
  458. $views_field['field']['id'] = 'field';
  459. $views_field['argument']['id'] = 'string';
  460. $views_field['filter']['id'] = 'string';
  461. $views_field['sort']['id'] = 'standard';
  462. break;
  463. default:
  464. $views_field['field']['id'] = 'field';
  465. $views_field['argument']['id'] = 'standard';
  466. $views_field['filter']['id'] = 'standard';
  467. $views_field['sort']['id'] = 'standard';
  468. }
  469. }
  470. // Do post-processing for a few field types.
  471. $process_method = 'processViewsDataFor' . Container::camelize($field_type);
  472. if (method_exists($this, $process_method)) {
  473. $this->{$process_method}($table, $field_definition, $views_field, $column_name);
  474. }
  475. return $views_field;
  476. }
  477. /**
  478. * Processes the views data for a language field.
  479. *
  480. * @param string $table
  481. * The table the language field is added to.
  482. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
  483. * The field definition.
  484. * @param array $views_field
  485. * The views field data.
  486. * @param string $field_column_name
  487. * The field column being processed.
  488. */
  489. protected function processViewsDataForLanguage($table, FieldDefinitionInterface $field_definition, array &$views_field, $field_column_name) {
  490. // Apply special titles for the langcode field.
  491. if ($field_definition->getName() == $this->entityType->getKey('langcode')) {
  492. if ($table == $this->entityType->getDataTable() || $table == $this->entityType->getRevisionDataTable()) {
  493. $views_field['title'] = $this->t('Translation language');
  494. }
  495. if ($table == $this->entityType->getBaseTable() || $table == $this->entityType->getRevisionTable()) {
  496. $views_field['title'] = $this->t('Original language');
  497. }
  498. }
  499. }
  500. /**
  501. * Processes the views data for an entity reference field.
  502. *
  503. * @param string $table
  504. * The table the language field is added to.
  505. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
  506. * The field definition.
  507. * @param array $views_field
  508. * The views field data.
  509. * @param string $field_column_name
  510. * The field column being processed.
  511. */
  512. protected function processViewsDataForEntityReference($table, FieldDefinitionInterface $field_definition, array &$views_field, $field_column_name) {
  513. // @todo Should the actual field handler respect that this just renders a
  514. // number?
  515. // @todo Create an optional entity field handler, that can render the
  516. // entity.
  517. // @see https://www.drupal.org/node/2322949
  518. if ($entity_type_id = $field_definition->getItemDefinition()->getSetting('target_type')) {
  519. $entity_type = $this->entityManager->getDefinition($entity_type_id);
  520. if ($entity_type instanceof ContentEntityType) {
  521. $views_field['relationship'] = [
  522. 'base' => $this->getViewsTableForEntityType($entity_type),
  523. 'base field' => $entity_type->getKey('id'),
  524. 'label' => $entity_type->getLabel(),
  525. 'title' => $entity_type->getLabel(),
  526. 'id' => 'standard',
  527. ];
  528. $views_field['field']['id'] = 'field';
  529. $views_field['argument']['id'] = 'numeric';
  530. $views_field['filter']['id'] = 'numeric';
  531. $views_field['sort']['id'] = 'standard';
  532. }
  533. else {
  534. $views_field['field']['id'] = 'field';
  535. $views_field['argument']['id'] = 'string';
  536. $views_field['filter']['id'] = 'string';
  537. $views_field['sort']['id'] = 'standard';
  538. }
  539. }
  540. if ($field_definition->getName() == $this->entityType->getKey('bundle')) {
  541. $views_field['filter']['id'] = 'bundle';
  542. }
  543. }
  544. /**
  545. * Processes the views data for a text field with formatting.
  546. *
  547. * @param string $table
  548. * The table the field is added to.
  549. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
  550. * The field definition.
  551. * @param array $views_field
  552. * The views field data.
  553. * @param string $field_column_name
  554. * The field column being processed.
  555. */
  556. protected function processViewsDataForTextLong($table, FieldDefinitionInterface $field_definition, array &$views_field, $field_column_name) {
  557. // Connect the text field to its formatter.
  558. if ($field_column_name == 'value') {
  559. $views_field['field']['format'] = $field_definition->getName() . '__format';
  560. $views_field['field']['id'] = 'field';
  561. }
  562. }
  563. /**
  564. * Processes the views data for a UUID field.
  565. *
  566. * @param string $table
  567. * The table the field is added to.
  568. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
  569. * The field definition.
  570. * @param array $views_field
  571. * The views field data.
  572. * @param string $field_column_name
  573. * The field column being processed.
  574. */
  575. protected function processViewsDataForUuid($table, FieldDefinitionInterface $field_definition, array &$views_field, $field_column_name) {
  576. // It does not make sense for UUID fields to be click sortable.
  577. $views_field['field']['click sortable'] = FALSE;
  578. }
  579. /**
  580. * {@inheritdoc}
  581. */
  582. public function getViewsTableForEntityType(EntityTypeInterface $entity_type) {
  583. return $entity_type->getDataTable() ?: $entity_type->getBaseTable();
  584. }
  585. }