From e3371760921208f1c076609bf3278686810804ad Mon Sep 17 00:00:00 2001 From: catch 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 --- .../views/filter/ModerationStateFilter.php | 13 +- ...tate_filter_base_table_filter_group_or.yml | 268 ++++++++++++++++++ .../Kernel/ViewsModerationStateFilterTest.php | 28 +- 3 files changed, 297 insertions(+), 12 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 9a744d562e5..e205818f4f2 100644 --- a/core/modules/content_moderation/src/Plugin/views/filter/ModerationStateFilter.php +++ b/core/modules/content_moderation/src/Plugin/views/filter/ModerationStateFilter.php @@ -122,6 +122,7 @@ class ModerationStateFilter extends InOperator implements DependentWithRemovalPl $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. @@ -155,7 +156,8 @@ class ModerationStateFilter extends InOperator implements DependentWithRemovalPl $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 { @@ -185,7 +187,14 @@ class ModerationStateFilter extends InOperator implements DependentWithRemovalPl $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 00000000000..5a45433c7bc --- /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 52e55612604..721272d0b42 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 @@ class ViewsModerationStateFilterTest extends ViewsKernelTestBase { $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], []); + // 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', - ]); + // 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', - ]); + // 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.