diff --git a/config/schema/media_bulk_config.schema.yml b/config/schema/media_bulk_config.schema.yml index 5d09450..ac4ffc3 100644 --- a/config/schema/media_bulk_config.schema.yml +++ b/config/schema/media_bulk_config.schema.yml @@ -13,6 +13,15 @@ media_bulk_upload.media_bulk_config.*: media_types: type: sequence label: 'Media Types' + show_alt: + type: boolean + label: 'Show Alt text input' + alt_required: + type: boolean + label: 'Alt text required' + show_title: + type: boolean + label: 'Show Title text input' form_mode: label: 'Form Mode' type: string diff --git a/modules/dropzonejs/media_bulk_upload_dropzonejs.module b/modules/dropzonejs/media_bulk_upload_dropzonejs.module index d0d09ec..beb7d07 100644 --- a/modules/dropzonejs/media_bulk_upload_dropzonejs.module +++ b/modules/dropzonejs/media_bulk_upload_dropzonejs.module @@ -4,41 +4,54 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Form\FormStateInterface; use Drupal\file\FileInterface; +use Drupal\media_bulk_upload\Entity\MediaBulkConfigInterface; /** * Implements hook_media_bulk_upload_file_ids_alter(). * - * @param array $file_ids - * @param string $media_bulk_config_id + * @param array $files_data + * The uploaded files data. + * @param \Drupal\media_bulk_upload\Entity\MediaBulkConfigInterface $media_bulk_config + * The bulk media upload config ID. * * @return void */ -function media_bulk_upload_dropzonejs_media_bulk_upload_file_ids_alter(array &$file_ids, string $media_bulk_config_id) { - if (!isset($file_ids['uploaded_files'])) { +function media_bulk_upload_dropzonejs_media_bulk_upload_files_alter(array &$files_data, MediaBulkConfigInterface $media_bulk_config) { + if (!isset($files_data['uploaded_files'])) { return; } - $fileIds = []; - $fileStorage = \Drupal::entityTypeManager()->getStorage('file'); + $files = []; + $file_storage = \Drupal::entityTypeManager()->getStorage('file'); - foreach ($file_ids['uploaded_files'] as $fileData) { - if (!is_array($fileData) || !isset($fileData['path'])) { + foreach ($files_data['uploaded_files'] as $file_data) { + if (!is_array($file_data) || !isset($file_data['path'])) { continue; } - /** @var \Drupal\file\FileInterface $fileEntity */ - $fileEntity = $fileStorage->create([ - 'uri' => $fileData['path'], + /** @var \Drupal\file\FileInterface $file_entity */ + $file_entity = $file_storage->create([ + 'uri' => $file_data['path'], 'uid' => \Drupal::currentUser()->id(), - 'filename' => $fileData['filename'], + 'filename' => $file_data['filename'], ]); - $fileEntity->setPermanent(); - $fileEntity->save(); - $fileIds[] = $fileEntity->id(); + $file_entity->setTemporary(); + $file_entity->save(); + $metadata = []; + if ($media_bulk_config->get('show_alt')) { + $metadata['alt'] = $file_data['metadata']['alt']; + } + if ($media_bulk_config->get('show_title')) { + $metadata['title'] = $file_data['metadata']['title']; + } + $files[$file_entity->id()] = [ + 'file' => $file_entity, + 'metadata' => $metadata, + ]; } - if (!empty($fileIds)) { - $file_ids = $fileIds; + if (!empty($files)) { + $files_data = $files; } } diff --git a/src/Entity/MediaBulkConfig.php b/src/Entity/MediaBulkConfig.php index fda5da1..7bda828 100644 --- a/src/Entity/MediaBulkConfig.php +++ b/src/Entity/MediaBulkConfig.php @@ -36,6 +36,7 @@ use Drupal\Core\Config\Entity\ConfigEntityBase; * "uuid", * "media_types", * "show_alt", + * "alt_required", * "show_title", * "form_mode", * "upload_location", diff --git a/src/Form/MediaBulkConfigForm.php b/src/Form/MediaBulkConfigForm.php index 7dcfd99..589c636 100644 --- a/src/Form/MediaBulkConfigForm.php +++ b/src/Form/MediaBulkConfigForm.php @@ -87,6 +87,32 @@ class MediaBulkConfigForm extends EntityForm implements ContainerInjectionInterf '#required' => TRUE, ]; + $show_alt = $mediaBulkConfig->get('show_alt'); + $form['show_alt'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Show Alt text input for uploaded files.'), + '#description' => $this->t('Check if you want to be able to add Alt text + to the uploaded files. Please do NOT use [ or ] symbols in your text.'), + '#default_value' => (boolean) $show_alt, + ]; + + $alt_required = $mediaBulkConfig->get('alt_required'); + $form['alt_required'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Make Alt text input required.'), + '#description' => $this->t('Check if you want the Alt text to be required for image files.'), + '#default_value' => (boolean) $alt_required, + ]; + + $show_title = $mediaBulkConfig->get('show_title'); + $form['show_title'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Show title text input for uploaded files.'), + '#description' => $this->t('Check if you want to be able to add title text + to the uploaded files. Please do NOT use [ or ] symbols in your text.'), + '#default_value' => (boolean) $show_title, + ]; + $form['form_mode'] = [ '#type' => 'select', '#title' => $this->t('Form Mode'), diff --git a/src/Form/MediaBulkUploadForm.php b/src/Form/MediaBulkUploadForm.php index fb3388b..f33159e 100644 --- a/src/Form/MediaBulkUploadForm.php +++ b/src/Form/MediaBulkUploadForm.php @@ -20,6 +20,8 @@ use Drupal\media_bulk_upload\Entity\MediaBulkConfigInterface; use Drupal\media_bulk_upload\MediaSubFormManager; use Exception; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; +use Symfony\Component\Mime\MimeTypeGuesserInterface; /** * Class BulkMediaUploadForm. @@ -77,6 +79,27 @@ class MediaBulkUploadForm extends FormBase { */ protected $allowed_extensions = []; + /** + * The module handler. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface + */ + private $moduleHandler; + + /** + * The mime type guesser. + * + * @var \Symfony\Component\Mime\MimeTypeGuesserInterface + */ + private $mimeTypeGuesser; + + /** + * The file system. + * + * @var \Drupal\Core\File\FileSystemInterface + */ + private $fileSystem; + /** * The current user. * @@ -102,11 +125,17 @@ class MediaBulkUploadForm extends FormBase { * Current User. * @param \Drupal\Core\Messenger\MessengerInterface $messenger * The messenger. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler + * The module handler. + * @param \Symfony\Component\Mime\MimeTypeGuesserInterface $mimeTypeGuesser + * The mime type guesser. + * @param \Drupal\Core\File\FileSystemInterface $fileSystem + * The file system. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ - public function __construct(EntityTypeManagerInterface $entityTypeManager, MediaSubFormManager $mediaSubFormManager, AccountProxyInterface $currentUser, MessengerInterface $messenger, FileRepositoryInterface $fileRepository) { + public function __construct(EntityTypeManagerInterface $entityTypeManager, MediaSubFormManager $mediaSubFormManager, AccountProxyInterface $currentUser, MessengerInterface $messenger, FileRepositoryInterface $fileRepository, ModuleHandlerInterface $moduleHandler, MimeTypeGuesserInterface $mimeTypeGuesser, FileSystemInterface $fileSystem) { $this->mediaTypeStorage = $entityTypeManager->getStorage('media_type'); $this->mediaBulkConfigStorage = $entityTypeManager->getStorage('media_bulk_config'); $this->mediaStorage = $entityTypeManager->getStorage('media'); @@ -115,6 +144,9 @@ class MediaBulkUploadForm extends FormBase { $this->currentUser = $currentUser; $this->messenger = $messenger; $this->fileRepository = $fileRepository; + $this->moduleHandler = $moduleHandler; + $this->mimeTypeGuesser = $mimeTypeGuesser; + $this->fileSystem = $fileSystem; $this->maxFileSizeForm = ''; } @@ -130,7 +162,10 @@ class MediaBulkUploadForm extends FormBase { $container->get('media_bulk_upload.subform_manager'), $container->get('current_user'), $container->get('messenger'), - $container->get('file.repository') + $container->get('file.repository'), + $container->get('module_handler'), + $container->get('file.mime_type.guesser'), + $container->get('file_system') ); } @@ -236,6 +271,9 @@ class MediaBulkUploadForm extends FormBase { '#description' => $this->t('Click or drop your files here. You can upload up to @limit files at once.', ['@limit' => ini_get('max_file_uploads')]), '#upload_validators' => $validators, '#upload_location' => $mediaBulkConfig->get('upload_location'), + '#show_alt' => (boolean) $mediaBulkConfig->get('show_alt'), + '#alt_required' => (boolean) $mediaBulkConfig->get('alt_required'), + '#show_title' => (boolean) $mediaBulkConfig->get('show_title'), ]; if ($this->mediaSubFormManager->validateMediaFormDisplayUse($mediaBulkConfig)) { @@ -285,7 +323,7 @@ class MediaBulkUploadForm extends FormBase { * File Size. * * @return bool - * TRUE if the given size is larger than the one that is set. + * TRUE if the given size is larger than the one that is set. */ protected function isMaxFileSizeLarger($MaxFileSize) { $size = Bytes::toNumber($MaxFileSize); @@ -326,16 +364,21 @@ class MediaBulkUploadForm extends FormBase { /** @var MediaBulkConfigInterface $mediaBulkConfig */ $mediaBulkConfig = $this->mediaBulkConfigStorage->load($mediaBundleConfigId); - $fileIds = $values['file_upload']; + $filesData = $values['file_upload']; - \Drupal::moduleHandler()->alter('media_bulk_upload_file_ids', $fileIds, $mediaBundleConfigId); + $this->moduleHandler->alter('media_bulk_upload_files', $filesData, $mediaBulkConfig); - if (empty($fileIds)) { + if (empty($filesData)) { return; } + $metadata = []; + foreach ($filesData as $file) { + $metadata[$file['file']->id()] = $file['metadata']; + } + /** @var \Drupal\file\FileInterface[] $files */ - $files = $this->fileStorage->loadMultiple($fileIds); + $files = $this->fileStorage->loadMultiple(array_keys($filesData)); $mediaTypes = $this->mediaSubFormManager->getMediaTypeManager()->getBulkMediaTypes($mediaBulkConfig); $mediaType = reset($mediaTypes); @@ -354,6 +397,7 @@ class MediaBulkUploadForm extends FormBase { 'media_bulk_config' => $mediaBulkConfig, 'media_form_display' => $mediaFormDisplay, 'file' => $file, + 'metadata' => $metadata[$file->id()], 'form' => $form, 'form_state' => $form_state, ], @@ -388,10 +432,11 @@ class MediaBulkUploadForm extends FormBase { $mediaBulkConfig = $operation_details['media_bulk_config']; $mediaFormDisplay = $operation_details['media_form_display']; $file = $operation_details['file']; + $metadata = $operation_details['metadata']; $form = $operation_details['form']; $form_state = $operation_details['form_state']; try { - $media = $this->processFile($mediaBulkConfig, $file); + $media = $this->processFile($mediaBulkConfig, $file, $metadata); if ($this->mediaSubFormManager->validateMediaFormDisplayUse($operation_details['media_bulk_config'])) { $extracted = $mediaFormDisplay->extractFormValues($media, $form['fields']['shared'], $form_state); $this->copyFormValuesToEntity($media, $extracted, $form_state); @@ -404,9 +449,11 @@ class MediaBulkUploadForm extends FormBase { '@id' => $id, ] ); - } catch (Exception $e) { + } + catch (Exception $e) { watchdog_exception('media_bulk_upload', $e); } + } /** @@ -445,6 +492,8 @@ class MediaBulkUploadForm extends FormBase { * Media Bulk Config. * @param \Drupal\file\FileInterface $file * File entity. + * @param array $metadata + * Additional metadata for the file. * * @return \Drupal\media\MediaInterface * The unsaved media entity that is created. @@ -454,7 +503,7 @@ class MediaBulkUploadForm extends FormBase { * @throws \Drupal\Core\Entity\EntityStorageException * @throws \Exception */ - protected function processFile(MediaBulkConfigInterface $mediaBulkConfig, FileInterface $file) { + protected function processFile(MediaBulkConfigInterface $mediaBulkConfig, FileInterface $file, array $metadata = []) { $filename = $file->getFilename(); if (!$this->validateFile($file)) { @@ -504,7 +553,7 @@ class MediaBulkUploadForm extends FormBase { throw new Exception('File entity could not be moved.'); } - $values = $this->getNewMediaValues($mediaType, $file); + $values = $this->getNewMediaValues($mediaType, $file, $metadata); /** @var \Drupal\media\MediaInterface $media */ return $this->mediaStorage->create($values); @@ -540,7 +589,7 @@ class MediaBulkUploadForm extends FormBase { : Environment::getUploadMaxSize(); if ((int) $maxFileSize === 0) { - return true; + return TRUE; } return $fileSize <= $maxFileSize; @@ -577,19 +626,22 @@ class MediaBulkUploadForm extends FormBase { * Media Type ID. * @param \Drupal\file\FileInterface $file * File entity. + * @param array $metadata + * Additional metadata for the file. * * @return array * Return an array describing the new media entity. */ - protected function getNewMediaValues(MediaTypeInterface $mediaType, FileInterface $file) { + protected function getNewMediaValues(MediaTypeInterface $mediaType, FileInterface $file, array $metadata) { $targetFieldName = $this->mediaSubFormManager->getMediaTypeManager() ->getTargetFieldName($mediaType); return [ 'bundle' => $mediaType->id(), - 'name' => $file->getFilename(), + 'name' => $metadata['title'] ?: $file->getFilename(), $targetFieldName => [ 'target_id' => $file->id(), - 'title' => $file->getFilename(), + 'title' => $metadata['title'] ?: $file->getFilename(), + 'alt' => $metadata['alt'] ?? '', ], ]; } @@ -639,20 +691,39 @@ class MediaBulkUploadForm extends FormBase { public function validateForm(array &$form, FormStateInterface $form_state) { // Validate all uploaded files. $uploaded_files = $form_state->getValue(['file_upload', 'uploaded_files']); + $media_bundle_config_id = $form_state->getValue(['media_bundle_config']); + $media_bulk_config = $this->mediaBulkConfigStorage->load($media_bundle_config_id); + if (empty($uploaded_files)) { $form_state->setErrorByName('file_upload', $this->t('No media files have been provided.')); } else { + $show_alt = (boolean) $media_bulk_config->get('show_alt'); + $alt_required = (boolean) $media_bulk_config->get('alt_required'); + foreach ($uploaded_files as $uploaded_file) { + $errors = []; + + // Validate file alt. + $mime = $this->mimeTypeGuesser->guessMimeType($uploaded_file['path']); + if ( + strpos($mime, 'image/') !== FALSE + && $show_alt + && $alt_required + && empty($uploaded_file['metadata']['alt']) + ) { + $errors[] = $this->t('Alt value for images is required.'); + } + // Create a new file entity since some modules only validate new files. $file = $this->fileStorage->create([ - 'uri' => $uploaded_file['path'] + 'uri' => $uploaded_file['path'], ]); // Let other modules perform validation on the new file. - $errors = \Drupal::moduleHandler()->invokeAll('file_validate', [ - $file - ]); + $errors = array_merge($errors, $this->moduleHandler->invokeAll('file_validate', [ + $file, + ])); // Process any reported errors. if (!empty($errors)) { @@ -660,8 +731,7 @@ class MediaBulkUploadForm extends FormBase { try { // Delete the uploaded file if it has validation errors. - $file_system = \Drupal::service('file_system'); - $file_system->delete($uploaded_file['path']); + $this->fileSystem->delete($uploaded_file['path']); } catch (Exception $e) { watchdog_exception('media_bulk_upload', $e);