From c1c3ae32ca01f819a1fbdaea70bcf4e4cdc98d73 Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Wed, 17 Apr 2024 00:24:52 +0100 Subject: [PATCH] =?UTF-8?q?Issue=20#1766338=20by=20vasike,=20John=20Pitcai?= =?UTF-8?q?rn,=20sagesolutions,=20jenlampton,=20ckaotik,=20andyanderso,=20?= =?UTF-8?q?SoulReceiver,=20Krzysztof=20Doma=C5=84ski,=20liquidcms,=20smust?= =?UTF-8?q?grave,=20luenemann,=20sorin.eugen,=20dawehner,=20xenophyle,=20L?= =?UTF-8?q?endude,=20zebda,=20pameeela,=20longwave,=20alison:=20Incorrect?= =?UTF-8?q?=20filter=20group=20OR=20behavior,=20LEFT=20JOIN=20changed=20to?= =?UTF-8?q?=20INNER=20JOIN?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 0dac7cab3278db9c320955486857db9458c701e0) --- .../Views/TaxonomyIndexTidUiTest.php | 63 ++++++++++++++++++- core/modules/views/src/ManyToOneHelper.php | 5 +- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php b/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php index 7e49395d42a5..18167fe7153d 100644 --- a/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php +++ b/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php @@ -92,6 +92,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', @@ -369,8 +381,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()]], @@ -385,6 +401,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: @@ -490,6 +510,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 82a42a4e70b9..237afa64b435 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; } -- GitLab