From aec9cf8ca15958546b882f8eb371080dbd39b9ed Mon Sep 17 00:00:00 2001 From: Dave Long <dave@longwaveconsulting.com> Date: Fri, 4 Aug 2023 18:33:46 +0100 Subject: [PATCH] =?UTF-8?q?Issue=20#2559961=20by=20angrytoast,=20Krzysztof?= =?UTF-8?q?=20Doma=C5=84ski,=20drup16,=20Lendude,=20vasike,=20Leksat,=20sa?= =?UTF-8?q?m711,=20tar=5Finet,=20mlncn,=20JordiK,=20adinac,=20Pascal-,=20j?= =?UTF-8?q?oshua.boltz,=20froboy,=20oriol=5Fe9g,=20alison,=20codesmith,=20?= =?UTF-8?q?luenemann,=20specky=5Frum,=20daffie:=20ManyToOneHelper=20ignore?= =?UTF-8?q?s=20group=20configuration=20for=20some=20cases?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Views/TaxonomyIndexTidUiTest.php | 133 ++++++++++++++++++ core/modules/views/src/ManyToOneHelper.php | 8 +- 2 files changed, 137 insertions(+), 4 deletions(-) diff --git a/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php b/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php index 173460d4b2fb..ecb844727200 100644 --- a/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php +++ b/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php @@ -358,4 +358,137 @@ public function testExposedUnpublishedFilterOptions() { $this->assertEmpty($this->cssSelect('option[value="' . $this->terms[1][0]->id() . '"]')); } + /** + * Tests using the TaxonomyIndexTid in a filter group. + */ + public function testFilterGrouping() { + $node_type = $this->drupalCreateContentType(['type' => 'page']); + + // Create the tag field itself. + $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. + $node_no_term = $this->drupalCreateNode(); + $node_with_term_1_0 = $this->drupalCreateNode([ + $field_name => [['target_id' => $this->terms[1][0]->id()]], + ]); + $node_with_terms_1_0_and_1_1 = $this->drupalCreateNode([ + $field_name => [ + ['target_id' => $this->terms[1][0]->id()], + ['target_id' => $this->terms[1][1]->id()], + ], + ]); + $node_with_term_2_0 = $this->drupalCreateNode([ + $field_name => [['target_id' => $this->terms[2][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: + // - multiple values vs single value + // - not vs or operator values + $view = View::load('test_filter_taxonomy_index_tid'); + $display =& $view->getDisplay('default'); + // Case 1: + // - filter "tid" with multiple terms as "is none of" + // - filter "tid_2" with a single term as "is one of" + $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'] = 'not'; + $display['display_options']['filters']['tid']['group'] = 2; + $display['display_options']['filters']['tid_2'] = $display['display_options']['filters']['tid']; + $display['display_options']['filters']['tid_2']['id'] = 'tid_2'; + $display['display_options']['filters']['tid_2']['value'][0] = $this->terms[2][0]->id(); + $display['display_options']['filters']['tid_2']['operator'] = 'or'; + $display['display_options']['filters']['tid_2']['group'] = 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 2.0 and the untagged node will be shown. + $this->assertSession()->pageTextNotContains($node_with_term_1_0->label()); + $this->assertSession()->pageTextNotContains($node_with_terms_1_0_and_1_1->label()); + $this->assertSession()->pageTextContainsOnce($node_with_term_2_0->label()); + $this->assertSession()->pageTextContainsOnce($node_no_term->label()); + + // Case 2: + // - filter "tid" with multiple terms as "is one of" + // - filter "tid_2" with a single term 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']['tid_2'] = $display['display_options']['filters']['tid']; + $display['display_options']['filters']['tid_2']['id'] = 'tid_2'; + $display['display_options']['filters']['tid_2']['value'][0] = $this->terms[2][0]->id(); + $display['display_options']['filters']['tid_2']['operator'] = 'or'; + $display['display_options']['filters']['tid_2']['group'] = 2; + $view->save(); + + $this->drupalGet('test-filter-taxonomy-index-tid'); + // We expect all the tagged nodes but not the untagged node. + $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_2_0->label()); + $this->assertSession()->pageTextNotContains($node_no_term->label()); + + // Case 3: + // - filter "tid" with a single term as "is none of" + // - filter "tid_2" with a single term as "is one of" + $view = View::load('test_filter_taxonomy_index_tid'); + $display =& $view->getDisplay('default'); + $display['display_options']['filters']['tid']['value'] = []; + $display['display_options']['filters']['tid']['value'][0] = $this->terms[1][0]->id(); + $display['display_options']['filters']['tid']['operator'] = 'not'; + $display['display_options']['filters']['tid']['group'] = 2; + $display['display_options']['filters']['tid_2'] = $display['display_options']['filters']['tid']; + $display['display_options']['filters']['tid_2']['id'] = 'tid_2'; + $display['display_options']['filters']['tid_2']['value'][0] = $this->terms[2][0]->id(); + $display['display_options']['filters']['tid_2']['operator'] = 'or'; + $display['display_options']['filters']['tid_2']['group'] = 2; + $view->save(); + + $this->drupalGet('test-filter-taxonomy-index-tid'); + // We expect none of the nodes tagged with term 1.0. The node tagged with + // term 2.0 and the untagged node should be shown. + $this->assertSession()->pageTextNotContains($node_with_term_1_0->label()); + $this->assertSession()->pageTextNotContains($node_with_terms_1_0_and_1_1->label()); + $this->assertSession()->pageTextContainsOnce($node_with_term_2_0->label()); + $this->assertSession()->pageTextContainsOnce($node_no_term->label()); + + // Case 4: + // - filter "tid" with a single term as "is one of" + // - filter "tid_2" with a single term as "is one of" + $view = View::load('test_filter_taxonomy_index_tid'); + $display =& $view->getDisplay('default'); + $display['display_options']['filters']['tid']['value'] = []; + $display['display_options']['filters']['tid']['value'][0] = $this->terms[1][0]->id(); + $display['display_options']['filters']['tid']['operator'] = 'or'; + $display['display_options']['filters']['tid']['group'] = 2; + $display['display_options']['filters']['tid_2'] = $display['display_options']['filters']['tid']; + $display['display_options']['filters']['tid_2']['id'] = 'tid_2'; + $display['display_options']['filters']['tid_2']['value'][0] = $this->terms[2][0]->id(); + $view->save(); + + $this->drupalGet('test-filter-taxonomy-index-tid'); + // We expect all the tagged nodes to be shown but not the untagged node. + $this->assertSession()->pageTextContainsOnce($node_with_term_1_0->label()); + $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()); + } + } diff --git a/core/modules/views/src/ManyToOneHelper.php b/core/modules/views/src/ManyToOneHelper.php index 7f493ddb76f7..82a42a4e70b9 100644 --- a/core/modules/views/src/ManyToOneHelper.php +++ b/core/modules/views/src/ManyToOneHelper.php @@ -327,18 +327,18 @@ public function addFilter() { $placeholder .= '[]'; if ($operator == 'IS NULL') { - $this->handler->query->addWhereExpression(0, "$field $operator"); + $this->handler->query->addWhereExpression($options['group'], "$field $operator"); } else { - $this->handler->query->addWhereExpression(0, "$field $operator($placeholder)", [$placeholder => $value]); + $this->handler->query->addWhereExpression($options['group'], "$field $operator($placeholder)", [$placeholder => $value]); } } else { if ($operator == 'IS NULL') { - $this->handler->query->addWhereExpression(0, "$field $operator"); + $this->handler->query->addWhereExpression($options['group'], "$field $operator"); } else { - $this->handler->query->addWhereExpression(0, "$field $operator $placeholder", [$placeholder => $value]); + $this->handler->query->addWhereExpression($options['group'], "$field $operator $placeholder", [$placeholder => $value]); } } } -- GitLab