From d522e19ef189b9565a06b98423b141bf289186f0 Mon Sep 17 00:00:00 2001
From: Riyas N R <riyas.nr@qed42.com>
Date: Thu, 27 Feb 2025 23:04:07 +0530
Subject: [PATCH 1/9] Issue #3509141: Missing Aria Label value in Views

---
 .../Plugin/views/field/FieldPluginBase.php    | 16 ++++++++++
 .../src/Functional/Handler/FieldWebTest.php   | 32 +++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
index b60cfbf199d1..b4ac416c85cb 100644
--- a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
+++ b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
@@ -509,6 +509,7 @@ protected function defineOptions() {
         'trim_whitespace' => ['default' => FALSE],
         'alt' => ['default' => ''],
         'rel' => ['default' => ''],
+        'aria_label' => ['default' => ''],
         'link_class' => ['default' => ''],
         'prefix' => ['default' => ''],
         'suffix' => ['default' => ''],
@@ -893,6 +894,17 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
           ],
         ],
       ];
+      $form['alter']['aria_label'] = [
+        '#title' => $this->t('Aria label Text'),
+        '#type' => 'textfield',
+        '#default_value' => $this->options['alter']['aria_label'],
+        '#description' => $this->t('Include Aria label attribute.'),
+        '#states' => [
+          'visible' => [
+            ':input[name="options[alter][make_link]"]' => ['checked' => TRUE],
+          ],
+        ],
+      ];
       $form['alter']['prefix'] = [
         '#title' => $this->t('Prefix text'),
         '#type' => 'textfield',
@@ -1579,6 +1591,10 @@ protected function renderAsLink($alter, $text, $tokens) {
       $options['attributes']['rel'] = $rel;
     }
 
+    if (!empty($alter['aria_label']) && $aria_label = $this->viewsTokenReplace($alter['aria_label'], $tokens)) {
+      $options['attributes']['aria-label'] = $aria_label;
+    }
+
     $target = trim($this->viewsTokenReplace($alter['target'], $tokens));
     if (!empty($target)) {
       $options['attributes']['target'] = $target;
diff --git a/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php b/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
index 72fd5a0cd297..2cefca2ad2ad 100644
--- a/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
+++ b/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
@@ -683,4 +683,36 @@ public function testTextRendering(): void {
     $this->assertNotSubString($output, '…', 'No ellipsis should appear if the output is not trimmed');
   }
 
+  /**
+   * Tests the aria-label attribute rendering.
+   */
+  public function testAriaLabelRendering(): void {
+    /** @var \Drupal\Core\Render\RendererInterface $renderer */
+    $renderer = \Drupal::service('renderer');
+    $view = Views::getView('test_field_output');
+    $view->initHandlers();
+
+    // Get the 'name' field handler and configure its alter options.
+    $name_field = $view->field['name'];
+    $name_field->options['alter'] = [
+      'make_link' => TRUE,
+      'path' => 'test-path',
+      'aria_label' => 'Test aria label',
+      'external' => FALSE,
+      'alt' => '',
+      'link_class' => '',
+      'target' => '',
+    ];
+
+    // Generate the view preview output and render it to a string.
+    $output = $view->preview();
+    $output = (string) $renderer->renderRoot($output);
+
+    // Verify the full HTML structure including the aria-label attribute.
+    $this->assertNotEmpty($this->xpathContent(
+      $output,
+      "//li/div[contains(@class, 'views-field') and contains(@class, 'views-field-name')]/span[contains(@class, 'field-content')]/a[@href='/test-path' and @aria-label='Test aria label']"
+    ));
+  }
+
 }
-- 
GitLab


From 9a7c06a855556d642ce8268a8825dc27f9d67b9a Mon Sep 17 00:00:00 2001
From: Riyas N R <riyas.nr@qed42.com>
Date: Thu, 27 Feb 2025 23:42:43 +0530
Subject: [PATCH 2/9] Issue #3509141: Modify view data type schema to add
 aria_label

---
 core/modules/views/config/schema/views.data_types.schema.yml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/core/modules/views/config/schema/views.data_types.schema.yml b/core/modules/views/config/schema/views.data_types.schema.yml
index 0e011d73dc15..61af073c3840 100644
--- a/core/modules/views/config/schema/views.data_types.schema.yml
+++ b/core/modules/views/config/schema/views.data_types.schema.yml
@@ -532,6 +532,9 @@ views_field:
         rel:
           type: string
           label: 'Rel Text'
+        aria_label:
+          type: string
+          label: 'Aria label Text'
         link_class:
           type: string
           label: 'Link class'
-- 
GitLab


From 50d038fcbc8dd361ebab8b56e8a5fed5b880eded Mon Sep 17 00:00:00 2001
From: Riyas N R <riyas.nr@qed42.com>
Date: Fri, 28 Feb 2025 00:38:45 +0530
Subject: [PATCH 3/9] Issue #3509141: Modify test logic

---
 .../src/Functional/Handler/FieldWebTest.php   | 49 ++++++++++---------
 1 file changed, 27 insertions(+), 22 deletions(-)

diff --git a/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php b/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
index 2cefca2ad2ad..423a1e9a84ea 100644
--- a/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
+++ b/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
@@ -687,32 +687,37 @@ public function testTextRendering(): void {
    * Tests the aria-label attribute rendering.
    */
   public function testAriaLabelRendering(): void {
-    /** @var \Drupal\Core\Render\RendererInterface $renderer */
-    $renderer = \Drupal::service('renderer');
-    $view = Views::getView('test_field_output');
-    $view->initHandlers();
+    $view = Views::getView('test_click_sort');
+    $view->setDisplay();
 
-    // Get the 'name' field handler and configure its alter options.
-    $name_field = $view->field['name'];
-    $name_field->options['alter'] = [
-      'make_link' => TRUE,
-      'path' => 'test-path',
-      'aria_label' => 'Test aria label',
-      'external' => FALSE,
-      'alt' => '',
-      'link_class' => '',
-      'target' => '',
-    ];
+    $view->displayHandlers->get('default')->overrideOption('fields', [
+      'name' => [
+        'id' => 'name',
+        'table' => 'views_test_data',
+        'field' => 'name',
+        'alter' => [
+          'make_link' => TRUE,
+          'path' => 'test-path',
+          'aria_label' => 'Test aria label',
+          'external' => FALSE,
+          'alt' => '',
+          'link_class' => '',
+          'target' => '',
+        ],
+      ],
+    ]);
 
-    // Generate the view preview output and render it to a string.
-    $output = $view->preview();
-    $output = (string) $renderer->renderRoot($output);
+    // Save the view configuration to ensure changes are applied.
+    $view->save();
+
+    // Visit the view's page.
+    $this->drupalGet('test_click_sort');
 
     // Verify the full HTML structure including the aria-label attribute.
-    $this->assertNotEmpty($this->xpathContent(
-      $output,
-      "//li/div[contains(@class, 'views-field') and contains(@class, 'views-field-name')]/span[contains(@class, 'field-content')]/a[@href='/test-path' and @aria-label='Test aria label']"
-    ));
+    $this->assertSession()->elementExists(
+      'xpath',
+      "//tr/td[contains(@class, 'views-field-name')]/a[@href='/test-path' and @aria-label='Test aria label']"
+    );
   }
 
 }
-- 
GitLab


From fb29811ac1488a8416bd4ea4b0232861153335e3 Mon Sep 17 00:00:00 2001
From: Riyas N R <riyas.nr@qed42.com>
Date: Fri, 28 Feb 2025 00:47:26 +0530
Subject: [PATCH 4/9] Issue #3509141: Add comment

---
 core/modules/views/tests/src/Functional/Handler/FieldWebTest.php | 1 +
 1 file changed, 1 insertion(+)

diff --git a/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php b/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
index 423a1e9a84ea..6ee123ac1bfe 100644
--- a/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
+++ b/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
@@ -690,6 +690,7 @@ public function testAriaLabelRendering(): void {
     $view = Views::getView('test_click_sort');
     $view->setDisplay();
 
+    // Set the field to be a link with an aria-label attribute.
     $view->displayHandlers->get('default')->overrideOption('fields', [
       'name' => [
         'id' => 'name',
-- 
GitLab


From ed4716139b1397ed4e25398598e9896919aa5b4f Mon Sep 17 00:00:00 2001
From: Riyas N R <riyas.nr@qed42.com>
Date: Fri, 28 Feb 2025 01:10:17 +0530
Subject: [PATCH 5/9] Issue #3509141: Modify test logic

---
 .../src/Functional/Handler/FieldWebTest.php   | 56 ++++++-------------
 1 file changed, 18 insertions(+), 38 deletions(-)

diff --git a/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php b/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
index 6ee123ac1bfe..39ecdf49d411 100644
--- a/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
+++ b/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
@@ -521,7 +521,7 @@ public function testFieldClasses(): void {
   }
 
   /**
-   * Tests trimming/read-more/ellipses.
+   * Tests trimming/read-more/ellipses and aria-label rendering.
    */
   public function testTextRendering(): void {
     /** @var \Drupal\Core\Render\RendererInterface $renderer */
@@ -681,44 +681,24 @@ public function testTextRendering(): void {
       return $name_field->advancedRender($row);
     });
     $this->assertNotSubString($output, '…', 'No ellipsis should appear if the output is not trimmed');
-  }
-
-  /**
-   * Tests the aria-label attribute rendering.
-   */
-  public function testAriaLabelRendering(): void {
-    $view = Views::getView('test_click_sort');
-    $view->setDisplay();
-
-    // Set the field to be a link with an aria-label attribute.
-    $view->displayHandlers->get('default')->overrideOption('fields', [
-      'name' => [
-        'id' => 'name',
-        'table' => 'views_test_data',
-        'field' => 'name',
-        'alter' => [
-          'make_link' => TRUE,
-          'path' => 'test-path',
-          'aria_label' => 'Test aria label',
-          'external' => FALSE,
-          'alt' => '',
-          'link_class' => '',
-          'target' => '',
-        ],
-      ],
-    ]);
 
-    // Save the view configuration to ensure changes are applied.
-    $view->save();
-
-    // Visit the view's page.
-    $this->drupalGet('test_click_sort');
-
-    // Verify the full HTML structure including the aria-label attribute.
-    $this->assertSession()->elementExists(
-      'xpath',
-      "//tr/td[contains(@class, 'views-field-name')]/a[@href='/test-path' and @aria-label='Test aria label']"
-    );
+    // Tests for the aria-label attribute rendering.
+    $name_field->options['alter'] = [
+      'make_link' => TRUE,
+      'path' => 'test-path',
+      'aria_label' => 'Test aria label',
+      'external' => FALSE,
+      'alt' => '',
+      'link_class' => '',
+      'target' => '',
+    ];
+    $output = (string) $renderer->executeInRenderContext(new RenderContext(), function () use ($name_field, $row) {
+      return $name_field->advancedRender($row);
+    });
+    $this->assertNotEmpty($this->xpathContent(
+      $output,
+      "//a[@href='/test-path' and @aria-label='Test aria label']"
+    ));
   }
 
 }
-- 
GitLab


From 202a066c2ff90cc8f1d99dd1cf9fa9d594494a0e Mon Sep 17 00:00:00 2001
From: Riyas N R <riyas.nr@qed42.com>
Date: Fri, 28 Feb 2025 01:33:53 +0530
Subject: [PATCH 6/9] Issue #3509141: Modify test logic

---
 .../views/tests/src/Functional/Handler/FieldWebTest.php      | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php b/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
index 39ecdf49d411..a7b165929786 100644
--- a/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
+++ b/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php
@@ -695,10 +695,7 @@ public function testTextRendering(): void {
     $output = (string) $renderer->executeInRenderContext(new RenderContext(), function () use ($name_field, $row) {
       return $name_field->advancedRender($row);
     });
-    $this->assertNotEmpty($this->xpathContent(
-      $output,
-      "//a[@href='/test-path' and @aria-label='Test aria label']"
-    ));
+    $this->assertSubString($output, 'aria-label="Test aria label"', 'Aria label attribute should be present.');
   }
 
 }
-- 
GitLab


From c74bee74c60a05261a18d52de477083ee2059b58 Mon Sep 17 00:00:00 2001
From: Riyas N R <riyas.nr@qed42.com>
Date: Tue, 4 Mar 2025 17:51:48 +0530
Subject: [PATCH 7/9] Issue #3509141: Add post update hook and test coverage
 for update hook

---
 core/modules/views/src/ViewsConfigUpdater.php | 34 ++++++++++++++
 .../Functional/Update/AriaLabelUpdateTest.php | 45 +++++++++++++++++++
 core/modules/views/views.post_update.php      | 12 +++++
 3 files changed, 91 insertions(+)
 create mode 100644 core/modules/views/tests/src/Functional/Update/AriaLabelUpdateTest.php

diff --git a/core/modules/views/src/ViewsConfigUpdater.php b/core/modules/views/src/ViewsConfigUpdater.php
index 83eb1072bb71..71fea7733e61 100644
--- a/core/modules/views/src/ViewsConfigUpdater.php
+++ b/core/modules/views/src/ViewsConfigUpdater.php
@@ -302,4 +302,38 @@ public function processRememberRolesUpdate(array &$handler, string $handler_type
     return FALSE;
   }
 
+  /**
+   * Checks if 'aria_label' setting of a field handler needs to be updated.
+   *
+   * @param \Drupal\views\ViewEntityInterface $view
+   *   The view entity.
+   *
+   * @return bool
+   *   TRUE if the view has any fields that need 'aria_label' updates.
+   */
+  public function needsAriaLabelUpdate(ViewEntityInterface $view): bool {
+    return $this->processDisplayHandlers($view, FALSE, function (&$handler, $handler_type) {
+      return $this->processAriaLabelUpdate($handler, $handler_type);
+    });
+  }
+
+  /**
+   * Processes fields and adds an empty 'aria_label' if not set.
+   *
+   * @param array $handler
+   *   A display handler.
+   * @param string $handler_type
+   *   The handler type.
+   *
+   * @return bool
+   *   Whether the handler was updated.
+   */
+  public function processAriaLabelUpdate(array &$handler, string $handler_type): bool {
+    if ($handler_type === 'field' && isset($handler['alter']) && !isset($handler['alter']['aria_label'])) {
+      $handler['alter']['aria_label'] = '';
+      return TRUE;
+    }
+    return FALSE;
+  }
+
 }
diff --git a/core/modules/views/tests/src/Functional/Update/AriaLabelUpdateTest.php b/core/modules/views/tests/src/Functional/Update/AriaLabelUpdateTest.php
new file mode 100644
index 000000000000..63fad0e7721d
--- /dev/null
+++ b/core/modules/views/tests/src/Functional/Update/AriaLabelUpdateTest.php
@@ -0,0 +1,45 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\views\Functional\Update;
+
+use Drupal\FunctionalTests\Update\UpdatePathTestBase;
+use Drupal\views\Entity\View;
+
+/**
+ * Tests the upgrade path for adding aria labels to views field handler.
+ *
+ * @group Update
+ *
+ * @see views_post_update_add_aria_label()
+ */
+class AriaLabelUpdateTest extends UpdatePathTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setDatabaseDumpFiles(): void {
+    $this->databaseDumpFiles = [
+      __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-10.3.0.filled.standard.php.gz',
+    ];
+  }
+
+  /**
+   * Tests that numeric argument plugins are updated properly.
+   */
+  public function testAriaLabelPostUpdate(): void {
+    $view = View::load('files');
+    $data = $view->toArray();
+    $this->assertArrayHasKey('alter', $data['display']['default']['display_options']['fields']['filename']);
+    $this->assertArrayNotHasKey('aria_label', $data['display']['default']['display_options']['fields']['filename']['alter']);
+
+    $this->runUpdates();
+
+    $view = View::load('files');
+    $data = $view->toArray();
+    $this->assertEquals('', $data['display']['default']['display_options']['fields']['filename']['alter']['aria_label']);
+
+  }
+
+}
diff --git a/core/modules/views/views.post_update.php b/core/modules/views/views.post_update.php
index e124ca9e8b43..2542467b5c8f 100644
--- a/core/modules/views/views.post_update.php
+++ b/core/modules/views/views.post_update.php
@@ -76,3 +76,15 @@ function views_post_update_update_remember_role_empty(?array &$sandbox = NULL):
     return $view_config_updater->needsRememberRolesUpdate($view);
   });
 }
