Commit 170919be authored by catch's avatar catch
Browse files

Issue #3442227 by dww, smustgrave: Use labels in Views argument summaries for entity references

(cherry picked from commit a62995de)
parent 9fb79f28
Loading
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -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;
  }

}
+212 −0
Original line number Diff line number Diff line
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: {  }
+152 −0
Original line number Diff line number Diff line
<?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);
  }

}