Commit d089745d authored by catch's avatar catch
Browse files

Issue #2494617 by Lendude, danflanagan8, Bès, Shreya Shetty, stBorchert,...

Issue #2494617 by Lendude, danflanagan8, Bès, Shreya Shetty, stBorchert, Boobaa, DuaelFr, joey-santiago, drubb, nikitagupta, dawehner, alexpott: TermName views argument_validator is not working as expected

(cherry picked from commit 091a83df)
parent 1615365f
Loading
Loading
Loading
Loading
+10 −10
Original line number Diff line number Diff line
@@ -66,22 +66,22 @@ public function validateArgument($argument) {
      $argument = str_replace('-', ' ', $argument);
      $this->argument->argument = $argument;
    }
    // If bundles is set then restrict the loaded terms to the given bundles.
    if (!empty($this->options['bundles'])) {
      $terms = $this->termStorage->loadByProperties(['name' => $argument, 'vid' => $this->options['bundles']]);
    }
    else {
      $terms = $this->termStorage->loadByProperties(['name' => $argument]);

    if (!$terms) {
      // Returned empty array no terms with the name.
      return FALSE;
    }

    // Not knowing which term will be used if more than one is returned check
    // each one.
    // $terms are already bundle tested but we need to test access control.
    foreach ($terms as $term) {
      if (!$this->validateEntity($term)) {
        return FALSE;
      if ($this->validateEntity($term)) {
        return TRUE;
      }
    }

    return TRUE;
    return FALSE;
  }

}
+235 −0
Original line number Diff line number Diff line
langcode: en
status: true
dependencies:
  config:
    - taxonomy.vocabulary.tags
  module:
    - taxonomy
    - user
id: test_taxonomy_name_argument
label: 'Test taxonomy term argument'
module: views
description: ''
tag: ''
base_table: taxonomy_term_field_data
base_field: tid
display:
  default:
    display_plugin: default
    id: default
    display_title: Master
    position: 0
    display_options:
      access:
        type: perm
        options:
          perm: 'access content'
      cache:
        type: tag
        options: {  }
      query:
        type: views_query
        options:
          disable_sql_rewrite: false
          distinct: false
          replica: false
          query_comment: ''
          query_tags: {  }
      exposed_form:
        type: basic
        options:
          submit_button: Apply
          reset_button: false
          reset_button_label: Reset
          exposed_sorts_label: 'Sort by'
          expose_sort_order: true
          sort_asc_label: Asc
          sort_desc_label: Desc
      pager:
        type: mini
        options:
          items_per_page: 10
          offset: 0
          id: 0
          total_pages: null
          expose:
            items_per_page: false
            items_per_page_label: 'Items per page'
            items_per_page_options: '5, 10, 25, 50'
            items_per_page_options_all: false
            items_per_page_options_all_label: '- All -'
            offset: false
            offset_label: Offset
          tags:
            previous: ‹‹
            next: ››
      style:
        type: default
        options:
          grouping: {  }
          row_class: ''
          default_row_class: true
          uses_fields: false
      row:
        type: fields
        options:
          inline: {  }
          separator: ''
          hide_empty: false
          default_field_elements: true
      fields:
        name:
          id: name
          table: taxonomy_term_field_data
          field: name
          entity_type: taxonomy_term
          entity_field: name
          label: ''
          alter:
            alter_text: false
            make_link: false
            absolute: false
            trim: false
            word_boundary: false
            ellipsis: false
            strip_tags: false
            html: false
          hide_empty: false
          empty_zero: false
          type: string
          settings:
            link_to_entity: true
          plugin_id: term_name
          relationship: none
          group_type: group
          admin_label: ''
          exclude: false
          element_type: ''
          element_class: ''
          element_label_type: ''
          element_label_class: ''
          element_label_colon: true
          element_wrapper_type: ''
          element_wrapper_class: ''
          element_default_classes: true
          empty: ''
          hide_alter_empty: true
          click_sort_column: value
          group_column: value
          group_columns: {  }
          group_rows: true
          delta_limit: 0
          delta_offset: 0
          delta_reversed: false
          delta_first_last: false
          multi_type: separator
          separator: ', '
          field_api_classes: false
          convert_spaces: false
      filters:
        vid:
          id: vid
          table: taxonomy_term_field_data
          field: vid
          relationship: none
          group_type: group
          admin_label: ''
          operator: in
          value:
            tags: tags
          group: 1
          exposed: false
          expose:
            operator_id: ''
            label: ''
            description: ''
            use_operator: false
            operator: ''
            operator_limit_selection: false
            operator_list: {  }
            identifier: ''
            required: false
            remember: false
            multiple: false
            remember_roles:
              authenticated: authenticated
            reduce: false
          is_grouped: false
          group_info:
            label: ''
            description: ''
            identifier: ''
            optional: true
            widget: select
            multiple: false
            remember: false
            default_group: All
            default_group_multiple: {  }
            group_items: {  }
          entity_type: taxonomy_term
          entity_field: vid
          plugin_id: bundle
      sorts: {  }
      header: {  }
      footer: {  }
      empty: {  }
      relationships: {  }
      arguments:
        name:
          id: name
          table: taxonomy_term_field_data
          field: name
          relationship: none
          group_type: group
          admin_label: ''
          default_action: ignore
          exception:
            value: all
            title_enable: false
            title: All
          title_enable: false
          title: ''
          default_argument_type: fixed
          default_argument_options:
            argument: ''
          default_argument_skip_url: false
          summary_options:
            base_path: ''
            count: true
            items_per_page: 25
            override: false
          summary:
            sort_order: asc
            number_of_records: 0
            format: default_summary
          specify_validation: true
          validate:
            type: taxonomy_term_name
            fail: 'not found'
          validate_options:
            bundles:
              views_testing_tags: views_testing_tags
            operation: view
            access: false
            transform: false
          glossary: false
          limit: 0
          case: none
          path_case: none
          transform_dash: false
          break_phrase: false
          add_table: false
          require_value: false
          entity_type: taxonomy_term
          entity_field: name
          plugin_id: string
      display_extenders: {  }
    cache_metadata:
      max-age: -1
      contexts:
        - 'languages:language_content'
        - 'languages:language_interface'
        - url
        - url.query_args
        - user.permissions
      tags: {  }
