Drupal's core media module is an exceptional tool for media management and embedding within a Drupal site. With minimal configuration, it enables efficient management of various media types, making it an ideal choice. However, it is worth mentioning that there are few feature requests in the issue queue that have remained unresolved for a significant period of time.
When I was working on a site that extensively utilized remote media, I found myself in need of one of those pending features.
Here is that request https://www.drupal.org/project/drupal/issues/2983456
Although I attempted to use the available patches, they only provided a partial resolution to my specific requirement and did not fully meet my needs.
It is possible that the patches have been updated and are now fully functional, but I am not aware of their current status.
However, at the time when I needed the feature, I chose to develop it myself, focusing on keeping it simple and minimal.
As part of our requirements, we need to implement a trigger mechanism, specifically an entity operation, that will update the video thumbnail in our system whenever it is updated on the source platforms such as YouTube or Vimeo.
Implementation
Step 1:- Declare and define the controller.
File- my_module.routing.yml
# Refresh thumbnail route
my_module.refresh_thumbnail:
path: '/media/{media}/refresh-thumbnail'
defaults:
_controller: '\Drupal\my_module\Controller\RefreshThumbnailController::refreshThumbnail'
requirements:
_entity_access: 'media.update'
_csrf_token: 'TRUE'
File- RefreshThumbnailController.php
<?php
namespace Drupal\my_module\Controller;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\file\FileInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Url;
use Drupal\media\MediaInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Controller that triggers refresh thumbnail on a given media item.
*/
class RefreshThumbnailController extends ControllerBase {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* RefreshThumbnailController constructor.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
*/
public function __construct(EntityTypeManagerInterface $entityTypeManager) {
$this->entityTypeManager = $entityTypeManager;
}
/**
* {@inheritdoc}
*
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
* The Drupal service container.
*
* @return static
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity_type.manager')
);
}
/**
* Updates thumbnail on a media entity and reloads the page.
*
* @param \Drupal\media\MediaInterface $media
* The media item for which to update thumbnail.
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* A redirect response to return the user to the page they were on.
*/
public function refreshThumbnail(MediaInterface $media) {
$output = $this->refreshVideoThumbnail($media);
if ($output === TRUE) {
$this->messenger()
->addStatus(
$this->t('Updated thumbnail on media item %label', [
'%label' => $media->label(),
]));
}
elseif (is_string($output)) {
$this->messenger()->addMessage($output);
}
elseif ($output === FALSE) {
$this->messenger()
->addWarning(
$this->t('Thumbnail not updated for media item %label', [
'%label' => $media->label(),
]));
}
return new RedirectResponse($this->reloadPage());
}
/**
* Reloads the previous page or return to the media overview.
*/
protected function reloadPage() {
if ($destination = $this->getRedirectDestination()->get()) {
return $destination;
}
return Url::fromRoute('entity.media.collection')->toString();
}
/**
* Refresh media video thumbnail.
*
* @param \Drupal\media\MediaInterface $media
* Media object.
*/
public function refreshVideoThumbnail(MediaInterface $media) {
try {
// Get existing thumbnail id.
$thumb_target_id = $media->get('thumbnail')->target_id;
if ($thumb_target_id) {
// Load existing thumbnail.
$file = $this->entityTypeManager
->getStorage('file')
->load($thumb_target_id);
if ($file instanceof FileInterface) {
// Delete existing thumbnail.
$file->delete();
$media->set('thumbnail', NULL);
// Save media to regenerate thumbnail.
$this->entityTypeManager->getStorage('media')->save($media);
return TRUE;
}
}
}
catch (\Exception $e) {
return $e->getMessage();
}
return FALSE;
}
}
Step 2:- Adding entity operation.
File- my_module.module
<?php
/**
* Implements hook_entity_operation_alter().
*/
function my_module_entity_operation_alter(array &$operations, EntityInterface $entity) {
// Add action for media video only.
if ($entity->bundle() == 'video' && $entity->access('update')) {
$operations['refresh_thumbnail'] = [
'title' => t('Refresh Thumbnail'),
'url' => Url::fromRoute('my_module.refresh_thumbnail', [
'media' => $entity->id(),
]),
'weight' => 150,
];
}
}