class FileUploadForm
Same name in other branches
- 9 core/modules/media_library/src/Form/FileUploadForm.php \Drupal\media_library\Form\FileUploadForm
- 8.9.x core/modules/media_library/src/Form/FileUploadForm.php \Drupal\media_library\Form\FileUploadForm
- 11.x core/modules/media_library/src/Form/FileUploadForm.php \Drupal\media_library\Form\FileUploadForm
Creates a form to create media entities from uploaded files.
@internal Form classes are internal.
Hierarchy
- class \Drupal\Core\Form\FormBase implements \Drupal\Core\Form\FormInterface, \Drupal\Core\DependencyInjection\ContainerInjectionInterface uses \Drupal\Core\DependencyInjection\DependencySerializationTrait, \Drupal\Core\Logger\LoggerChannelTrait, \Drupal\Core\Messenger\MessengerTrait, \Drupal\Core\Routing\RedirectDestinationTrait, \Drupal\Core\StringTranslation\StringTranslationTrait
- class \Drupal\media_library\Form\AddFormBase extends \Drupal\Core\Form\FormBase implements \Drupal\Core\Form\BaseFormIdInterface, \Drupal\Core\Security\TrustedCallbackInterface
- class \Drupal\media_library\Form\FileUploadForm extends \Drupal\media_library\Form\AddFormBase
- class \Drupal\media_library\Form\AddFormBase extends \Drupal\Core\Form\FormBase implements \Drupal\Core\Form\BaseFormIdInterface, \Drupal\Core\Security\TrustedCallbackInterface
Expanded class hierarchy of FileUploadForm
2 files declare their use of FileUploadForm
- MediaLibraryAddFormTest.php in core/
modules/ media_library/ tests/ src/ Kernel/ MediaLibraryAddFormTest.php - media_library.module in core/
modules/ media_library/ media_library.module - Contains hook implementations for the media_library module.
File
-
core/
modules/ media_library/ src/ Form/ FileUploadForm.php, line 33
Namespace
Drupal\media_library\FormView source
class FileUploadForm extends AddFormBase {
/**
* The element info manager.
*
* @var \Drupal\Core\Render\ElementInfoManagerInterface
*/
protected $elementInfo;
/**
* The renderer service.
*
* @var \Drupal\Core\Render\ElementInfoManagerInterface
*/
protected $renderer;
/**
* The file system service.
*
* @var \Drupal\Core\File\FileSystemInterface
*/
protected $fileSystem;
/**
* The file usage service.
*
* @var \Drupal\file\FileUsage\FileUsageInterface
*/
protected $fileUsage;
/**
* The file repository service.
*
* @var \Drupal\file\FileRepositoryInterface
*/
protected $fileRepository;
/**
* Constructs a new FileUploadForm.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\media_library\MediaLibraryUiBuilder $library_ui_builder
* The media library UI builder.
* @param \Drupal\Core\Render\ElementInfoManagerInterface $element_info
* The element info manager.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer service.
* @param \Drupal\Core\File\FileSystemInterface $file_system
* The file system service.
* @param \Drupal\media_library\OpenerResolverInterface $opener_resolver
* The opener resolver.
* @param \Drupal\file\FileUsage\FileUsageInterface $file_usage
* The file usage service.
* @param \Drupal\file\FileRepositoryInterface $file_repository
* The file repository service.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, MediaLibraryUiBuilder $library_ui_builder, ElementInfoManagerInterface $element_info, RendererInterface $renderer, FileSystemInterface $file_system, OpenerResolverInterface $opener_resolver, FileUsageInterface $file_usage, FileRepositoryInterface $file_repository) {
parent::__construct($entity_type_manager, $library_ui_builder, $opener_resolver);
$this->elementInfo = $element_info;
$this->renderer = $renderer;
$this->fileSystem = $file_system;
$this->fileUsage = $file_usage;
$this->fileRepository = $file_repository;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('entity_type.manager'), $container->get('media_library.ui_builder'), $container->get('element_info'), $container->get('renderer'), $container->get('file_system'), $container->get('media_library.opener_resolver'), $container->get('file.usage'), $container->get('file.repository'));
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return $this->getBaseFormId() . '_upload';
}
/**
* {@inheritdoc}
*/
protected function getMediaType(FormStateInterface $form_state) {
if ($this->mediaType) {
return $this->mediaType;
}
$media_type = parent::getMediaType($form_state);
// The file upload form only supports media types which use a file field as
// a source field.
$field_definition = $media_type->getSource()
->getSourceFieldDefinition($media_type);
if (!is_a($field_definition->getClass(), FileFieldItemList::class, TRUE)) {
throw new \InvalidArgumentException('Can only add media types which use a file field as a source field.');
}
return $media_type;
}
/**
* {@inheritdoc}
*/
protected function buildInputElement(array $form, FormStateInterface $form_state) {
// Create a file item to get the upload validators.
$media_type = $this->getMediaType($form_state);
$item = $this->createFileItem($media_type);
/** @var \Drupal\media_library\MediaLibraryState $state */
$state = $this->getMediaLibraryState($form_state);
if (!$state->hasSlotsAvailable()) {
return $form;
}
$slots = $state->getAvailableSlots();
// Add a container to group the input elements for styling purposes.
$form['container'] = [
'#type' => 'container',
];
$process = (array) $this->elementInfo
->getInfoProperty('managed_file', '#process', []);
$form['container']['upload'] = [
'#type' => 'managed_file',
'#title' => $this->formatPlural($slots, 'Add file', 'Add files'),
// @todo Move validation in https://www.drupal.org/node/2988215
'#process' => array_merge([
'::validateUploadElement',
], $process, [
'::processUploadElement',
]),
'#upload_validators' => $item->getUploadValidators(),
// Set multiple to true only if available slots is not exactly one
// to ensure correct language (singular or plural) in UI
'#multiple' => $slots != 1 ? TRUE : FALSE,
// Do not limit the number uploaded. There is validation based on the
// number selected in the media library that prevents overages.
// @see Drupal\media_library\Form\AddFormBase::updateLibrary()
'#cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
'#remaining_slots' => $slots,
];
$file_upload_help = [
'#theme' => 'file_upload_help',
'#upload_validators' => $form['container']['upload']['#upload_validators'],
'#cardinality' => $slots,
];
// The file upload help needs to be rendered since the description does not
// accept render arrays. The FileWidget::formElement() method adds the file
// upload help in the same way, so any theming improvements made to file
// fields would also be applied to this upload field.
// @see \Drupal\file\Plugin\Field\FieldWidget\FileWidget::formElement()
$form['container']['upload']['#description'] = $this->renderer
->renderInIsolation($file_upload_help);
return $form;
}
/**
* Validates the upload element.
*
* @param array $element
* The upload element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*
* @return array
* The processed upload element.
*/
public function validateUploadElement(array $element, FormStateInterface $form_state) {
if ($form_state::hasAnyErrors()) {
// When an error occurs during uploading files, remove all files so the
// user can re-upload the files.
$element['#value'] = [];
}
$values = $form_state->getValue('upload', []);
if (count($values['fids']) > $element['#cardinality'] && $element['#cardinality'] !== FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
$form_state->setError($element, $this->t('A maximum of @count files can be uploaded.', [
'@count' => $element['#cardinality'],
]));
$form_state->setValue('upload', []);
$element['#value'] = [];
}
return $element;
}
/**
* Processes an upload (managed_file) element.
*
* @param array $element
* The upload element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*
* @return array
* The processed upload element.
*/
public function processUploadElement(array $element, FormStateInterface $form_state) {
$element['upload_button']['#submit'] = [
'::uploadButtonSubmit',
];
// Limit the validation errors to make sure
// FormValidator::handleErrorsWithLimitedValidation doesn't remove the
// current selection from the form state.
// @see Drupal\Core\Form\FormValidator::handleErrorsWithLimitedValidation()
$element['upload_button']['#limit_validation_errors'] = [
[
'upload',
],
[
'current_selection',
],
];
$element['upload_button']['#ajax'] = [
'callback' => '::updateFormCallback',
'wrapper' => 'media-library-wrapper',
// Add a fixed URL to post the form since AJAX forms are automatically
// posted to <current> instead of $form['#action'].
// @todo Remove when https://www.drupal.org/project/drupal/issues/2504115
// is fixed.
'url' => Url::fromRoute('media_library.ui'),
'options' => [
'query' => $this->getMediaLibraryState($form_state)
->all() + [
FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
],
],
];
return $element;
}
/**
* {@inheritdoc}
*/
protected function buildEntityFormElement(MediaInterface $media, array $form, FormStateInterface $form_state, $delta) {
$element = parent::buildEntityFormElement($media, $form, $form_state, $delta);
$source_field = $this->getSourceFieldName($media->bundle->entity);
if (isset($element['fields'][$source_field])) {
$element['fields'][$source_field]['widget'][0]['#process'][] = [
static::class,
'hideExtraSourceFieldComponents',
];
}
return $element;
}
/**
* Processes an image or file source field element.
*
* @param array $element
* The entity form source field element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current form state.
* @param array $form
* The complete form.
*
* @return array
* The processed form element.
*/
public static function hideExtraSourceFieldComponents($element, FormStateInterface $form_state, $form) {
// Remove original button added by ManagedFile::processManagedFile().
if (!empty($element['remove_button'])) {
$element['remove_button']['#access'] = FALSE;
}
// Remove preview added by ImageWidget::process().
if (!empty($element['preview'])) {
$element['preview']['#access'] = FALSE;
}
$element['#title_display'] = 'none';
$element['#description_display'] = 'none';
// Remove the filename display.
foreach ($element['#files'] as $file) {
$element['file_' . $file->id()]['filename']['#access'] = FALSE;
}
return $element;
}
/**
* Submit handler for the upload button, inside the managed_file element.
*
* @param array $form
* The form render array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
public function uploadButtonSubmit(array $form, FormStateInterface $form_state) {
$files = $this->entityTypeManager
->getStorage('file')
->loadMultiple($form_state->getValue('upload', []));
$this->processInputValues($files, $form, $form_state);
}
/**
* {@inheritdoc}
*/
protected function createMediaFromValue(MediaTypeInterface $media_type, EntityStorageInterface $media_storage, $source_field_name, $file) {
if (!$file instanceof FileInterface) {
throw new \InvalidArgumentException('Cannot create a media item without a file entity.');
}
// Create a file item to get the upload location.
$item = $this->createFileItem($media_type);
$upload_location = $item->getUploadLocation();
if (!$this->fileSystem
->prepareDirectory($upload_location, FileSystemInterface::CREATE_DIRECTORY)) {
throw new FileWriteException("The destination directory '{$upload_location}' is not writable");
}
$file = $this->fileRepository
->move($file, $upload_location);
if (!$file) {
throw new \RuntimeException("Unable to move file to '{$upload_location}'");
}
return parent::createMediaFromValue($media_type, $media_storage, $source_field_name, $file);
}
/**
* Create a file field item.
*
* @param \Drupal\media\MediaTypeInterface $media_type
* The media type of the media item.
*
* @return \Drupal\file\Plugin\Field\FieldType\FileItem
* A created file item.
*/
protected function createFileItem(MediaTypeInterface $media_type) {
$field_definition = $media_type->getSource()
->getSourceFieldDefinition($media_type);
$data_definition = FieldItemDataDefinition::create($field_definition);
return new FileItem($data_definition);
}
/**
* {@inheritdoc}
*/
protected function prepareMediaEntityForSave(MediaInterface $media) {
/** @var \Drupal\file\FileInterface $file */
$file = $media->get($this->getSourceFieldName($media->bundle->entity))->entity;
$file->setPermanent();
$file->save();
}
/**
* Submit handler for the remove button.
*
* @param array $form
* The form render array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
public function removeButtonSubmit(array $form, FormStateInterface $form_state) {
// Retrieve the delta of the media item from the parents of the remove
// button.
$triggering_element = $form_state->getTriggeringElement();
$delta = array_slice($triggering_element['#array_parents'], -2, 1)[0];
/** @var \Drupal\media\MediaInterface $removed_media */
$removed_media = $form_state->get([
'media',
$delta,
]);
$file = $removed_media->get($this->getSourceFieldName($removed_media->bundle->entity))->entity;
if ($file instanceof FileInterface && empty($this->fileUsage
->listUsage($file))) {
$file->delete();
}
parent::removeButtonSubmit($form, $form_state);
}
}
Members
Title Sort descending | Deprecated | Modifiers | Object type | Summary | Overriden Title | Overrides |
---|---|---|---|---|---|---|
AddFormBase::$entityTypeManager | protected | property | The entity type manager. | |||
AddFormBase::$libraryUiBuilder | protected | property | The media library UI builder. | |||
AddFormBase::$mediaType | protected | property | The type of media items being created by this form. | |||
AddFormBase::$openerResolver | protected | property | The opener resolver. | |||
AddFormBase::$viewBuilder | protected | property | The media view builder. | |||
AddFormBase::buildActions | protected | function | Returns an array of supported actions for the form. | |||
AddFormBase::buildCurrentSelectionArea | protected | function | Returns a render array containing the current selection. | |||
AddFormBase::buildForm | public | function | Form constructor. | Overrides FormInterface::buildForm | ||
AddFormBase::buildMediaLibraryUi | protected | function | Build the render array of the media library UI. | |||
AddFormBase::buildSelectedItemElement | protected | function | Returns a render array for a single pre-selected media item. | |||
AddFormBase::getAddedMediaItems | protected | function | Get all added media items from the form state. | |||
AddFormBase::getBaseFormId | public | function | Returns a string identifying the base form. | Overrides BaseFormIdInterface::getBaseFormId | ||
AddFormBase::getCurrentMediaItems | protected | function | Get all pre-selected and added media items from the form state. | |||
AddFormBase::getMediaLibraryState | protected | function | Get the media library state from the form state. | |||
AddFormBase::getPreSelectedMediaItems | protected | function | Get all pre-selected media items from the form state. | |||
AddFormBase::getSelectedMediaItemCount | private | function | Get the number of selected media. | |||
AddFormBase::getSourceFieldName | protected | function | Returns the name of the source field for a media type. | |||
AddFormBase::isAdvancedUi | protected | function | Determines if the "advanced UI" of the Media Library is enabled. | |||
AddFormBase::preRenderAddedMedia | public | function | Converts the set of newly added media into an item list for rendering. | |||
AddFormBase::processInputValues | protected | function | Creates media items from source field input values. | |||
AddFormBase::submitForm | public | function | Form submission handler. | Overrides FormInterface::submitForm | ||
AddFormBase::trustedCallbacks | public static | function | Lists the trusted callbacks provided by the implementing class. | Overrides TrustedCallbackInterface::trustedCallbacks | ||
AddFormBase::updateFormCallback | public | function | AJAX callback to update the entire form based on source field input. | |||
AddFormBase::updateLibrary | public | function | AJAX callback to send the new media item(s) to the media library. | |||
AddFormBase::updateWidget | public | function | AJAX callback to send the new media item(s) to the calling code. | |||
AddFormBase::validateForm | public | function | Form validation handler. | Overrides FormBase::validateForm | ||
AddFormBase::validateMediaEntity | protected | function | Validate a created media item. | |||
DependencySerializationTrait::$_entityStorages | protected | property | ||||
DependencySerializationTrait::$_serviceIds | protected | property | ||||
DependencySerializationTrait::__sleep | public | function | 1 | |||
DependencySerializationTrait::__wakeup | public | function | 2 | |||
FileUploadForm::$elementInfo | protected | property | The element info manager. | |||
FileUploadForm::$fileRepository | protected | property | The file repository service. | |||
FileUploadForm::$fileSystem | protected | property | The file system service. | |||
FileUploadForm::$fileUsage | protected | property | The file usage service. | |||
FileUploadForm::$renderer | protected | property | The renderer service. | |||
FileUploadForm::buildEntityFormElement | protected | function | Builds the sub-form for setting required fields on a new media item. | Overrides AddFormBase::buildEntityFormElement | ||
FileUploadForm::buildInputElement | protected | function | Builds the element for submitting source field value(s). | Overrides AddFormBase::buildInputElement | ||
FileUploadForm::create | public static | function | Instantiates a new instance of this class. | Overrides AddFormBase::create | ||
FileUploadForm::createFileItem | protected | function | Create a file field item. | |||
FileUploadForm::createMediaFromValue | protected | function | Creates a new, unsaved media item from a source field value. | Overrides AddFormBase::createMediaFromValue | ||
FileUploadForm::getFormId | public | function | Returns a unique string identifying the form. | Overrides FormInterface::getFormId | ||
FileUploadForm::getMediaType | protected | function | Get the media type from the form state. | Overrides AddFormBase::getMediaType | ||
FileUploadForm::hideExtraSourceFieldComponents | public static | function | Processes an image or file source field element. | |||
FileUploadForm::prepareMediaEntityForSave | protected | function | Prepares a created media item to be permanently saved. | Overrides AddFormBase::prepareMediaEntityForSave | ||
FileUploadForm::processUploadElement | public | function | Processes an upload (managed_file) element. | |||
FileUploadForm::removeButtonSubmit | public | function | Submit handler for the remove button. | Overrides AddFormBase::removeButtonSubmit | ||
FileUploadForm::uploadButtonSubmit | public | function | Submit handler for the upload button, inside the managed_file element. | |||
FileUploadForm::validateUploadElement | public | function | Validates the upload element. | |||
FileUploadForm::__construct | public | function | Constructs a new FileUploadForm. | Overrides AddFormBase::__construct | ||
FormBase::$configFactory | protected | property | The config factory. | 3 | ||
FormBase::$requestStack | protected | property | The request stack. | 1 | ||
FormBase::$routeMatch | protected | property | The route match. | |||
FormBase::config | protected | function | Retrieves a configuration object. | |||
FormBase::configFactory | protected | function | Gets the config factory for this form. | 3 | ||
FormBase::container | private | function | Returns the service container. | |||
FormBase::currentUser | protected | function | Gets the current user. | 2 | ||
FormBase::getRequest | protected | function | Gets the request object. | |||
FormBase::getRouteMatch | protected | function | Gets the route match. | |||
FormBase::logger | protected | function | Gets the logger for a specific channel. | |||
FormBase::redirect | protected | function | Returns a redirect response object for the specified route. | |||
FormBase::resetConfigFactory | public | function | Resets the configuration factory. | |||
FormBase::setConfigFactory | public | function | Sets the config factory for this form. | |||
FormBase::setRequestStack | public | function | Sets the request stack object to use. | |||
LoggerChannelTrait::$loggerFactory | protected | property | The logger channel factory service. | |||
LoggerChannelTrait::getLogger | protected | function | Gets the logger for a specific channel. | |||
LoggerChannelTrait::setLoggerFactory | public | function | Injects the logger channel factory. | |||
MessengerTrait::$messenger | protected | property | The messenger. | 16 | ||
MessengerTrait::messenger | public | function | Gets the messenger. | 16 | ||
MessengerTrait::setMessenger | public | function | Sets the messenger. | |||
RedirectDestinationTrait::$redirectDestination | protected | property | The redirect destination service. | 2 | ||
RedirectDestinationTrait::getDestinationArray | protected | function | Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url. | |||
RedirectDestinationTrait::getRedirectDestination | protected | function | Returns the redirect destination service. | |||
RedirectDestinationTrait::setRedirectDestination | public | function | Sets the redirect destination service. | |||
StringTranslationTrait::$stringTranslation | protected | property | The string translation service. | 3 | ||
StringTranslationTrait::formatPlural | protected | function | Formats a string containing a count of items. | |||
StringTranslationTrait::getNumberOfPlurals | protected | function | Returns the number of plurals supported by a given language. | |||
StringTranslationTrait::getStringTranslation | protected | function | Gets the string translation service. | |||
StringTranslationTrait::setStringTranslation | public | function | Sets the string translation service to use. | 2 | ||
StringTranslationTrait::t | protected | function | Translates a string to the current language or to a given language. | |||
TrustedCallbackInterface::THROW_EXCEPTION | constant | Untrusted callbacks throw exceptions. | ||||
TrustedCallbackInterface::TRIGGER_SILENCED_DEPRECATION | constant | Untrusted callbacks trigger silenced E_USER_DEPRECATION errors. | ||||
TrustedCallbackInterface::TRIGGER_WARNING | Deprecated | constant | Untrusted callbacks trigger E_USER_WARNING errors. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.