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