diff --git a/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php b/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php index a6f00a60b4abf97f23a50e04eeaec7c7fd9de899..31ed23421bef10dfdda4b419c53fcc8432a23c69 100644 --- a/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php +++ b/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php @@ -94,6 +94,18 @@ protected function setUp($import_test_views = TRUE, $modules = []): void { } ViewTestData::createTestViews(static::class, ['taxonomy_test_views']); + // Extra taxonomy and terms. + Vocabulary::create([ + 'vid' => 'other_tags', + 'name' => 'Other tags', + ])->save(); + + $this->terms[3][0] = $term = Term::create([ + 'vid' => 'tags', + 'name' => "Term 3.0", + ]); + $term->save(); + Vocabulary::create([ 'vid' => 'empty_vocabulary', 'name' => 'Empty Vocabulary', @@ -371,8 +383,12 @@ public function testFilterGrouping() { $field_name = 'taxonomy_tags'; $this->createEntityReferenceField('node', $node_type->id(), $field_name, NULL, 'taxonomy_term'); - // Create 4 nodes: 1 node without any tagging, 2 nodes tagged with 1 term, - // and 1 node with 2 tagged terms. + // Create the other tag field itself. + $field_name2 = 'taxonomy_other_tags'; + $this->createEntityReferenceField('node', $node_type->id(), $field_name2, NULL, 'taxonomy_term'); + + // Create 5 nodes: 1 node without any tagging, 2 nodes tagged with 1 term, + // 1 node with 2 tagged terms and 1 with other tags term. $node_no_term = $this->drupalCreateNode(); $node_with_term_1_0 = $this->drupalCreateNode([ $field_name => [['target_id' => $this->terms[1][0]->id()]], @@ -387,6 +403,10 @@ public function testFilterGrouping() { $field_name => [['target_id' => $this->terms[2][0]->id()]], ]); + $node_with_term_3_0 = $this->drupalCreateNode([ + $field_name2 => [['target_id' => $this->terms[3][0]->id()]], + ]); + // Create two groups. The first group contains the published filter and set // up the second group as an 'OR' group. The first subgroup of the second // filter group will vary as follows: @@ -492,6 +512,45 @@ public function testFilterGrouping() { $this->assertSession()->pageTextContainsOnce($node_with_terms_1_0_and_1_1->label()); $this->assertSession()->pageTextContainsOnce($node_with_term_2_0->label()); $this->assertSession()->pageTextNotContains($node_no_term->label()); + + // Different fields/taxonomies filters/values. + // Case 5: OR + // - filter "tid" with terms from tags as "is one of" + // - filter "taxonomy_other_tags_target_id" with term from other tags + // as "is one of". + $view = View::load('test_filter_taxonomy_index_tid'); + $display = &$view->getDisplay('default'); + $display['display_options']['filters']['tid']['value'][0] = $this->terms[1][0]->id(); + $display['display_options']['filters']['tid']['value'][1] = $this->terms[1][1]->id(); + $display['display_options']['filters']['tid']['operator'] = 'or'; + $display['display_options']['filters']['tid']['group'] = 2; + $display['display_options']['filters']['taxonomy_other_tags_target_id'] = $display['display_options']['filters']['tid']; + $display['display_options']['filters']['taxonomy_other_tags_target_id']['id'] = 'taxonomy_other_tags_target_id'; + $display['display_options']['filters']['taxonomy_other_tags_target_id']['value'][0] = $this->terms[3][0]->id(); + $display['display_options']['filters']['taxonomy_other_tags_target_id']['operator'] = 'or'; + $display['display_options']['filters']['taxonomy_other_tags_target_id']['group'] = 2; + $display['display_options']['filters']['taxonomy_other_tags_target_id']['table'] = 'node__taxonomy_other_tags'; + $display['display_options']['filters']['taxonomy_other_tags_target_id']['field'] = 'taxonomy_other_tags_target_id'; + unset($display['display_options']['filters']['tid_2']); + $display['display_options']['filter_groups'] = [ + 'operator' => 'AND', + 'groups' => [ + 1 => 'AND', + 2 => 'OR', + ], + ]; + $view->save(); + + $this->drupalGet('test-filter-taxonomy-index-tid'); + // We expect no nodes tagged with term 1.0 or 1.1. The node tagged with + // term 3.0 and the untagged node will be shown. + $this->assertSession()->pageTextContainsOnce($node_with_term_1_0->label()); + // The view does not have DISTINCT query enabled, the node tagged with + // both 1.0 and 1.1 will appear twice. + $this->assertSession()->pageTextMatchesCount(2, "/{$node_with_terms_1_0_and_1_1->label()}/"); + $this->assertSession()->pageTextContainsOnce($node_with_term_3_0->label()); + $this->assertSession()->pageTextNotContains($node_with_term_2_0->label()); + $this->assertSession()->pageTextNotContains($node_no_term->label()); } } diff --git a/core/modules/views/src/ManyToOneHelper.php b/core/modules/views/src/ManyToOneHelper.php index 82a42a4e70b91cc09cec3826ff693785679da1f3..237afa64b435f324ad0db5c35c61cd02181a43cc 100644 --- a/core/modules/views/src/ManyToOneHelper.php +++ b/core/modules/views/src/ManyToOneHelper.php @@ -181,9 +181,12 @@ public function ensureMyTable() { // query optimization, INNER joins are slightly faster, so use them // when we know we can. $join = $this->getJoin(); - if (isset($join)) { + $group = $this->handler->options['group'] ?? FALSE; + // Only if there is no group with OR operator. + if (isset($join) && !($group && $this->handler->query->where[$group]['type'] === 'OR')) { $join->type = 'INNER'; } + $this->handler->tableAlias = $this->handler->query->ensureTable($this->handler->table, $this->handler->relationship, $join); $this->handler->view->many_to_one_tables[$field] = $this->handler->value; }