Skip to content
Snippets Groups Projects
Verified Commit 18c45f5f authored by Alex Pott's avatar Alex Pott
Browse files

Issue #2765297 by mohit_aghera, joseph.olstad, sylus, ducktape, alexpott,...

Issue #2765297 by mohit_aghera, joseph.olstad, sylus, ducktape, alexpott, anmolgoyal74, heikki, kishor_kolekar, kriboogh, googletorp, dnotes, mpp, Berdir, borisson_, Lendude, xjm: Return translated term name on views "Content: Has taxonomy term ID (with depth)"
parent 1f94e17f
Branches
Tags
31 merge requests!11131[10.4.x-only-DO-NOT-MERGE]: Issue ##2842525 Ajax attached to Views exposed filter form does not trigger callbacks,!9470[10.3.x-only-DO-NOT-MERGE]: #3331771 Fix file_get_contents(): Passing null to parameter,!8540Issue #3457061: Bootstrap Modal dialog Not closing after 10.3.0 Update,!8528Issue #3456871 by Tim Bozeman: Support NULL services,!8373Issue #3427374 by danflanagan8, Vighneshh: taxonomy_tid ViewsArgumentDefault...,!7526Expose roles in response,!7352Draft: Resolve #3203489 "Set filename as",!5423Draft: Resolve #3329907 "Test2",!3878Removed unused condition head title for views,!3818Issue #2140179: $entity->original gets stale between updates,!3742Issue #3328429: Create item list field formatter for displaying ordered and unordered lists,!3731Claro: role=button on status report items,!3651Issue #3347736: Create new SDC component for Olivero (header-search),!3531Issue #3336994: StringFormatter always displays links to entity even if the user in context does not have access,!3478Issue #3337882: Deleted menus are not removed from content type config,!3355Issue #3209129: Scrolling problems when adding a block via layout builder,!3154Fixes #2987987 - CSRF token validation broken on routes with optional parameters.,!3133core/modules/system/css/components/hidden.module.css,!2964Issue #2865710 : Dependencies from only one instance of a widget are used in display modes,!2812Issue #3312049: [Followup] Fix Drupal.Commenting.FunctionComment.MissingReturnType returns for NULL,!2794Issue #3100732: Allow specifying `meta` data on JSON:API objects,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2062Issue #3246454: Add weekly granularity to views date sort,!1105Issue #3025039: New non translatable field on translatable content throws error,!1073issue #3191727: Focus states on mobile second level navigation items fixed,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!877Issue #2708101: Default value for link text is not saved,!617Issue #3043725: Provide a Entity Handler for user cancelation,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493
Pipeline #121418 canceled
Pipeline: drupal