+183 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\taxonomy\Kernel\Views;

use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\views\Views;

/**
 * Tests the plugin of the taxonomy: taxonomy_term_name argument validator.
 *
 * @group taxonomy
 */
class ArgumentValidatorTermNameTest extends TaxonomyTestBase {

  /**
   * Stores the taxonomy term used by this test.
   *
   * @var array
   */
  protected $terms = [];

  /**
   * Stores the taxonomy names used by this test.
   *
   * @var array
   */
  protected $names = [];

  /**
   * Stores the taxonomy IDs used by this test.
   *
   * @var array
   */
  protected $ids = [];

  /**
   * {@inheritdoc}
   */
  public static $testViews = ['test_taxonomy_name_argument'];

  /**
   * {@inheritdoc}
   */
  protected function setUp($import_test_views = TRUE): void {
    parent::setUp($import_test_views);

    // Add three terms to the 'tags' vocabulary.
    for ($i = 0; $i < 3; $i++) {
      $this->terms[] = $term = $this->createTerm();
      $this->names[] = $term->label();
      $this->ids[] = $term->id();
    }

    // Create a second vocabulary.
    $vocabulary2 = Vocabulary::create([
      'name' => 'Views testing tags 2',
      'vid' => 'views_testing_tags_2',
    ]);
    $vocabulary2->save();
    // Add term in this vocabulary that has same name as term 3.
    $duplicate = $this->createTerm([
      'name' => $this->names[2],
      'vid' => 'views_testing_tags_2',
    ]);
    $this->terms[] = $duplicate;
    $this->names[] = $duplicate->label();
    $this->ids[] = $duplicate->id();

    // Add uniquely named term in second vocab as well.
    $unique = $this->createTerm([
      'vid' => 'views_testing_tags_2',
    ]);
    $this->terms[] = $unique;
    $this->names[] = $unique->label();
    $this->ids[] = $unique->id();
  }

