SA-CORE-2023-001 by danflanagan8, larowlan, xjm, seanB, Berdir, benjifisher, longwave, jenlampton, lauriii

(cherry picked from commit 147e3d5bb3d74cbe32c6498f792265f8f71406eb)
merge-requests/3157/head
xjm 2023-01-18 06:48:01 -06:00
parent 749ee8a8a7
commit 1dc26aefc4
No known key found for this signature in database
GPG Key ID: 206B0B8743BDF4C2
2 changed files with 76 additions and 7 deletions

View File

@ -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));

View File

@ -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.");
}
}