diff --git a/core/modules/media/js/plugins/drupalmedia/plugin.es6.js b/core/modules/media/js/plugins/drupalmedia/plugin.es6.js index a0f398a022..15b3f5f4d2 100644 --- a/core/modules/media/js/plugins/drupalmedia/plugin.es6.js +++ b/core/modules/media/js/plugins/drupalmedia/plugin.es6.js @@ -152,7 +152,10 @@ } }); } - const hostEntityLangcode = document.getElementById(editor.name).getAttribute('data-media-embed-host-entity-langcode'); + // @see media_field_widget_form_alter(). + const hostEntityLangcode = document + .getElementById(editor.name) + .getAttribute('data-media-embed-host-entity-langcode'); if (hostEntityLangcode) { data.langcode = hostEntityLangcode; } diff --git a/core/modules/media/js/plugins/drupalmedia/plugin.js b/core/modules/media/js/plugins/drupalmedia/plugin.js index e625736448..73092be269 100644 --- a/core/modules/media/js/plugins/drupalmedia/plugin.js +++ b/core/modules/media/js/plugins/drupalmedia/plugin.js @@ -120,6 +120,7 @@ } }); } + var hostEntityLangcode = document.getElementById(editor.name).getAttribute('data-media-embed-host-entity-langcode'); if (hostEntityLangcode) { data.langcode = hostEntityLangcode; @@ -289,4 +290,4 @@ linkCommandIntegrator(editor); } }); -})(jQuery, Drupal, CKEDITOR); +})(jQuery, Drupal, CKEDITOR); \ No newline at end of file diff --git a/core/modules/media/media.module b/core/modules/media/media.module index 138b246e39..d9e51a24db 100644 --- a/core/modules/media/media.module +++ b/core/modules/media/media.module @@ -18,7 +18,6 @@ use Drupal\field\FieldConfigInterface; use Drupal\media\Plugin\media\Source\OEmbedInterface; use Drupal\Core\Field\FieldItemListInterface; -use Drupal\Core\Entity\ContentEntityInterface; /** * Implements hook_help(). @@ -510,12 +509,8 @@ function media_field_widget_form_alter(&$element, FormStateInterface $form_state if (!empty($context['items']) && $context['items'] instanceof FieldItemListInterface) { $element['#attributes']['data-media-embed-host-entity-langcode'] = $context['items']->getLangcode(); } - else { - $entity = $form_state->getFormObject()->getEntity(); - if ($entity instanceof ContentEntityInterface) { - $element['#attributes']['data-media-embed-host-entity-langcode'] = $entity->language()->getId(); - } + elseif ($entity = $form_state->getFormObject()->getEntity()) { + $element['#attributes']['data-media-embed-host-entity-langcode'] = $entity->language()->getId(); } } } - diff --git a/core/modules/media/src/Form/EditorMediaDialog.php b/core/modules/media/src/Form/EditorMediaDialog.php index 266f2c401e..2f73f9d2e0 100644 --- a/core/modules/media/src/Form/EditorMediaDialog.php +++ b/core/modules/media/src/Form/EditorMediaDialog.php @@ -103,10 +103,8 @@ public function buildForm(array $form, FormStateInterface $form_state, EditorInt $media = $this->entityRepository->loadEntityByUuid('media', $media_embed_element['data-entity-uuid']); - if (!empty($editor_object['langcode'])) { - if ($media->hasTranslation($editor_object['langcode'])) { - $media = $media->getTranslation($editor_object['langcode']); - } + if (!empty($editor_object['langcode']) && $media->hasTranslation($editor_object['langcode'])) { + $media = $media->getTranslation($editor_object['langcode']); } if ($image_field = $this->getMediaImageSourceField($media)) { $settings = $media->{$image_field}->getItemDefinition()->getSettings(); @@ -151,18 +149,14 @@ public function buildForm(array $form, FormStateInterface $form_state, EditorInt '#access' => $filter_caption->status && ($filter_html->status === FALSE || !empty($allowed_attributes['data-caption'])), ]; - if ($form['alt']['#access'] === FALSE && $form['align']['#access'] === FALSE && $form['caption']['#access'] === FALSE) { + if ((empty($form['alt']) || $form['alt']['#access'] === FALSE) && $form['align']['#access'] === FALSE && $form['caption']['#access'] === FALSE) { $format = $editor->getFilterFormat(); $form['no_access_notice'] = [ '#markup' => $this->t('There is nothing to override for this media.'), ]; if ($this->currentUser()->hasPermission('administer filters')) { - $text_format_edit_link = $format - ->toLink($format->label(), 'edit-form') - ->toString(); - $form['no_access_notice'] = [ - '#markup' => $this->t('There is nothing to override for this media. Edit the text format %format to modify the attributes that can be overridden.', ['%format' => $text_format_edit_link]), - ]; + $edit_url = $format->toUrl('edit-form')->toString(); + $form['no_access_notice']['#markup'] = $this->t('There is nothing to override for this media. Edit the text format %format to modify the attributes that can be overridden.', ['@edit_url' => $edit_url, '%format' => $format->label()]); } } @@ -195,10 +189,10 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $form_state->setValue(['attributes', 'alt'], '""'); } - // The `alt` and `title` attributes are optional: if they're not set, their - // default values simply will not be overridden. It's important to set - // these to FALSE instead of unsetting the value so that We explicitly - // inform the client side about the new value. + // The `alt` attribute is optional: if it isn't set, the default value + // simply will not be overridden. It's important to set it to FALSE + // instead of unsetting the value. This way we explicitly inform + // the client side about the new value. if ($form_state->hasValue(['attributes', 'alt']) && trim($form_state->getValue(['attributes', 'alt'])) === '') { $form_state->setValue(['attributes', 'alt'], FALSE); } diff --git a/core/modules/media/src/Plugin/Filter/MediaEmbed.php b/core/modules/media/src/Plugin/Filter/MediaEmbed.php index f035425bdb..f07ba49dcd 100644 --- a/core/modules/media/src/Plugin/Filter/MediaEmbed.php +++ b/core/modules/media/src/Plugin/Filter/MediaEmbed.php @@ -26,7 +26,7 @@ * @Filter( * id = "media_embed", * title = @Translation("Embed media"), - * description = @Translation("Embeds media items using a custom tag, <drupal-media>. If used in conjunction with the 'Align/Caption' filters, make sure this filter is configured to run after them. If you are using the HTML filter, be sure the data-align and/or data-caption attributes are allowed on the <drupal-media> tag. If you would like users to be able to override the alt text on image media, add the alt attribute as well to the <drupal-media> tag."), + * description = @Translation("Embeds media items using a custom tag, <drupal-media>. If used in conjunction with the 'Align/Caption' filters, make sure this filter is configured to run after them. If you are using the HTML filter, be sure the data-align and/or data-caption attributes are allowed on the <drupal-media> tag. If you would like users to be able to override the alt text on image media, add the alt attribute to the <drupal-media> tag as well."), * type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_REVERSIBLE, * settings = { * "default_view_mode" = "full", diff --git a/core/modules/media/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php b/core/modules/media/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php index a4371b8585..07130ab496 100644 --- a/core/modules/media/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php +++ b/core/modules/media/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php @@ -505,8 +505,8 @@ public function testDialogAccess() { $page->pressButton('Close'); $this->getSession()->switchToIFrame('ckeditor'); - // Test that setting disabling `filter_caption` and `filter_align` disables - // the respective fields in the dialog. + // Test that disabling `filter_caption` and `filter_align` disables the + // respective fields in the dialog. $filter_format ->setFilterConfig('filter_caption', [ 'status' => FALSE, @@ -537,6 +537,7 @@ public function testDialogAccess() { $this->waitForMetadataDialog(); $assert_session->fieldExists('attributes[data-align]'); $assert_session->fieldExists('hasCaption'); + $assert_session->pageTextNotContains('There is nothing to override for this media. Edit the text format Test format to modify the attributes that can be overridden.'); // The alt field should be unaffected. $assert_session->fieldExists('attributes[alt]'); } @@ -556,10 +557,10 @@ public function testAlt() { $this->assertNotEmpty($assert_session->waitForElementVisible('xpath', '//img[contains(@alt, "default alt")]')); $page->pressButton('Edit media'); $this->waitForMetadataDialog(); - $alt = $page->findField('attributes[alt]'); + // Assert that the placeholder is set to the value of the media field's // alt text. - $this->assertSame('default alt', $alt->getAttribute('placeholder')); + $assert_session->elementAttributeContains('named', ['field', 'attributes[alt]'], 'placeholder', 'default alt'); // Fill in the alt field in the dialog. $who_is_zartan = 'Zartan is the leader of the Dreadnoks.'; @@ -569,7 +570,7 @@ public function testAlt() { // Assert that the img within the media embed within the ckeditor contains // the overridden alt text set in the dialog. - $this->assertNotEmpty($img = $assert_session->waitForElementVisible('xpath', '//img[contains(@alt, "' . $who_is_zartan . '")]')); + $this->assertNotEmpty($assert_session->waitForElementVisible('xpath', '//img[contains(@alt, "' . $who_is_zartan . '")]')); // Reopen the dialog. $page->pressButton('Edit media'); @@ -582,23 +583,26 @@ public function testAlt() { // the second time around. $cobra_commander_bio = 'The supreme leader of the terrorist organization Cobra'; // Set the alt field to the new alt text. - $alt->setValue($cobra_commander_bio); + $page->fillField('attributes[alt]', $cobra_commander_bio); $this->submitDialog(); $this->getSession()->switchToIFrame('ckeditor'); - // Assert that the img within the media embed within the ckeditor contains - // the overridden alt text set in the dialog. - $this->assertNotEmpty($img = $assert_session->waitForElementVisible('xpath', '//img[contains(@alt, "' . $cobra_commander_bio . '")]')); + // Assert that the img within the media embed preview + // within the ckeditor contains the overridden alt text set in the dialog. + $this->assertNotEmpty($assert_session->waitForElementVisible('xpath', '//img[contains(@alt, "' . $cobra_commander_bio . '")]')); // Reopen the dialog. $page->pressButton('Edit media'); $this->waitForMetadataDialog(); - // The alt field should now display the override instead of the default. + // The default value of the alt field should now display the override + // instead of the value on the media image field. $alt = $page->findField('attributes[alt]'); $this->assertSame($cobra_commander_bio, $alt->getValue()); // Test that setting alt value to two double quotes will signal to the // MediaEmbed filter to unset the attribute on the media image field. - $alt->setValue('""'); + // Note: intentionally adding a space after the two double quotes to test + // the string is trimmed to two quotes. + $alt->setValue('"" '); $this->submitDialog(); $this->getSession()->switchToIFrame('ckeditor'); $img = $assert_session->waitForElementVisible('xpath', '//img'); @@ -626,7 +630,7 @@ public function testAlt() { */ public function testTranslationAlt() { \Drupal::service('module_installer')->install(['language', 'content_translation']); - $this->rebuildContainer(); + $this->resetAll(); ConfigurableLanguage::create(['id' => 'fr'])->save(); ContentLanguageSettings::loadByEntityTypeBundle('media', 'image') ->setDefaultLangcode('en') @@ -674,7 +678,6 @@ public function testTranslationAlt() { $translation->title = 'Animaux avec des noms étranges'; $translation->body->value = $host->body->value; $translation->body->format = $host->body->format; - $translation->body->lang = 'fr'; $translation->save(); $this->grantPermissions(Role::load(RoleInterface::AUTHENTICATED_ID), ['translate any entity']); @@ -690,10 +693,10 @@ public function testTranslationAlt() { $this->assertNotEmpty($assert_session->waitForElementVisible('xpath', '//img[contains(@alt, "texte alternatif par défaut")]')); $page->pressButton('Edit media'); $this->waitForMetadataDialog(); - $alt = $page->findField('attributes[alt]'); + $alt = $assert_session->fieldExists('attributes[alt]')->getValue(); // Assert that the placeholder is set to the value of the media field's // alt text. - $this->assertSame('texte alternatif par défaut', $alt->getAttribute('placeholder')); + $assert_session->elementAttributeContains('named', ['field', 'attributes[alt]'], 'placeholder', 'texte alternatif par défaut'); // Fill in the alt field in the dialog. $qui_est_zartan = 'Zartan est le chef des Dreadnoks.'; @@ -703,7 +706,7 @@ public function testTranslationAlt() { // Assert that the img within the media embed within the ckeditor contains // the overridden alt text set in the dialog. - $this->assertNotEmpty($img = $assert_session->waitForElementVisible('xpath', '//img[contains(@alt, "' . $qui_est_zartan . '")]')); + $this->assertNotEmpty($assert_session->waitForElementVisible('xpath', '//img[contains(@alt, "' . $qui_est_zartan . '")]')); $this->getSession()->switchToIFrame(); $page->pressButton('Save'); $assert_session->elementExists('xpath', '//img[contains(@alt, "' . $qui_est_zartan . '")]'); @@ -982,15 +985,14 @@ public function testAlignment() { foreach ($alignments as $alignment) { $this->fillFieldInMetadataDialog('attributes[data-align]', $alignment); // Now verify the result. - $this->assertNotEmpty($assert_session->waitForElementVisible('css', 'drupal-media[data-align="' . $alignment . '"]', 2000)); - $this->assertNotEmpty($assert_session->waitForElementVisible('css', '.caption-drupal-media.align-' . $alignment, 2000)); - + $selector = sprintf('drupal-media[data-align="%s"] .caption-drupal-media.align-%s', $alignment, $alignment); + $this->assertNotEmpty($assert_session->waitForElementVisible('css', $selector, 2000)); // Assert that the resultant downcast drupal-media tag has the proper // `data-align` attribute. - $drupal_media = $this->getDrupalMediaFromSource(); + $this->assertNotEmpty($drupal_media = $this->getDrupalMediaFromSource()); $this->assertSame($alignment, $drupal_media->getAttribute('data-align')); - // Leave source mode. + // Press the source button again to leave source mode. $this->pressEditorButton('source'); // Having entered source mode means we need to reassign an id to the // CKEditor iframe. @@ -1007,7 +1009,7 @@ public function testAlignment() { $assert_session->elementExists('css', '.cke_widget_drupalmedia:not([class*="align-"])'); // Assert that the resultant downcast drupal-media tag has no data-align // attribute. - $drupal_media = $this->getDrupalMediaFromSource(); + $this->assertNotEmpty($drupal_media = $this->getDrupalMediaFromSource()); $this->assertFalse($drupal_media->hasAttribute('data-align')); } @@ -1195,8 +1197,8 @@ protected function clickPathLinkByTitleAttribute($text) { /** * Get the drupal-media element from the ckeditor source. * - * @return \DOMNode - * The drupal-media element. + * @return \DOMNode|null + * The drupal-media element or NULL if it can't be found. */ protected function getDrupalMediaFromSource() { $this->pressEditorButton('source'); @@ -1205,7 +1207,13 @@ protected function getDrupalMediaFromSource() { ->getValue(); $dom = Html::load($value); $xpath = new \DOMXPath($dom); - return $xpath->query('//drupal-media')[0]; + $list = $xpath->query('//drupal-media'); + if (!empty($list[0])) { + $drupal_media = $list[0]; + $this->assertInstanceOf(\DOMNode::class, $drupal_media); + return $drupal_media; + } + return NULL; } }