EntityViewsData.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  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. // Load all typed data definitions of all fields. This should cover each of
  228. // the entity base, revision, data tables.
  229. $field_definitions = $this->entityManager->getBaseFieldDefinitions($this->entityType->id());
  230. /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
  231. if ($table_mapping = $this->storage->getTableMapping($field_definitions)) {
  232. // Fetch all fields that can appear in both the base table and the data
  233. // table.
  234. $entity_keys = $this->entityType->getKeys();
  235. $duplicate_fields = array_intersect_key($entity_keys, array_flip(['id', 'revision', 'bundle']));
  236. // Iterate over each table we have so far and collect field data for each.
  237. // Based on whether the field is in the field_definitions provided by the
  238. // entity manager.
  239. // @todo We should better just rely on information coming from the entity
  240. // storage.
  241. // @todo https://www.drupal.org/node/2337511
  242. foreach ($table_mapping->getTableNames() as $table) {
  243. foreach ($table_mapping->getFieldNames($table) as $field_name) {
  244. // To avoid confusing duplication in the user interface, for fields
  245. // that are on both base and data tables, only add them on the data
  246. // table (same for revision vs. revision data).
  247. if ($data_table && ($table === $base_table || $table === $revision_table) && in_array($field_name, $duplicate_fields)) {
  248. continue;
  249. }
  250. $this->mapFieldDefinition($table, $field_name, $field_definitions[$field_name], $table_mapping, $data[$table]);
  251. }
  252. }
  253. foreach ($field_definitions as $field_definition) {
  254. if ($table_mapping->requiresDedicatedTableStorage($field_definition->getFieldStorageDefinition())) {
  255. $table = $table_mapping->getDedicatedDataTableName($field_definition->getFieldStorageDefinition());
  256. $data[$table]['table']['group'] = $this->entityType->getLabel();
  257. $data[$table]['table']['provider'] = $this->entityType->getProvider();
  258. $data[$table]['table']['join'][$views_base_table] = [
  259. 'left_field' => $base_field,
  260. 'field' => 'entity_id',
  261. 'extra' => [
  262. ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE],
  263. ],
  264. ];
  265. if ($revisionable) {
  266. $revision_table = $table_mapping->getDedicatedRevisionTableName($field_definition->getFieldStorageDefinition());
  267. $data[$revision_table]['table']['group'] = $this->t('@entity_type revision', ['@entity_type' => $this->entityType->getLabel()]);
  268. $data[$revision_table]['table']['provider'] = $this->entityType->getProvider();
  269. $data[$revision_table]['table']['join'][$views_revision_base_table] = [
  270. 'left_field' => $revision_field,
  271. 'field' => 'entity_id',
  272. 'extra' => [
  273. ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE],
  274. ],
  275. ];
  276. }
  277. }
  278. }
  279. }
  280. // Add the entity type key to each table generated.
  281. $entity_type_id = $this->entityType->id();
  282. array_walk($data, function (&$table_data) use ($entity_type_id) {
  283. $table_data['table']['entity type'] = $entity_type_id;
  284. });
  285. return $data;
  286. }
  287. /**
  288. * Sets the entity links in case corresponding link templates exist.
  289. *
  290. * @param array $data
  291. * The views data of the base table.
  292. */
  293. protected function addEntityLinks(array &$data) {
  294. $entity_type_id = $this->entityType->id();
  295. $t_arguments = ['@entity_type_label' => $this->entityType->getLabel()];
  296. if ($this->entityType->hasLinkTemplate('canonical')) {
  297. $data['view_' . $entity_type_id] = [
  298. 'field' => [
  299. 'title' => $this->t('Link to @entity_type_label', $t_arguments),
  300. 'help' => $this->t('Provide a view link to the @entity_type_label.', $t_arguments),
  301. 'id' => 'entity_link',
  302. ],
  303. ];
  304. }
  305. if ($this->entityType->hasLinkTemplate('edit-form')) {
  306. $data['edit_' . $entity_type_id] = [
  307. 'field' => [
  308. 'title' => $this->t('Link to edit @entity_type_label', $t_arguments),
  309. 'help' => $this->t('Provide an edit link to the @entity_type_label.', $t_arguments),
  310. 'id' => 'entity_link_edit',
  311. ],
  312. ];
  313. }
  314. if ($this->entityType->hasLinkTemplate('delete-form')) {
  315. $data['delete_' . $entity_type_id] = [
  316. 'field' => [
  317. 'title' => $this->t('Link to delete @entity_type_label', $t_arguments),
  318. 'help' => $this->t('Provide a delete link to the @entity_type_label.', $t_arguments),
  319. 'id' => 'entity_link_delete',
  320. ],
  321. ];
  322. }
  323. }
  324. /**
  325. * Puts the views data for a single field onto the views data.
  326. *
  327. * @param string $table
  328. * The table of the field to handle.
  329. * @param string $field_name
  330. * The name of the field to handle.
  331. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
  332. * The field definition defined in Entity::baseFieldDefinitions()
  333. * @param \Drupal\Core\Entity\Sql\TableMappingInterface $table_mapping
  334. * The table mapping information
  335. * @param array $table_data
  336. * A reference to a specific entity table (for example data_table) inside
  337. * the views data.
  338. */
  339. protected function mapFieldDefinition($table, $field_name, FieldDefinitionInterface $field_definition, TableMappingInterface $table_mapping, &$table_data) {
  340. // Create a dummy instance to retrieve property definitions.
  341. $field_column_mapping = $table_mapping->getColumnNames($field_name);
  342. $field_schema = $this->getFieldStorageDefinitions()[$field_name]->getSchema();
  343. $field_definition_type = $field_definition->getType();
  344. // Add all properties to views table data. We need an entry for each
  345. // column of each field, with the first one given special treatment.
  346. // @todo Introduce concept of the "main" column for a field, rather than
  347. // assuming the first one is the main column. See also what the
  348. // mapSingleFieldViewsData() method does with $first.
  349. $first = TRUE;
  350. foreach ($field_column_mapping as $field_column_name => $schema_field_name) {
  351. $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);
  352. $table_data[$schema_field_name]['entity field'] = $field_name;
  353. $first = FALSE;
  354. }
  355. }
  356. /**
  357. * Provides the views data for a given data type and schema field.
  358. *
  359. * @param string $table
  360. * The table of the field to handle.
  361. * @param string $field_name
  362. * The machine name of the field being processed.
  363. * @param string $field_type
  364. * The type of field being handled.
  365. * @param string $column_name
  366. * For fields containing multiple columns, the column name being processed.
  367. * @param string $column_type
  368. * Within the field, the column type being handled.
  369. * @param bool $first
  370. * TRUE if this is the first column within the field.
  371. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
  372. * The field definition.
  373. *
  374. * @return array
  375. * The modified views data field definition.
  376. */
  377. protected function mapSingleFieldViewsData($table, $field_name, $field_type, $column_name, $column_type, $first, FieldDefinitionInterface $field_definition) {
  378. $views_field = [];
  379. // Provide a nicer, less verbose label for the first column within a field.
  380. // @todo Introduce concept of the "main" column for a field, rather than
  381. // assuming the first one is the main column.
  382. if ($first) {
  383. $views_field['title'] = $field_definition->getLabel();
  384. }
  385. else {
  386. $views_field['title'] = $field_definition->getLabel() . " ($column_name)";
  387. }
  388. if ($description = $field_definition->getDescription()) {
  389. $views_field['help'] = $description;
  390. }
  391. // Set up the field, sort, argument, and filters, based on
  392. // the column and/or field data type.
  393. // @todo Allow field types to customize this.
  394. // @see https://www.drupal.org/node/2337515
  395. switch ($field_type) {
  396. // Special case a few field types.
  397. case 'timestamp':
  398. case 'created':
  399. case 'changed':
  400. $views_field['field']['id'] = 'field';
  401. $views_field['argument']['id'] = 'date';
  402. $views_field['filter']['id'] = 'date';
  403. $views_field['sort']['id'] = 'date';
  404. break;
  405. case 'language':
  406. $views_field['field']['id'] = 'field';
  407. $views_field['argument']['id'] = 'language';
  408. $views_field['filter']['id'] = 'language';
  409. $views_field['sort']['id'] = 'standard';
  410. break;
  411. case 'boolean':
  412. $views_field['field']['id'] = 'field';
  413. $views_field['argument']['id'] = 'numeric';
  414. $views_field['filter']['id'] = 'boolean';
  415. $views_field['sort']['id'] = 'standard';
  416. break;
  417. case 'uri':
  418. // Let's render URIs as URIs by default, not links.
  419. $views_field['field']['id'] = 'field';
  420. $views_field['field']['default_formatter'] = 'string';
  421. $views_field['argument']['id'] = 'string';
  422. $views_field['filter']['id'] = 'string';
  423. $views_field['sort']['id'] = 'standard';
  424. break;
  425. case 'text':
  426. case 'text_with_summary':
  427. // Treat these three long text fields the same.
  428. $field_type = 'text_long';
  429. // Intentional fall-through here to the default processing!
  430. default:
  431. // For most fields, the field type is generic enough to just use
  432. // the column type to determine the filters etc.
  433. switch ($column_type) {
  434. case 'int':
  435. case 'integer':
  436. case 'smallint':
  437. case 'tinyint':
  438. case 'mediumint':
  439. case 'float':
  440. case 'double':
  441. case 'decimal':
  442. $views_field['field']['id'] = 'field';
  443. $views_field['argument']['id'] = 'numeric';
  444. $views_field['filter']['id'] = 'numeric';
  445. $views_field['sort']['id'] = 'standard';
  446. break;
  447. case 'char':
  448. case 'string':
  449. case 'varchar':
  450. case 'varchar_ascii':
  451. case 'tinytext':
  452. case 'text':
  453. case 'mediumtext':
  454. case 'longtext':
  455. $views_field['field']['id'] = 'field';
  456. $views_field['argument']['id'] = 'string';
  457. $views_field['filter']['id'] = 'string';
  458. $views_field['sort']['id'] = 'standard';
  459. break;
  460. default:
  461. $views_field['field']['id'] = 'field';
  462. $views_field['argument']['id'] = 'standard';
  463. $views_field['filter']['id'] = 'standard';
  464. $views_field['sort']['id'] = 'standard';
  465. }
  466. }
  467. // Do post-processing for a few field types.
  468. $process_method = 'processViewsDataFor' . Container::camelize($field_type);
  469. if (method_exists($this, $process_method)) {
  470. $this->{$process_method}($table, $field_definition, $views_field, $column_name);
  471. }
  472. return $views_field;
  473. }
  474. /**
  475. * Processes the views data for a language field.
  476. *
  477. * @param string $table
  478. * The table the language field is added to.
  479. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
  480. * The field definition.
  481. * @param array $views_field
  482. * The views field data.
  483. * @param string $field_column_name
  484. * The field column being processed.
  485. */
  486. protected function processViewsDataForLanguage($table, FieldDefinitionInterface $field_definition, array &$views_field, $field_column_name) {
  487. // Apply special titles for the langcode field.
  488. if ($field_definition->getName() == $this->entityType->getKey('langcode')) {
  489. if ($table == $this->entityType->getDataTable() || $table == $this->entityType->getRevisionDataTable()) {
  490. $views_field['title'] = $this->t('Translation language');
  491. }
  492. if ($table == $this->entityType->getBaseTable() || $table == $this->entityType->getRevisionTable()) {
  493. $views_field['title'] = $this->t('Original language');
  494. }
  495. }
  496. }
  497. /**
  498. * Processes the views data for an entity reference field.
  499. *
  500. * @param string $table
  501. * The table the language field is added to.
  502. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
  503. * The field definition.
  504. * @param array $views_field
  505. * The views field data.
  506. * @param string $field_column_name
  507. * The field column being processed.
  508. */
  509. protected function processViewsDataForEntityReference($table, FieldDefinitionInterface $field_definition, array &$views_field, $field_column_name) {
  510. // @todo Should the actual field handler respect that this just renders a
  511. // number?
  512. // @todo Create an optional entity field handler, that can render the
  513. // entity.
  514. // @see https://www.drupal.org/node/2322949
  515. if ($entity_type_id = $field_definition->getItemDefinition()->getSetting('target_type')) {
  516. $entity_type = $this->entityManager->getDefinition($entity_type_id);
  517. if ($entity_type instanceof ContentEntityType) {
  518. $views_field['relationship'] = [
  519. 'base' => $this->getViewsTableForEntityType($entity_type),
  520. 'base field' => $entity_type->getKey('id'),
  521. 'label' => $entity_type->getLabel(),
  522. 'title' => $entity_type->getLabel(),
  523. 'id' => 'standard',
  524. ];
  525. $views_field['field']['id'] = 'field';
  526. $views_field['argument']['id'] = 'numeric';
  527. $views_field['filter']['id'] = 'numeric';
  528. $views_field['sort']['id'] = 'standard';
  529. }
  530. else {
  531. $views_field['field']['id'] = 'field';
  532. $views_field['argument']['id'] = 'string';
  533. $views_field['filter']['id'] = 'string';
  534. $views_field['sort']['id'] = 'standard';
  535. }
  536. }
  537. if ($field_definition->getName() == $this->entityType->getKey('bundle')) {
  538. $views_field['filter']['id'] = 'bundle';
  539. }
  540. }
  541. /**
  542. * Processes the views data for a text field with formatting.
  543. *
  544. * @param string $table
  545. * The table the field is added to.
  546. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
  547. * The field definition.
  548. * @param array $views_field
  549. * The views field data.
  550. * @param string $field_column_name
  551. * The field column being processed.
  552. */
  553. protected function processViewsDataForTextLong($table, FieldDefinitionInterface $field_definition, array &$views_field, $field_column_name) {
  554. // Connect the text field to its formatter.
  555. if ($field_column_name == 'value') {
  556. $views_field['field']['format'] = $field_definition->getName() . '__format';
  557. $views_field['field']['id'] = 'field';
  558. }
  559. }
  560. /**
  561. * Processes the views data for a UUID field.
  562. *
  563. * @param string $table
  564. * The table the field is added to.
  565. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
  566. * The field definition.
  567. * @param array $views_field
  568. * The views field data.
  569. * @param string $field_column_name
  570. * The field column being processed.
  571. */
  572. protected function processViewsDataForUuid($table, FieldDefinitionInterface $field_definition, array &$views_field, $field_column_name) {
  573. // It does not make sense for UUID fields to be click sortable.
  574. $views_field['field']['click sortable'] = FALSE;
  575. }
  576. /**
  577. * {@inheritdoc}
  578. */
  579. public function getViewsTableForEntityType(EntityTypeInterface $entity_type) {
  580. return $entity_type->getDataTable() ?: $entity_type->getBaseTable();
  581. }
  582. }