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