Video Embed Field - ResponsiveThumbnail formatter

By k, 13 April, 2020

Authored on

Mon, 04/13/2020 - 20:43
Image
roses

There is a module named Video Embed Field which allows you to embed videos from different providers and show their thumbnail previews. At time of writing this article the media module is available on core then you can do the same by using a core' solution (Details: https://www.drupal.org/docs/8/core/modules/media/creating-and-configuring-media-types).

This module allows to configure a "Thumbnail" as a formatter within the "manage display" form of a content type using a video embed field, where it possibles to select an image style to display the thumbnail of the video. Unfortunately, it is not possible to select a Responsive image styles (included in core).

To solve this particular issue on an existing running site then I was asked to create a new custom formatter to expose the thumbnail by using a responsive image style. So I would like to share how I was able to extend from `ResponsiveImageFormatter` class in order to create this integration.

Basically I mixed the given `Thumbnail` formatter from video embed field module within the power of the `ResponsiveImageFormatter` from the core modue named responsive image, by coding as follows:

<?php

namespace Drupal\keboca\Plugin\Field\FieldFormatter;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\responsive_image\Plugin\Field\FieldFormatter\ResponsiveImageFormatter;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Plugin implementation of the 'Responsive Thumbnail' formatter.
 *
 * @FieldFormatter(
 *   id = "keboca_video_embed_responsive_thumbnail",
 *   label = @Translation("Responsive Thumbnail"),
 *   field_types = {
 *     "video_embed_field"
 *   }
 * )
 */
class VideoEmbedResponsiveThumbnail extends ResponsiveImageFormatter {

  /**
   * The embed provider plugin manager.
   *
   * @var \Drupal\video_embed_field\ProviderManagerInterface
   */
  protected $providerManager;

  /**
   * Setter method to inject provider manager service.
   *
   * @param \Drupal\video_embed_field\ProviderManagerInterface $providerManager
   */
  public function setProviderManager(\Drupal\video_embed_field\ProviderManagerInterface $providerManager): void {
    $this->providerManager = $providerManager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    /** @var static $plugin */
    $plugin = new static(
      $plugin_id,
      $plugin_definition,
      $configuration['field_definition'],
      $configuration['settings'],
      $configuration['label'],
      $configuration['view_mode'],
      $configuration['third_party_settings'],
      $container->get('entity_type.manager')
        ->getStorage('responsive_image_style'),
      $container->get('entity_type.manager')->getStorage('image_style'),
      $container->get('link_generator'),
      $container->get('current_user')
    );

    // Prepare current plugin by injecting extra required services.
    $plugin->setProviderManager(
      $container->get('video_embed_field.provider_manager')
    );
    return $plugin;
  }

  /**
   * {@inheritdoc}
   */
  public function prepareView(array $entities_items) {
    /** @var \Drupal\Core\Field\FieldItemList[] $entities_items */
    foreach ($entities_items as $items) {
      /** @var \Drupal\Core\Field\FieldItemList $entities_items $item */
      foreach ($items as $item) {
        /** @var \Drupal\video_embed_field\ProviderPluginInterface $provider */
        if ($provider = $this->providerManager->loadProviderFromInput($item->value)) {
          // Be sure the thumbnail will be available later on.
          $provider->downloadThumbnail();
        }
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $element = [];
    foreach ($items as $delta => $item) {
      /** @var \Drupal\video_embed_field\ProviderPluginInterface $provider */
      $provider = $this->providerManager->loadProviderFromInput($item->value);

      if (!$provider) {
        $element[$delta] = ['#theme' => 'video_embed_field_missing_provider'];
      }
      else {
        $element[$delta] = [
          '#theme' => 'responsive_image',
          '#responsive_image_style_id' => $this->getSetting('responsive_image_style'),
          '#uri' => $provider->getLocalThumbnailUri(),
          '#alt' => $provider->getName(),
          '#title' => $provider->getName(),
        ];
      }
    }
    return $element;
  }

}

I really hope the code is self explanatory where I overwrote the `create` method to inject an extra service plus It is downloading the thumbnail while prepare the view to be render to finally render the current thumbnail by using the selected responsive image style.

Hope it helps you at some point!

Happy coding!

 

--

Disclaimer

I'm aware there is an existing ticket where it's possible to apply a patch to enable this feature however it seems there are some issues to be addressed,

commented 11 December 2018 at 12:07 Status:Needs review» Needs work Tried out this patch, and upon installation I had issues accessing the field formatter with an error: "The "responsive_image_style" entity type does not exist." we probably need to check if the module is enabled and installed. I'll see if I can fix the patch.https://www.drupal.org/project/video_embed_field/issues/2905584#comment-12890236

Because some complexity with the project where I was working with it then it wasn't possible to apply the patch that was the reason I had to create a custom formatter.

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.