369 lines
12 KiB
PHP
369 lines
12 KiB
PHP
<?php
|
|
|
|
namespace Drupal\media;
|
|
|
|
use Drupal\Component\Utility\NestedArray;
|
|
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
|
|
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
|
|
use Drupal\Core\Entity\EntityFieldManagerInterface;
|
|
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
|
use Drupal\Core\Field\FieldTypePluginManagerInterface;
|
|
use Drupal\Core\Form\FormStateInterface;
|
|
use Drupal\Core\Config\ConfigFactoryInterface;
|
|
use Drupal\Core\Plugin\PluginBase;
|
|
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
|
|
|
/**
|
|
* Base implementation of media source plugin.
|
|
*/
|
|
abstract class MediaSourceBase extends PluginBase implements MediaSourceInterface, ContainerFactoryPluginInterface {
|
|
|
|
/**
|
|
* Plugin label.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $label;
|
|
|
|
/**
|
|
* The entity type manager service.
|
|
*
|
|
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
|
*/
|
|
protected $entityTypeManager;
|
|
|
|
/**
|
|
* The entity field manager service.
|
|
*
|
|
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
|
|
*/
|
|
protected $entityFieldManager;
|
|
|
|
/**
|
|
* The field type plugin manager service.
|
|
*
|
|
* @var \Drupal\Core\Field\FieldTypePluginManagerInterface
|
|
*/
|
|
protected $fieldTypeManager;
|
|
|
|
/**
|
|
* The config factory service.
|
|
*
|
|
* @var \Drupal\Core\Config\ConfigFactoryInterface
|
|
*/
|
|
protected $configFactory;
|
|
|
|
/**
|
|
* Constructs a new class instance.
|
|
*
|
|
* @param array $configuration
|
|
* A configuration array containing information about the plugin instance.
|
|
* @param string $plugin_id
|
|
* The plugin ID for the plugin instance.
|
|
* @param mixed $plugin_definition
|
|
* The plugin implementation definition.
|
|
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
|
* Entity type manager service.
|
|
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
|
|
* Entity field manager service.
|
|
* @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager
|
|
* The field type plugin manager service.
|
|
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
|
* The config factory service.
|
|
*/
|
|
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, FieldTypePluginManagerInterface $field_type_manager, ConfigFactoryInterface $config_factory) {
|
|
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
|
$this->entityTypeManager = $entity_type_manager;
|
|
$this->entityFieldManager = $entity_field_manager;
|
|
$this->fieldTypeManager = $field_type_manager;
|
|
$this->configFactory = $config_factory;
|
|
|
|
// Add the default configuration of the media source to the plugin.
|
|
$this->setConfiguration($configuration);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
|
return new static(
|
|
$configuration,
|
|
$plugin_id,
|
|
$plugin_definition,
|
|
$container->get('entity_type.manager'),
|
|
$container->get('entity_field.manager'),
|
|
$container->get('plugin.manager.field.field_type'),
|
|
$container->get('config.factory')
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function setConfiguration(array $configuration) {
|
|
$this->configuration = NestedArray::mergeDeep(
|
|
$this->defaultConfiguration(),
|
|
$configuration
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function getConfiguration() {
|
|
return $this->configuration;
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function defaultConfiguration() {
|
|
return [
|
|
'source_field' => '',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function getMetadata(MediaInterface $media, $attribute_name) {
|
|
switch ($attribute_name) {
|
|
case 'default_name':
|
|
return 'media:' . $media->bundle() . ':' . $media->uuid();
|
|
|
|
case 'thumbnail_uri':
|
|
$default_thumbnail_filename = $this->pluginDefinition['default_thumbnail_filename'];
|
|
return $this->configFactory->get('media.settings')->get('icon_base_uri') . '/' . $default_thumbnail_filename;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function calculateDependencies() {
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* Get the source field options for the media type form.
|
|
*
|
|
* This returns all fields related to media entities, filtered by the allowed
|
|
* field types in the media source annotation.
|
|
*
|
|
* @return string[]
|
|
* A list of source field options for the media type form.
|
|
*/
|
|
protected function getSourceFieldOptions() {
|
|
// If there are existing fields to choose from, allow the user to reuse one.
|
|
$options = [];
|
|
foreach ($this->entityFieldManager->getFieldStorageDefinitions('media') as $field_name => $field) {
|
|
$allowed_type = in_array($field->getType(), $this->pluginDefinition['allowed_field_types'], TRUE);
|
|
if ($allowed_type && !$field->isBaseField()) {
|
|
$options[$field_name] = $field->getLabel();
|
|
}
|
|
}
|
|
return $options;
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
|
$options = $this->getSourceFieldOptions();
|
|
$form['source_field'] = [
|
|
'#type' => 'select',
|
|
'#title' => $this->t('Field with source information'),
|
|
'#default_value' => $this->configuration['source_field'],
|
|
'#empty_option' => $this->t('- Create -'),
|
|
'#options' => $options,
|
|
'#description' => $this->t('Select the field that will store essential information about the media item. If "Create" is selected a new field will be automatically created.'),
|
|
];
|
|
|
|
if (!$options && $form_state->get('operation') === 'add') {
|
|
$form['source_field']['#access'] = FALSE;
|
|
$field_definition = $this->fieldTypeManager->getDefinition(reset($this->pluginDefinition['allowed_field_types']));
|
|
$form['source_field_message'] = [
|
|
'#markup' => $this->t('%field_type field will be automatically created on this type to store the essential information about the media item.', [
|
|
'%field_type' => $field_definition['label'],
|
|
]),
|
|
];
|
|
}
|
|
elseif ($form_state->get('operation') === 'edit') {
|
|
$form['source_field']['#access'] = FALSE;
|
|
$fields = $this->entityFieldManager->getFieldDefinitions('media', $form_state->get('type')->id());
|
|
$form['source_field_message'] = [
|
|
'#markup' => $this->t('%field_name field is used to store the essential information about the media item.', [
|
|
'%field_name' => $fields[$this->configuration['source_field']]->getLabel(),
|
|
]),
|
|
];
|
|
}
|
|
|
|
return $form;
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
|
|
foreach (array_intersect_key($form_state->getValues(), $this->configuration) as $config_key => $config_value) {
|
|
$this->configuration[$config_key] = $config_value;
|
|
}
|
|
|
|
// If no source field is explicitly set, create it now.
|
|
if (empty($this->configuration['source_field'])) {
|
|
$field_storage = $this->createSourceFieldStorage();
|
|
$field_storage->save();
|
|
$this->configuration['source_field'] = $field_storage->getName();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates the source field storage definition.
|
|
*
|
|
* By default, the first field type listed in the plugin definition's
|
|
* allowed_field_types array will be the generated field's type.
|
|
*
|
|
* @return \Drupal\field\FieldStorageConfigInterface
|
|
* The unsaved field storage definition.
|
|
*/
|
|
protected function createSourceFieldStorage() {
|
|
return $this->entityTypeManager
|
|
->getStorage('field_storage_config')
|
|
->create([
|
|
'entity_type' => 'media',
|
|
'field_name' => $this->getSourceFieldName(),
|
|
'type' => reset($this->pluginDefinition['allowed_field_types']),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Returns the source field storage definition.
|
|
*
|
|
* @return \Drupal\Core\Field\FieldStorageDefinitionInterface|null
|
|
* The field storage definition or NULL if it doesn't exists.
|
|
*/
|
|
protected function getSourceFieldStorage() {
|
|
// Nothing to do if no source field is configured yet.
|
|
$field = $this->configuration['source_field'];
|
|
if ($field) {
|
|
// Even if we do know the name of the source field, there's no
|
|
// guarantee that it exists.
|
|
$fields = $this->entityFieldManager->getFieldStorageDefinitions('media');
|
|
return $fields[$field] ?? NULL;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function getSourceFieldDefinition(MediaTypeInterface $type) {
|
|
// Nothing to do if no source field is configured yet.
|
|
$field = $this->configuration['source_field'];
|
|
if ($field) {
|
|
// Even if we do know the name of the source field, there is no
|
|
// guarantee that it already exists.
|
|
$fields = $this->entityFieldManager->getFieldDefinitions('media', $type->id());
|
|
return $fields[$field] ?? NULL;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function createSourceField(MediaTypeInterface $type) {
|
|
$storage = $this->getSourceFieldStorage() ?: $this->createSourceFieldStorage();
|
|
return $this->entityTypeManager
|
|
->getStorage('field_config')
|
|
->create([
|
|
'field_storage' => $storage,
|
|
'bundle' => $type->id(),
|
|
'label' => $this->pluginDefinition['label'],
|
|
'required' => TRUE,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Determine the name of the source field.
|
|
*
|
|
* @return string
|
|
* The source field name. If one is already stored in configuration, it is
|
|
* returned. Otherwise, a new, unused one is generated.
|
|
*/
|
|
protected function getSourceFieldName() {
|
|
// If the Field UI module is installed, and has a specific prefix
|
|
// configured, use that. Otherwise, just default to using 'field_' as
|
|
// a prefix, which is the default that Field UI ships with.
|
|
$prefix = $this->configFactory->get('field_ui.settings')
|
|
->get('field_prefix') ?? 'field_';
|
|
// Some media sources are using a deriver, so their plugin IDs may contain
|
|
// a separator (usually ':') which is not allowed in field names.
|
|
$base_id = $prefix . 'media_' . str_replace(static::DERIVATIVE_SEPARATOR, '_', $this->getPluginId());
|
|
$tries = 0;
|
|
$storage = $this->entityTypeManager->getStorage('field_storage_config');
|
|
|
|
// Iterate at least once, until no field with the generated ID is found.
|
|
do {
|
|
$id = $base_id;
|
|
// If we've tried before, increment and append the suffix.
|
|
if ($tries) {
|
|
$id .= '_' . $tries;
|
|
}
|
|
$field = $storage->load('media.' . $id);
|
|
$tries++;
|
|
} while ($field);
|
|
|
|
return $id;
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function getSourceFieldValue(MediaInterface $media) {
|
|
$source_field = $this->configuration['source_field'];
|
|
if (empty($source_field)) {
|
|
throw new \RuntimeException('Source field for media source is not defined.');
|
|
}
|
|
|
|
$items = $media->get($source_field);
|
|
if ($items->isEmpty()) {
|
|
return NULL;
|
|
}
|
|
|
|
$field_item = $items->first();
|
|
return $field_item->{$field_item->mainPropertyName()};
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function prepareViewDisplay(MediaTypeInterface $type, EntityViewDisplayInterface $display) {
|
|
$display->setComponent($this->getSourceFieldDefinition($type)->getName(), [
|
|
'label' => 'visually_hidden',
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function prepareFormDisplay(MediaTypeInterface $type, EntityFormDisplayInterface $display) {
|
|
// Make sure the source field is placed just after the "name" basefield.
|
|
$name_component = $display->getComponent('name');
|
|
$source_field_weight = ($name_component && isset($name_component['weight'])) ? $name_component['weight'] + 5 : -50;
|
|
$display->setComponent($this->getSourceFieldDefinition($type)->getName(), [
|
|
'weight' => $source_field_weight,
|
|
]);
|
|
}
|
|
|
|
}
|