Issue #2852898 by smustgrave, _utsavsharma, mherchel, larowlan, bnjmnm, borisson_, kershme, DuaelFr: 508 Compliance Issue -Edit links on content page are not unique

merge-requests/5828/head
Lee Rowlands 2023-12-22 12:52:18 +10:00
parent 7393eba281
commit 6ee5f78c66
No known key found for this signature in database
GPG Key ID: 2B829A3DF9204DC4
4 changed files with 79 additions and 9 deletions

View File

@ -142,13 +142,35 @@ class EntityListBuilder extends EntityHandlerBase implements EntityListBuilderIn
protected function getDefaultOperations(EntityInterface $entity) {
$operations = [];
if ($entity->access('update') && $entity->hasLinkTemplate('edit-form')) {
$edit_url = $this->ensureDestination($entity->toUrl('edit-form'));
if (!empty($entity->label())) {
$label = $this->t('Edit @entity_label', ['@entity_label' => $entity->label()]);
}
else {
$label = $this->t('Edit @entity_bundle @entity_id', ['@entity_bundle' => $entity->bundle(), '@entity_id' => $entity->id()]);
}
$attributes = $edit_url->getOption('attributes') ?: [];
$attributes += ['aria-label' => $label];
$edit_url->setOption('attributes', $attributes);
$operations['edit'] = [
'title' => $this->t('Edit'),
'weight' => 10,
'url' => $this->ensureDestination($entity->toUrl('edit-form')),
'url' => $edit_url,
];
}
if ($entity->access('delete') && $entity->hasLinkTemplate('delete-form')) {
$delete_url = $this->ensureDestination($entity->toUrl('delete-form'));
if (!empty($entity->label())) {
$label = $this->t('Delete @entity_label', ['@entity_label' => $entity->label()]);
}
else {
$label = $this->t('Delete @entity_bundle @entity_id', ['@entity_bundle' => $entity->bundle(), '@entity_id' => $entity->id()]);
}
$attributes = $delete_url->getOption('attributes') ?: [];
$attributes += ['aria-label' => $label];
$delete_url->setOption('attributes', $attributes);
$operations['delete'] = [
'title' => $this->t('Delete'),
'weight' => 100,
@ -159,7 +181,7 @@ class EntityListBuilder extends EntityHandlerBase implements EntityListBuilderIn
'width' => 880,
]),
],
'url' => $this->ensureDestination($entity->toUrl('delete-form')),
'url' => $delete_url,
];
}

View File

