You are here

class MediaBridge in Open Social 10.2.x

Same name and namespace in other branches
  1. 10.3.x modules/custom/social_graphql/src/Plugin/GraphQL/DataProducer/MediaBridge.php \Drupal\social_graphql\Plugin\GraphQL\DataProducer\MediaBridge
  2. 10.0.x modules/custom/social_graphql/src/Plugin/GraphQL/DataProducer/MediaBridge.php \Drupal\social_graphql\Plugin\GraphQL\DataProducer\MediaBridge
  3. 10.1.x modules/custom/social_graphql/src/Plugin/GraphQL/DataProducer/MediaBridge.php \Drupal\social_graphql\Plugin\GraphQL\DataProducer\MediaBridge

The media bridge provides a way to get data from File fields and Media.

It acts similar to the property_path data producers by picking specific data off an entity. However, it accepts both a \Drupal\media\Plugin\media\Source\File implementation as well as a \Drupal\file\Plugin\Field\FieldType\FileItem instance.

This allows the same resolver to be used regardless of implementation which should make it easier for Open Social to switch out to a Media based implementation behind the scenes.

@todo This solution is implemented to allow relatively transparent resolving of Media related typs. It serves as a way to allow us to move towards the Media library while being stuck with traditional File fields. This is not necessarily an elegant solution. It should not be used as examples for other data producers (it tries to do do too much). We should strive to remove it as soon as we have transitioned fully to the Media module.

Plugin annotation


@DataProducer(
  id = "media_bridge",
  name = @Translation("Media bridge"),
  description = @Translation("Provides data about image fields and media sources."),
  produces = @ContextDefinition("mixed",
    label = @Translation("Value")
  ),
  consumes = {
    "value" = @ContextDefinition("mixed",
      label = @Translation("Value (Media source or FileItem)")
    ),
    "field" = @ContextDefinition("string",
      label = @Translation("Field name")
    )
  }
)

Hierarchy

Expanded class hierarchy of MediaBridge

File

modules/custom/social_graphql/src/Plugin/GraphQL/DataProducer/MediaBridge.php, line 50

Namespace

Drupal\social_graphql\Plugin\GraphQL\DataProducer
View source
class MediaBridge extends DataProducerPluginBase implements ContainerFactoryPluginInterface {

  /**
   * The entity buffer service.
   *
   * @var \Drupal\graphql\GraphQL\Buffers\EntityBuffer
   */
  protected $entityBuffer;

  /**
   * {@inheritdoc}
   *
   * @codeCoverageIgnore
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($configuration, $plugin_id, $plugin_definition, $container
      ->get('graphql.buffer.entity'));
  }

  /**
   * MediaBridge constructor.
   *
   * @param array $configuration
   *   The plugin configuration array.
   * @param string $pluginId
   *   The plugin id.
   * @param array $pluginDefinition
   *   The plugin definition array.
   * @param \Drupal\graphql\GraphQL\Buffers\EntityBuffer $entityBuffer
   *   The entity buffer service.
   *
   * @codeCoverageIgnore
   */
  public function __construct(array $configuration, $pluginId, array $pluginDefinition, EntityBuffer $entityBuffer) {
    parent::__construct($configuration, $pluginId, $pluginDefinition);
    $this->entityBuffer = $entityBuffer;
  }

  /**
   * Resolve the value for this data producer.
   *
   * @param mixed $value
   *   The media source or file item.
   * @param string $field
   *   The name of the data to return.
   *
   * @return \GraphQL\Deferred|null
   *   The resolved value for a File Item.
   */
  public function resolve($value, $field) {

    // To make consuming fields easier we convert field item lists to field
    // items.
    if ($value instanceof FieldItemListInterface) {
      $value = $value
        ->first();
    }
    if ($value instanceof FileItem) {
      return $this
        ->resolveFileItem($value, $field);
    }
    if ($value instanceof MediaInterface) {
      return $this
        ->resolveMediaEntity($value, $field);
    }
    throw new \RuntimeException("MediaBridge data producer called with unsupported input type. Must be FileItem field instance or Media entity.");
  }

  /**
   * Resolve field for FileItem.
   *
   * @param \Drupal\file\Plugin\Field\FieldType\FileItem $file
   *   The media source or file item.
   * @param string $field
   *   The name of the data to return.
   *
   * @return mixed
   *   The resolved value for a File Item.
   */
  protected function resolveFileItem(FileItem $file, $field) {
    switch ($field) {
      case 'id':
        if ($file
          ->isEmpty()) {
          return NULL;
        }
        $entity_id = $file
          ->get('target_id')
          ->getValue();
        $target_type = $file
          ->getFieldDefinition()
          ->getSetting('target_type');
        $resolver = $this->entityBuffer
          ->add($target_type, $entity_id);
        return new Deferred(function () use ($resolver) {

          /** @var \Drupal\file\Entity\File $file_entity */
          $file_entity = $resolver();
          return $file_entity
            ->uuid();
        });
      case 'url':
        if ($file
          ->isEmpty()) {
          return NULL;
        }
        $entity_id = $file
          ->get('target_id')
          ->getValue();
        $target_type = $file
          ->getFieldDefinition()
          ->getSetting('target_type');
        $resolver = $this->entityBuffer
          ->add($target_type, $entity_id);
        return new Deferred(function () use ($resolver) {

          /** @var \Drupal\file\Entity\File $file_entity */
          $file_entity = $resolver();
          return $file_entity
            ->createFileUrl(FALSE);
        });
      case 'title':
        return $file
          ->get('title')
          ->getString();
      case 'alt':
        return $file
          ->get('alt')
          ->getString();
      default:
        throw new \RuntimeException("Unsupported field for FileItem: '{$field}'.");
    }
  }

  /**
   * Resolve field for media entity.
   *
   * @param \Drupal\media\MediaInterface $value
   *   The media source or file item.
   * @param string $field
   *   The name of the data to return.
   *
   * @return mixed
   *   The resolved value for a Media entity.
   *
   * @todo https://www.drupal.org/project/social/issues/3191642
   */
  protected function resolveMediaEntity(MediaInterface $value, $field) {
    switch ($field) {
      case 'id':
        return $value
          ->uuid();
      case 'url':
      case 'title':
      case 'alt':

        // Fetch the source field from the media entity which allows us to treat
        // it like a regular file item.
        $source_field_name = $value
          ->getSource()
          ->getConfiguration()['source_field'];
        $source_field = $value->{$source_field_name}
          ->first();
        return $this
          ->resolveFileItem($source_field, $field);
      default:
        throw new \RuntimeException("Unsupported field for Media entity: '{$field}'.");
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
MediaBridge::$entityBuffer protected property The entity buffer service.
MediaBridge::create public static function @codeCoverageIgnore Overrides ContainerFactoryPluginInterface::create
MediaBridge::resolve public function Resolve the value for this data producer.
MediaBridge::resolveFileItem protected function Resolve field for FileItem.
MediaBridge::resolveMediaEntity protected function Resolve field for media entity.
MediaBridge::__construct public function MediaBridge constructor.