diff --git a/media_entity.module b/media_entity.module index d54f773..8d4cc02 100644 --- a/media_entity.module +++ b/media_entity.module @@ -6,6 +6,8 @@ */ use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\field\Entity\FieldConfig; +use Drupal\media_entity\Entity\MediaBundle; /** * Implements hook_help(). @@ -82,3 +84,36 @@ function media_entity_copy_icons($source, $destination) { } } } + +/** + * Implements hook_ENTITY_TYPE_insert(). + */ +function media_entity_media_bundle_insert(MediaBundle $media_bundle) { + // When creating new bundles, add also a source field, if configured to do so. + if (!$media_bundle->isSyncing() && empty($media_bundle->getTypeConfiguration()['source_field']) && $media_bundle->getCreateSourceField()) { + $media_type_manager = \Drupal::service('plugin.manager.media_entity.type'); + $instance = $media_type_manager->createInstance($media_bundle->getType()->getPluginId(), $media_bundle->getTypeConfiguration()); + $default_field = $instance->getDefaultSourceField(); + if (!empty($default_field['storage'])) { + // Save the field storage and create the instance. + $default_field['storage']->save(); + FieldConfig::create([ + 'entity_type' => 'media', + 'field_name' => $default_field['field_name'], + 'label' => $default_field['label'], + 'required' => TRUE, + 'bundle' => $media_bundle->id(), + ])->save(); + // Make the field visible on the form display. + $form_display = entity_get_form_display('media', $media_bundle->id(), 'default'); + $form_display->setComponent($default_field['field_name'], [ + 'type' => $default_field['field_widget'], + ])->save(); + // Make the field visible on the media entity itself. + $dispaly = entity_get_display('media', $media_bundle->id(), 'default'); + $dispaly->setComponent($default_field['field_name'], [ + 'type' => $default_field['field_formatter'], + ])->save(); + } + } +} diff --git a/src/Entity/MediaBundle.php b/src/Entity/MediaBundle.php index 8833f82..5227d50 100644 --- a/src/Entity/MediaBundle.php +++ b/src/Entity/MediaBundle.php @@ -2,8 +2,8 @@ namespace Drupal\media_entity\Entity; -use Drupal\Core\Entity\EntityDescriptionInterface; use Drupal\Core\Config\Entity\ConfigEntityBundleBase; +use Drupal\Core\Entity\EntityDescriptionInterface; use Drupal\Core\Entity\EntityWithPluginCollectionInterface; use Drupal\Core\Plugin\DefaultSingleLazyPluginCollection; use Drupal\media_entity\MediaBundleInterface; @@ -44,6 +44,7 @@ use Drupal\media_entity\MediaInterface; * "type_configuration", * "field_map", * "status", + * "create_source_field", * }, * links = { * "add-form" = "/admin/structure/media/add", @@ -121,11 +122,18 @@ class MediaBundle extends ConfigEntityBundleBase implements MediaBundleInterface /** * Default status of this media bundle. * - * @var array + * @var bool */ public $status = TRUE; /** + * A flag indicating if we should create a source field upon save. + * + * @var bool + */ + public $create_source_field = TRUE; + + /** * {@inheritdoc} */ public function id() { @@ -230,6 +238,13 @@ class MediaBundle extends ConfigEntityBundleBase implements MediaBundleInterface /** * {@inheritdoc} */ + public function getCreateSourceField() { + return $this->create_source_field; + } + + /** + * {@inheritdoc} + */ public function shouldCreateNewRevision() { return $this->new_revision; } diff --git a/src/MediaBundleForm.php b/src/MediaBundleForm.php index 36365f3..d50d22d 100644 --- a/src/MediaBundleForm.php +++ b/src/MediaBundleForm.php @@ -170,6 +170,22 @@ class MediaBundleForm extends EntityForm { $form['type_configuration'][$plugin->getPluginId()] += $instance->buildConfigurationForm([], $form_state); } + // Add a checkbox to allow the field being created automattically on save. + if (!empty($form['type_configuration'][$plugin->getPluginId()]['source_field']) && empty($plugin_configuration['source_field'])) { + $has_source_field_options = !empty($form['type_configuration'][$plugin->getPluginId()]['source_field']['#options']); + $form['type_configuration'][$plugin->getPluginId()]['create_source_field'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Create source field automatically when saving this form.'), + '#description' => $this->t('If checked, a default field will be created and used as a source field. You can change this setting later on.'), + '#default_value' => $bundle->getCreateSourceField(), + // Try to place this checkbox close to the sourcefield select element. + '#weight' => !empty($form['type_configuration'][$plugin->getPluginId()]['source_field']['#weight']) ? $form['type_configuration'][$plugin->getPluginId()]['source_field']['#weight'] + 0.01 : -2, + '#access' => !$has_source_field_options, + ]; + // If there are no options, the dropdown is meaningless. + $form['type_configuration'][$plugin->getPluginId()]['source_field']['#access'] = $has_source_field_options; + } + // Field mapping configuration. $form['field_mapping'] = [ '#type' => 'fieldset', @@ -313,6 +329,14 @@ class MediaBundleForm extends EntityForm { $plugin_configuration = !empty($this->configurableInstances[$plugin]['plugin_config']) ? $this->configurableInstances[$plugin]['plugin_config'] : []; $instance = $this->mediaTypeManager->createInstance($plugin, $plugin_configuration); $instance->submitConfigurationForm($form, $form_state); + + // Save the flag to auto-create a source field. + $this->entity->create_source_field = $form_state->getValue([ + 'type_configuration', + $plugin, + 'create_source_field', + ]); + } /** diff --git a/src/MediaBundleInterface.php b/src/MediaBundleInterface.php index 97e02f9..6bc850a 100644 --- a/src/MediaBundleInterface.php +++ b/src/MediaBundleInterface.php @@ -89,6 +89,14 @@ interface MediaBundleInterface extends ConfigEntityInterface, RevisionableEntity public function getStatus(); /** + * Returns the flag that indicate if a source field should be auto-created. + * + * @return bool + * TRUE if the field should be created when saving the bundle. + */ + public function getCreateSourceField(); + + /** * Sets whether a new revision should be created by default. * * @param bool $new_revision diff --git a/src/MediaTypeBase.php b/src/MediaTypeBase.php index a472e7d..0041851 100644 --- a/src/MediaTypeBase.php +++ b/src/MediaTypeBase.php @@ -3,14 +3,14 @@ namespace Drupal\media_entity; use Drupal\Component\Plugin\PluginBase; +use Drupal\Component\Utility\NestedArray; use Drupal\Core\Config\Config; use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\Component\Utility\NestedArray; +use Drupal\Core\StringTranslation\StringTranslationTrait; use Symfony\Component\DependencyInjection\ContainerInterface; -use Drupal\Core\Form\FormStateInterface; /** * Base implementation of media type plugin. @@ -158,4 +158,11 @@ abstract class MediaTypeBase extends PluginBase implements MediaTypeInterface, C return 'media:' . $media->bundle() . ':' . $media->uuid(); } + /** + * {@inheritdoc} + */ + public function getDefaultSourceField() { + return []; + } + } diff --git a/src/MediaTypeInterface.php b/src/MediaTypeInterface.php index 2a171c2..9e84257 100644 --- a/src/MediaTypeInterface.php +++ b/src/MediaTypeInterface.php @@ -2,8 +2,8 @@ namespace Drupal\media_entity; -use Drupal\Component\Plugin\PluginInspectionInterface; use Drupal\Component\Plugin\ConfigurablePluginInterface; +use Drupal\Component\Plugin\PluginInspectionInterface; use Drupal\Core\Plugin\PluginFormInterface; /** @@ -85,4 +85,26 @@ interface MediaTypeInterface extends PluginInspectionInterface, ConfigurablePlug */ public function getDefaultName(MediaInterface $media); + /** + * Provide a default source field. + * + * Plugins defining media bundles are suggested to implement this method and + * create a field that will be used as default source field, on bundle + * creation. Make sure this method returns unsaved entities, once these are + * only going to be saved and used if the user marked the option to use the + * default field provided. + * + * @return array + * An associative array containing the following keys: + * 'config' => \Drupal\field\Entity\FieldStorageConfig A config entity for + * this field storage. + * 'field_name' => (string) The name to be used for the field instance. + * 'label' => (string) The label to be used for the field instance. + * 'field_widget' => (string) The id of the widget to use. + * 'field_formatter' => (string) The id of the formatter to use. + * Note that the storage config entity need to be returned unsaved, and the + * main form will be responsible for saving them. + */ + public function getDefaultSourceField(); + }