Problem/Motivation

0. Create a site with two languages and some translated content.
1. Create a view of revisions.
2. Look at the "langcode" part of the select query.
3. Observe it is selected with "langcode as langcode" instead of "node_field_revision.langcode AS node_field_revision_langcode"

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Comments

Sam152 created an issue. See original summary.

sam152’s picture

Title: Views langcode field select incorrectly assumed to be a "formula" when using a revision base table » Views langcode field select in TranslationLanguageRenderer incorrectly assumed to be a "formula" when using a revision base table
Issue summary: View changes
Status: Active » Needs review
StatusFileSize
new763 bytes

I don't expect this is the correct fix, but it illustrates the problem area of the code.

Basically from what I can grok, the return value of $query->ensureTable() is NULL when using the revision as the view base table. Hence the following situation comes up:

$this->langcodeAlias = $query->addField(NULL, $langcode_key);

The docblock defines $table as:

* @param $table
* The table this field is attached to. If NULL, it is assumed this will
* be a formula; otherwise, ensureTable is used to make sure the
* table exists.

So the field is assumed to be a formula and is selected as:

langcode as langcode

instead of:

node_field_revision.langcode AS node_field_revision_langcode

The langcode always comes from the basetable of the view, so somehow, we should use that instead?

sam152’s picture

sam152’s picture

Issue tags: +WI critical blocker
sam152’s picture

Issue summary: View changes
sam152’s picture

plach’s picture

Assigned: Unassigned » plach
Status: Closed (duplicate) » Needs work
Issue tags: -WI critical blocker +WI critical
plach’s picture

Title: Views langcode field select in TranslationLanguageRenderer incorrectly assumed to be a "formula" when using a revision base table » "TranslationLanguageRenderer" uses wrong table for the "langcode" key with entity revision views
Status: Needs work » Needs review
StatusFileSize
new3.32 KB
new11.97 KB

Here's an attempt to fix this properly.

plach’s picture

Assigned: plach » Unassigned
plach’s picture

Title: "TranslationLanguageRenderer" uses wrong table for the "langcode" key with entity revision views » "TranslationLanguageRenderer" uses the wrong table for the "langcode" column with entity revision views
sam152’s picture

This patch reads correctly to me based on what I was observing. If the view base table is the entity revision table, use that instead of the return value of $storage->getTableMapping()->getFieldTableName() which is the base table.

+1 RTBC

timmillwood’s picture

Status: Needs review » Reviewed & tested by the community

Took me a while to understand what's going on, and still not 100% sure, but this seems to make sense.

berdir’s picture

+++ b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php
@@ -28,13 +28,47 @@ public function query(QueryPluginBase $query, $relationship = NULL) {
+      switch ($base_table) {
+        case $revision_table:
+          $langcode_table = $revision_table;
+          break;
+        case $revision_data_table:
+          $langcode_table = $revision_data_table;
+          break;
+      }

That's a creative way of using a switch :)

This should at least have a comment that explains this I think.

One confusing thing is that we are mixing terminoly here. an "entity base table" is never the revision or revision data table. But this isn't the entity base table, it's the views base table, so maybe we should use $views_base_table to make that distinction a bit clearer?

timmillwood’s picture

@Berdir - this is the part of the patch that took me longest to understand, so yes, commenting and updating variable names is a good suggestion.

plach’s picture

Status: Reviewed & tested by the community » Needs work

Good points :)

plach’s picture

Status: Needs work » Needs review
StatusFileSize
new11.96 KB
new1.26 KB

Addressed the review above.

plach’s picture

Forgot the comment, sorry.

The last submitted patch, 17: views-entity_row_renderer_revision-2896381.patch, failed testing. View results

timmillwood’s picture

Status: Needs review » Reviewed & tested by the community

Lovely!

amateescu’s picture

