diff --git a/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php b/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php index 1766346a7d4..4bd939f753b 100644 --- a/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php +++ b/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php @@ -2,6 +2,7 @@ namespace Drupal\media_library\Plugin\Field\FieldWidget; +use Drupal\Component\Render\FormattableMarkup; use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\SortArray; use Drupal\Core\Ajax\AjaxResponse; @@ -391,6 +392,20 @@ class MediaLibraryWidget extends WidgetBase implements TrustedCallbackInterface ]; foreach ($referenced_entities as $delta => $media_item) { + if ($media_item->access('view')) { + // @todo Make the view mode configurable in https://www.drupal.org/project/drupal/issues/2971209 + $preview = $view_builder->view($media_item, 'media_library'); + } + else { + $item_label = $media_item->access('view label') ? $media_item->label() : new FormattableMarkup('@label @id', [ + '@label' => $media_item->getEntityType()->getSingularLabel(), + '@id' => $media_item->id(), + ]); + $preview = [ + '#theme' => 'media_embed_error', + '#message' => $this->t('You do not have permission to view @item_label.', ['@item_label' => $item_label]), + ]; + } $element['selection'][$delta] = [ '#theme' => 'media_library_item__widget', '#attributes' => [ @@ -414,22 +429,21 @@ class MediaLibraryWidget extends WidgetBase implements TrustedCallbackInterface '#value' => $this->t('Remove'), '#media_id' => $media_item->id(), '#attributes' => [ - 'aria-label' => $this->t('Remove @label', ['@label' => $media_item->label()]), + 'aria-label' => $media_item->access('view label') ? $this->t('Remove @label', ['@label' => $media_item->label()]) : $this->t('Remove media'), ], '#ajax' => [ 'callback' => [static::class, 'updateWidget'], 'wrapper' => $wrapper_id, 'progress' => [ 'type' => 'throbber', - 'message' => $this->t('Removing @label.', ['@label' => $media_item->label()]), + 'message' => $media_item->access('view label') ? $this->t('Removing @label.', ['@label' => $media_item->label()]) : $this->t('Removing media.'), ], ], '#submit' => [[static::class, 'removeItem']], // Prevent errors in other widgets from preventing removal. '#limit_validation_errors' => $limit_validation_errors, ], - // @todo Make the view mode configurable in https://www.drupal.org/project/drupal/issues/2971209 - 'rendered_entity' => $view_builder->view($media_item, 'media_library'), + 'rendered_entity' => $preview, 'target_id' => [ '#type' => 'hidden', '#value' => $media_item->id(), @@ -698,9 +712,8 @@ class MediaLibraryWidget extends WidgetBase implements TrustedCallbackInterface // Announce the updated content to screen readers. if ($is_remove_button) { - $announcement = new TranslatableMarkup('@label has been removed.', [ - '@label' => Media::load($field_state['removed_item_id'])->label(), - ]); + $media_item = Media::load($field_state['removed_item_id']); + $announcement = $media_item->access('view label') ? new TranslatableMarkup('@label has been removed.', ['@label' => $media_item->label()]) : new TranslatableMarkup('Media has been removed.'); } else { $new_items = count(static::getNewMediaItems($element, $form_state)); diff --git a/core/modules/media_library/tests/src/FunctionalJavascript/EntityReferenceWidgetTest.php b/core/modules/media_library/tests/src/FunctionalJavascript/EntityReferenceWidgetTest.php index 94a0d511fde..141269e043f 100644 --- a/core/modules/media_library/tests/src/FunctionalJavascript/EntityReferenceWidgetTest.php +++ b/core/modules/media_library/tests/src/FunctionalJavascript/EntityReferenceWidgetTest.php @@ -4,6 +4,8 @@ namespace Drupal\Tests\media_library\FunctionalJavascript; use Drupal\field\Entity\FieldConfig; use Drupal\FunctionalJavascriptTests\SortableTestTrait; +use Drupal\user\Entity\Role; +use Drupal\user\RoleInterface; /** * Tests the Media library entity reference widget. @@ -579,4 +581,58 @@ JS; $this->getSession()->executeScript($script); } + /** + * Tests the preview displayed by the field widget. + */ + public function testWidgetPreview() { + $assert_session = $this->assertSession(); + $page = $this->getSession()->getPage(); + + $node = $this->drupalCreateNode([ + 'type' => 'basic_page', + 'field_unlimited_media' => [ + $this->mediaItems['Horse'], + ], + ]); + $media_id = $this->mediaItems['Horse']->id(); + + // Assert that preview is present for current user, who can view media. + $this->drupalGet($node->toUrl('edit-form')); + $assert_session->elementTextContains('css', '[data-drupal-selector="edit-field-unlimited-media-selection-0"]', 'Horse'); + $remove_button = $page->find('css', '[data-drupal-selector="edit-field-unlimited-media-selection-0-remove-button"]'); + $this->assertSame('Remove Horse', $remove_button->getAttribute('aria-label')); + $assert_session->pageTextNotContains('You do not have permission to view media item'); + $remove_button->press(); + $this->waitForText("Removing Horse."); + $this->waitForText("Horse has been removed."); + // Logout without saving. + $this->drupalLogout(); + + // Create a user who can edit content but not view media. + // Must remove permission from authenticated role first, otherwise the new + // user will inherit that permission. + $role = Role::load(RoleInterface::AUTHENTICATED_ID); + $role->revokePermission('view media'); + $role->save(); + $non_media_editor = $this->drupalCreateUser([ + 'access content', + 'create basic_page content', + 'edit any basic_page content', + ]); + $this->drupalLogin($non_media_editor); + + // Assert that preview does not reveal media name. + $this->drupalGet($node->toUrl('edit-form')); + // There should be no preview name. + $assert_session->elementTextNotContains('css', '[data-drupal-selector="edit-field-unlimited-media-selection-0"]', 'Horse'); + // The remove button should have a generic message. + $remove_button = $page->find('css', '[data-drupal-selector="edit-field-unlimited-media-selection-0-remove-button"]'); + $this->assertSame('Remove media', $remove_button->getAttribute('aria-label')); + $assert_session->pageTextContains("You do not have permission to view media item $media_id."); + // Confirm ajax text does not reveal media name. + $remove_button->press(); + $this->waitForText("Removing media."); + $this->waitForText("Media has been removed."); + } + }