You are here

abstract class MediaSourceBase in Drupal 10

Same name and namespace in other branches
  1. 8 core/modules/media/src/MediaSourceBase.php \Drupal\media\MediaSourceBase
  2. 9 core/modules/media/src/MediaSourceBase.php \Drupal\media\MediaSourceBase

Base implementation of media source plugin.

Hierarchy

Expanded class hierarchy of MediaSourceBase

3 files declare their use of MediaSourceBase
File.php in core/modules/media/src/Plugin/media/Source/File.php
OEmbed.php in core/modules/media/src/Plugin/media/Source/OEmbed.php
Test.php in core/modules/media/tests/modules/media_test_source/src/Plugin/media/Source/Test.php

File

core/modules/media/src/MediaSourceBase.php, line 20

Namespace

Drupal\media
View source
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() {

    // 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 = 'field_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,
    ]);
  }

}

Members