I'm glad to see this was so easy to fix. I just found a couple of points to address:

  1. +++ b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php
    @@ -28,13 +28,48 @@ public function query(QueryPluginBase $query, $relationship = NULL) {
    +   * @param string $relationship
    +   *   (optional) The relationship, used by a field.
    ...
    +  protected function getLangcodeTable($relationship) {
    

    By looking at the method definition, it seems that the $relationship param is not really optional?

  2. +++ b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php
    @@ -28,13 +28,48 @@ public function query(QueryPluginBase $query, $relationship = NULL) {
    +   * @return string|bool
    +   *   A table name or FALSE if none could be found.
    

    We should break out of this habit of returning FALSE when we actually can (and should) return NULL :)

plach’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new899 bytes
new12.18 KB

Actually the method will always return a string.

amateescu’s picture

Status: Needs review » Reviewed & tested by the community

Great, that reads much better now ;)

jibran’s picture

Issue tags: +VDC
jibran’s picture

TranslationLanguageRenderer changes look good to me.

+++ b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php
@@ -28,13 +28,48 @@ public function query(QueryPluginBase $query, $relationship = NULL) {
+    // 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.

This comment convinced me.

Just one questions: This is just adding the correct table to the query. It wouldn't affect the existing view in the storage. It would affect only their output. Right?

plach’s picture

This is just adding the correct table to the query. It wouldn't affect the existing view in the storage. It would affect only their output. Right?

Yes, it's just ensuring the query is generated correctly at runtime.

jibran’s picture

Thanks, RTBC +1

timmillwood’s picture

This is blocking #2862041: Provide useful Views filters for Content Moderation State fields so hopefully we can get it committed for better Views support in Content Moderation.

tacituseu’s picture

@plach: curious about the !$relationship part of:

if (!$relationship && $this->entityType->isRevisionable())) {
  $query_base_table = $this->view->storage->get('base_table');
  ...
}

is this meant to limit the scope ? (there are two other issues affected by the same part of code and showing similar symptoms),
would you see an advantage of doing it like this instead:

if ($this->entityType->isRevisionable()) {
  // Determine the primary table to seek
  if (!$relationship || empty($query->relationships[$relationship])) {
    $query_base_table = $this->view->storage->get('base_table');
  }
  else {
    $query_base_table = $query->relationships[$relationship]['base'];
  }
  ...
}

to cover both cases.

plach’s picture

@tacituseu:

Courious about the !$relationship part of [...] is this meant to limit the scope ?

Well, actually, the reason is there is no way to define a revision relationship AFAIK. But that's a good suggestion, if it is introduced then the code should work automatically.

plach’s picture

Status: Reviewed & tested by the community » Needs review
tacituseu’s picture

@plach: Indeed, I'm so used to running with the ERR patch adding it that I totally forgot about it, thanks.
Edit: Manually tested #30 with the ERR patch and it works just fine.

plach’s picture

Cool, can you point me to the issue?

tacituseu’s picture

It's #2799479: Views doesn't recognize relationship to host, I referenced this one from it already.

plach’s picture

@tacituseu:

Thanks, any other concern or can we move this back to RTBC?

tacituseu’s picture

Status: Needs review » Reviewed & tested by the community

None from me, setting back.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

timmillwood’s picture

Version: 8.5.x-dev » 8.4.x-dev

This is required by #2862041: Provide useful Views filters for Content Moderation State fields which is required for Content Moderation to become stable, so moving back to 8.4.x

tacituseu’s picture

Priority: Normal » Major

Since this blocks a Major should-have it should be Major too.

catch’s picture

  1. +++ b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php
    @@ -28,13 +28,52 @@ public function query(QueryPluginBase $query, $relationship = NULL) {
    +      /** @var \Drupal\views\Plugin\views\query\Sql $query */
    

    Why is this necessary when $query is typehinted?

Everything else looks good, the inline comments in the patch are useful.

Uploading a test-only patch for the bot since I can't see one on the issue. The

Status: Reviewed & tested by the community » Needs work
catch’s picture

Status: Needs work » Reviewed & tested by the community

Good fail.

amateescu’s picture

Re #40.1: That's because the method type hints the generic QueryPluginBase class and we're using some methods that are only in \Drupal\views\Plugin\views\query\Sql, so basically for better IDE autocompletion :)

catch’s picture

Status: Reviewed & tested by the community » Fixed

OK, those aren't my favourite comments, but fair enough.

Committed/pushed to 8.5.x and cherry-picked to 8.4.x. Thanks!

  • catch committed 10c87c6 on 8.5.x
    Issue #2896381 by plach, Sam152, tacituseu, amateescu, Berdir:...

  • catch committed 5150cc6 on 8.4.x
    Issue #2896381 by plach, Sam152, tacituseu, amateescu, Berdir:...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.