From 87bc567b6ec9d5aa3d9956888157d0d872705a87 Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Mon, 26 Feb 2024 11:15:05 +0000
Subject: [PATCH] Issue #3396741 by recrit, smustgrave: Content Moderation
 moderation_state_filter cannot join the entity revision table when the filter
 uses relationship to the entity revision table

(cherry picked from commit f742d155c1ee259f88988a6d7b48215b06a53a99)
---
 .../views/filter/ModerationStateFilter.php    |   5 +-
 ...ation_filter_via_revision_relationship.yml | 351 ++++++++++++++++++
 .../content_moderation_test_views.module      |  23 ++
 .../Kernel/ViewsModerationStateFilterTest.php |  28 ++
 4 files changed, 405 insertions(+), 2 deletions(-)
 create mode 100644 core/modules/content_moderation/tests/modules/content_moderation_test_views/config/install/views.view.test_content_moderation_filter_via_revision_relationship.yml

diff --git a/core/modules/content_moderation/src/Plugin/views/filter/ModerationStateFilter.php b/core/modules/content_moderation/src/Plugin/views/filter/ModerationStateFilter.php
index 0dfbe3d865d8..b5b9f1dcc9cc 100644
--- a/core/modules/content_moderation/src/Plugin/views/filter/ModerationStateFilter.php
+++ b/core/modules/content_moderation/src/Plugin/views/filter/ModerationStateFilter.php
@@ -144,16 +144,17 @@ protected function opSimple() {
         $entity_base_table = $entity_type->getBaseTable();
         $entity_revision_base_table = $entity_type->isTranslatable() ? $entity_type->getRevisionDataTable() : $entity_type->getRevisionTable();
         if ($this->table === $entity_revision_base_table) {
+          $entity_revision_base_table_alias = $this->relationship ?: $this->table;
           $configuration = [
             'table' => $entity_base_table,
             'field' => $entity_type->getKey('id'),
-            'left_table' => $entity_revision_base_table,
+            'left_table' => $entity_revision_base_table_alias,
             'left_field' => $entity_type->getKey('id'),
             'type' => 'INNER',
           ];
 
           $join = Views::pluginManager('join')->createInstance('standard', $configuration);
-          $entity_base_table_alias = $this->query->addRelationship($entity_base_table, $join, $entity_revision_base_table);
+          $entity_base_table_alias = $this->query->addRelationship($entity_base_table, $join, $entity_revision_base_table_alias);
         }
 
         $bundle_condition = $this->view->query->getConnection()->condition('AND');
diff --git a/core/modules/content_moderation/tests/modules/content_moderation_test_views/config/install/views.view.test_content_moderation_filter_via_revision_relationship.yml b/core/modules/content_moderation/tests/modules/content_moderation_test_views/config/install/views.view.test_content_moderation_filter_via_revision_relationship.yml
new file mode 100644
index 000000000000..ca998cde89df
--- /dev/null
+++ b/core/modules/content_moderation/tests/modules/content_moderation_test_views/config/install/views.view.test_content_moderation_filter_via_revision_relationship.yml
@@ -0,0 +1,351 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - content_moderation
+    - user
+id: test_content_moderation_filter_via_revision_relationship
+label: test_content_moderation_filter_via_revision_relationship
+module: views
+description: ''
+tag: ''
+base_table: users_field_data
+base_field: uid
+display:
+  default:
+    id: default
+    display_title: Default
+    display_plugin: default
+    position: 0
+    display_options:
+      title: test_content_moderation_filter_via_revision_relationship
+      fields:
+        name:
+          id: name
+          table: users_field_data
+          field: name
+          relationship: none
+          group_type: group
+          admin_label: ''
+          entity_type: user
+          entity_field: name
+          plugin_id: field
+          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: false
+            ellipsis: false
+            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: user_name
+          settings:
+            link_to_entity: false
+          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
+        title:
+          id: title
+          table: node_field_revision
+          field: title
+          relationship: uid_revision_test
+          group_type: group
+          admin_label: ''
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+          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: string
+          settings:
+            link_to_entity: false
+          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
+        moderation_state:
+          id: moderation_state
+          table: node_field_revision
+          field: moderation_state
+          relationship: uid_revision_test
+          group_type: group
+          admin_label: ''
+          entity_type: node
+          plugin_id: moderation_state_field
+          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: content_moderation_state
+          settings: {  }
+          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
+      pager:
+        type: none
+        options:
+          offset: 0
+      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
+      access:
+        type: perm
+        options:
+          perm: 'access user profiles'
+      cache:
+        type: tag
+        options: {  }
+      empty: {  }
+      sorts:
+        vid:
+          id: vid
+          table: node_field_revision
+          field: vid
+          relationship: uid_revision_test
+          group_type: group
+          admin_label: ''
+          entity_type: node
+          entity_field: vid
+          plugin_id: standard
+          order: ASC
+          expose:
+            label: ''
+            field_identifier: ''
+          exposed: false
+      arguments: {  }
+      filters:
+        moderation_state:
+          id: moderation_state
+          table: node_field_revision
+          field: moderation_state
+          relationship: uid_revision_test
+          group_type: group
+          admin_label: ''
+          entity_type: node
+          plugin_id: moderation_state_filter
+          operator: in
+          value: {  }
+          group: 1
+          exposed: true
+          expose:
+            operator_id: moderation_state_op
+            label: 'Moderation state'
+            description: ''
+            use_operator: false
+            operator: moderation_state_op
+            operator_limit_selection: false
+            operator_list: {  }
+            identifier: moderation_state
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+              anonymous: '0'
+              administrator: '0'
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+      style:
+        type: default
+      row:
+        type: fields
+      query:
+        type: views_query
+        options:
+          query_comment: ''
+          disable_sql_rewrite: false
+          distinct: false
+          replica: false
+          query_tags: {  }
+      relationships:
+        uid_revision_test:
+          id: uid_revision_test
+          table: users_field_data
+          field: uid_revision_test
+          relationship: none
+          group_type: group
+          admin_label: 'node revisions'
+          entity_type: user
+          plugin_id: standard
+          required: true
+      header: {  }
+      footer: {  }
+      display_extenders: {  }
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+        - user.permissions
+      tags:
+        - 'config:workflow_list'
+  page_1:
+    id: page_1
+    display_title: Page
+    display_plugin: page
+    position: 1
+    display_options:
+      display_extenders: {  }
+      path: test-content-moderation-filter-revision-relationship
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+        - user.permissions
+      tags:
+        - 'config:workflow_list'
diff --git a/core/modules/content_moderation/tests/modules/content_moderation_test_views/content_moderation_test_views.module b/core/modules/content_moderation/tests/modules/content_moderation_test_views/content_moderation_test_views.module
index 11fe27088391..47f34c21f667 100644
--- a/core/modules/content_moderation/tests/modules/content_moderation_test_views/content_moderation_test_views.module
+++ b/core/modules/content_moderation/tests/modules/content_moderation_test_views/content_moderation_test_views.module
@@ -20,3 +20,26 @@ function content_moderation_test_views_views_query_alter(ViewExecutable $view, Q
     $query->addOrderBy('node_field_revision', 'vid', 'ASC');
   }
 }