@ -58,11 +58,17 @@ class ConfigEntityListTest extends BrowserTestBase {
$this->assertInstanceOf(ConfigTest::class, $entity);
// Test getOperations() method.
$edit_url = $entity->toUrl()->setOption('query', $this->getRedirectDestination()->getAsArray());
$edit_url->setOption('attributes', ['aria-label' => 'Edit ' . $entity->label()]);
$delete_url = $entity->toUrl('delete-form')->setOption('query', $this->getRedirectDestination()->getAsArray());
$delete_url->setOption('attributes', ['aria-label' => 'Delete ' . $entity->label()]);
$expected_operations = [
'edit' => [
'title' => 'Edit',
'weight' => 10,
'url' => $entity->toUrl()->setOption('query', $this->getRedirectDestination()->getAsArray()),
'url' => $edit_url,
],
'disable' => [
'title' => 'Disable',
@ -79,7 +85,7 @@ class ConfigEntityListTest extends BrowserTestBase {
'width' => 880,
]),
],
'url' => $entity->toUrl('delete-form')->setOption('query', $this->getRedirectDestination()->getAsArray()),
'url' => $delete_url,
],
];
@ -140,11 +146,16 @@ class ConfigEntityListTest extends BrowserTestBase {
$entity = $list['default'];
// Test getOperations() method.
$edit_url = $entity->toUrl()->setOption('query', $this->getRedirectDestination()->getAsArray());
$edit_url->setOption('attributes', ['aria-label' => 'Edit ' . $entity->label()]);
$delete_url = $entity->toUrl('delete-form')->setOption('query', $this->getRedirectDestination()->getAsArray());
$delete_url->setOption('attributes', ['aria-label' => 'Delete ' . $entity->label()]);
$expected_operations = [
'edit' => [
'title' => 'Edit',
'weight' => 10,
'url' => $entity->toUrl()->setOption('query', $this->getRedirectDestination()->getAsArray()),
'url' => $edit_url,
],
'delete' => [
'title' => 'Delete',
@ -156,7 +167,41 @@ class ConfigEntityListTest extends BrowserTestBase {
'width' => 880,
]),
],
'url' => $entity->toUrl('delete-form')->setOption('query', $this->getRedirectDestination()->getAsArray()),
'url' => $delete_url,
],
];
$actual_operations = $controller->getOperations($entity);
// Sort the operations to normalize link order.
uasort($actual_operations, ['Drupal\Component\Utility\SortArray', 'sortByWeightElement']);
$this->assertEquals($expected_operations, $actual_operations, 'The operations are identical.');
// Test getOperations when label doesn't exist.
$entity->set('label', '');
$entity->save();
$edit_url = $entity->toUrl()->setOption('query', $this->getRedirectDestination()->getAsArray());
$edit_url->setOption('attributes', ['aria-label' => 'Edit ' . $entity->bundle() . ' ' . $entity->id()]);
$delete_url = $entity->toUrl('delete-form')->setOption('query', $this->getRedirectDestination()->getAsArray());
$delete_url->setOption('attributes', ['aria-label' => 'Delete ' . $entity->bundle() . ' ' . $entity->id()]);
$expected_operations = [
'edit' => [
'title' => 'Edit',
'weight' => 10,
'url' => $edit_url,
],
'delete' => [
'title' => 'Delete',
'weight' => 100,
'attributes' => [
'class' => ['use-ajax'],
'data-dialog-type' => 'modal',
'data-dialog-options' => Json::encode([
'width' => 880,
]),
],
'url' => $delete_url,
],
];

View File

@ -75,7 +75,10 @@ class UserAdminTest extends BrowserTestBase {
$this->assertSession()->pageTextContains($admin_user->getAccountName());
// Test for existence of edit link in table.
$link = $user_a->toLink('Edit', 'edit-form', ['query' => ['destination' => $user_a->toUrl('collection')->toString()]])->toString();
$link = $user_a->toLink('Edit', 'edit-form', [
'query' => ['destination' => $user_a->toUrl('collection')->toString()],
'attributes' => ['aria-label' => 'Edit ' . $user_a->label()],
])->toString();
$this->assertSession()->responseContains($link);
// Test exposed filter elements.

View File

@ -184,8 +184,8 @@ class RowRenderCacheTest extends ViewsKernelTestBase {
$output = $view->style_plugin->getField($index, 'delete_node');
$this->assertSame($expected, (string) $output);
$expected = $access ? ' <div class="dropbutton-wrapper" data-drupal-ajax-container><div class="dropbutton-widget"><ul class="dropbutton">' .
'<li><a href="' . $node_url . '/edit?destination=/" hreflang="en">Edit</a></li>' .
'<li><a href="' . $node_url . '/delete?destination=/" class="use-ajax" data-dialog-type="modal" data-dialog-options="' . Html::escape(Json::encode(['width' => 880])) . '" hreflang="en">Delete</a></li>' .
'<li><a href="' . $node_url . '/edit?destination=/" aria-label="Edit ' . $node->label() . '" hreflang="en">Edit</a></li>' .
'<li><a href="' . $node_url . '/delete?destination=/" aria-label="Delete ' . $node->label() . '" class="use-ajax" data-dialog-type="modal" data-dialog-options="' . Html::escape(Json::encode(['width' => 880])) . '" hreflang="en">Delete</a></li>' .
'</ul></div></div>' : '';
$output = $view->style_plugin->getField($index, 'operations');
$this->assertSame($expected, (string) $output);