#121420

    ......@@ -3,6 +3,7 @@
    namespace Drupal\taxonomy\Plugin\views\argument;
    use Drupal\Core\Entity\EntityStorageInterface;
    use Drupal\Core\Entity\EntityRepositoryInterface;
    use Drupal\Core\Form\FormStateInterface;
    use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
    use Drupal\taxonomy\TaxonomyIndexDepthQueryTrait;
    ......@@ -26,16 +27,26 @@ class IndexTidDepth extends ArgumentPluginBase implements ContainerFactoryPlugin
    /**
    * @var \Drupal\Core\Entity\EntityStorageInterface
    *
    * @deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. There is no
    * replacement.
    *
    * @see https://www.drupal.org/node/3427843
    */
    protected $termStorage;
    /**
    * {@inheritdoc}
    */
    public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityStorageInterface $termStorage) {
    public function __construct(array $configuration, $plugin_id, $plugin_definition, protected EntityStorageInterface|EntityRepositoryInterface $entityRepository) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->termStorage = $termStorage;
    if ($entityRepository instanceof EntityStorageInterface) {
    // @phpstan-ignore-next-line
    $this->termStorage = $entityRepository;
    @trigger_error('Calling ' . __CLASS__ . '::__construct() with the $termStorage argument as \Drupal\Core\Entity\EntityStorageInterface is deprecated in drupal:10.3.0 and it will require Drupal\Core\Entity\EntityRepositoryInterface in drupal:11.0.0. See https://www.drupal.org/node/3427843', E_USER_DEPRECATED);
    $this->entityRepository = \Drupal::service('entity.repository');
    }
    }
    /**
    ......@@ -46,7 +57,7 @@ public static function create(ContainerInterface $container, array $configuratio
    $configuration,
    $plugin_id,
    $plugin_definition,
    $container->get('entity_type.manager')->getStorage('taxonomy_term')
    $container->get('entity.repository')
    );
    }
    ......@@ -114,9 +125,9 @@ public function query($group_by = FALSE) {
    }
    public function title() {
    $term = $this->termStorage->load($this->argument);
    $term = $this->entityRepository->getCanonical('taxonomy_term', $this->argument);
    if (!empty($term)) {
    return $term->getName();
    return $term->label();
    }
    // TODO review text
    return $this->t('No name');
    ......
    ......@@ -2,6 +2,7 @@
    namespace Drupal\taxonomy\Plugin\views\argument;
    use Drupal\Core\Entity\EntityRepositoryInterface;
    use Drupal\Core\Entity\EntityStorageInterface;
    use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
    use Drupal\views\Attribute\ViewsArgument;
    ......@@ -20,16 +21,25 @@ class Taxonomy extends NumericArgument implements ContainerFactoryPluginInterfac
    /**
    * @var \Drupal\Core\Entity\EntityStorageInterface
    *
    * @deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. There is no
    * replacement.
    *
    * @see https://www.drupal.org/node/3427843
    */
    protected $termStorage;
    /**
    * {@inheritdoc}
    */
    public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityStorageInterface $term_storage) {
    public function __construct(array $configuration, $plugin_id, $plugin_definition, protected EntityStorageInterface|EntityRepositoryInterface $entityRepository) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->termStorage = $term_storage;
    if ($entityRepository instanceof EntityStorageInterface) {
    // @phpstan-ignore-next-line
    $this->termStorage = $this->entityRepository;
    @trigger_error('Calling ' . __CLASS__ . '::__construct() with the $termStorage argument as \Drupal\Core\Entity\EntityStorageInterface is deprecated in drupal:10.3.0 and it will require Drupal\Core\Entity\EntityRepositoryInterface in drupal:11.0.0. See https://www.drupal.org/node/3427843', E_USER_DEPRECATED);
    $this->entityRepository = \Drupal::service('entity.repository');
    }
    }
    /**
    ......@@ -40,7 +50,7 @@ public static function create(ContainerInterface $container, array $configuratio
    $configuration,
    $plugin_id,
    $plugin_definition,
    $container->get('entity_type.manager')->getStorage('taxonomy_term')
    $container->get('entity.repository')
    );
    }
    ......@@ -50,9 +60,9 @@ public static function create(ContainerInterface $container, array $configuratio
    public function title() {
    // There might be no valid argument.
    if ($this->argument) {
    $term = $this->termStorage->load($this->argument);
    $term = $this->entityRepository->getCanonical('taxonomy_term', $this->argument);
    if (!empty($term)) {
    return $term->getName();
    return $term->label();
    }
    }
    // TODO review text
    ......
    ......@@ -112,6 +112,7 @@ function taxonomy_tokens($type, $tokens, array $data, array $options, Bubbleable
    $replacements = [];
    if ($type == 'term' && !empty($data['term'])) {
    $term = $data['term'];
    $term = \Drupal::service('entity.repository')->getTranslationFromContext($term, isset($options['langcode']) ? $options['langcode'] : NULL);
    foreach ($tokens as $name => $original) {
    switch ($name) {
    ......@@ -120,7 +121,7 @@ function taxonomy_tokens($type, $tokens, array $data, array $options, Bubbleable
    break;
    case 'name':
    $replacements[$original] = $term->getName();
    $replacements[$original] = $term->label();
    break;
    case 'description':
    ......
    <?php
    declare(strict_types=1);
    namespace Drupal\taxonomy_test\Plugin\views\argument;
    use Drupal\Core\Entity\EntityStorageInterface;
    use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
    use Drupal\taxonomy\Plugin\views\argument\Taxonomy;
    use Symfony\Component\DependencyInjection\ContainerInterface;
    /**
    * Test argument handler for testing deprecation in IndexTidDepth plugin.
    *
    * @ingroup views_argument_handlers
    *
    * @ViewsArgument("taxonomy_views_argument_test")
    */
    class TaxonomyViewsArgumentTest extends Taxonomy {
    /**
    * Constructs new IndexTidDepthTestPlugin object.
    */
    public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityStorageInterface $term_storage, protected EntityTypeBundleInfoInterface $entityTypeBundleInfo) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $term_storage);
    }
    /**
    * {@inheritdoc}
    */
    public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
    return new static(
    $configuration,
    $plugin_id,
    $plugin_definition,
    $container->get('entity_type.manager')->getStorage('taxonomy_term'),
    $container->get('entity_type.bundle.info'),
    );
    }
    }
    langcode: en
    status: true
    dependencies:
    config:
    - core.entity_view_mode.node.teaser
    module:
    - node
    - taxonomy
    - user
    id: taxonomy_translated_term_name_test
    label: 'Taxonomy Translated Term Name Test'
    module: taxonomy
    description: 'Content belonging to a certain taxonomy term.'
    tag: default
    base_table: node_field_data
    base_field: nid
    display:
    default:
    id: default
    display_title: Default
    display_plugin: default
    position: 0
    display_options:
    query:
    type: views_query
    options:
    query_comment: ''
    disable_sql_rewrite: false
    distinct: false
    replica: false
    query_tags: { }
    access:
    type: perm
    options:
    perm: 'access content'
    cache:
    type: tag
    options: { }
    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: 0
    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: ››
    sorts:
    sticky:
    id: sticky
    table: taxonomy_index
    field: sticky
    order: DESC
    plugin_id: standard
    relationship: none
    group_type: group
    admin_label: ''
    exposed: false
    expose:
    label: ''
    created:
    id: created
    table: taxonomy_index
    field: created
    order: DESC
    plugin_id: date
    relationship: none
    group_type: group
    admin_label: ''
    exposed: false
    expose:
    label: ''
    granularity: second
    arguments:
    term_node_tid_depth:
    id: term_node_tid_depth
    table: node_field_data
    field: term_node_tid_depth
    relationship: none
    group_type: group
    admin_label: ''
    default_action: ignore
    exception:
    value: all
    title_enable: false
    title: All
    title_enable: true
    title: '{{ arguments.term_node_tid_depth }}'
    default_argument_type: fixed
    default_argument_options:
    argument: ''
    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: 'entity:taxonomy_term'
    fail: 'not found'
    validate_options:
    access: true
    operation: view
    multiple: 0
    bundles: { }
    depth: 2
    break_phrase: false
    use_taxonomy_term_path: false
    entity_type: node
    plugin_id: taxonomy_index_tid_depth
    filters:
    langcode:
    id: langcode
    table: node_field_data
    field: langcode
    relationship: none
    group_type: group
    admin_label: ''
    operator: in
    value:
    '***LANGUAGE_language_content***': '***LANGUAGE_language_content***'
    group: 1
    exposed: false
    expose:
    operator_id: ''
    label: ''
    description: ''
    use_operator: false
    operator: ''
    identifier: ''
    required: false
    remember: false
    multiple: false
    remember_roles:
    authenticated: authenticated
    reduce: false
    operator_limit_selection: false
    operator_list: { }
    is_grouped: false
    group_info:
    label: ''
    description: ''
    identifier: ''
    optional: true
    widget: select
    multiple: false
    remember: false
    default_group: All
    default_group_multiple: { }
    group_items: { }
    plugin_id: language
    entity_type: node
    entity_field: langcode
    status:
    id: status
    table: taxonomy_index
    field: status
    relationship: none
    group_type: group
    admin_label: ''
    operator: '='
    value: '1'
    group: 1
    exposed: false
    expose:
    operator_id: ''
    label: ''
    description: ''
    use_operator: false
    operator: ''
    identifier: ''
    required: false
    remember: false
    multiple: false
    remember_roles:
    authenticated: authenticated
    operator_limit_selection: false
    operator_list: { }
    is_grouped: false
    group_info:
    label: ''
    description: ''
    identifier: ''
    optional: true
    widget: select
    multiple: false
    remember: false
    default_group: All
    default_group_multiple: { }
    group_items: { }
    plugin_id: boolean
    style:
    type: default
    options:
    grouping: { }
    row_class: ''
    default_row_class: true
    uses_fields: false
    row:
    type: 'entity:node'
    options:
    view_mode: teaser
    header:
    entity_taxonomy_term:
    id: entity_taxonomy_term
    table: views
    field: entity_taxonomy_term
    relationship: none
    group_type: group
    admin_label: ''
    empty: true
    tokenize: true
    target: '{{ raw_arguments.tid }}'
    view_mode: full
    bypass_access: false
    plugin_id: entity
    footer: { }
    empty: { }
    relationships: { }
    fields: { }
    display_extenders: { }
    link_url: ''
    link_display: page_1
    cache_metadata:
    contexts:
    - 'languages:language_interface'
    - url
    - url.query_args
    - 'user.node_grants:view'
    - user.permissions
    max-age: -1
    tags: { }
    page_1:
    id: page_1
    display_title: Page
    display_plugin: page
    position: 1
    display_options:
    query:
    type: views_query
    options: { }
    display_extenders: { }
    path: taxonomy/test/%
    cache_metadata:
    max-age: -1
    contexts: { }
    tags: { }
    page_2:
    id: page_2
    display_title: Page
    display_plugin: page
    position: 1
    display_options:
    arguments:
    tid:
    id: tid
    table: taxonomy_term_field_data
    field: tid
    relationship: term_node_tid
    group_type: group
    admin_label: ''
    entity_type: taxonomy_term
    entity_field: tid
    plugin_id: taxonomy
    default_action: ignore
    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
    query:
    type: views_query
    options: { }
    defaults:
    relationships: false
    arguments: false
    relationships:
    term_node_tid:
    id: term_node_tid
    table: node_field_data
    field: term_node_tid
    relationship: none
    group_type: group
    admin_label: term
    entity_type: node
    plugin_id: node_term_data
    required: false
    vids: { }
    display_extenders: { }
    path: taxonomy/test2/%
    cache_metadata:
    max-age: -1
    contexts: { }
    tags: { }
    <?php
    declare(strict_types=1);
    namespace Drupal\Tests\taxonomy\Functional\Views;
    use Drupal\Core\Url;
    use Drupal\Tests\taxonomy\Functional\TaxonomyTranslationTestTrait;
    /**
    * Tests for views translation.
    *
    * @group taxonomy
    */
    class TermTranslationViewsTest extends TaxonomyTestBase {
    use TaxonomyTranslationTestTrait;
    /**
    * Term to translated term mapping.
    *
    * @var array
    */
    protected $termTranslationMap = [
    'one' => 'translatedOne',
    'two' => 'translatedTwo',
    'three' => 'translatedThree',
    ];
    /**
    * Created terms.
    *
    * @var \Drupal\taxonomy\Entity\Term[]
    */
    protected $terms = [];
    /**
    * {@inheritdoc}
    */
    protected static $modules = ['taxonomy', 'language', 'content_translation', 'views'];
    /**
    * Views used by this test.
    *
    * @var array
    */
    public static $testViews = ['taxonomy_translated_term_name_test'];
    /**
    * {@inheritdoc}
    */
    protected $defaultTheme = 'stark';
    /**
    * Language object.
    *
    * @var \Drupal\Core\Language\LanguageInterface|null
    */
    protected $translationLanguage;
    /**
    * {@inheritdoc}
    */
    protected function setUp($import_test_views = TRUE, $modules = []): void {
    parent::setUp($import_test_views, $modules);
    $this->setupLanguages();
    $this->enableTranslation();
    $this->setUpTerms();
    $this->translationLanguage = \Drupal::languageManager()->getLanguage($this->translateToLangcode);
    }
    /**
    * Ensure that proper translation is returned when contextual filter.
    *
    * Taxonomy term: Term ID & Content: Has taxonomy term ID (with depth)
    * contextual filters are enabled for two separate view modes.
    */
    public function testTermsTranslationWithContextualFilter() {
    $this->drupalLogin($this->rootUser);
    foreach ($this->terms as $term) {
    // Test with "Content: Has taxonomy term ID (with depth)" contextual filter.
    // Generate base language url and send request.
    $url = Url::fromRoute('view.taxonomy_translated_term_name_test.page_1', ['arg_0' => $term->id()])->toString();
    $this->drupalGet($url);
    $this->assertSession()->pageTextContains($term->label());
    // Generate translation URL and send request.
    $url = Url::fromRoute('view.taxonomy_translated_term_name_test.page_1', ['arg_0' => $term->id()], ['language' => $this->translationLanguage])->toString();
    $this->drupalGet($url);
    $this->assertSession()->pageTextContains($this->termTranslationMap[$term->label()]);
    // Test with "Taxonomy term: Term ID" contextual filter.
    // Generate base language url and send request.
    $url = Url::fromRoute('view.taxonomy_translated_term_name_test.page_2', ['arg_0' => $term->id()])->toString();
    $this->drupalGet($url);
    $this->assertSession()->pageTextContains($term->label());
    // Generate translation URL and send request.
    $url = Url::fromRoute('view.taxonomy_translated_term_name_test.page_2', ['arg_0' => $term->id()], ['language' => $this->translationLanguage])->toString();
    $this->drupalGet($url);
    $this->assertSession()->pageTextContains($this->termTranslationMap[$term->label()]);
    }
    }
    /**
    * Setup translated terms in a hierarchy.
    */
    protected function setUpTerms() {
    $parent_vid = 0;
    foreach ($this->termTranslationMap as $name => $translation) {
    $term = $this->createTerm([
    'name' => $name,
    'langcode' => $this->baseLangcode,
    'parent' => $parent_vid,
    'vid' => $this->vocabulary->id(),
    ]);
    $term->addTranslation($this->translateToLangcode, [
    'name' => $translation,
    ]);
    $term->save();
    // Each term is nested under the last.
    $parent_vid = $term->id();
    $this->terms[] = $term;
    }
    }
    }
    <?php
    declare(strict_types=1);
    namespace Drupal\Tests\taxonomy\Kernel\Views;
    use Drupal\KernelTests\KernelTestBase;
    use Drupal\taxonomy_test\Plugin\views\argument\TaxonomyViewsArgumentTest;
    use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
    /**
    * Tests deprecation messages in views argument plugins.
    *
    * @group taxonomy
    */
    class ViewsArgumentDeprecationTest extends KernelTestBase {
    use ExpectDeprecationTrait;
    /**
    * {@inheritdoc}
    */
    protected static $modules = [
    'system',
    'taxonomy',
    'taxonomy_test',
    'views',
    ];
    /**
    * Test the deprecation message in ViewsArgument plugin.
    *
    * @group legacy
    */
    public function testDeprecation(): void {
    $this->expectDeprecation('Calling Drupal\taxonomy\Plugin\views\argument\Taxonomy::__construct() with the $termStorage argument as \Drupal\Core\Entity\EntityStorageInterface is deprecated in drupal:10.3.0 and it will require Drupal\Core\Entity\EntityRepositoryInterface in drupal:11.0.0. See https://www.drupal.org/node/3427843');
    $plugin = \Drupal::service('plugin.manager.views.argument')->createInstance('taxonomy_views_argument_test', []);
    $this->assertInstanceOf(TaxonomyViewsArgumentTest::class, $plugin);
    }
    }
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Please register or to comment