Unverified Commit 3839c0d3 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #2877994 by Lendude, Krzysztof Domański, mahmoud-zayed, joseph.olstad,...

Issue #2877994 by Lendude, Krzysztof Domański, mahmoud-zayed, joseph.olstad, caspervoogt, gngn, timomueller, cri2mars, pavlosdan, aleksip, johndevman, paper boy, patrickroma, Bessonweb, alexpott, tibbsa, ConradFlashback, larowlan, DuneBL, jess_m, arakwar: Entity Links fields does not have translation support
parent 8a568390
Loading
Loading
Loading
Loading
+5 −1
Changes for core/modules/views/src/Plugin/views/field/EntityLink.php: 5 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -36,7 +36,11 @@ protected function renderLink(ResultRow $row) {
   */
  protected function getUrlInfo(ResultRow $row) {
    $template = $this->getEntityLinkTemplate();
    return $this->getEntity($row)->toUrl($template)->setAbsolute($this->options['absolute']);
    $entity = $this->getEntity($row);
    if ($this->languageManager->isMultilingual()) {
      $entity = $this->getEntityTranslation($entity, $row);
    }
    return $entity->toUrl($template)->setAbsolute($this->options['absolute']);
  }

  /**
+93 −5
Changes for core/modules/views/src/Plugin/views/field/LinkBase.php: 93 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -3,9 +3,13 @@
namespace Drupal\views\Plugin\views\field;

use Drupal\Core\Access\AccessManagerInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Routing\RedirectDestinationTrait;
use Drupal\views\Entity\Render\EntityTranslationRenderTrait;
use Drupal\views\ResultRow;
use Symfony\Component\DependencyInjection\ContainerInterface;

@@ -17,6 +21,7 @@
abstract class LinkBase extends FieldPluginBase {

  use RedirectDestinationTrait;
  use EntityTranslationRenderTrait;

  /**
   * The access manager service.
@@ -32,6 +37,27 @@ abstract class LinkBase extends FieldPluginBase {
   */
  protected $currentUser;

  /**
   * The language manager.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The entity repository.
   *
   * @var \Drupal\Core\Entity\EntityRepositoryInterface
   */
  protected $entityRepository;

  /**
   * Constructs a LinkBase object.
   *
@@ -43,10 +69,32 @@ abstract class LinkBase extends FieldPluginBase {
   *   The plugin implementation definition.
   * @param \Drupal\Core\Access\AccessManagerInterface $access_manager
   *   The access manager.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface|null $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Entity\EntityRepositoryInterface|null $entity_repository
   *   The entity repository.
   * @param \Drupal\Core\Language\LanguageManagerInterface|null $language_manager
   *   The language manager.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, AccessManagerInterface $access_manager) {
  public function __construct(array $configuration, $plugin_id, $plugin_definition, AccessManagerInterface $access_manager, EntityTypeManagerInterface $entity_type_manager = NULL, EntityRepositoryInterface $entity_repository = NULL, LanguageManagerInterface $language_manager = NULL) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->accessManager = $access_manager;
    if (!$entity_type_manager) {
      @trigger_error('Passing the entity type manager service to \Drupal\views\Plugin\views\field\LinkBase::__construct is required since 8.7.0, see https://www.drupal.org/node/3023427.', E_USER_DEPRECATED);
      $entity_type_manager = \Drupal::service('entity_type.manager');
    }
    $this->entityTypeManager = $entity_type_manager;
    if (!$entity_repository) {
      @trigger_error('Passing the entity repository service to \Drupal\views\Plugin\views\field\LinkBase::__construct is required since 8.7.0, see https://www.drupal.org/node/3023427.', E_USER_DEPRECATED);
      $entity_repository = \Drupal::service('entity.repository');
    }
    $this->entityRepository = $entity_repository;

    if (!$language_manager) {
      @trigger_error('Passing the language manager service to \Drupal\views\Plugin\views\field\LinkBase::__construct is required since 8.7.0, see https://www.drupal.org/node/3023427.', E_USER_DEPRECATED);
      $language_manager = \Drupal::service('language_manager');
    }
    $this->languageManager = $language_manager;
  }

  /**
@@ -57,7 +105,10 @@ public static function create(ContainerInterface $container, array $configuratio
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('access_manager')
      $container->get('access_manager'),
      $container->get('entity_type.manager'),
      $container->get('entity.repository'),
      $container->get('language_manager')
    );
  }

@@ -115,6 +166,9 @@ public function usesGroupBy() {
   * {@inheritdoc}
   */
  public function query() {
    if ($this->languageManager->isMultilingual()) {
      $this->getEntityTranslationRenderer()->query($this->query, $this->relationship);
    }
    $this->addAdditionalFields();
  }

@@ -178,9 +232,8 @@ protected function renderLink(ResultRow $row) {
   */
  protected function addLangcode(ResultRow $row) {
    $entity = $this->getEntity($row);
    $langcode_key = $entity ? $entity->getEntityType()->getKey('langcode') : FALSE;
    if ($langcode_key && isset($this->aliases[$langcode_key])) {
      $this->options['alter']['language'] = $entity->language();
    if ($this->languageManager->isMultilingual()) {
      $this->options['alter']['language'] = $this->getEntityTranslation($entity, $row)->language();
    }
  }

@@ -194,4 +247,39 @@ protected function getDefaultLabel() {
    return $this->t('link');
  }

  /**
   * {@inheritdoc}
   */
  protected function getEntityTypeId() {
    return $this->getEntityType();
  }

  /**
   * {@inheritdoc}
   */
  protected function getEntityTypeManager() {
    return $this->entityTypeManager;
  }

  /**
   * {@inheritdoc}
   */
  protected function getEntityRepository() {
    return $this->entityRepository;
  }

  /**
   * {@inheritdoc}
   */
  protected function getLanguageManager() {
    return $this->languageManager;
  }

  /**
   * {@inheritdoc}
   */
  protected function getView() {
    return $this->view;
  }

}
+337 −0
Changes for core/modules/views/tests/modules/views_test_config/test_views/views.view.test_link_base_links.yml: 337 added lines, 0 removed lines.
Original line number Diff line number Diff line
langcode: en
status: true
dependencies:
  module:
    - content_translation
    - node
    - user
id: test_link_base_links
label: 'test link base links'
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
core: 8.x
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: 25
          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
      row:
        type: fields
        options:
          default_field_elements: true
          inline: {  }
          separator: ''
          hide_empty: false
      fields:
        view_node:
          id: view_node
          table: node
          field: view_node
          relationship: none
          group_type: group
          admin_label: ''
          label: ''
          exclude: false
          alter:
            alter_text: false
            text: ''
            make_link: false
            path: ''
            absolute: false
            external: false
            replace_spaces: false
            path_case: none
            trim_whitespace: false
            alt: ''
            rel: ''
            link_class: ''
            prefix: ''
            suffix: ''
            target: ''
            nl2br: false
            max_length: 0
            word_boundary: true
            ellipsis: true
            more_link: false
            more_link_text: ''
            more_link_path: ''
            strip_tags: false
            trim: false
            preserve_tags: ''
            html: false
          element_type: ''
          element_class: ''
          element_label_type: ''
          element_label_class: ''
          element_label_colon: false
          element_wrapper_type: ''
          element_wrapper_class: ''
          element_default_classes: true
          empty: ''
          hide_empty: false
          empty_zero: false
          hide_alter_empty: true
          text: view
          output_url_as_text: false
          absolute: false
          entity_type: node
          plugin_id: entity_link
        delete_node:
          id: delete_node
          table: node
          field: delete_node
          relationship: none
          group_type: group
          admin_label: ''
          label: ''
          exclude: false
          alter:
            alter_text: false
            text: ''
            make_link: false
            path: ''
            absolute: false
            external: false
            replace_spaces: false
            path_case: none
            trim_whitespace: false
            alt: ''
            rel: ''
            link_class: ''
            prefix: ''
            suffix: ''
            target: ''
            nl2br: false
            max_length: 0
            word_boundary: true
            ellipsis: true
            more_link: false
            more_link_text: ''
            more_link_path: ''
            strip_tags: false
            trim: false
            preserve_tags: ''
            html: false
          element_type: ''
          element_class: ''
          element_label_type: ''
          element_label_class: ''
          element_label_colon: false
          element_wrapper_type: ''
          element_wrapper_class: ''
          element_default_classes: true
          empty: ''
          hide_empty: false
          empty_zero: false
          hide_alter_empty: true
          text: delete
          output_url_as_text: false
          absolute: false
          entity_type: node
          plugin_id: entity_link_delete
        edit_node:
          id: edit_node
          table: node
          field: edit_node
          relationship: none
          group_type: group
          admin_label: ''
          label: ''
          exclude: false
          alter:
            alter_text: false
            text: ''
            make_link: false
            path: ''
            absolute: false
            external: false
            replace_spaces: false
            path_case: none
            trim_whitespace: false
            alt: ''
            rel: ''
            link_class: ''
            prefix: ''
            suffix: ''
            target: ''
            nl2br: false
            max_length: 0
            word_boundary: true
            ellipsis: true
            more_link: false
            more_link_text: ''
            more_link_path: ''
            strip_tags: false
            trim: false
            preserve_tags: ''
            html: false
          element_type: ''
          element_class: ''
          element_label_type: ''
          element_label_class: ''
          element_label_colon: false
          element_wrapper_type: ''
          element_wrapper_class: ''
          element_default_classes: true
          empty: ''
          hide_empty: false
          empty_zero: false
          hide_alter_empty: true
          text: edit
          output_url_as_text: false
          absolute: false
          entity_type: node
          plugin_id: entity_link_edit
        view_node_1:
          id: view_node_1
          table: node
          field: view_node
          relationship: none
          group_type: group
          admin_label: ''
          label: ''
          exclude: false
          alter:
            alter_text: false
            text: ''
            make_link: false
            path: ''
            absolute: false
            external: false
            replace_spaces: false
            path_case: none
            trim_whitespace: false
            alt: ''
            rel: ''
            link_class: ''
            prefix: ''
            suffix: ''
            target: ''
            nl2br: false
            max_length: 0
            word_boundary: true
            ellipsis: true
            more_link: false
            more_link_text: ''
            more_link_path: ''
            strip_tags: false
            trim: false
            preserve_tags: ''
            html: false
          element_type: ''
          element_class: ''
          element_label_type: ''
          element_label_class: ''
          element_label_colon: false
          element_wrapper_type: ''
          element_wrapper_class: ''
          element_default_classes: true
          empty: ''
          hide_empty: false
          empty_zero: false
          hide_alter_empty: true
          text: view
          output_url_as_text: true
          absolute: false
          entity_type: node
          plugin_id: entity_link
      filters: { }
      sorts:
        created:
          id: created
          table: node_field_data
          field: created
          order: DESC
          entity_type: node
          entity_field: created
          plugin_id: date
          relationship: none
          group_type: group
          admin_label: ''
          exposed: false
          expose:
            label: ''
          granularity: second
      title: 'test link base links'
      header: {  }
      footer: {  }
      empty: {  }
      relationships: {  }
      arguments: {  }
      display_extenders: {  }
    cache_metadata:
      max-age: -1
      contexts:
        - 'languages:language_content'
        - 'languages:language_interface'
        - url.query_args
        - 'user.node_grants:view'
        - user.permissions
      tags: {  }
  page_1:
    display_plugin: page
    id: page_1
    display_title: Page
    position: 1
    display_options:
      display_extenders: {  }
      path: test-link-base-links
    cache_metadata:
      max-age: -1
      contexts:
        - 'languages:language_content'
        - 'languages:language_interface'
        - url.query_args
        - 'user.node_grants:view'
        - user.permissions
      tags: {  }
+91 −0
Changes for core/modules/views/tests/src/Functional/Handler/FieldEntityLinkBaseTest.php: 91 added lines, 0 removed lines.
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\views\Functional\Handler;

use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\node\Entity\Node;
use Drupal\Tests\views\Functional\ViewTestBase;

/**
 * Tests the core Drupal\views\Plugin\views\field\LinkBase handler.
 *
 * @group views
 */
class FieldEntityLinkBaseTest extends ViewTestBase {

  /**
   * Views used by this test.
   *
   * @var array
   */
  public static $testViews = ['test_link_base_links'];

  /**
   * {@inheritdoc}
   */
  public static $modules = ['node', 'language'];

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

    $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);

    // Add languages and refresh the container so the entity manager will have
    // fresh data.
    ConfigurableLanguage::createFromLangcode('hu')->save();
    ConfigurableLanguage::createFromLangcode('es')->save();
    $this->rebuildContainer();

    // Create an English and Hungarian nodes and add a Spanish translation.
    foreach (['en', 'hu'] as $langcode) {
      $entity = Node::create([
        'title' => $this->randomMachineName(),
        'type' => 'article',
        'langcode' => $langcode,
      ]);
      $entity->save();
      $translation = $entity->addTranslation('es');
      $translation->set('title', $entity->getTitle() . ' in Spanish');
      $translation->save();
    }

    $this->drupalLogin($this->rootUser);

  }

  /**
   * Tests entity link fields.
   */
  public function testEntityLink() {
    $this->drupalGet('test-link-base-links');
    $session = $this->assertSession();

    // Tests 'Link to Content'.
    $session->linkByHrefExists('/node/1');
    $session->linkByHrefExists('/es/node/1');
    $session->linkByHrefExists('/hu/node/2');
    $session->linkByHrefExists('/es/node/2');

    // Tests 'Link to delete Content'.
    $session->linkByHrefExists('/node/1/delete');
    $session->linkByHrefExists('/es/node/1/delete');
    $session->linkByHrefExists('/hu/node/2/delete');
    $session->linkByHrefExists('/es/node/2/delete');

    // Tests 'Link to edit Content'.
    $session->linkByHrefExists('/node/1/edit');
    $session->linkByHrefExists('/es/node/1/edit');
    $session->linkByHrefExists('/hu/node/2/edit');
    $session->linkByHrefExists('/es/node/2/edit');

    // Tests the second 'Link to Content' rendered as text.
    $session->pageTextContains('/node/1');
    $session->pageTextContains('/es/node/1');
    $session->pageTextContains('/hu/node/2');
    $session->pageTextContains('/es/node/2');
  }

}