diff -u b/core/modules/media/media.libraries.yml b/core/modules/media/media.libraries.yml
--- b/core/modules/media/media.libraries.yml
+++ b/core/modules/media/media.libraries.yml
@@ -12,7 +12,7 @@
dependencies:
- core/drupal.form
-media_file_widget:
+file_widget:
version: VERSION
js:
'js/media_file_widget.js': {}
diff -u b/core/modules/media/src/Plugin/Field/FieldWidget/MediaFileWidget.php b/core/modules/media/src/Plugin/Field/FieldWidget/MediaFileWidget.php
--- b/core/modules/media/src/Plugin/Field/FieldWidget/MediaFileWidget.php
+++ b/core/modules/media/src/Plugin/Field/FieldWidget/MediaFileWidget.php
@@ -15,6 +15,7 @@
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\ElementInfoManagerInterface;
+use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Url;
use Drupal\file\Element\ManagedFile;
use Drupal\file\Entity\File;
@@ -31,7 +32,7 @@
* @FieldWidget(
* id = "media_file",
* label = @Translation("File"),
- * media_handlers = {
+ * media_sources = {
* "file"
* },
* field_types = {
@@ -56,6 +57,13 @@
protected $entityTypeManager;
/**
+ * The renderer.
+ *
+ * @var \Drupal\Core\Render\RendererInterface
+ */
+ protected $renderer;
+
+ /**
* Constructs a MediaFileWidget object.
*
* @param string $plugin_id
@@ -72,11 +80,14 @@
* Any third party settings.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
+ * @param \Drupal\Core\Render\RendererInterface $renderer
+ * The renderer.
*/
- public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, ElementInfoManagerInterface $element_info, EntityTypeManagerInterface $entity_type_manager) {
+ public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, ElementInfoManagerInterface $element_info, EntityTypeManagerInterface $entity_type_manager, RendererInterface $renderer) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
$this->elementInfo = $element_info;
$this->entityTypeManager = $entity_type_manager;
+ $this->renderer = $renderer;
}
/**
@@ -90,7 +101,8 @@
$configuration['settings'],
$configuration['third_party_settings'],
$container->get('element_info'),
- $container->get('entity_type.manager')
+ $container->get('entity_type.manager'),
+ $container->get('renderer')
);
}
@@ -135,21 +147,20 @@
* {@inheritdoc}
*/
public static function isApplicable(FieldDefinitionInterface $field_definition) {
- if (parent::isApplicable($field_definition) && $field_definition->getSetting('target_type') == 'media') {
- /** @var \Drupal\media\Entity\MediaType[] $bundles */
- $allowed_types = MediaType::loadMultiple($field_definition->getSetting('handler_settings')['target_bundles']);
-
- $media_handlers = [];
- $definitions = \Drupal::service('plugin.manager.field.widget')->getDefinitions();
- foreach ($definitions as $definition) {
- if ($definition['class'] == static::class) {
- $media_handlers = $definition['media_handlers'];
- }
- }
+ $settings = $field_definition->getSettings();
+ if (parent::isApplicable($field_definition) && $settings['target_type'] == 'media') {
+ /** @var \Drupal\media\MediaTypeInterface[] $allowed_types */
+ $allowed_types = MediaType::loadMultiple($settings['handler_settings']['target_bundles']);
+
+ $plugin_definition = \Drupal::service('plugin.manager.field.widget')
+ ->getDefinition('media_file');
+
+ // The widget applies if any of the media types that can be referenced by
+ // the field are using the media sources listed in the plugin's
+ // media_sources array.
foreach ($allowed_types as $type) {
- /** @var \Drupal\media\Entity\MediaType $type */
- if (in_array($type->getSource()->getPluginId(), $media_handlers)) {
+ if (in_array($type->get('source'), $plugin_definition['media_sources'])) {
return TRUE;
}
}
@@ -158,22 +169,10 @@
}
/**
- * Override form method.
- *
- * Special handling for updating items from the field state and for
- * providing a ajax wrapper.
- *
- * @param \Drupal\Core\Field\FieldItemListInterface $items
- * The fields items for the widget.
- * @param array $form
- * The widget form elements.
- * @param \Drupal\Core\Form\FormStateInterface $form_state
- * The form_state of the widget form.
- * @param int $get_delta
- * Used to get only a specific delta value of a multiple value field.
+ * {@inheritdoc}
*
- * @return array
- * The basic form structure.
+ * Special handling for updating items from the field state and for providing
+ * an Ajax wrapper.
*/
public function form(FieldItemListInterface $items, array &$form, FormStateInterface $form_state, $get_delta = NULL) {
$field_name = $this->fieldDefinition->getName();
@@ -188,8 +187,8 @@
}
$build = parent::form($items, $form, $form_state);
- // Add a hidden textfield to the form, which is used to pass values
- // from the modal to the widget. This is similar to how the
+ // Add a hidden textfield to the form, which is used to pass values from the
+ // modal to the widget. This is similar to how the
// EntityReferenceAutocompleteWidget stores values.
$build[$field_name . '_media_file_selection'] = [
'#type' => 'textfield',
@@ -199,11 +198,14 @@
'class' => ['visually-hidden'],
],
];
+ // @TODO: Document this element.
$build[$field_name . '_media_file_update_widget'] = [
'#type' => 'submit',
'#name' => $field_name . '-media-file-update-button',
'#value' => $this->t('Add selection'),
- '#submit' => [[static::class, 'addItems']],
+ '#submit' => [
+ [static::class, 'addItems'],
+ ],
'#ajax' => [
'callback' => [static::class, 'updateWidget'],
'wrapper' => $wrapper_id,
@@ -216,42 +218,29 @@
'#limit_validation_errors' => [array_merge($parents, [$field_name])],
];
- // Wrap the widget in a div so that it can be re-loaded via AJAX.
+ // Wrap the widget in a DIV so that it can be re-loaded via AJAX.
$build['#prefix'] = '
';
$build['#suffix'] = '
';
return $build;
}
/**
- * Create a multivalue reference field.
+ * {@inheritdoc}
*
* Special handling for draggable multiple widgets and upload field.
- *
- * @param \Drupal\Core\Field\FieldItemListInterface $items
- * The fields items for the widget.
- * @param array $form
- * The widget form elements.
- * @param \Drupal\Core\Form\FormStateInterface $form_state
- * The form_state of the widget form.
- *
- * @return array
- * The widget element.
*/
protected function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
$field_name = $this->fieldDefinition->getName();
// Determine the number of widgets to display.
$cardinality = $this->fieldDefinition->getFieldStorageDefinition()->getCardinality();
- switch ($cardinality) {
- case FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED:
- $max = count($items);
- $is_multiple = TRUE;
- break;
-
- default:
- $max = $cardinality - 1;
- $is_multiple = ($cardinality > 1);
- break;
+ if ($cardinality === FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
+ $max = count($items);
+ $is_multiple = TRUE;
+ }
+ else {
+ $max = $cardinality - 1;
+ $is_multiple = ($cardinality > 1);
}
$title = $this->fieldDefinition->getLabel();
@@ -294,20 +283,28 @@
}
$empty_single_allowed = ($cardinality == 1 && $delta == 0);
+ // @TODO: Explain why programmed forms cannot be $empty_multiple_allowed.
$empty_multiple_allowed = ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED || $delta < $cardinality) && !$form_state->isProgrammed();
// Add a managed file field for new uploads except when this is a programmed
// multiple form.
if ($empty_single_allowed || $empty_multiple_allowed) {
-
// Fetch the upload validators from the source field.
$upload_validators = [];
- $allowed_types = MediaType::loadMultiple($this->fieldDefinition->getSetting('handler_settings')['target_bundles']);
+
+ $allowed_types = $this->fieldDefinition->getSetting('handler_settings')['target_bundles'];
+ /** @var \Drupal\media\MediaTypeInterface[] $allowed_types */
+ $allowed_types = $this->entityTypeManager
+ ->getStorage('media_type')
+ ->loadMultiple($allowed_types);
+
foreach ($allowed_types as $type) {
- /** @var \Drupal\media\Entity\MediaType $type */
$source_field = $type->getSource()->getSourceFieldDefinition($type);
$source_data_definition = FieldItemDataDefinition::create($source_field);
$file_item = new FileItem($source_data_definition);
+ // @TODO: The upload validation should be smarter and as permissive as
+ // possible, since we don't know which media type will apply to the
+ // uploaded file.
$upload_validators = array_merge($upload_validators, $file_item->getUploadValidators());
}
@@ -324,9 +321,9 @@
'#type' => 'managed_file',
'#required' => $delta == 0 && $this->fieldDefinition->isRequired(),
'#upload_validators' => $upload_validators,
- '#description' => \Drupal::service('renderer')->renderPlain($file_upload_help),
- '#value_callback' => [get_class($this), 'uploadFieldValueCallback'],
- '#process' => array_merge($element_info['#process'], [[get_class($this), 'uploadFieldProcess']]),
+ '#description' => $this->renderer->renderPlain($file_upload_help),
+ '#value_callback' => [static::class, 'uploadFieldValueCallback'],
+ '#process' => array_merge($element_info['#process'], [[static::class, 'uploadFieldProcess']]),
'#progress_indicator' => $this->getSetting('progress_indicator'),
'#extended' => TRUE,
'#element_validate' => $element_info['#element_validate'],
@@ -337,11 +334,11 @@
'#cardinality' => $cardinality,
'#attached' => array_merge_recursive(
$element_info['#attached'],
- ['library' => ['media/media_file_widget']]
+ ['library' => ['media/file_widget']]
),
- '#multiple' => $cardinality != 1 ? TRUE : FALSE,
+ '#multiple' => $cardinality != 1,
];
- if ($cardinality != 1 && $cardinality != -1) {
+ if ($cardinality > 1) {
$elements['upload'][$delta][$field_name . '_media_file_upload']['#element_validate'] = [
[static::class, 'validateMultipleCount'],
];
@@ -357,7 +354,9 @@
$elements['#open'] = TRUE;
$elements['#theme'] = 'media_file_widget_multiple';
$elements['#theme_wrappers'] = ['details'];
- $elements['#process'] = [[get_class($this), 'processMultiple']];
+ $elements['#process'] = [
+ [static::class, 'processMultiple'],
+ ];
$elements['#title'] = $title;
$elements['#description'] = $description;
$elements['#field_name'] = $field_name;
@@ -378,15 +377,15 @@
/** @var \Drupal\Core\Field\EntityReferenceFieldItemListInterface $items */
$referenced_entities = $items->referencedEntities();
if (isset($referenced_entities[$delta])) {
- /** @var \Drupal\media\Entity\Media $media */
+ /** @var \Drupal\media\MediaInterface $media */
$media = $referenced_entities[$delta];
/** @var \Drupal\field\FieldConfigInterface $source_field */
$source_field = $media->getSource()->getSourceFieldDefinition($media->bundle->entity);
- /** @var \Drupal\file\Entity\File $file */
+ /** @var \Drupal\file\FileInterface $file */
$file = $media->get($source_field->getName())->entity;
- // We use a hidden field weith the media id and show a managed file
- // to show the source field value for the media item.
+ // We use a hidden field with the media ID and show a managed file for the
+ // media item's source field value.
$element += [
'#field_name' => $field_name,
// Add media entity values for storage.
@@ -413,7 +412,9 @@
'#remove_delta' => $element['#delta'],
'#attributes' => ['class' => ['remove-button']],
'#validate' => [],
- '#submit' => [[static::class, 'removeItem']],
+ '#submit' => [
+ [static::class, 'removeItem'],
+ ],
'#limit_validation_errors' => [array_merge($form['#parents'], [$field_name])],
'#ajax' => [
'callback' => [static::class, 'updateWidget'],
@@ -539,8 +540,8 @@
array_pop($array_parents);
$previously_uploaded_count = count(Element::children(NestedArray::getValue($form, $array_parents))) - 1;
- $field_storage_definitions = \Drupal::entityManager()->getFieldStorageDefinitions($element['#entity_type']);
- $field_storage = $field_storage_definitions[$element['#field_name']];
+ /** @var FieldStorageDefinitionInterface $field_storage */
+ $field_storage = \Drupal::service('entity_field.manager')->getFieldStorageDefinitions($element['#entity_type'])[$element['#field_name']];
$newly_uploaded_count = count($values['fids']);
$total_uploaded_count = $newly_uploaded_count + $previously_uploaded_count;
if ($total_uploaded_count > $field_storage->getCardinality()) {
@@ -567,7 +568,7 @@
/**
* Process callback for the upload field.
*
- * Change the ajax functionality for the upload button.
+ * Change the Ajax functionality for the upload button.
*
* @param array $element
* The file field element array.
@@ -614,7 +615,7 @@
/**
* Ajax callback for the upload field.
*
- * This ajax callback takes care of the following things:
+ * This callback takes care of the following things:
* - Add commands from ManagedFile::uploadAjaxCallback() to handle
* file uploads.
* - Pass the file IDs to a modal.