View source
<?php
namespace Drupal\media_bulk_upload\Form;
use Drupal\Component\Utility\Bytes;
use Drupal\Component\Utility\Environment;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\file\FileInterface;
use Drupal\media\MediaInterface;
use Drupal\media\MediaTypeInterface;
use Drupal\media_bulk_upload\Entity\MediaBulkConfigInterface;
use Drupal\media_bulk_upload\MediaSubFormManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
class MediaBulkUploadForm extends FormBase {
protected $mediaTypeStorage;
protected $mediaBulkConfigStorage;
protected $mediaStorage;
protected $fileStorage;
protected $mediaSubFormManager;
protected $maxFileSizeForm;
protected $allowed_extensions = [];
protected $currentUser;
public function __construct(EntityTypeManagerInterface $entityTypeManager, MediaSubFormManager $mediaSubFormManager, AccountProxyInterface $currentUser, MessengerInterface $messenger) {
$this->mediaTypeStorage = $entityTypeManager
->getStorage('media_type');
$this->mediaBulkConfigStorage = $entityTypeManager
->getStorage('media_bulk_config');
$this->mediaStorage = $entityTypeManager
->getStorage('media');
$this->fileStorage = $entityTypeManager
->getStorage('file');
$this->maxFileSizeForm = Environment::getUploadMaxSize();
$this->mediaSubFormManager = $mediaSubFormManager;
$this->currentUser = $currentUser;
$this->messenger = $messenger;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('entity_type.manager'), $container
->get('media_bulk_upload.subform_manager'), $container
->get('current_user'), $container
->get('messenger'));
}
public function getFormId() {
return 'media_bulk_upload_form';
}
public function buildForm(array $form, FormStateInterface $form_state, MediaBulkConfigInterface $media_bulk_config = NULL) {
$mediaBulkConfig = $media_bulk_config;
if ($mediaBulkConfig === NULL) {
return $form;
}
$mediaTypeManager = $this->mediaSubFormManager
->getMediaTypeManager();
$mediaTypes = $this->mediaSubFormManager
->getMediaTypeManager()
->getBulkMediaTypes($mediaBulkConfig);
$mediaTypeLabels = [];
foreach ($mediaTypes as $mediaType) {
$extensions = $mediaTypeManager
->getMediaTypeExtensions($mediaType);
natsort($extensions);
$this
->addAllowedExtensions($extensions);
$maxFileSize = $mediaTypeManager
->getTargetFieldMaxSize($mediaType);
if (empty($maxFileSize)) {
$maxFileSize = $this->mediaSubFormManager
->getDefaultMaxFileSize();
}
$mediaTypeLabels[] = $mediaType
->label() . ' (max ' . $maxFileSize . '): ' . implode(', ', $extensions);
if ($this
->isMaxFileSizeLarger($maxFileSize)) {
$this
->setMaxFileSizeForm($maxFileSize);
}
}
$form['#tree'] = TRUE;
$form['information_wrapper'] = [
'#type' => 'container',
'#attributes' => [
'class' => [
'media-bulk-upload-information-wrapper',
],
],
];
$form['information_wrapper']['information_label'] = [
'#type' => 'html_tag',
'#tag' => 'label',
'#value' => $this
->t('Information'),
'#attributes' => [
'class' => [
'form-control-label',
],
'for' => 'media_bulk_upload_information',
],
];
$form['information_wrapper']['information'] = [
'#theme' => 'item_list',
'#title' => $this
->t('Media Types:'),
'#items' => $mediaTypeLabels,
];
$form['information_wrapper']['warning'] = [
'#type' => 'html_tag',
'#tag' => 'span',
'#id' => 'media_bulk_upload_information',
'#name' => 'media_bulk_upload_information',
'#value' => '<p>Please be
aware that if file extensions overlap between the media types that are
available in this upload form, that the media entity will be assigned
automatically to one of these types.</p>',
];
$form['dropzonejs'] = [
'#type' => 'dropzonejs',
'#title' => $this
->t('Dropzone'),
'#required' => TRUE,
'#dropzone_description' => $this
->t('Click or drop your files here'),
'#max_filesize' => $this->maxFileSizeForm,
'#extensions' => implode(' ', $this->allowed_extensions),
];
if ($this->mediaSubFormManager
->validateMediaFormDisplayUse($mediaBulkConfig)) {
$form['fields'] = [
'#type' => 'fieldset',
'#title' => $this
->t('Fields'),
'shared' => [
'#field_parents' => [
'fields',
'shared',
],
'#parents' => [
'fields',
'shared',
],
],
];
$this->mediaSubFormManager
->buildMediaSubForm($form['fields']['shared'], $form_state, $mediaBulkConfig);
}
$form['media_bundle_config'] = [
'#type' => 'value',
'#value' => $mediaBulkConfig
->id(),
];
$form['submit'] = [
'#type' => 'submit',
'#value' => $this
->t('Submit'),
];
return $form;
}
protected function addAllowedExtensions(array $extensions) {
$this->allowed_extensions = array_unique(array_merge($this->allowed_extensions, $extensions));
return $this;
}
protected function isMaxFileSizeLarger($MaxFileSize) {
$size = Bytes::toInt($MaxFileSize);
$currentSize = Bytes::toInt($this->maxFileSizeForm);
return $size > $currentSize;
}
protected function setMaxFileSizeForm($newMaxFileSize) {
$this->maxFileSizeForm = $newMaxFileSize;
return $this;
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$values = $form_state
->getValues();
$mediaBundleConfigId = $values['media_bundle_config'];
$mediaBulkConfig = $this->mediaBulkConfigStorage
->load($mediaBundleConfigId);
$files = $values['dropzonejs']['uploaded_files'];
$mediaTypes = $this->mediaSubFormManager
->getMediaTypeManager()
->getBulkMediaTypes($mediaBulkConfig);
$mediaType = reset($mediaTypes);
$mediaFormDisplay = $this->mediaSubFormManager
->getMediaFormDisplay($mediaBulkConfig, $mediaType);
$this
->prepareFormValues($form_state);
$savedMediaItems = [];
foreach ($files as $file) {
try {
$media = $this
->processFile($mediaBulkConfig, $file);
if (!$media) {
continue;
}
if ($this->mediaSubFormManager
->validateMediaFormDisplayUse($mediaBulkConfig)) {
$extracted = $mediaFormDisplay
->extractFormValues($media, $form['fields']['shared'], $form_state);
$this
->copyFormValuesToEntity($media, $extracted, $form_state);
}
$media
->save();
$savedMediaItems[] = $media;
} catch (\Exception $e) {
watchdog_exception('media_bulk_upload', $e);
}
}
if (!empty($savedMediaItems)) {
$this
->messenger()
->addStatus($this
->t('@count media item(s) are created.', [
'@count' => count($savedMediaItems),
]));
}
}
protected function processFile(MediaBulkConfigInterface $mediaBulkConfig, array $file) {
$fileInfo = pathinfo($file['filename']);
$filename = $fileInfo['basename'];
if (!$this
->validateFilename($fileInfo)) {
$this
->messenger()
->addError($this
->t('File :filename does not have a valid extension or filename.', [
':filename' => $filename,
]));
throw new \Exception("File {$filename} does not have a valid extension or filename.");
}
$allowedMediaTypes = $this->mediaSubFormManager
->getMediaTypeManager()
->getBulkMediaTypes($mediaBulkConfig);
$matchingMediaTypes = $this->mediaSubFormManager
->getMediaTypeManager()
->getMediaTypeIdsByFileExtension($fileInfo['extension']);
$mediaTypes = array_intersect_key($matchingMediaTypes, $allowedMediaTypes);
$mediaType = reset($mediaTypes);
if (!$this
->validateFileSize($mediaType, $file['path'])) {
$fileSizeSetting = $this->mediaSubFormManager
->getMediaTypeManager()
->getTargetFieldMaxSize($mediaType);
$mediaTypeLabel = $mediaType
->label();
$this
->messenger()
->addError($this
->t('File :filename exceeds the maximum file size of :file_size for media type :media_type exceeded.', [
':filename' => $filename,
':file_size' => $fileSizeSetting,
':media_type' => $mediaTypeLabel,
]));
throw new \Exception("File {$filename} exceeds the maximum file size of {$fileSizeSetting} for media type {$mediaTypeLabel} exceeded.");
}
$uri_scheme = $this->mediaSubFormManager
->getTargetFieldDirectory($mediaType);
$destination = $uri_scheme . '/' . $file['filename'];
$file_default_scheme = \Drupal::config('system.file')
->get('default_scheme') . '://';
if ($uri_scheme === $file_default_scheme) {
$destination = $uri_scheme . $file['filename'];
}
$fileEntity = $this->fileStorage
->create([
'uri' => $file['path'],
'uid' => $this->currentUser
->id(),
'status' => FILE_STATUS_PERMANENT,
]);
$fileEntity
->save();
file_move($fileEntity, $destination);
if (!$fileEntity) {
$this
->messenger()
->addError($this
->t('File :filename could not be created.', [
':filename' => $filename,
]), 'error');
throw new \Exception('File entity could not be created.');
}
$values = $this
->getNewMediaValues($mediaType, $fileInfo, $fileEntity);
$media = $this->mediaStorage
->create($values);
return $media;
}
protected function validateFilename(array $fileInfo) {
return !(empty($fileInfo['filename']) || empty($fileInfo['extension']));
}
protected function validateFileSize(MediaTypeInterface $mediaType, $filePath) {
$fileSizeSetting = $this->mediaSubFormManager
->getMediaTypeManager()
->getTargetFieldMaxSize($mediaType);
$fileSize = filesize($filePath);
$maxFileSize = !empty($fileSizeSetting) ? Bytes::toInt($fileSizeSetting) : Environment::getUploadMaxSize();
if ($maxFileSize == 0) {
return true;
}
return $fileSize <= $maxFileSize;
}
protected function getNewMediaValues(MediaTypeInterface $mediaType, array $fileInfo, FileInterface $file) {
$targetFieldName = $this->mediaSubFormManager
->getMediaTypeManager()
->getTargetFieldName($mediaType);
return [
'bundle' => $mediaType
->id(),
'name' => $fileInfo['filename'],
$targetFieldName => [
'target_id' => $file
->id(),
'title' => $fileInfo['filename'],
],
];
}
protected function copyFormValuesToEntity(MediaInterface $media, array $extracted, FormStateInterface $form_state) {
foreach ($form_state
->getValues() as $name => $values) {
if (isset($extracted[$name]) || !$media
->hasField($name)) {
continue;
}
$media
->set($name, $values);
}
}
protected function prepareFormValues(FormStateInterface $form_state) {
$shared = $form_state
->getValue([
'fields',
'shared',
]);
if (empty($shared['name'][0]['value'])) {
unset($shared['name']);
$form_state
->setValue([
'fields',
'shared',
], $shared);
}
return $this;
}
}