  /**
   * Tests the term name argument validator plugin.
   */
  public function testArgumentValidatorTermName() {
    $view = Views::getView('test_taxonomy_name_argument');
    $view->initHandlers();

    // Test with name that does not correspond to any term.
    $this->assertFalse($view->argument['name']->setArgument('not a term name'));
    $view->argument['name']->validated_title = NULL;
    $view->argument['name']->argument_validated = NULL;

    // Test with term in the wrong vocabulary.
    $this->assertFalse($view->argument['name']->setArgument($this->names[4]));
    $view->argument['name']->validated_title = NULL;
    $view->argument['name']->argument_validated = NULL;

    // Test with a couple valid names.
    $this->assertTrue($view->argument['name']->setArgument($this->names[0]));
    $this->assertEquals($this->names[0], $view->argument['name']->getTitle());
    $view->argument['name']->validated_title = NULL;
    $view->argument['name']->argument_validated = NULL;

    $this->assertTrue($view->argument['name']->setArgument($this->names[1]));
    $this->assertEquals($this->names[1], $view->argument['name']->getTitle());
    $view->argument['name']->validated_title = NULL;
    $view->argument['name']->argument_validated = NULL;

    // Test that multiple valid terms don't validate because multiple arguments
    // are currently not supported.
    $multiple_terms = $this->names[0] . '+' . $this->names[1];
    $this->assertFalse($view->argument['name']->setArgument($multiple_terms));
    $view->argument['name']->validated_title = NULL;
    $view->argument['name']->argument_validated = NULL;

    // Test term whose name is shared by term in disallowed bundle.
    $this->assertTrue($view->argument['name']->setArgument($this->names[2]));
    $this->assertEquals($this->names[2], $view->argument['name']->getTitle());
    $view->argument['name']->validated_title = NULL;
    $view->argument['name']->argument_validated = NULL;

    // Add the second vocabulary as an allowed bundle.
    $view->argument['name']->options['validate_options']['bundles']['views_testing_tags_2'] = 'views_testing_tags_2';

    // Test that an array of bundles is handled by passing terms with unique
    // names in each bundle.
    $this->assertTrue($view->argument['name']->setArgument($this->names[0]));
    $this->assertEquals($this->names[0], $view->argument['name']->getTitle());
    $view->argument['name']->validated_title = NULL;
    $view->argument['name']->argument_validated = NULL;

    $this->assertTrue($view->argument['name']->setArgument($this->names[4]));
    $this->assertEquals($this->names[4], $view->argument['name']->getTitle());
    $view->argument['name']->validated_title = NULL;
    $view->argument['name']->argument_validated = NULL;

    // Allow any and all bundles.
    $view->argument['name']->options['validate_options']['bundles'] = [];

    // Test that an empty array of bundles is handled by testing terms with
    // unique names in each bundle.
    $this->assertTrue($view->argument['name']->setArgument($this->names[0]));
    $this->assertEquals($this->names[0], $view->argument['name']->getTitle());
    $view->argument['name']->validated_title = NULL;
    $view->argument['name']->argument_validated = NULL;

    $this->assertTrue($view->argument['name']->setArgument($this->names[4]));
    $this->assertEquals($this->names[4], $view->argument['name']->getTitle());
  }

  /**
   * Tests the access checking in term name argument validator plugin.
   */
  public function testArgumentValidatorTermNameAccess() {
    $this->installConfig(['user']);
    $this->setCurrentUser($this->createUser(['access content']));
    $view = Views::getView('test_taxonomy_name_argument');
    $view->initHandlers();

    // Enable access checking on validator.
    $view->argument['name']->options['validate_options']['access'] = TRUE;
    // Allow all bundles.
    $view->argument['name']->options['validate_options']['bundles'] = [];

    // A uniquely named unpublished term in an allowed bundle.
    $this->terms[0]->setUnpublished()->save();
    $this->assertFalse($view->argument['name']->setArgument($this->names[0]));
    $view->argument['name']->validated_title = NULL;
    $view->argument['name']->argument_validated = NULL;

    // A name used by two terms in a single vocabulary. One is unpublished.
    // We re-name the second term to match the first one.
    $this->terms[1]->set('name', $this->names[0])->save();
    $this->names[1] = $this->terms[1]->label();
    $this->assertTrue($view->argument['name']->setArgument($this->names[0]));
    $this->assertEquals($this->names[0], $view->argument['name']->getTitle());
    $view->argument['name']->validated_title = NULL;
    $view->argument['name']->argument_validated = NULL;

    // A name shared by a term in each vocabulary. One is unpublished.
    $this->terms[3]->setUnpublished()->save();
    $this->assertTrue($view->argument['name']->setArgument($this->names[3]));
    $this->assertEquals($this->names[3], $view->argument['name']->getTitle());
  }

}