Verified Commit c1c3ae32 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #1766338 by vasike, John Pitcairn, sagesolutions, jenlampton, ckaotik,...

Issue #1766338 by vasike, John Pitcairn, sagesolutions, jenlampton, ckaotik, andyanderso, SoulReceiver, Krzysztof Domański, liquidcms, smustgrave, luenemann, sorin.eugen, dawehner, xenophyle, Lendude, zebda, pameeela, longwave, alison: Incorrect filter group OR behavior, LEFT JOIN changed to INNER JOIN

(cherry picked from commit 0dac7cab)
parent c3f53dc2
Loading
Loading
Loading
Loading
Loading
+61 −2
Original line number Diff line number Diff line
@@ -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());
  }

}
+4 −1
Original line number Diff line number Diff line
@@ -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;
        }