Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Close #3741 Add contextual links to embedded media. #3844

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@
"filter_autop returns self closing br element with slash, lets alter to br (2350049)": "https://www.drupal.org/files/issues/2024-08-15/2350049-48-reroll-against-11.x.patch",
"[10.2 regression] CKEditor 5 breaks when 'Source'/Source editing button is added and 'Manually editable HTML tags' are specified (3410100)": "https://www.drupal.org/files/issues/2024-01-23/drupal-revert-source-editing-validation-tightening-3410100-38.patch",
"[Apache only] Wrong file header returned, when converting an image for example to webp (3310963)": "https://www.drupal.org/files/issues/2024-05-15/3310963-32.patch",
"Hardcode a higher WebP conversion quality setting (3320689)": "https://gist.githubusercontent.com/joeparsons/d99b6c6eef240e8eaf768ba79e1c9f1b/raw/9b99325bd20907db0506969fc4f5823b46065c6b/3320689-10-3-x-hardcoded.patch"
"Hardcode a higher WebP conversion quality setting (3320689)": "https://gist.githubusercontent.com/joeparsons/d99b6c6eef240e8eaf768ba79e1c9f1b/raw/9b99325bd20907db0506969fc4f5823b46065c6b/3320689-10-3-x-hardcoded.patch",
"Provide option to display contextual links on embedded entities (3174252)": "web/profiles/custom/az_quickstart/patches/composer/drupal/core/3174252-Provide-option-to-display-contextual-links-on-embedded-entities.diff"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we're ready to start using local patches. This path assumes the root level composer is configured a certain way which, although likely, we can't count on.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'll put a patch on drupal.org

},
"drupal/draggableviews": {
"Row weights not displaying on sort view (3252365)": "https://www.drupal.org/files/issues/2023-08-25/3252365-check-remove-select-all-class.patch",
Expand Down
1 change: 1 addition & 0 deletions config/install/filter.format.full_html.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@ filters:
default_view_mode: default
allowed_view_modes: { }
allowed_media_types: { }
show_contextual_links: true
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,4 @@ filters:
az_square: az_square
az_very_small: az_very_small
allowed_media_types: { }
show_contextual_links: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
diff --git a/core/modules/media/config/schema/media.schema.yml b/core/modules/media/config/schema/media.schema.yml
index 4311b11049c688520e4a1efd086f1ba3e398498c..bfa7b3929de54b0580bb5fae958341d1ed11f95f 100644
--- a/core/modules/media/config/schema/media.schema.yml
+++ b/core/modules/media/config/schema/media.schema.yml
@@ -141,3 +141,6 @@ filter_settings.media_embed:
sequence:
type: string
label: 'Media type'
+ show_contextual_links:
+ type: boolean
+ label: 'Show contextual links for embedded media'
diff --git a/core/modules/media/media.post_update.php b/core/modules/media/media.post_update.php
index 7ab89500d231bfe7956e110d0d875e3df58315fe..6318f7e0be61d5b3182234c82f048241d0203a8c 100644
--- a/core/modules/media/media.post_update.php
+++ b/core/modules/media/media.post_update.php
@@ -5,6 +5,8 @@
* Post update functions for Media.
*/

+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
/**
* Implements hook_removed_post_updates().
*/
@@ -20,3 +22,52 @@ function media_removed_post_updates() {
'media_post_update_remove_mappings_targeting_source_field' => '11.0.0',
];
}
+
+/**
+ * Disable contextual links for media embeds in all text formats.
+ */
+function media_post_update_add_show_contextual_links_as_false(&$sandbox = NULL): TranslatableMarkup {
+ // Initialize batch variables if this is the first run.
+ if (!isset($sandbox['total'])) {
+ // Load all filter_format configurations.
+ $config_names = \Drupal::service('config.storage')->listAll('filter.format.');
+ $sandbox['config_names'] = $config_names;
+ $sandbox['total'] = count($sandbox['config_names']);
+ $sandbox['progress'] = 0;
+
+ // In case there are no configurations to process.
+ if ($sandbox['total'] == 0) {
+ $sandbox['total'] = 1;
+ $sandbox['progress'] = 1;
+ }
+ }
+
+ // Process configurations in chunks of 50.
+ $config_names = array_splice($sandbox['config_names'], 0, 50);
+
+ foreach ($config_names as $config_name) {
+ $config = \Drupal::service('config.factory')->getEditable($config_name);
+ $filters = $config->get('filters');
+
+ if (isset($filters['media_embed'])) {
+ $media_embed_settings = $filters['media_embed'];
+ if (empty($media_embed_settings['settings']['show_contextual_links'])) {
+ $media_embed_settings['settings']['show_contextual_links'] = FALSE;
+ // Update the settings in the filters array.
+ $filters['media_embed'] = $media_embed_settings;
+ $config->set('filters', $filters);
+ $config->save();
+ }
+ }
+
+ $sandbox['progress']++;
+ }
+
+ // Determine if the batch process is complete.
+ $sandbox['#finished'] = ($sandbox['progress'] / $sandbox['total']);
+
+ return new TranslatableMarkup('Processed Filter Formats (@count/@total)', [
+ '@count' => $sandbox['progress'],
+ '@total' => $sandbox['total'],
+ ]);
+}
diff --git a/core/modules/media/src/Plugin/Filter/MediaEmbed.php b/core/modules/media/src/Plugin/Filter/MediaEmbed.php
index 118422bf2c28d594569aa58a806ef722e4e0c4e4..71b7e1d65cc786786853181e1d6be45e57dae2b4 100644
--- a/core/modules/media/src/Plugin/Filter/MediaEmbed.php
+++ b/core/modules/media/src/Plugin/Filter/MediaEmbed.php
@@ -39,6 +39,7 @@
"default_view_mode" => "default",
"allowed_view_modes" => [],
"allowed_media_types" => [],
+ "show_contextual_links" => FALSE,
],
)]
class MediaEmbed extends FilterBase implements ContainerFactoryPluginInterface, TrustedCallbackInterface {
@@ -182,6 +183,13 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
'#element_validate' => [[static::class, 'validateOptions']],
];

