From 5496d64a4a906b2e057a49d6c819c92f5cb73e15 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Fri, 23 Sep 2022 15:13:01 +0200
Subject: [PATCH] Issue #3291520 by sardara, Ratan Priya, alexpott, smustgrave:
 Incorrect label in taxonomy glossary for terms that start with zero

---
 .../views/argument/ArgumentPluginBase.php     |   4 +-
 .../views.view.test_taxonomy_glossary.yml     | 201 ++++++++++++------
 .../src/Functional/TaxonomyGlossaryTest.php   |  35 ++-
 3 files changed, 170 insertions(+), 70 deletions(-)

diff --git a/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php b/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php
index a3838e5fd718..d156ad72a7f3 100644
--- a/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php
+++ b/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php
@@ -994,8 +994,8 @@ public function summaryArgument($data) {
    *   The query results for the row.
    */
   public function summaryName($data) {
-    $value = $data->{$this->name_alias};
-    if (empty($value) && !empty($this->definition['empty field name'])) {
+    $value = (string) $data->{$this->name_alias};
+    if ($value === '' && isset($this->definition['empty field name'])) {
       $value = $this->definition['empty field name'];
     }
     return $value;
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_taxonomy_glossary.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_taxonomy_glossary.yml
index ffa1becad11a..64c7ec98330c 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_taxonomy_glossary.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_taxonomy_glossary.yml
@@ -12,84 +12,34 @@ base_table: taxonomy_term_field_data
 base_field: tid
 display:
   default:
-    display_plugin: default
     id: default
     display_title: Default
+    display_plugin: default
     position: 0
     display_options:
-      access:
-        type: none
-        options: {  }
-      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
-      row:
-        type: fields
+      title: test_taxonomy_glossary
       fields:
         name:
           id: name
           table: taxonomy_term_field_data
           field: name
+          relationship: none
+          group_type: group
+          admin_label: ''
           entity_type: taxonomy_term
           entity_field: name
+          plugin_id: term_name
           label: ''
+          exclude: false
           alter:
             alter_text: false
             make_link: false
             absolute: false
-            trim: false
             word_boundary: false
             ellipsis: false
             strip_tags: false
+            trim: 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: ''
@@ -99,8 +49,13 @@ display:
           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
@@ -112,13 +67,42 @@ display:
           separator: ', '
           field_api_classes: false
           convert_spaces: false
-      filters: {  }
-      sorts: {  }
-      title: test_taxonomy_glossary
-      header: {  }
-      footer: {  }
+      pager:
+        type: mini
+        options:
+          offset: 0
+          items_per_page: 10
+          total_pages: null
+          id: 0
+          tags:
+            next: ››
+            previous: ‹‹
+          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
+      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: none
+        options: {  }
+      cache:
+        type: tag
+        options: {  }
       empty: {  }
-      relationships: {  }
+      sorts: {  }
       arguments:
         name:
           id: name
@@ -127,6 +111,9 @@ display:
           relationship: none
           group_type: group
           admin_label: ''
+          entity_type: taxonomy_term
+          entity_field: name
+          plugin_id: string
           default_action: ignore
           exception:
             value: all
@@ -141,8 +128,8 @@ display:
           summary_options:
             base_path: ''
             count: true
-            items_per_page: 25
             override: false
+            items_per_page: 25
           summary:
             sort_order: asc
             number_of_records: 0
@@ -160,22 +147,102 @@ display:
           break_phrase: false
           add_table: false
           require_value: false
+      filters: {  }
+      style:
+        type: default
+      row:
+        type: fields
+      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
+        - url.query_args
+      tags: {  }
+  attachment_1:
+    id: attachment_1
+    display_title: Attachment
+    display_plugin: attachment
+    position: 2
+    display_options:
+      pager:
+        type: none
+        options:
+          offset: 0
+      arguments:
+        name:
+          id: name
+          table: taxonomy_term_field_data
+          field: name
+          relationship: none
+          group_type: group
+          admin_label: ''
           entity_type: taxonomy_term
           entity_field: name
           plugin_id: string
+          default_action: summary
+          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
+            override: false
+            items_per_page: 25
+          summary:
+            sort_order: asc
+            number_of_records: 0
+            format: default_summary
+          specify_validation: true
+          validate:
+            type: none
+            fail: 'not found'
+          validate_options: {  }
+          glossary: true
+          limit: 1
+          case: lower
+          path_case: lower
+          transform_dash: false
+          break_phrase: false
+          add_table: false
+          require_value: false
+      defaults:
+        arguments: false
       display_extenders: {  }
+      displays:
+        default: default
+        page_1: page_1
     cache_metadata:
       max-age: -1
       contexts:
         - 'languages:language_content'
         - 'languages:language_interface'
         - url
-        - url.query_args
       tags: {  }
   page_1:
-    display_plugin: page
     id: page_1
     display_title: Page
+    display_plugin: page
     position: 1
     display_options:
       display_extenders: {  }
diff --git a/core/modules/views/tests/src/Functional/TaxonomyGlossaryTest.php b/core/modules/views/tests/src/Functional/TaxonomyGlossaryTest.php
index f883bb0999a3..9113ba80de3f 100644
--- a/core/modules/views/tests/src/Functional/TaxonomyGlossaryTest.php
+++ b/core/modules/views/tests/src/Functional/TaxonomyGlossaryTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\views\Functional;
 
+use Drupal\Core\Url;
 use Drupal\Tests\taxonomy\Traits\TaxonomyTestTrait;
 
 /**
@@ -39,6 +40,9 @@ class TaxonomyGlossaryTest extends ViewTestBase {
    */
   protected $taxonomyTerms;
 
+  /**
+   * {@inheritdoc}
+   */
   protected function setUp($import_test_views = TRUE, $modules = ['views_test_config']): void {
     parent::setUp($import_test_views, $modules);
 
@@ -49,15 +53,44 @@ protected function setUp($import_test_views = TRUE, $modules = ['views_test_conf
     for ($i = 0; $i < 10; $i++) {
       $this->taxonomyTerms[] = $this->createTerm($vocabulary);
     }
+    $this->taxonomyTerms[] = $this->createTerm($vocabulary, ['name' => '0' . $this->randomMachineName()]);
   }
 
   /**
    * Tests a taxonomy glossary view.
    */
   public function testTaxonomyGlossaryView() {
+    $initials = [];
+    foreach ($this->taxonomyTerms as $term) {
+      $char = mb_strtolower(substr($term->label(), 0, 1));
+      $initials += [$char => 0];
+      $initials[$char]++;
+    }
+
+    $this->drupalGet('test_taxonomy_glossary');
+    $assert_session = $this->assertSession();
+
+    foreach ($initials as $char => $count) {
+      $href = Url::fromUserInput('/test_taxonomy_glossary/' . $char)->toString();
+
+      $xpath = $assert_session->buildXPathQuery('//a[@href=:href and normalize-space(text())=:label]', [
+        ':href' => $href,
+        ':label' => $char,
+      ]);
+      $link = $assert_session->elementExists('xpath', $xpath);
+
+      // Assert that the expected number of results is indicated in the link.
+      preg_match("/{$char} \(([0-9]+)\)/", $link->getParent()->getText(), $matches);
+      $this->assertEquals($count, $matches[1]);
+    }
+
+    // Check that no other glossary links but the expected ones have been
+    // rendered.
+    $assert_session->elementsCount('xpath', '/ancestor::ul//a', count($initials), $link);
+
     // Go the taxonomy glossary page for the first term.
     $this->drupalGet('test_taxonomy_glossary/' . substr($this->taxonomyTerms[0]->getName(), 0, 1));
-    $this->assertSession()->pageTextContains($this->taxonomyTerms[0]->getName());
+    $assert_session->pageTextContains($this->taxonomyTerms[0]->getName());
   }
 
 }
-- 
GitLab