+
+/**
+ * Implements hook_views_data_alter().
+ *
+ * @see \Drupal\Tests\content_moderation\Kernel\ViewsModerationStateFilterTest
+ */
+function content_moderation_test_views_views_data_alter(array &$data) {
+  if (isset($data['users_field_data'])) {
+    $data['users_field_data']['uid_revision_test'] = [
+      'help' => t('Relate the content revision to the user who created it.'),
+      'real field' => 'uid',
+      'relationship' => [
+        'title' => t('Content revision authored'),
+        'help' => t('Relate the content revision to the user who created it. This relationship will create one record for each content revision item created by the user.'),
+        'id' => 'standard',
+        'base' => 'node_field_revision',
+        'base field' => 'uid',
+        'field' => 'uid',
+        'label' => t('node revisions'),
+      ],
+    ];
+  }
+}
diff --git a/core/modules/content_moderation/tests/src/Kernel/ViewsModerationStateFilterTest.php b/core/modules/content_moderation/tests/src/Kernel/ViewsModerationStateFilterTest.php
index c4912798df98..063d91149580 100644
--- a/core/modules/content_moderation/tests/src/Kernel/ViewsModerationStateFilterTest.php
+++ b/core/modules/content_moderation/tests/src/Kernel/ViewsModerationStateFilterTest.php
@@ -240,6 +240,34 @@ public function testModerationStateFilterOnJoinedEntity() {
     ]);
     $view->execute();
     $this->assertIdenticalResultset($view, [], ['name' => 'name']);
+
+    // Revision Data Table Relationship: Filtering by the published state will
+    // filter out the sample content.
+    $view = Views::getView('test_content_moderation_filter_via_revision_relationship');
+    $view->setExposedInput([
+      'moderation_state' => 'editorial-published',
+    ]);
+    $view->execute();
+    $this->assertIdenticalResultset($view, [
+      [
+        'name' => 'Test user',
+        'title' => 'Test node',
+        'moderation_state' => 'published',
+      ],
+    ], [
+      'name' => 'name',
+      'title' => 'title',
+      'moderation_state' => 'moderation_state',
+    ]);
+
+    // Revision Data Table Relationship: Filtering by the draft state will
+    // filter out the sample content.
+    $view = Views::getView('test_content_moderation_filter_via_revision_relationship');
+    $view->setExposedInput([
+      'moderation_state' => 'editorial-draft',
+    ]);
+    $view->execute();
+    $this->assertIdenticalResultset($view, [], ['name' => 'name']);
   }
 
   /**
-- 
GitLab