On this page
Creating a custom MediaSource plugin for external assets
Creating your own media source plugins are the link between the asset you want to represent and the Drupal entity that will hold its data. Their documented interfaces are very good sources of information (MediaSourceInterface
, MediaTypeInterface
). Drupal core by default ships with 5 media source plugins: File
, AudioFile
, VideoFile
, Image
, and OEmbed
. Which are good sources of inspiration on how to create your own.
This example, creates a custom ExternalImage
media source that uses a text_long field to store a JSON object that will contain the information about our external asset. This object would contain all the relevant properties: alt
, source
, uri
. For example:
{
"alt": "Main building of Moscow State University",
"source": "Wikimedia Commons",
"author": "Dmitry A. Mottl (cropped by King of Hearts)",
"uri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Moscow_State_University_crop.jpg/800px-Moscow_State_University_crop.jpg"
}
For this we will extend the MediaSourceBase
class, the allowed_field_types property of the MediaSource annotation specifies which type of fields will be used to extract information about the asset, in this case a text_long
field, used to store the JSON object with the properties of the image.
<?php
namespace Drupal\chip_distribution_image_media_type\Plugin\media\Source;
use Drupal\media\MediaInterface;
use Drupal\media\MediaSourceBase;
use Drupal\json_field\Plugin\Field\FieldType\JSONItem;
/**
* External image entity media source.
*
* @see \Drupal\file\FileInterface
*
* @MediaSource(
* id = "external_image",
* label = @Translation("External Image"),
* description = @Translation("Use remote images."),
* allowed_field_types = {"text_long"},
* thumbnail_alt_metadata_attribute = "alt",
* default_thumbnail_filename = "no-thumbnail.png"
* )
*/
class DistributionImage extends MediaSourceBase {
We will also implement the getMetadataAttributes()
method to define which attributes can be contained on the JSON object. When creating a custom media entity type on the Drupal UI, Drupal uses this information to allow you to map this attributes to media entity fields.
public function getMetadataAttributes() {
return [
'title' => $this->t('Title'),
'alt_text' => $this->t('Alternative text'),
'caption' => $this->t('Caption'),
'credit' => $this->t('Credit'),
'id' => $this->t('ID'),
'uri' => $this->t('URL'),
'width' => $this->t('Width'),
'height' => $this->t('Height'),
];
}
And finally all the magic to allow displaying thumbnails for our newly created MediaSourcePlugin
happens on the getMetadata()
method, that receives the $media
entity itself as a parameter, and the name of the metadata it wishes to obtain the value for:
public function getMetadata(MediaInterface $media, $attribute_name) {
// Get the text_long field where the JSON object is stored
$remote_field = $media->get($this->configuration['source_field']);
$json_arr = json_decode($remote_field->value);
// If the source field is not required, it may be empty.
if (!$remote_field) {
return parent::getMetadata($media, $attribute_name);
}
switch ($attribute_name) {
// This is used to set the name of the media entity if the user leaves the field blank.
case 'default_name':
return $json_arr->alt_text;
// This is used to generate the thumbnail field.
case 'thumbnail_uri':
return $json_arr->uri;
default:
return $json_arr->$attribute_name ?? parent::getMetadata($media, $attribute_name);
}
}
This is because every Media entity has a thumbnail field used to display a preview of your media assets on views like /admin/media/content
. To populate this field, the media module uses the thumbnail_uri
attribute of the media source plugin used by your media entity type (phew, that was long!).
The media module uses this special thumbnail_uri attribute to download an image, and while configuring the media type using this media source plugin you can specify if this download will occur while creating the entity or later when running the cron. You could also use a module like the remote_stream_wrapper to even avoid downloading the thumbnail, and creating the thumbnail file entity in drupal using the remote URI directly, the only drawback of using the remote_stream_wrapper
module for this is that it seems like it doesn't allow generating image styles out of file fields using this remote URIs.
Additional resources
- The Media Remote contrib module is another example of a MediaSource plugin, which includes validator constraints and the Media Library form integration.
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion