From 79b08530bee1df9856abb1dd2d780679b9474e45 Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Tue, 11 Aug 2020 10:57:25 +0100
Subject: [PATCH] Issue #3112433 by AndyF, Baysaa, Sam152, SpadXIII: Content
 moderation state filter incorrectly groups content type condition

(cherry picked from commit e3371760921208f1c076609bf3278686810804ad)
---
 .../views/filter/ModerationStateFilter.php    |  13 +-
 ...tate_filter_base_table_filter_group_or.yml | 268 ++++++++++++++++++
 .../Kernel/ViewsModerationStateFilterTest.php |  32 ++-
 3 files changed, 299 insertions(+), 14 deletions(-)
 create mode 100644 core/modules/content_moderation/tests/modules/content_moderation_test_views/config/install/views.view.test_content_moderation_state_filter_base_table_filter_group_or.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 69309f00d3c8..4c7ea7c52522 100644
--- a/core/modules/content_moderation/src/Plugin/views/filter/ModerationStateFilter.php
+++ b/core/modules/content_moderation/src/Plugin/views/filter/ModerationStateFilter.php
@@ -123,6 +123,7 @@ protected function opSimple() {
     $this->ensureMyTable();
 
     $entity_type = $this->entityTypeManager->getDefinition($this->getEntityType());
+    $bundle_condition = NULL;
     if ($entity_type->hasKey('bundle')) {
       // Get a list of bundles that are being moderated by the workflows
       // configured in this filter.
@@ -156,7 +157,8 @@ protected function opSimple() {
           $entity_base_table_alias = $this->query->addRelationship($entity_base_table, $join, $entity_revision_base_table);
         }
 
-        $this->query->addWhere($this->options['group'], "$entity_base_table_alias.{$entity_type->getKey('bundle')}", $moderated_bundles, 'IN');
+        $bundle_condition = new Condition('AND');
+        $bundle_condition->condition("$entity_base_table_alias.{$entity_type->getKey('bundle')}", $moderated_bundles, 'IN');
       }
       // Otherwise, force the query to return an empty result.
       else {
@@ -186,7 +188,14 @@ protected function opSimple() {
       $field->condition($and);
     }
 
-    $this->query->addWhere($this->options['group'], $field);
+    if ($bundle_condition) {
+      // The query must match the bundle AND the workflow/state conditions.
+      $bundle_condition->condition($field);
+      $this->query->addWhere($this->options['group'], $bundle_condition);
+    }
+    else {
+      $this->query->addWhere($this->options['group'], $field);
+    }
   }
 
   /**
diff --git a/core/modules/content_moderation/tests/modules/content_moderation_test_views/config/install/views.view.test_content_moderation_state_filter_base_table_filter_group_or.yml b/core/modules/content_moderation/tests/modules/content_moderation_test_views/config/install/views.view.test_content_moderation_state_filter_base_table_filter_group_or.yml
new file mode 100644
index 000000000000..5a45433c7bca
--- /dev/null
+++ b/core/modules/content_moderation/tests/modules/content_moderation_test_views/config/install/views.view.test_content_moderation_state_filter_base_table_filter_group_or.yml
@@ -0,0 +1,268 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - content_moderation
+    - node
+    - user
+id: test_content_moderation_state_filter_base_table_filter_group_or
+label: test_content_moderation_state_filter_base_table_filter_group_or
+module: views
+description: ''
+tag: ''
+base_table: node_field_data
+base_field: nid
+display:
+  default:
+    display_plugin: default
+    id: default
+    display_title: Master
+    position: 0
+    display_options:
+      access:
+        type: perm
+        options:
+          perm: 'access content'
+      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_data
+          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: 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
+          entity_type: node
+          entity_field: nid
+          plugin_id: field
+      filters:
+        moderation_state:
+          id: moderation_state
+          table: node_field_data
+          field: moderation_state
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: in
+          value: {  }
+          group: 1
+          exposed: true
+          expose:
+            operator_id: moderation_state_op
+            label: 'Default Revision State'
+            description: ''
+            use_operator: false
+            operator: moderation_state_op
+            identifier: default_revision_state
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+              anonymous: '0'
+              administrator: '0'
+            reduce: false
+            operator_limit_selection: false
+            operator_list: {  }
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          entity_type: node
+          plugin_id: moderation_state_filter
+        moderation_state_1:
+          id: moderation_state_1
+          table: node_field_data
+          field: moderation_state
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: 'not empty'
+          value: {  }
+          group: 2
+          exposed: false
+          expose:
+            operator_id: ''
+            label: ''
+            description: ''
+            use_operator: false
+            operator: ''
+            identifier: ''
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+            reduce: false
+            operator_limit_selection: false
+            operator_list: {  }
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          entity_type: node
+          plugin_id: moderation_state_filter
+      sorts:
+        nid:
+          id: nid
+          table: node_field_data
+          field: nid
+          relationship: none
+          group_type: group
+          admin_label: ''
+          order: ASC
+          exposed: false
+          expose:
+            label: ''
+          entity_type: node
+          entity_field: nid
+          plugin_id: standard
+      header: {  }
+      footer: {  }
+      empty: {  }
+      relationships: {  }
+      arguments: {  }
+      display_extenders: {  }
+      filter_groups:
+        operator: AND
+        groups:
+          1: OR
+          2: OR
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url
+        - 'user.node_grants:view'
+        - user.permissions
+      tags:
+        - 'config:workflow_list'
+  page_1:
+    display_plugin: page
+    id: page_1
+    display_title: Page
+    position: 1
+    display_options:
+      display_extenders: {  }
+      path: filter-test-path
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url
+        - 'user.node_grants:view'
+        - user.permissions
+      tags:
+        - 'config:workflow_list'
diff --git a/core/modules/content_moderation/tests/src/Kernel/ViewsModerationStateFilterTest.php b/core/modules/content_moderation/tests/src/Kernel/ViewsModerationStateFilterTest.php
index 52e55612604a..721272d0b425 100644
--- a/core/modules/content_moderation/tests/src/Kernel/ViewsModerationStateFilterTest.php
+++ b/core/modules/content_moderation/tests/src/Kernel/ViewsModerationStateFilterTest.php
@@ -133,18 +133,26 @@ public function testStateFilterViewsRelationship() {
     $translated_forward_revision->moderation_state = 'translated_draft';
     $translated_forward_revision->save();
 
-    // The three default revisions are listed when no filter is specified.
-    $this->assertNodesWithFilters([$node, $second_node, $third_node], []);
-
-    // The default revision of node one and three are published.
-    $this->assertNodesWithFilters([$node, $third_node], [
-      'default_revision_state' => 'editorial-published',
-    ]);
-
-    // The default revision of node two is draft.
-    $this->assertNodesWithFilters([$second_node], [
-      'default_revision_state' => 'editorial-draft',
-    ]);
+    // Test the filter within an AND filter group (the default) and an OR filter
+    // group.
+    $base_table_views = [
+      'test_content_moderation_state_filter_base_table',
+      'test_content_moderation_state_filter_base_table_filter_group_or',
+    ];
+    foreach ($base_table_views as $view_id) {
+      // The three default revisions are listed when no filter is specified.
+      $this->assertNodesWithFilters([$node, $second_node, $third_node], [], $view_id);
+
+      // The default revision of node one and three are published.
+      $this->assertNodesWithFilters([$node, $third_node], [
+        'default_revision_state' => 'editorial-published',
+      ], $view_id);
+
+      // The default revision of node two is draft.
+      $this->assertNodesWithFilters([$second_node], [
+        'default_revision_state' => 'editorial-draft',
+      ], $view_id);
+    }
 
     // Test the same three revisions on a view displaying content revisions.
     // Both nodes have one draft revision.
-- 
GitLab