diff --git a/core/modules/views/src/Plugin/views/argument/EntityReferenceArgument.php b/core/modules/views/src/Plugin/views/argument/EntityReferenceArgument.php index fecb31ee7d23d4f5fe16f980aa5e50f570868bff..d23b9c12b05b119c54218727aa1ee05a1c499246 100644 --- a/core/modules/views/src/Plugin/views/argument/EntityReferenceArgument.php +++ b/core/modules/views/src/Plugin/views/argument/EntityReferenceArgument.php @@ -61,4 +61,19 @@ public function titleQuery() { return $titles; } + /** + * {@inheritdoc} + */ + public function summaryName($data) { + $id = $data->{$this->name_alias}; + $entity = $id ? $this->entityTypeManager->getStorage($this->definition['target_entity_type_id'])->load($id) : NULL; + if ($entity) { + return $this->entityRepository->getTranslationFromContext($entity)->label(); + } + if (($id === NULL || $id === '') && isset($this->definition['empty field name'])) { + return $this->definition['empty field name']; + } + return $id; + } + } diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_summary.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_summary.yml new file mode 100644 index 0000000000000000000000000000000000000000..3d845e092f7e2dcdc72b89638406cde8f98e826f --- /dev/null +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_summary.yml @@ -0,0 +1,212 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - node.type.article + module: + - node + - user +id: test_argument_summary +label: test_argument_summary +module: views +description: '' +tag: '' +base_table: node_field_data +base_field: nid +display: + default: + id: default + display_title: Default + display_plugin: default + position: 0 + display_options: + title: test_argument_summary + fields: + title: + id: title + table: node_field_data + field: title + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: title + plugin_id: field + label: '' + exclude: false + alter: + alter_text: false + make_link: false + absolute: false + word_boundary: false + ellipsis: false + strip_tags: false + trim: false + html: 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_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: true + 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 + pager: + type: none + options: + offset: 0 + items_per_page: 0 + 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 + access: + type: perm + options: + perm: 'access content' + cache: + type: tag + options: { } + empty: { } + sorts: + created: + id: created + table: node_field_data + field: created + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: created + plugin_id: date + order: DESC + expose: + label: '' + field_identifier: '' + exposed: false + granularity: second + arguments: + field_tags_target_id: + id: field_tags_target_id + table: node__field_tags + field: field_tags_target_id + relationship: none + group_type: group + admin_label: '' + plugin_id: entity_target_id + default_action: summary + exception: + value: all + title_enable: false + title: All + title_enable: false + title: '' + default_argument_type: fixed + default_argument_options: + argument: '' + summary_options: + base_path: '' + count: true + override: false + items_per_page: 25 + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: false + validate: + type: none + fail: 'not found' + validate_options: { } + break_phrase: false + not: false + filters: + status: + id: status + table: node_field_data + field: status + entity_type: node + entity_field: status + plugin_id: boolean + value: '1' + group: 1 + expose: + operator: '' + type: + id: type + table: node_field_data + field: type + entity_type: node + entity_field: type + plugin_id: bundle + value: + article: article + style: + type: default + row: + type: 'entity:node' + options: + view_mode: teaser + query: + type: views_query + options: + query_comment: '' + disable_sql_rewrite: false + distinct: false + replica: false + query_tags: { } + relationships: { } + header: { } + footer: { } + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - 'user.node_grants:view' + - user.permissions + tags: { } + page_1: + id: page_1 + display_title: Page + display_plugin: page + position: 1 + display_options: + display_extenders: { } + path: test-argument-summary + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - 'user.node_grants:view' + - user.permissions + tags: { } diff --git a/core/modules/views/tests/src/Kernel/Handler/ArgumentSummaryTest.php b/core/modules/views/tests/src/Kernel/Handler/ArgumentSummaryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9cbdfb9ccc4297dc60b9a98fafa5457f8feaff53 --- /dev/null +++ b/core/modules/views/tests/src/Kernel/Handler/ArgumentSummaryTest.php @@ -0,0 +1,152 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\views\Kernel\Handler; + +use Drupal\Core\Field\FieldStorageDefinitionInterface; +use Drupal\node\NodeTypeInterface; +use Drupal\taxonomy\VocabularyInterface; +use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait; +use Drupal\Tests\views\Kernel\ViewsKernelTestBase; +use Drupal\node\Entity\Node; +use Drupal\node\Entity\NodeType; +use Drupal\taxonomy\Entity\Term; +use Drupal\taxonomy\TermInterface; +use Drupal\taxonomy\Entity\Vocabulary; +use Drupal\views\Views; + +/** + * Tests the summary of results when an argument is not provided. + * + * @group views + */ +class ArgumentSummaryTest extends ViewsKernelTestBase { + + use EntityReferenceFieldCreationTrait; + + /** + * {@inheritdoc} + */ + public static $testViews = ['test_argument_summary']; + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'field', + 'node', + 'taxonomy', + 'text', + 'user', + 'views', + ]; + + /** + * Node type with an autocomplete tagging field. + * + * @var \Drupal\node\NodeTypeInterface + */ + protected NodeTypeInterface $nodeType; + + /** + * The vocabulary used for the test tag field. + * + * @var \Drupal\taxonomy\VocabularyInterface + */ + protected VocabularyInterface $tagVocabulary; + + /** + * {@inheritdoc} + */ + protected function setUp($import_test_views = TRUE): void { + parent::setUp($import_test_views); + + $this->installEntitySchema('node'); + $this->installEntitySchema('taxonomy_term'); + $this->installEntitySchema('user'); + + // Create the content type with an autocomplete tagging field. + $this->nodeType = NodeType::create([ + 'type' => 'article', + 'name' => 'Article', + ]); + $this->nodeType->save(); + + // Create the vocabulary for the tag field. + $this->tagVocabulary = Vocabulary::create([ + 'name' => 'Views testing tags', + 'vid' => 'views_testing_tags', + ]); + $this->tagVocabulary->save(); + + // Create the tag field itself. + $handler_settings = [ + 'target_bundles' => [ + $this->tagVocabulary->id() => $this->tagVocabulary->id(), + ], + 'auto_create' => TRUE, + ]; + $this->createEntityReferenceField( + 'node', + $this->nodeType->id(), + 'field_tags', + NULL, + 'taxonomy_term', + 'default', + $handler_settings, + FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, + ); + } + + /** + * Creates a term in the tag vocabulary. + * + * @return \Drupal\taxonomy\TermInterface $term + */ + protected function createTag(): TermInterface { + $tag = Term::create([ + 'name' => $this->randomMachineName(), + 'vid' => $this->tagVocabulary->id(), + ]); + $tag->save(); + return $tag; + } + + /** + * Tests the argument summary feature. + */ + public function testArgumentSummary(): void { + // Setup 2 tags. + $tags = []; + for ($i = 0; $i < 2; $i++) { + $tags[$i] = $this->createTag(); + } + + // Setup 4 nodes with different tags. + for ($i = 0; $i < 4; $i++) { + Node::create([ + 'type' => $this->nodeType->id(), + 'title' => $this->randomMachineName(), + // For odd numbered nodes, use both tags, even only get 1 tag. + 'field_tags' => ($i % 2) ? $tags : [$tags[0]->id()], + ])->save(); + } + + $view = Views::getView('test_argument_summary'); + $result = $view->preview('default'); + + // For the purposes of this test, we don't care about any markup or + // formatting, only that the summary is showing the tag labels and the + // correct counts. So strip all tags and extra whitespace to make the + // assertions more clear. + $renderer = $this->container->get('renderer'); + $output = (string) $renderer->renderRoot($result); + $output = trim(preg_replace('/\s+/', ' ', strip_tags($output))); + + // Output should show first tag on 4 nodes, the second tag on only 2. + $this->assertStringContainsString($tags[0]->label() . ' (4)', $output); + $this->assertStringContainsString($tags[1]->label() . ' (2)', $output); + } + +}