+
+/**
+ * Add ARIA labels to views for better accessibility..
+ */
+function views_post_update_add_aria_label(?array &$sandbox = NULL): void {
+  /** @var \Drupal\views\ViewsConfigUpdater $view_config_updater */
+  $view_config_updater = \Drupal::classResolver(ViewsConfigUpdater::class);
+  $view_config_updater->setDeprecationsEnabled(FALSE);
+  \Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'view', function (ViewEntityInterface $view) use ($view_config_updater): bool {
+    return $view_config_updater->needsAriaLabelUpdate($view);
+  });
+}
-- 
GitLab


From 099fa5a343beae11af829f3cc9dfee262da60853 Mon Sep 17 00:00:00 2001
From: Riyas N R <riyas.nr@qed42.com>
Date: Tue, 4 Mar 2025 19:23:53 +0530
Subject: [PATCH 8/9] Issue #3509141: Add legacy group to test file

---
 .../views/tests/src/Functional/Update/AriaLabelUpdateTest.php    | 1 +
 1 file changed, 1 insertion(+)

diff --git a/core/modules/views/tests/src/Functional/Update/AriaLabelUpdateTest.php b/core/modules/views/tests/src/Functional/Update/AriaLabelUpdateTest.php
index 63fad0e7721d..2d86e66ccb5b 100644
--- a/core/modules/views/tests/src/Functional/Update/AriaLabelUpdateTest.php
+++ b/core/modules/views/tests/src/Functional/Update/AriaLabelUpdateTest.php
@@ -11,6 +11,7 @@
  * Tests the upgrade path for adding aria labels to views field handler.
  *
  * @group Update
+ * @group legacy
  *
  * @see views_post_update_add_aria_label()
  */
-- 
GitLab


From 73b361b365bc118f35feaea23d3d097c80390968 Mon Sep 17 00:00:00 2001
From: Riyas N R <riyas.nr@qed42.com>
Date: Tue, 4 Mar 2025 19:32:32 +0530
Subject: [PATCH 9/9] Issue #3509141: Add legacy group to test file

---
 .../tests/src/Functional/Update/EntityArgumentUpdateTest.php     | 1 +
 1 file changed, 1 insertion(+)

diff --git a/core/modules/views/tests/src/Functional/Update/EntityArgumentUpdateTest.php b/core/modules/views/tests/src/Functional/Update/EntityArgumentUpdateTest.php
index d7a96775c55d..7eede1afdc43 100644
--- a/core/modules/views/tests/src/Functional/Update/EntityArgumentUpdateTest.php
+++ b/core/modules/views/tests/src/Functional/Update/EntityArgumentUpdateTest.php
@@ -11,6 +11,7 @@
  * Tests the upgrade path for converting numeric arguments to entity_target_id.
  *
  * @group Update
+ * @group legacy
  *
  * @see views_post_update_views_data_argument_plugin_id()
  */
-- 
GitLab