But I just want to upload images to my site…
There is a clear difference between what a user expects from a CMS when they try to upload an image, and what they get out of the box. This is something that we hear all the time, and yet we, as a Drupal community, struggle to do it right.
There are not simple answers on why Drupal has issues regarding media management. As technology evolves, newer and simpler tools raise the bar on what users expects to see on their apps. Take Instagram for example. An entire team of people (not just devs) are focused on making the experience as simple as possible.
Therefore it’s normal to expect that everyone wants to have this type of simplicity everywhere. However, implementing this solutions is not always trivial, as you will see.
We are working in a new project that needs some image management capabilities, and just to avoid reinventing the wheel, we looked to the solutions by two mature distributions for Drupal 8, Thunder and Lightning.
Thunder seemed more aligned to what we were looking for, so we just tried to replicate the features into our platform. But there was a catch. Thunder is still using Media from a contrib module, and we wanted to stay as close to core as possible.
After spending a few hours replicating most of the functionality it became evident that there are a lot of concepts under the hood interesting to explore. Just to warn you, this article is not about of how to create a media management library. Instead we will focus on understand what we are configuring and why.
The Journey Begins.
Before Media entities was a thing, this is how a media gallery was designed with Drupal. You basically add an image field to a content type.
Drupal 8.5 introduces the concept of Media entities. This is an important concept because each time you upload media into a site you may want to associate some metadata to be able to search them later. For example, if you want to categorize images, you need to add a vocabulary to an image. The media entity acts as a bridge between your assets and the fields that enrich them.
After installing the Media module you can create Media entities types. This is, if you have images, you may want to have Media Images; the same applies for videos and audio.
We wanted to create an image gallery, therefore we created a content type called Image Gallery, that has an entity reference field that references… that’s right, media entities.
So far this is quite simple, just core modules, and two entities types referenced by a field.
Making It Usable
Now the challenge is to make this easy to use. The first step is to replace the entity reference with something much more flexible. Here is where our first contributed module comes in. Meet the Entity Browser module.
The Goal of this module is to provide a generic entity browser/picker/selector. It can be used in any context where one needs to select few entities and do something with them.
There is a great article that explains a lot of the details on this module. Let’s keep this simple to understand the full picture. Just make sure to use the 8.x-2.0 branch that is compatible with Media module provided by core.
The entity browser, as we said, allows you to replace the entity reference widget with something more fancy. It also allows you to create – in place – a new media entity. But, you will need an extra pair of modules to provide the fanciness you need.
The dropzone module allows you to upload multiple media items in a single upload. One of the main differences between media and and Drupal core is that the media name is required now, so you may need some custom code to auto populate this field somehow in case you want to hide it.
Another module you will need is Views, which fortunately is in core now, so you
don’t need to download it. The views module is used to generate a view that
lists media entities, there is a special field you need to attach to this view,
that is the Media: Entity browser bulk select form
field.
Customizing the Rest
So let’s recap, we have two entities (Media Image, and Image Gallery), referenced by a entity reference. The widget that we are using for the entity reference is an Entity Browser widget, that allows you not only to select existing media (by using a view) but also to upload new images using dropzone.
If a new image is uploaded, a new Media Entity is created and the image is attached to it automatically. If an image is selected, an existing entity will be referenced by the content type Gallery using the entity reference field. All this steps are handled by the Entity Browser module.
Another feature usually expected by clients is the ability to select which part of an image is the important one. You can use the Focal Point module that allows you to specify a focal point to focus and crop the image.
If we take a look to the selection of images done by Thunder, we can see there is a green indicator that shows we choose an image. This is done by custom code. But don’t worry, if you use the same names defined by thunder for the views and fields (as we did), you can borrow the code from media_thunder that adds the magic.
You may want to copy media_thunder/css
, media_thunder/img
and
media_thunder/js
as well.
/**
* Implements hook_preprocess_views_view().
*/
function custom_module_media_preprocess_views_view(&$variables) {
$custom_module_media_browser = [
'image_browser',
'video_browser',
];
if (in_array($variables['view']->id(), $custom_module_media_browser)) {
$variables['view_array']['#attached']['library'][] = 'custom_module_media/entity_browser_view';
}
}
By default you see a lot of fields that are not relevant when you upload the image. Let’s see how we can configure the form to make it easier to use.
What you see in the image is how the media entity form mode is configured. This is the UI that you can use to hide the things you don’t need.
You may want to do the same thing with the display mode of the media entity to indicate what to show once the image is uploaded.
The entity browser allows you to select which display mode use after selecting an image. That is defined in the entity reference widget settings.
But the elements rendered in the Media entity are configured as part of the display mode of of the Media Entity.
And here’s some good news: we are experimenting with the new Layout Builder module, and we are happy to confirm this is working fine within the media ecosystem.
Configuring the thumbnail view mode to show only what you need makes the form really easy to use.
Conclusions
As you can see, there are a good balance between core modules and contributed modules. This is the work of several years of work by dozens of developers around the world.
There is still a lot of things that can be improved and polished. Even more, the recently committed Allow creation of file entities from binary data via REST requests functionality to core and modules like jsonAPI open the door to replace this solution by something more decoupled of Drupal.
The trick to get what you want is to play with the form modes and display modes of each entity involved. Is a bit of try and error but you will gain a lot of understanding of the Drupal basics.
And in the future? Who knows, maybe next versions of Drupal will include this feature ready to use of the box, until then, have fun configuring your own set of building blocks.