diff --git a/src/EntityEmbedDisplay/EntityEmbedDisplayBase.php b/src/EntityEmbedDisplay/EntityEmbedDisplayBase.php
index a696fbc..3c4460b 100644
--- a/src/EntityEmbedDisplay/EntityEmbedDisplayBase.php
+++ b/src/EntityEmbedDisplay/EntityEmbedDisplayBase.php
@@ -237,7 +237,7 @@ abstract class EntityEmbedDisplayBase extends PluginBase implements ContainerFac
* The currently set context value.
*/
public function getContextValue($name) {
- return $this->context[$name];
+ return !empty($this->context[$name]) ? $this->context[$name] : NULL;
}
/**
@@ -323,6 +323,20 @@ abstract class EntityEmbedDisplayBase extends PluginBase implements ContainerFac
return array_key_exists($name, $attributes) ? $attributes[$name] : $default;
}
+ /**
+ * Check if attribute is set.
+ *
+ * @param string $name
+ * The name of the attribute.
+ *
+ * @return bool
+ * Returns true of value is set.
+ */
+ public function hasAttribute($name) {
+ $attributes = $this->getAttributeValues();
+ return array_key_exists($name, $attributes);
+ }
+
/**
* Gets the current language code.
*
diff --git a/src/EntityEmbedDisplay/EntityEmbedDisplayManager.php b/src/EntityEmbedDisplay/EntityEmbedDisplayManager.php
index ce560df..b245cae 100644
--- a/src/EntityEmbedDisplay/EntityEmbedDisplayManager.php
+++ b/src/EntityEmbedDisplay/EntityEmbedDisplayManager.php
@@ -5,8 +5,10 @@ namespace Drupal\entity_embed\EntityEmbedDisplay;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Image\Image;
use Drupal\Core\Plugin\DefaultPluginManager;
use Drupal\Component\Plugin\Exception\PluginException;
+use Drupal\entity_embed\Plugin\entity_embed\EntityEmbedDisplay\MediaImageDecorator;
/**
* Provides an Entity Embed display plugin manager.
@@ -176,4 +178,12 @@ class EntityEmbedDisplayManager extends DefaultPluginManager {
}, $definitions);
}
+ public function createInstance($plugin_id, array $configuration = []) {
+ $instance = parent::createInstance($plugin_id, $configuration);
+ // Use decorator pattern to add alt and title fields to dialog when
+ // embedding media with image source.
+ $decorator = new MediaImageDecorator($instance);
+ return $decorator;
+ }
+
}
diff --git a/src/EntityEmbedDisplay/FieldFormatterEntityEmbedDisplayBase.php b/src/EntityEmbedDisplay/FieldFormatterEntityEmbedDisplayBase.php
index 038bba2..364c345 100644
--- a/src/EntityEmbedDisplay/FieldFormatterEntityEmbedDisplayBase.php
+++ b/src/EntityEmbedDisplay/FieldFormatterEntityEmbedDisplayBase.php
@@ -169,6 +169,11 @@ abstract class FieldFormatterEntityEmbedDisplayBase extends EntityEmbedDisplayBa
$formatter = $this->getFieldFormatter();
$formatter->prepareView([$fakeEntity->id() => $items]);
$build = $formatter->viewElements($items, $this->getLangcode());
+ // Don't ever cache a representation of an embedded entity, since the host
+ // entity may be overriding specific values (such as an `alt` attribute)
+ // which means that this particular rendered representation is unique to the
+ // host entity, and hence nonsensical to cache separately anyway.
+ unset($build[0]['#cache']['keys']);
// For some reason $build[0]['#printed'] is TRUE, which means it will fail
// to render later. So for now we manually fix that.
// @todo Investigate why this is needed.
diff --git a/src/Form/EntityEmbedDialog.php b/src/Form/EntityEmbedDialog.php
index f2b3597..6f725da 100644
--- a/src/Form/EntityEmbedDialog.php
+++ b/src/Form/EntityEmbedDialog.php
@@ -487,7 +487,10 @@ class EntityEmbedDialog extends FormBase {
];
$plugin_id = !empty($values['attributes']['data-entity-embed-display']) ? $values['attributes']['data-entity-embed-display'] : $entity_element['data-entity-embed-display'];
if (!empty($plugin_id)) {
- if (is_string($entity_element['data-entity-embed-display-settings'])) {
+ if (empty($entity_element['data-entity-embed-display-settings'])) {
+ $entity_element['data-entity-embed-display-settings'] = [];
+ }
+ elseif (is_string($entity_element['data-entity-embed-display-settings'])) {
$entity_element['data-entity-embed-display-settings'] = Json::decode($entity_element['data-entity-embed-display-settings']);
}
$display = $this->entityEmbedDisplayManager->createInstance($plugin_id, $entity_element['data-entity-embed-display-settings']);
diff --git a/src/Plugin/Derivative/FieldFormatterDeriver.php b/src/Plugin/Derivative/FieldFormatterDeriver.php
index 26a8b06..6c0970c 100644
--- a/src/Plugin/Derivative/FieldFormatterDeriver.php
+++ b/src/Plugin/Derivative/FieldFormatterDeriver.php
@@ -5,6 +5,7 @@ namespace Drupal\entity_embed\Plugin\Derivative;
use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
+use Drupal\entity_embed\Plugin\entity_embed\EntityEmbedDisplay\MediaReferenceFieldFormatter;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Field\FormatterPluginManager;
diff --git a/src/Plugin/Derivative/ViewModeDeriver.php b/src/Plugin/Derivative/ViewModeDeriver.php
index f23d70e..0a408f2 100644
--- a/src/Plugin/Derivative/ViewModeDeriver.php
+++ b/src/Plugin/Derivative/ViewModeDeriver.php
@@ -6,6 +6,8 @@ use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
+use Drupal\entity_embed\Plugin\entity_embed\EntityEmbedDisplay\MediaViewModeFieldFormatter;
+use Drupal\entity_embed\Plugin\entity_embed\EntityEmbedDisplay\ViewModeFieldFormatter;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
diff --git a/src/Plugin/entity_embed/EntityEmbedDisplay/MediaImageDecorator.php b/src/Plugin/entity_embed/EntityEmbedDisplay/MediaImageDecorator.php
new file mode 100644
index 0000000..1202338
--- /dev/null
+++ b/src/Plugin/entity_embed/EntityEmbedDisplay/MediaImageDecorator.php
@@ -0,0 +1,275 @@
+decorated = $decorated;
+ }
+
+ public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+ $form = $this->decorated->buildConfigurationForm($form, $form_state);
+
+ $plugin_id = $this->decorated->getPluginId();
+
+ if (in_array($plugin_id, $this->excludeList)) {
+ return $form;
+ }
+
+ /** @var EntityInterface $entity */
+ $entity = $this->decorated->getEntityFromContext();
+
+ if ($entity->getEntityTypeId() == 'media' && $image_field = $this->getMediaImageSourceField($entity)) {
+
+ $settings = $entity->{$image_field}->getItemDefinition()->getSettings();
+ $attributes = $this->getAttributeValues();
+
+ $alt = isset($attributes['alt']) ? $attributes['alt'] : $entity->{$image_field}->alt;
+ $title = isset($attributes['title']) ? $attributes['title'] : $entity->{$image_field}->title;
+
+ // Setting empty alt to double quotes. See ImageFieldFormatter.
+ if ($settings['alt_field_required'] && $alt == '') {
+ $alt = '""';
+ }
+
+ if (!empty($settings['alt_field'])) {
+
+ // Add support for editing the alternate and title text attributes.
+ $form['alt'] = [
+ '#type' => 'textfield',
+ '#title' => $this->t('Alternate text'),
+ '#default_value' => $alt,
+ '#description' => $this->t('This text will be used by screen readers, search engines, or when the image cannot be loaded.'),
+ '#required' => $settings['alt_field_required'],
+ '#required_error' => $this->t('Alternative text is required.
(Only in rare cases should this be left empty. To create empty alternative text, enter ""
— two double quotes without any content).'),
+ '#maxlength' => 512,
+ ];
+ }
+
+ if (!empty($settings['title_field'])) {
+ $form['title'] = [
+ '#type' => 'textfield',
+ '#title' => $this->t('Title'),
+ '#default_value' => $title,
+ '#description' => t('The title is used as a tool tip when the user hovers the mouse over the image.'),
+ '#maxlength' => 1024,
+ '#required' => $settings['title_field_required'],
+ ];
+ }
+ }
+
+ return $form;
+ }
+
+ public function access(AccountInterface $account = NULL) {
+ return $this->decorated->access($account);
+ }
+
+ public function calculateDependencies() {
+ return $this->decorated->calculateDependencies();
+ }
+
+ public function getConfiguration() {
+ return $this->decorated->getConfiguration();
+ }
+
+ public function build() {
+ $build = $this->decorated->build();
+
+
+ $plugin_id = $this->decorated->getPluginId();
+
+ if (in_array($plugin_id, $this->excludeList)) {
+ return $build;
+ }
+
+ /** @var EntityInterface $entity */
+ $entity = $this->decorated->getEntityFromContext();
+
+ if ($entity->getEntityTypeId() == 'media' && $image_field = $this->getMediaImageSourceField($entity)) {
+ $settings = $entity->{$image_field}->getItemDefinition()->getSettings();
+
+ if (!empty($settings['alt_field']) && $this->hasAttribute('alt')) {
+ $entity->{$image_field}->alt = $this->getAttributeValue('alt');
+ $entity->thumbnail->alt = $this->getAttributeValue('alt');
+ }
+
+ if (!empty($settings['title_field']) && $this->hasAttribute('title')) {
+ $entity->{$image_field}->title = $this->getAttributeValue('title');
+ $entity->thumbnail->title = $this->getAttributeValue('title');
+ }
+ }
+
+ return $build;
+ }
+
+ public function getPluginDefinition() {
+ return $this->decorated->getPluginDefinition();
+ }
+
+ public function getPluginId() {
+ return $this->decorated->getPluginId();
+ }
+
+ public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
+ return $this->decorated->validateConfigurationForm($form, $form_state);
+ }
+
+ public function defaultConfiguration() {
+ return $this->decorated->defaultConfiguration();
+ }
+
+ public function setConfiguration(array $configuration) {
+ return $this->decorated->setConfiguration($configuration);
+ }
+
+ public function setContextValue($name, $value) {
+ if (method_exists($this->decorated, 'setContextValue')) {
+ $this->decorated->setContextValue($name, $value);
+ }
+ }
+
+ public function getContextValues() {
+ if (method_exists($this->decorated, 'getContextValues')) {
+ return $this->decorated->getContextValues();
+ }
+ else {
+ return [];
+ }
+ }
+
+ public function getContextValue($name) {
+ if (method_exists($this->decorated, 'getContextValue')) {
+ return $this->decorated->getContextValue($name);
+ }
+ return NULL;
+ }
+
+ public function hasContextValue($name) {
+ if (method_exists($this->decorated, 'hasContextValue')) {
+ return $this->decorated->hasContextValue($name);
+ }
+ }
+
+ public function setAttributes(array $attributes) {
+ if (method_exists($this->decorated, 'setAttributes')) {
+ $this->decorated->setAttributes($attributes);
+ }
+ }
+
+ public function getAttributeValues() {
+ if (method_exists($this->decorated, 'getAttributeValues')) {
+ return $this->decorated->getAttributeValues();
+ }
+ }
+
+ public function getAttributeValue($name, $default = NULL) {
+ if (method_exists($this->decorated, 'getAttributeValue')) {
+ return $this->decorated->getAttributeValue($name, $default);
+ }
+ }
+
+ public function hasAttribute($name) {
+ if (method_exists($this->decorated, 'hasAttribute')) {
+ return $this->decorated->hasAttribute($name);
+ }
+ }
+
+ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
+
+ $plugin_id = $this->decorated->getPluginId();
+
+ if (in_array($plugin_id, $this->excludeList)) {
+ $this->decorated->submitConfigurationForm($form, $form_state);
+ return;
+ }
+
+ /** @var EntityInterface $entity */
+ $entity = $this->decorated->getEntityFromContext();
+
+ if ($image_field = $this->getMediaImageSourceField($entity)) {
+ $settings = $entity->{$image_field}->getItemDefinition()->getSettings();
+ $values = $form_state->getValue(['attributes', 'data-entity-embed-display-settings']);
+
+ if (!empty($settings['alt_field'])) {
+ // When the alt attribute is set to two double quotes, transform it to
+ // the empty string: two double quotes signify "empty alt attribute".
+ // See ImagefieldFormatter.
+ if (trim($values['alt']) === '""') {
+ $values['alt'] = '""';
+ }
+ // If the alt text is unchanged from the values set on the
+ // field, there's no need for the alt property to be set.
+ if ($values['alt'] === $entity->{$image_field}->alt) {
+ $values['alt'] = '';
+ }
+
+ $form_state->setValue(['attributes', 'alt'], $values['alt']);
+ $form_state->unsetValue(['attributes', 'data-entity-embed-display-settings', 'alt']);
+ }
+
+ if (!empty($settings['title_field'])) {
+ if (empty($values['title'])) {
+ $values['title'] = '';
+ }
+ // If the title text is unchanged from the values set on the
+ // field, there's no need for the title property to be set.
+ if ($values['title'] === $entity->{$image_field}->title) {
+ $values['title'] = '';
+ }
+
+ $form_state->setValue(['attributes', 'title'], $values['title']);
+ $form_state->unsetValue(['attributes', 'data-entity-embed-display-settings', 'title']);
+ }
+ }
+ $this->decorated->submitConfigurationForm($form, $form_state);
+ }
+
+ /**
+ * Get image field from source config.
+ *
+ * @param \Drupal\media\MediaInterface $media
+ * Embedded entity.
+ *
+ * @return string|null
+ * String of image field name.
+ */
+ protected function getMediaImageSourceField(MediaInterface $media) {
+
+ if (!$media->getSource() instanceof Image) {
+ return NULL;
+ }
+
+ $config = $media->getSource()->getConfiguration();
+
+ if (!empty($config['source_field'])) {
+ return $config['source_field'];
+ }
+
+ return NULL;
+ }
+
+}
diff --git a/tests/modules/entity_embed_translation_test/config/install/core.entity_form_display.node.article.default.yml b/tests/modules/entity_embed_test/config/install/core.entity_form_display.node.article.default.yml
similarity index 100%
rename from tests/modules/entity_embed_translation_test/config/install/core.entity_form_display.node.article.default.yml
rename to tests/modules/entity_embed_test/config/install/core.entity_form_display.node.article.default.yml
diff --git a/tests/modules/entity_embed_test/config/install/core.entity_view_display.media.image.embed.yml b/tests/modules/entity_embed_test/config/install/core.entity_view_display.media.image.embed.yml
new file mode 100644
index 0000000..60ae55d
--- /dev/null
+++ b/tests/modules/entity_embed_test/config/install/core.entity_view_display.media.image.embed.yml
@@ -0,0 +1,29 @@
+langcode: en
+status: true
+dependencies:
+ config:
+ - field.field.media.image.field_media_image
+ - image.style.medium
+ - media.type.image
+ module:
+ - image
+ - user
+id: media.image.default
+targetEntityType: media
+bundle: image
+mode: embed
+content:
+ field_media_image:
+ type: image
+ weight: 2
+ region: content
+ label: hidden
+ settings:
+ image_style: medium
+ image_link: ''
+ third_party_settings: { }
+hidden:
+ name: true
+ thumbnail: true
+ created: true
+ uid: true
diff --git a/tests/modules/entity_embed_translation_test/config/install/core.entity_view_display.node.article.default.yml b/tests/modules/entity_embed_test/config/install/core.entity_view_display.node.article.default.yml
similarity index 100%
rename from tests/modules/entity_embed_translation_test/config/install/core.entity_view_display.node.article.default.yml
rename to tests/modules/entity_embed_test/config/install/core.entity_view_display.node.article.default.yml
diff --git a/tests/modules/entity_embed_test/config/install/core.entity_view_mode.media.embed.yml b/tests/modules/entity_embed_test/config/install/core.entity_view_mode.media.embed.yml
new file mode 100644
index 0000000..6a87a05
--- /dev/null
+++ b/tests/modules/entity_embed_test/config/install/core.entity_view_mode.media.embed.yml
@@ -0,0 +1,9 @@
+langcode: en
+status: false
+dependencies:
+ module:
+ - media
+id: media.embed
+label: 'Embed'
+targetEntityType: media
+cache: true
diff --git a/tests/modules/entity_embed_translation_test/config/install/editor.editor.full_html.yml b/tests/modules/entity_embed_test/config/install/editor.editor.full_html.yml
similarity index 100%
rename from tests/modules/entity_embed_translation_test/config/install/editor.editor.full_html.yml
rename to tests/modules/entity_embed_test/config/install/editor.editor.full_html.yml
diff --git a/tests/modules/entity_embed_translation_test/config/install/embed.button.test_media_entity_embed.yml b/tests/modules/entity_embed_test/config/install/embed.button.test_media_entity_embed.yml
similarity index 100%
rename from tests/modules/entity_embed_translation_test/config/install/embed.button.test_media_entity_embed.yml
rename to tests/modules/entity_embed_test/config/install/embed.button.test_media_entity_embed.yml
diff --git a/tests/modules/entity_embed_translation_test/config/install/embed.button.test_node.yml b/tests/modules/entity_embed_test/config/install/embed.button.test_node.yml
similarity index 100%
rename from tests/modules/entity_embed_translation_test/config/install/embed.button.test_node.yml
rename to tests/modules/entity_embed_test/config/install/embed.button.test_node.yml
diff --git a/tests/modules/entity_embed_translation_test/config/install/field.field.media.image.field_media_image.yml b/tests/modules/entity_embed_test/config/install/field.field.media.image.field_media_image.yml
similarity index 100%
rename from tests/modules/entity_embed_translation_test/config/install/field.field.media.image.field_media_image.yml
rename to tests/modules/entity_embed_test/config/install/field.field.media.image.field_media_image.yml
diff --git a/tests/modules/entity_embed_translation_test/config/install/field.field.node.article.body.yml b/tests/modules/entity_embed_test/config/install/field.field.node.article.body.yml
similarity index 100%
rename from tests/modules/entity_embed_translation_test/config/install/field.field.node.article.body.yml
rename to tests/modules/entity_embed_test/config/install/field.field.node.article.body.yml
diff --git a/tests/modules/entity_embed_translation_test/config/install/field.storage.media.field_media_image.yml b/tests/modules/entity_embed_test/config/install/field.storage.media.field_media_image.yml
similarity index 100%
rename from tests/modules/entity_embed_translation_test/config/install/field.storage.media.field_media_image.yml
rename to tests/modules/entity_embed_test/config/install/field.storage.media.field_media_image.yml
diff --git a/tests/modules/entity_embed_translation_test/config/install/filter.format.full_html.yml b/tests/modules/entity_embed_test/config/install/filter.format.full_html.yml
similarity index 100%
rename from tests/modules/entity_embed_translation_test/config/install/filter.format.full_html.yml
rename to tests/modules/entity_embed_test/config/install/filter.format.full_html.yml
diff --git a/tests/modules/entity_embed_translation_test/config/install/media.type.image.yml b/tests/modules/entity_embed_test/config/install/media.type.image.yml
similarity index 100%
rename from tests/modules/entity_embed_translation_test/config/install/media.type.image.yml
rename to tests/modules/entity_embed_test/config/install/media.type.image.yml
diff --git a/tests/modules/entity_embed_translation_test/config/install/node.type.article.yml b/tests/modules/entity_embed_test/config/install/node.type.article.yml
similarity index 100%
rename from tests/modules/entity_embed_translation_test/config/install/node.type.article.yml
rename to tests/modules/entity_embed_test/config/install/node.type.article.yml
diff --git a/tests/modules/entity_embed_test/entity_embed_test.info.yml b/tests/modules/entity_embed_test/entity_embed_test.info.yml
index 45e7865..9b44c30 100644
--- a/tests/modules/entity_embed_test/entity_embed_test.info.yml
+++ b/tests/modules/entity_embed_test/entity_embed_test.info.yml
@@ -3,3 +3,13 @@ type: module
description: 'Support module for the Entity Embed module tests.'
core: 8.x
package: Testing
+dependencies:
+ - drupal:file
+ - drupal:image
+ - drupal:node
+ - drupal:text
+ - drupal:media
+ - drupal:ckeditor
+ - drupal:editor
+ - embed:embed
+ - entity_embed:entity_embed
diff --git a/tests/modules/entity_embed_translation_test/entity_embed_translation_test.info.yml b/tests/modules/entity_embed_translation_test/entity_embed_translation_test.info.yml
index 722468e..7d019ab 100644
--- a/tests/modules/entity_embed_translation_test/entity_embed_translation_test.info.yml
+++ b/tests/modules/entity_embed_translation_test/entity_embed_translation_test.info.yml
@@ -14,3 +14,4 @@ dependencies:
- drupal:editor
- embed:embed
- entity_embed:entity_embed
+
diff --git a/tests/src/FunctionalJavascript/EntityEmbedTestBase.php b/tests/src/FunctionalJavascript/EntityEmbedTestBase.php
index c56f12f..aa3e559 100644
--- a/tests/src/FunctionalJavascript/EntityEmbedTestBase.php
+++ b/tests/src/FunctionalJavascript/EntityEmbedTestBase.php
@@ -2,6 +2,7 @@
namespace Drupal\Tests\entity_embed\FunctionalJavascript;
+use Drupal\Component\Utility\Html;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
/**
@@ -42,4 +43,23 @@ JS;
$this->getSession()->wait(5000, "(typeof CKEDITOR != 'undefined' && typeof CKEDITOR.instances['edit-body-0-value'] != 'undefined' && CKEDITOR.instances['edit-body-0-value'].instanceReady)");
}
+ /**
+ * Get an embed code with given attributes.
+ *
+ * @param array $attributes
+ * The attributes to add.
+ *
+ * @return string
+ * A string containing a drupal-entity dom element.
+ */
+ protected function getEmbedCode(array $attributes) {
+ $dom = Html::load('This placeholder should not be rendered.');
+ $xpath = new \DOMXPath($dom);
+ $drupal_entity = $xpath->query('//drupal-entity')[0];
+ foreach ($attributes as $attribute => $value) {
+ $drupal_entity->setAttribute($attribute, $value);
+ }
+ return Html::serialize($dom);
+ }
+
}
diff --git a/tests/src/FunctionalJavascript/MediaImageTest.php b/tests/src/FunctionalJavascript/MediaImageTest.php
new file mode 100644
index 0000000..d0ae6df
--- /dev/null
+++ b/tests/src/FunctionalJavascript/MediaImageTest.php
@@ -0,0 +1,397 @@
+adminUser = $this->drupalCreateUser([
+ 'use text format full_html',
+ 'administer nodes',
+ 'edit any article content',
+ ]);
+ }
+
+ /**
+ * Tests the host entity's langcode is available in EntityEmbedDialog.
+ */
+ public function testAltAndTitle() {
+
+ \Drupal::service('file_system')->copy($this->root . '/core/misc/druplicon.png', 'public://example.jpg');
+ /** @var \Drupal\file\FileInterface $file */
+ $file = File::create([
+ 'uri' => 'public://example.jpg',
+ 'uid' => $this->adminUser->id(),
+ ]);
+ $file->save();
+
+ $media = Media::create([
+ 'bundle' => 'image',
+ 'name' => 'Media Image',
+ 'field_media_image' => [
+ [
+ 'target_id' => $file->id(),
+ 'alt' => 'default alt',
+ 'title' => 'default title',
+ ],
+ ],
+ ]);
+ $media->save();
+
+ $host = $this->createNode([
+ 'type' => 'article',
+ 'title' => 'host',
+ 'body' => [
+ 'value' => '',
+ 'format' => 'full_html',
+ ],
+ ]);
+
+ $this->drupalLogin($this->adminUser);
+ $this->drupalGet('node/' . $host->id() . '/edit');
+ $this->waitForEditor();
+
+ $this->assignNameToCkeditorIframe();
+
+ $this->assertSession()
+ ->waitForElementVisible('css', 'a.cke_button__test_media_entity_embed')
+ ->click();
+ $this->assertSession()->waitForId('drupal-modal');
+
+ $this->assertSession()
+ ->fieldExists('entity_id')
+ ->setValue('Media Image (1)');
+ $this->assertSession()->elementExists('css', 'button.js-button-next')->click();
+ $form = $this->assertSession()->waitForElementVisible('css', 'form.entity-embed-dialog-step--embed');
+
+ // Assert that the review step displays the selected entity with the label.
+ $text = $form->getText();
+ $this->assertContains('Media Image', $text);
+
+ $select = $this->assertSession()
+ ->selectExists('attributes[data-entity-embed-display]');
+
+ $select->setValue('entity_reference:entity_reference_entity_id');
+ $this->assertSession()->assertWaitOnAjaxRequest();
+
+ // Assert the id display doesn't have alt and title fields.
+ $this->assertSession()
+ ->fieldNotExists('attributes[data-entity-embed-display-settings][alt]');
+ $this->assertSession()
+ ->fieldNotExists('attributes[data-entity-embed-display-settings][title]');
+
+ $select->setValue('entity_reference:entity_reference_label');
+ $this->assertSession()->assertWaitOnAjaxRequest();
+
+ // Assert the label display doesn't have alt and title fields.
+ $this->assertSession()
+ ->fieldNotExists('attributes[data-entity-embed-display-settings][alt]');
+ $this->assertSession()
+ ->fieldNotExists('attributes[data-entity-embed-display-settings][title]');
+
+ $select->setValue('entity_reference:entity_reference_label');
+ $this->assertSession()->assertWaitOnAjaxRequest();
+
+ // @todo entity_reference:media_thumbnail should also have alt and title text.
+
+ $select->setValue('view_mode:media.embed');
+ $this->assertSession()->assertWaitOnAjaxRequest();
+
+ // Assert that the view_mode:media.embed display has alt and title fields,
+ // and that the default values match the values on the media's
+ // source image field.
+ $this->assertSession()
+ ->selectExists('attributes[data-entity-embed-display]')
+ ->setValue('view_mode:media.embed');
+ $this->assertSession()->assertWaitOnAjaxRequest();
+ $alt = $this->assertSession()
+ ->fieldExists('attributes[data-entity-embed-display-settings][alt]');
+ $this->assertEquals($media->field_media_image->alt, $alt->getValue());
+ $title = $this->assertSession()
+ ->fieldExists('attributes[data-entity-embed-display-settings][title]');
+ $this->assertEquals($media->field_media_image->title, $title->getValue());
+
+ $this->submitDialog();
+
+ $img = $this->assertSession()->elementExists('css', 'img');
+ $this->assertEquals("default alt", $img->getAttribute('alt'));
+ $this->assertEquals("default title", $img->getAttribute('title'));
+
+ $this->reopenDialog();
+
+ $this->assertSession()
+ ->fieldExists('attributes[data-entity-embed-display-settings][alt]')
+ ->setValue('overridden alt');
+ $this->assertSession()
+ ->fieldExists('attributes[data-entity-embed-display-settings][title]')
+ ->setValue('overridden title');
+
+ $this->submitDialog();
+
+ $img = $this->assertSession()->elementExists('css', 'img');
+ $this->assertEquals('overridden alt', $img->getAttribute('alt'));
+ $this->assertEquals('overridden title', $img->getAttribute('title'));
+
+ $this->config('field.field.media.image.field_media_image')
+ ->set('settings.alt_field', FALSE)
+ ->set('settings.title_field', FALSE)
+ ->save();
+
+ $field = FieldConfig::load('media.image.field_media_image');
+ $settings = $field->getSettings();
+ $settings['alt_field'] = FALSE;
+ $settings['title_field'] = FALSE;
+ $field->set('settings', $settings);
+ $field->save();
+
+ // @todo flush only what's necessary.
+ drupal_flush_all_caches();
+
+ $this->reopenDialog();
+
+ $this->assertSession()
+ ->fieldNotExists('attributes[data-entity-embed-display-settings][alt]');
+ $this->assertSession()
+ ->fieldNotExists('attributes[data-entity-embed-display-settings][title]');
+
+ $this->submitDialog();
+
+ $img = $this->assertSession()->elementExists('css', 'img');
+ $this->assertEquals('default alt', $img->getAttribute('alt'));
+ $this->assertEquals('default title', $img->getAttribute('title'));
+
+ $field = FieldConfig::load('media.image.field_media_image');
+ $settings = $field->getSettings();
+ $settings['alt_field'] = TRUE;
+ $field->set('settings', $settings);
+ $field->save();
+
+ // @todo flush only what's necessary.
+ drupal_flush_all_caches();
+
+ $this->reopenDialog();
+
+ // With only alt field enabled, only alt field should display.
+ $this->assertSession()
+ ->fieldExists('attributes[data-entity-embed-display-settings][alt]')->setValue('overridden alt');
+ $this->assertSession()
+ ->fieldNotExists('attributes[data-entity-embed-display-settings][title]');
+
+ $this->submitDialog();
+
+ $img = $this->assertSession()->elementExists('css', 'img');
+ $this->assertEquals('overridden alt', $img->getAttribute('alt'));
+ $this->assertEquals('default title', $img->getAttribute('title'));
+
+ $field = FieldConfig::load('media.image.field_media_image');
+ $settings = $field->getSettings();
+ $settings['alt_field'] = FALSE;
+ $settings['title_field'] = TRUE;
+ $field->set('settings', $settings);
+ $field->save();
+
+ // @todo flush only what's necessary.
+ drupal_flush_all_caches();
+
+ $this->reopenDialog();
+
+ // With only title field enabled, only title field should display.
+ $this->assertSession()
+ ->fieldExists('attributes[data-entity-embed-display-settings][title]')->setValue('overridden title');
+ $this->assertSession()
+ ->fieldNotExists('attributes[data-entity-embed-display-settings][alt]');
+
+ $this->submitDialog();
+
+ $img = $this->assertSession()->elementExists('css', 'img');
+ $this->assertEquals('overridden title', $img->getAttribute('title'));
+ $this->assertEquals('default alt', $img->getAttribute('alt'));
+
+ $field = FieldConfig::load('media.image.field_media_image');
+ $settings = $field->getSettings();
+ $settings['alt_field'] = TRUE;
+ $settings['title_field'] = TRUE;
+ $settings['alt_field_required'] = FALSE;
+ $settings['title_field_required'] = TRUE;
+ $field->set('settings', $settings);
+ $field->save();
+
+ // @todo flush only what's necessary.
+ drupal_flush_all_caches();
+
+ $this->reopenDialog();
+
+ $alt = $this->assertSession()
+ ->fieldExists('attributes[data-entity-embed-display-settings][alt]');
+ $this->assertFalse($alt->hasAttribute('required'));
+ $title = $this->assertSession()
+ ->fieldExists('attributes[data-entity-embed-display-settings][title]');
+ $this->assertTrue($title->hasAttribute('required'));
+
+ $this->submitDialog();
+
+ $field = FieldConfig::load('media.image.field_media_image');
+ $settings = $field->getSettings();
+ $settings['alt_field_required'] = TRUE;
+ $settings['title_field_required'] = FALSE;
+ $field->set('settings', $settings);
+ $field->save();
+
+ // @todo flush only what's necessary.
+ drupal_flush_all_caches();
+
+ $this->reopenDialog();
+
+ $alt = $this->assertSession()
+ ->fieldExists('attributes[data-entity-embed-display-settings][alt]');
+ $this->assertTrue($alt->hasAttribute('required'));
+ $title = $this->assertSession()
+ ->fieldExists('attributes[data-entity-embed-display-settings][title]');
+ $this->assertFalse($title->hasAttribute('required'));
+
+ // Test that setting value to double quote will allow setting the alt and title
+ // to empty.
+ $alt->setValue('""');
+ $title->setValue('""');
+
+ $this->submitDialog();
+
+ $img = $this->assertSession()->elementExists('css', 'img');
+ $this->assertEmpty($img->getAttribute('alt'));
+ $this->assertEmpty($img->getAttribute('title'));
+
+ // Test the same embed with different alt and title text.
+ $input = $this->getEmbedCode([
+ 'alt' => 'alt 1',
+ 'title' => 'title 1',
+ 'data-embed-button' => 'test_media_entity_embed',
+ 'data-entity-embed-display' => 'view_mode:media.embed',
+ 'data-entity-embed-display-settings' => '',
+ 'data-entity-type' => 'media',
+ 'data-entity-uuid' => $media->uuid(),
+ 'data-langcode' => 'en',
+ ]);
+ $input .= $this->getEmbedCode([
+ 'alt' => 'alt 2',
+ 'title' => 'title 2',
+ 'data-embed-button' => 'test_media_entity_embed',
+ 'data-entity-embed-display' => 'view_mode:media.embed',
+ 'data-entity-embed-display-settings' => '',
+ 'data-entity-type' => 'media',
+ 'data-entity-uuid' => $media->uuid(),
+ 'data-langcode' => 'en',
+ ]);
+ $input .= $this->getEmbedCode([
+ 'alt' => 'alt 3',
+ 'title' => 'title 3',
+ 'data-embed-button' => 'test_media_entity_embed',
+ 'data-entity-embed-display' => 'view_mode:media.embed',
+ 'data-entity-embed-display-settings' => '',
+ 'data-entity-type' => 'media',
+ 'data-entity-uuid' => $media->uuid(),
+ 'data-langcode' => 'en',
+ ]);
+
+ $this->getSession()->switchToIFrame();
+
+ $this->assertSession()
+ ->waitForElementVisible('css', 'a.cke_button__source')
+ ->click();
+
+ $source = $this->assertSession()
+ ->waitForElementVisible('xpath', "//textarea[contains(@class, 'cke_source')]");
+ $source->setValue($input);
+
+ // Exit "source" mode.
+ $this->assertSession()
+ ->waitForElementVisible('css', 'a.cke_button__source')
+ ->click();
+
+ $this->assertSession()->assertWaitOnAjaxRequest();
+ $this->assignNameToCkeditorIframe();
+ $this->getSession()->switchToIFrame('ckeditor');
+
+ $img = $this->assertSession()->waitForElement('xpath', "//img[contains(@alt, 'alt 1')]");
+ $this->assertEquals('alt 1', $img->getAttribute('alt'));
+ $this->assertEquals('title 1', $img->getAttribute('title'));
+
+ $img = $this->assertSession()->elementExists('xpath', "//img[contains(@alt, 'alt 2')]");
+ $this->assertEquals('alt 2', $img->getAttribute('alt'));
+ $this->assertEquals('title 2', $img->getAttribute('title'));
+
+ $img = $this->assertSession()->elementExists('xpath', "//img[contains(@alt, 'alt 3')]");
+ $this->assertEquals('alt 3', $img->getAttribute('alt'));
+ $this->assertEquals('title 3', $img->getAttribute('title'));
+
+ // Save the host entity.
+ $this->getSession()->switchToIFrame();
+ $this->assertSession()->buttonExists('Save')->press();
+
+ $img = $this->assertSession()->waitForElement('xpath', "//img[contains(@alt, 'alt 1')]");
+ $this->assertEquals('alt 1', $img->getAttribute('alt'));
+ $this->assertEquals('title 1', $img->getAttribute('title'));
+
+ $img = $this->assertSession()->elementExists('xpath', "//img[contains(@alt, 'alt 2')]");
+ $this->assertEquals('alt 2', $img->getAttribute('alt'));
+ $this->assertEquals('title 2', $img->getAttribute('title'));
+
+ $img = $this->assertSession()->elementExists('xpath', "//img[contains(@alt, 'alt 3')]");
+ $this->assertEquals('alt 3', $img->getAttribute('alt'));
+ $this->assertEquals('title 3', $img->getAttribute('title'));
+
+ }
+
+ /**
+ * Helper function to reopen EntityEmbedDialog for first embed.
+ */
+ protected function reopenDialog() {
+ $this->getSession()->switchToIFrame();
+ $select_and_edit_embed = "var editor = CKEDITOR.instances['edit-body-0-value'];
+ var entityEmbed = editor.widgets.getByElement(editor.editable().findOne('div'));
+ entityEmbed.focus();
+ editor.execCommand('editdrupalentity');";
+ $this->getSession()->executeScript($select_and_edit_embed);
+ $this->assertSession()->assertWaitOnAjaxRequest();
+ $this->assertSession()->waitForElementVisible('css', 'form.entity-embed-dialog-step--embed');
+ }
+
+ /**
+ * Helper function to submit dialog and focus on ckeditor frame.
+ */
+ protected function submitDialog() {
+ $this->assertSession()->elementExists('css', 'button.button--primary')->press();
+ $this->assertSession()->assertWaitOnAjaxRequest();
+
+ // Verify that the embedded entity preview in CKEditor displays the image
+ // with the default alt and title.
+ $this->getSession()->switchToIFrame('ckeditor');
+ }
+
+}