diff --git a/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php index 00ae5248718..5b4b3561cdd 100644 --- a/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php +++ b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php @@ -28,15 +28,54 @@ class TranslationLanguageRenderer extends EntityTranslationRendererBase { if (!$this->languageManager->isMultilingual() || !$this->entityType->hasKey('langcode')) { return; } - $langcode_key = $this->entityType->getKey('langcode'); - $storage = \Drupal::entityManager()->getStorage($this->entityType->id()); - - if ($table = $storage->getTableMapping()->getFieldTableName($langcode_key)) { - $table_alias = $query->ensureTable($table, $relationship); + $langcode_table = $this->getLangcodeTable($query, $relationship); + if ($langcode_table) { + /** @var \Drupal\views\Plugin\views\query\Sql $query */ + $table_alias = $query->ensureTable($langcode_table, $relationship); + $langcode_key = $this->entityType->getKey('langcode'); $this->langcodeAlias = $query->addField($table_alias, $langcode_key); } } + /** + * Returns the name of the table holding the "langcode" field. + * + * @param \Drupal\views\Plugin\views\query\QueryPluginBase $query + * The query being executed. + * @param string $relationship + * The relationship used by the entity type. + * + * @return string + * A table name. + */ + protected function getLangcodeTable(QueryPluginBase $query, $relationship) { + /** @var \Drupal\Core\Entity\Sql\SqlContentEntityStorage $storage */ + $storage = \Drupal::entityTypeManager()->getStorage($this->entityType->id()); + $langcode_key = $this->entityType->getKey('langcode'); + $langcode_table = $storage->getTableMapping()->getFieldTableName($langcode_key); + + // If the entity type is revisionable, we need to take into account views of + // entity revisions. Usually the view will use the entity data table as the + // query base table, however, in case of an entity revision view, we need to + // use the revision table or the revision data table, depending on which one + // is being used as query base table. + if ($this->entityType->isRevisionable()) { + $query_base_table = isset($query->relationships[$relationship]['base']) ? + $query->relationships[$relationship]['base'] : + $this->view->storage->get('base_table'); + $revision_table = $storage->getRevisionTable(); + $revision_data_table = $storage->getRevisionDataTable(); + if ($query_base_table === $revision_table) { + $langcode_table = $revision_table; + } + elseif ($query_base_table === $revision_data_table) { + $langcode_table = $revision_data_table; + } + } + + return $langcode_table; + } + /** * {@inheritdoc} */ diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_row_renderers_revisions_base.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_row_renderers_revisions_base.yml new file mode 100644 index 00000000000..a4ebba1c3e2 --- /dev/null +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_row_renderers_revisions_base.yml @@ -0,0 +1,225 @@ +uuid: b133bd43-c494-4db6-83f0-24380fe3964b +langcode: en +status: true +dependencies: + module: + - user +id: test_entity_row_renderers_revisions_base +label: test_entity_row_renderers_revisions_base +module: views +description: '' +tag: '' +base_table: node_field_revision +base_field: vid +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: 0 + display_options: + access: + type: perm + options: + perm: 'view all revisions' + cache: + type: tag + options: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: '' + query_tags: { } + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + pager: + type: none + options: + offset: 0 + style: + type: default + options: + grouping: { } + row_class: '' + default_row_class: true + uses_fields: false + row: + type: fields + options: + inline: { } + separator: '' + hide_empty: false + default_field_elements: true + fields: + nid: + id: nid + table: node_field_revision + field: nid + relationship: none + group_type: group + admin_label: '' + label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: number_integer + settings: + thousand_separator: '' + prefix_suffix: true + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + entity_type: node + entity_field: nid + plugin_id: field + uid: + id: uid + table: users_field_data + field: uid + relationship: revision_uid + group_type: group + admin_label: '' + label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: number_integer + settings: + thousand_separator: '' + prefix_suffix: true + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + entity_type: user + entity_field: uid + plugin_id: field + filters: { } + sorts: { } + header: { } + footer: { } + empty: { } + relationships: + revision_uid: + id: revision_uid + table: node_revision + field: revision_uid + relationship: none + group_type: group + admin_label: 'revision user' + required: false + entity_type: node + entity_field: revision_uid + plugin_id: standard + arguments: { } + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - 'user.node_grants:view' + - user.permissions + tags: { } + diff --git a/core/modules/views/tests/src/Kernel/Entity/RowEntityRenderersTest.php b/core/modules/views/tests/src/Kernel/Entity/RowEntityRenderersTest.php index b20f98118c8..a110f002094 100644 --- a/core/modules/views/tests/src/Kernel/Entity/RowEntityRenderersTest.php +++ b/core/modules/views/tests/src/Kernel/Entity/RowEntityRenderersTest.php @@ -5,6 +5,7 @@ namespace Drupal\Tests\views\Kernel\Entity; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\node\Entity\NodeType; use Drupal\Tests\views\Kernel\ViewsKernelTestBase; +use Drupal\user\Entity\User; use Drupal\views\Views; /** @@ -27,7 +28,10 @@ class RowEntityRenderersTest extends ViewsKernelTestBase { * * @var array */ - public static $testViews = ['test_entity_row_renderers']; + public static $testViews = [ + 'test_entity_row_renderers', + 'test_entity_row_renderers_revisions_base', + ]; /** * An array of added languages. @@ -43,6 +47,20 @@ class RowEntityRenderersTest extends ViewsKernelTestBase { */ protected $expected; + /** + * The author of the test content. + * + * @var \Drupal\user\UserInterface + */ + protected $testAuthor; + + /** + * An array of IDs of the test content. + * + * @var array[] + */ + protected $testIds; + /** * {@inheritdoc} */ @@ -64,19 +82,25 @@ class RowEntityRenderersTest extends ViewsKernelTestBase { ConfigurableLanguage::createFromLangcode($langcode)->save(); } + $this->testAuthor = User::create([ + 'name' => 'foo', + ]); + $this->testAuthor->save(); + // Make sure we do not try to render non-existing user data. $node_type = NodeType::create(['type' => 'test']); $node_type->setDisplaySubmitted(FALSE); $node_type->save(); $this->values = []; + $this->ids = []; $controller = \Drupal::entityManager()->getStorage('node'); $langcode_index = 0; for ($i = 0; $i < count($this->langcodes); $i++) { // Create a node with a different default language each time. $default_langcode = $this->langcodes[$langcode_index++]; - $node = $controller->create(['type' => 'test', 'uid' => 0, 'langcode' => $default_langcode]); + $node = $controller->create(['type' => 'test', 'uid' => $this->testAuthor->id(), 'langcode' => $default_langcode]); // Ensure the default language is processed first. $langcodes = array_merge([$default_langcode], array_diff($this->langcodes, [$default_langcode])); @@ -92,6 +116,11 @@ class RowEntityRenderersTest extends ViewsKernelTestBase { } $node->save(); + + $this->ids[] = [ + 'nid' => $node->id(), + 'uid' => $this->testAuthor->id(), + ]; } } } @@ -110,6 +139,15 @@ class RowEntityRenderersTest extends ViewsKernelTestBase { $this->checkLanguageRenderers('page_2', $this->values); } + /** + * Tests the row renderer with a revision base table. + */ + public function testRevisionBaseTable() { + $view = Views::getView('test_entity_row_renderers_revisions_base'); + $view->execute(); + $this->assertIdenticalResultset($view, $this->ids, ['nid' => 'nid', 'uid' => 'uid']); + } + /** * Checks that the language renderer configurations work as expected. *