Skip to content

Commit

Permalink
Close #3741 Add contextual links to embedded media.
Browse files Browse the repository at this point in the history
  • Loading branch information
trackleft committed Oct 28, 2024
1 parent 6ecda06 commit eb3ed21
Show file tree
Hide file tree
Showing 2 changed files with 224 additions and 1 deletion.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@
"[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",
"Provide option to display contextual links on embedded entities (3174252)": "https://git.drupalcode.org/project/drupal/-/merge_requests/5626.diff"
"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"
},
"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
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

0 comments on commit eb3ed21

Please sign in to comment.