From d19fa67a927cd32dcb5e66f5b2e92d4498f00bac Mon Sep 17 00:00:00 2001 From: catch Date: Sun, 10 Jul 2022 10:00:14 +0900 Subject: [PATCH] =?UTF-8?q?Issue=20#2494617=20by=20Lendude,=20danflanagan8?= =?UTF-8?q?,=20B=C3=A8s,=20Shreya=20Shetty,=20stBorchert,=20Boobaa,=20Duae?= =?UTF-8?q?lFr,=20joey-santiago,=20drubb,=20nikitagupta,=20dawehner,=20ale?= =?UTF-8?q?xpott:=20TermName=20views=20argument=5Fvalidator=20is=20not=20w?= =?UTF-8?q?orking=20as=20expected?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 091a83df7bd0e382a3ca135fb09a6900cd8275bc) --- .../views/argument_validator/TermName.php | 20 +- ...views.view.test_taxonomy_name_argument.yml | 235 ++++++++++++++++++ .../Views/ArgumentValidatorTermNameTest.php | 183 ++++++++++++++ 3 files changed, 428 insertions(+), 10 deletions(-) create mode 100644 core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_name_argument.yml create mode 100644 core/modules/taxonomy/tests/src/Kernel/Views/ArgumentValidatorTermNameTest.php diff --git a/core/modules/taxonomy/src/Plugin/views/argument_validator/TermName.php b/core/modules/taxonomy/src/Plugin/views/argument_validator/TermName.php index 1a81b2f9525..23920dba062 100644 --- a/core/modules/taxonomy/src/Plugin/views/argument_validator/TermName.php +++ b/core/modules/taxonomy/src/Plugin/views/argument_validator/TermName.php @@ -66,22 +66,22 @@ class TermName extends Entity { $argument = str_replace('-', ' ', $argument); $this->argument->argument = $argument; } - $terms = $this->termStorage->loadByProperties(['name' => $argument]); - - if (!$terms) { - // Returned empty array no terms with the name. - return FALSE; + // 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]); } - // 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; } } diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_name_argument.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_name_argument.yml new file mode 100644 index 00000000000..76a85abeab9 --- /dev/null +++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_name_argument.yml @@ -0,0 +1,235 @@ +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: { } diff --git a/core/modules/taxonomy/tests/src/Kernel/Views/ArgumentValidatorTermNameTest.php b/core/modules/taxonomy/tests/src/Kernel/Views/ArgumentValidatorTermNameTest.php new file mode 100644 index 00000000000..394499926df --- /dev/null +++ b/core/modules/taxonomy/tests/src/Kernel/Views/ArgumentValidatorTermNameTest.php @@ -0,0 +1,183 @@ +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()); + } + +}