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 isset($fields[$field]) ? $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 isset($fields[$field]) ? $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.'); } /** @var \Drupal\Core\Field\FieldItemInterface $field_item */ $field_item = $media->get($source_field)->first(); return $field_item->{$field_item->mainPropertyName()}; } /** * {@inheritdoc} */ public function prepareViewDisplay(MediaTypeInterface $type, EntityViewDisplayInterface $display) { $display->setComponent($this->getSourceFieldDefinition($type)->getName()); } /** * {@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, ]); } }