+ $form['show_contextual_links'] = [
+ '#title' => $this->t("Show contextual links for embedded media"),
+ '#type' => 'checkbox',
+ '#default_value' => $this->settings['show_contextual_links'],
+ '#description' => $this->t('If selected, displays contextual links to edit/delete/etc. embedded media items.'),
+ ];
+
return $form;
}

@@ -246,9 +254,11 @@ protected function renderMedia(MediaInterface $media, $view_mode, $langcode) {
// - caching an embedded media entity separately is unnecessary; the host
// entity is already render cached.
unset($build['#cache']['keys']);
- // - Contextual Links do not make sense for embedded entities; we only allow
- // the host entity to be contextually managed.
- $build['#pre_render'][] = static::class . '::disableContextualLinks';
+ // - Contextual Links do not always make sense for embedded entities; users
+ // must opt in to exposing contextual links.
+ if (!$this->settings['show_contextual_links']) {
+ $build['#pre_render'][] = static::class . '::disableContextualLinks';
+ }
// - default styling may break captioned media embeds; attach asset library
// to ensure captions behave as intended. Do not set this at the root
// level of the render array, otherwise it will be attached always,
diff --git a/core/modules/media/tests/src/Functional/MediaEmbedContextualLinksTest.php b/core/modules/media/tests/src/Functional/MediaEmbedContextualLinksTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2b1a290ee9ff8f0bb60f7c541da3183b72ad73ce
--- /dev/null
+++ b/core/modules/media/tests/src/Functional/MediaEmbedContextualLinksTest.php
@@ -0,0 +1,81 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\media\Functional;
+
+use Drupal\media\Entity\Media;
+use Drupal\node\Entity\Node;
+use Drupal\node\Entity\NodeType;
+
+/**
+ * Tests views contextual links on embed media.
+ *
+ * @group media
+ */
+class MediaEmbedContextualLinksTest extends MediaFunctionalTestBase {
+
+ /**
+ * {@inheritdoc}
+ */
+ protected static $modules = [
+ 'contextual',
+ ];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $defaultTheme = 'stark';
+
+ /**
+ * Tests contextual links for an embed media to node body.
+ */
+ public function testMediaEmbedShowContextualLinks(): void {
+ $this->drupalLogin($this->drupalCreateUser([
+ 'administer filters',
+ 'administer media',
+ 'access contextual links',
+ ]));
+ $this->drupalGet('admin/config/content/formats/add');
+ $this->submitForm([
+ 'name' => 'Media embed with contextual links',
+ 'format' => 'media_embed_with_contextual_link',
+ 'filters[media_embed][status]' => 1,
+ 'filters[media_embed][settings][show_contextual_links]' => 1,
+ ], 'Save configuration');
+ $this->assertSession()
+ ->pageTextContains('Added text format Media embed with contextual links.');
+
+ // Create a media type.
+ $mediaType = $this->createMediaType('test');
+
+ // Create a media item.
+ $media = Media::create([
+ 'bundle' => $mediaType->id(),
+ 'name' => 'Unnamed',
+ ]);
+ $media->save();
+
+ // Create a node type.
+ $node_type = NodeType::create([
+ 'type' => $this->randomMachineName(),
+ 'name' => $this->randomString(),
+ ]);
+ $node_type->save();
+
+ // Add body field to node type.
+ node_add_body_field($node_type);
+
+ $node = Node::create([
+ 'type' => $node_type->id(),
+ 'title' => 'Test embed media to node body',
+ ]);
+ $node->body->value = '<drupal-media data-entity-type="media" data-entity-uuid="' . $media->uuid() . '" data-view-mode="default">&nbsp;</drupal-media>';
+ $node->body->format = 'media_embed_with_contextual_link';
+ $node->save();
+
+ $this->drupalGet($node->toUrl());
+ $this->assertSession()->elementExists('css', 'div[data-contextual-id*="media:media=' . $media->id() . ':"]');
+ }
+
+}
diff --git a/core/profiles/demo_umami/config/install/filter.format.basic_html.yml b/core/profiles/demo_umami/config/install/filter.format.basic_html.yml
index b57e2a67a7950fe32b2a422be14c9154f510ae97..a5a7ffb7e28ed5c2733cb433d35af1f80b2aa7c0 100644
--- a/core/profiles/demo_umami/config/install/filter.format.basic_html.yml
+++ b/core/profiles/demo_umami/config/install/filter.format.basic_html.yml
@@ -71,3 +71,4 @@ filters:
image: image
remote_video: remote_video
video: video
+ show_contextual_links: false
diff --git a/core/profiles/demo_umami/config/install/filter.format.full_html.yml b/core/profiles/demo_umami/config/install/filter.format.full_html.yml
index 44a1d1ab590b2a92290db538287ff78138e01413..26977c062211d8253198eb552c482731584b5114 100644
--- a/core/profiles/demo_umami/config/install/filter.format.full_html.yml
+++ b/core/profiles/demo_umami/config/install/filter.format.full_html.yml
@@ -64,3 +64,4 @@ filters:
image: image
remote_video: remote_video
video: video
+ show_contextual_links: false