View source
<?php
namespace Drupal\media_library\Form;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Field\TypedData\FieldItemDataDefinition;
use Drupal\Core\File\Exception\FileWriteException;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\ElementInfoManagerInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Url;
use Drupal\file\FileRepositoryInterface;
use Drupal\file\FileInterface;
use Drupal\file\FileUsage\FileUsageInterface;
use Drupal\file\Plugin\Field\FieldType\FileFieldItemList;
use Drupal\file\Plugin\Field\FieldType\FileItem;
use Drupal\media\MediaInterface;
use Drupal\media\MediaTypeInterface;
use Drupal\media_library\MediaLibraryUiBuilder;
use Drupal\media_library\OpenerResolverInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class FileUploadForm extends AddFormBase {
protected $elementInfo;
protected $renderer;
protected $fileSystem;
protected $fileUsage;
protected $fileRepository;
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;
}
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'));
}
public function getFormId() {
return $this
->getBaseFormId() . '_upload';
}
protected function getMediaType(FormStateInterface $form_state) {
if ($this->mediaType) {
return $this->mediaType;
}
$media_type = parent::getMediaType($form_state);
$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;
}
protected function buildInputElement(array $form, FormStateInterface $form_state) {
$media_type = $this
->getMediaType($form_state);
$item = $this
->createFileItem($media_type);
$state = $this
->getMediaLibraryState($form_state);
if (!$state
->hasSlotsAvailable()) {
return $form;
}
$slots = $state
->getAvailableSlots();
$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'),
'#process' => array_merge([
'::validateUploadElement',
], $process, [
'::processUploadElement',
]),
'#upload_validators' => $item
->getUploadValidators(),
'#multiple' => $slots != 1 ? TRUE : FALSE,
'#cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
'#remaining_slots' => $slots,
];
$file_upload_help = [
'#theme' => 'file_upload_help',
'#upload_validators' => $form['container']['upload']['#upload_validators'],
'#cardinality' => $slots,
];
$form['container']['upload']['#description'] = $this->renderer
->renderInIsolation($file_upload_help);
return $form;
}
public function validateUploadElement(array $element, FormStateInterface $form_state) {
if ($form_state::hasAnyErrors()) {
$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;
}
public function processUploadElement(array $element, FormStateInterface $form_state) {
$element['upload_button']['#submit'] = [
'::uploadButtonSubmit',
];
$element['upload_button']['#limit_validation_errors'] = [
[
'upload',
],
[
'current_selection',
],
];
$element['upload_button']['#ajax'] = [
'callback' => '::updateFormCallback',
'wrapper' => 'media-library-wrapper',
'url' => Url::fromRoute('media_library.ui'),
'options' => [
'query' => $this
->getMediaLibraryState($form_state)
->all() + [
FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
],
],
];
return $element;
}
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;
}
public static function hideExtraSourceFieldComponents($element, FormStateInterface $form_state, $form) {
if (!empty($element['remove_button'])) {
$element['remove_button']['#access'] = FALSE;
}
if (!empty($element['preview'])) {
$element['preview']['#access'] = FALSE;
}
$element['#title_display'] = 'none';
$element['#description_display'] = 'none';
foreach ($element['#files'] as $file) {
$element['file_' . $file
->id()]['filename']['#access'] = FALSE;
}
return $element;
}
public function uploadButtonSubmit(array $form, FormStateInterface $form_state) {
$files = $this->entityTypeManager
->getStorage('file')
->loadMultiple($form_state
->getValue('upload', []));
$this
->processInputValues($files, $form, $form_state);
}
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.');
}
$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);
}
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);
}
protected function prepareMediaEntityForSave(MediaInterface $media) {
$file = $media
->get($this
->getSourceFieldName($media->bundle->entity))->entity;
$file
->setPermanent();
$file
->save();
}
public function removeButtonSubmit(array $form, FormStateInterface $form_state) {
$triggering_element = $form_state
->getTriggeringElement();
$delta = array_slice($triggering_element['#array_parents'], -2, 1)[0];
$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);
}
}