MediaBridge.php in Open Social 10.2.x
File
modules/custom/social_graphql/src/Plugin/GraphQL/DataProducer/MediaBridge.phpView source
<?php
namespace Drupal\social_graphql\Plugin\GraphQL\DataProducer;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\file\Plugin\Field\FieldType\FileItem;
use Drupal\graphql\GraphQL\Buffers\EntityBuffer;
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
use Drupal\media\MediaInterface;
use GraphQL\Deferred;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* 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.
*
* @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")
* )
* }
* )
*/
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}'.");
}
}
}
Classes
Name | Description |
---|---|
MediaBridge | The media bridge provides a way to get data from File fields and Media. |