diff --git a/modules/eb_widget/src/Plugin/EntityBrowser/Widget/DropzoneJsEbWidget.php b/modules/eb_widget/src/Plugin/EntityBrowser/Widget/DropzoneJsEbWidget.php index a43cefe..5de602d 100644 --- a/modules/eb_widget/src/Plugin/EntityBrowser/Widget/DropzoneJsEbWidget.php +++ b/modules/eb_widget/src/Plugin/EntityBrowser/Widget/DropzoneJsEbWidget.php @@ -1,18 +1,16 @@ dropzoneJsUploadSave = $dropzonejs_upload_save; $this->currentUser = $current_user; } @@ -72,7 +81,8 @@ class DropzoneJsEbWidget extends WidgetBase { $plugin_id, $plugin_definition, $container->get('event_dispatcher'), - $container->get('entity.manager'), + $container->get('entity_type.manager'), + $container->get('plugin.manager.entity_browser.widget_validation'), $container->get('dropzonejs.upload_save'), $container->get('current_user') ); @@ -93,7 +103,9 @@ class DropzoneJsEbWidget extends WidgetBase { /** * {@inheritdoc} */ - public function getForm(array &$original_form, FormStateInterface $form_state, array $aditional_widget_parameters) { + public function getForm(array &$original_form, FormStateInterface $form_state, array $additional_widget_parameters) { + $form = parent::getForm($original_form, $form_state, $additional_widget_parameters); + $config = $this->getConfiguration(); $form['upload'] = [ '#title' => t('File upload'), @@ -114,8 +126,53 @@ class DropzoneJsEbWidget extends WidgetBase { /** * {@inheritdoc} */ + public function prepareEntities(array $form, FormStateInterface $form_state) { + return $this->getFiles($form, $form_state); + } + + /** + * Gets uploaded files. + * + * We implement this to allow child classes to operate on different entity + * type while still having access to the files in the validate callback here. + * + * @param array $form + * Form structure. + * @param FormStateInterface $form_state + * Form state object. + * + * @return \Drupal\file\FileInterface[] + * Array of uploaded files. + */ + protected function getFiles(array $form, FormStateInterface $form_state) { + if (!$this->files) { + $this->files = []; + foreach ($form_state->getValue(['upload', 'uploaded_files'], []) as $file) { + $entity = $this->dropzoneJsUploadSave->fileEntityFromUri($file['path'], $this->currentUser); + //$destination = \Drupal::token()->replace($this->configuration['upload_location']); + //file_unmanaged_move($entity, $destination, FILE_EXISTS_RENAME); + $this->files[] = $entity; + } + } + + return $this->files; + } + + /** + * Gets upload location. + * + * @return string + * Destination folder URI. + */ + protected function getUploadLocation() { + return \Drupal::token()->replace($this->configuration['upload_location']); + } + + /** + * {@inheritdoc} + */ public function validate(array &$form, FormStateInterface $form_state) { - $upload = $form_state->getValue(['upload'], []); + $files = $this->getFiles($form, $form_state); $trigger = $form_state->getTriggeringElement(); $config = $this->getConfiguration(); @@ -126,14 +183,13 @@ class DropzoneJsEbWidget extends WidgetBase { // Validate if we are in fact uploading a files and all of them have the // right extensions. Although DropzoneJS should not even upload those files // it's still better not to rely only on client side validation. - if ($trigger['#value'] == 'Select') { - if (!empty($upload['uploaded_files'])) { + if ($trigger['#type'] == 'submit' && $trigger['#name'] == 'op') { + if (!empty($files)) { $errors = []; // @todo Check per user size allowance. $additional_validators = ['file_validate_size' => [Bytes::toInt($max_filesize), 0]]; - foreach ($upload['uploaded_files'] as $file) { - $file = $this->dropzoneJsUploadSave->fileEntityFromUri($file['path'], $this->currentUser); + foreach ($files as $file) { $errors += $this->dropzoneJsUploadSave->validateFile($file, $extensions, $additional_validators); } @@ -141,10 +197,20 @@ class DropzoneJsEbWidget extends WidgetBase { // @todo Output the actual errors from validateFile. $form_state->setError($form['widget']['upload'], t('Some files that you are trying to upload did not pass validation. Requirements are: max file %size, allowed extensions are %extensions', ['%size' => $max_filesize, '%extensions' => $extensions])); } + + $upload_location = $this->getUploadLocation(); + if (!file_prepare_directory($upload_location, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) { + $form_state->setError($form['widget']['upload'], t('Files could not be uploaded because the destination directory %destination is not configured correctly.', ['%destination' => $upload_location])); + } } else { $form_state->setError($form['widget']['upload'], t('At least one valid file should be uploaded.')); } + + // If there weren't any errors set, run the normal validators. + if (empty($form_state->getErrors())) { + parent::validate($form, $form_state); + } } } @@ -152,19 +218,13 @@ class DropzoneJsEbWidget extends WidgetBase { * {@inheritdoc} */ public function submit(array &$element, array &$form, FormStateInterface $form_state) { - $files = []; - $upload = $form_state->getValue('upload'); - $config = $this->getConfiguration(); - $user = \Drupal::currentUser(); - - foreach ($upload['uploaded_files'] as $uploaded_file) { - $file = $this->dropzoneJsUploadSave->saveFile($uploaded_file['path'], $config['settings']['upload_location'], $config['settings']['extensions'], $user); + $destination = $this->getUploadLocation(); - if ($file) { - $file->setPermanent(); - $file->save(); - $files[] = $file; - } + $files = []; + foreach ($this->prepareEntities($form, $form_state) as $file) { + $file->setPermanent(); + // This saves the entity. + $files[] = file_move($file, $destination . '/' . $file->getFilename(), FILE_EXISTS_RENAME); } if (!empty(array_filter($files))) { @@ -279,4 +339,11 @@ class DropzoneJsEbWidget extends WidgetBase { parent::submitConfigurationForm($form, $form_state); $this->configuration['max_filesize'] = $this->configuration['max_filesize'] . 'M'; } + + /** + * {@inheritdoc} + */ + public function __sleep() { + return array_diff(parent::__sleep(), ['files']); + } } diff --git a/modules/eb_widget/src/Plugin/EntityBrowser/Widget/MediaEntityDropzoneJsEbWidget.php b/modules/eb_widget/src/Plugin/EntityBrowser/Widget/MediaEntityDropzoneJsEbWidget.php index fa764dd..b1995a5 100644 --- a/modules/eb_widget/src/Plugin/EntityBrowser/Widget/MediaEntityDropzoneJsEbWidget.php +++ b/modules/eb_widget/src/Plugin/EntityBrowser/Widget/MediaEntityDropzoneJsEbWidget.php @@ -6,10 +6,7 @@ namespace Drupal\dropzonejs_eb_widget\Plugin\EntityBrowser\Widget; -use Drupal\Component\Utility\Bytes; -use Drupal\Component\Utility\NestedArray; -use Drupal\Core\Entity\EntityManagerInterface; -use Drupal\Core\Entity\EntityStorageInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Link; @@ -17,7 +14,7 @@ use Drupal\Core\Session\AccountProxyInterface; use Drupal\dropzonejs\DropzoneJsUploadSaveInterface; use Drupal\dropzonejs\Events\DropzoneMediaEntityCreateEvent; use Drupal\dropzonejs\Events\Events; -use Drupal\entity_browser\WidgetBase; +use Drupal\entity_browser\WidgetValidationManager; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -41,6 +38,13 @@ class MediaEntityDropzoneJsEbWidget extends DropzoneJsEbWidget { protected $moduleHandler; /** + * Media bundle. + * + * @var \Drupal\media_entity\MediaBundleInterface + */ + protected $bundle; + + /** * Constructs widget plugin. * * @param array $configuration @@ -51,6 +55,10 @@ class MediaEntityDropzoneJsEbWidget extends DropzoneJsEbWidget { * The plugin implementation definition. * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher * Event dispatcher service. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager service. + * @param \Drupal\entity_browser\WidgetValidationManager $validation_manager + * The Widget Validation Manager service. * @param \Drupal\dropzonejs\DropzoneJsUploadSaveInterface $dropzonejs_upload_save * The upload saving dropzonejs service. * @param \Drupal\Core\Session\AccountProxyInterface $current_user @@ -58,8 +66,8 @@ class MediaEntityDropzoneJsEbWidget extends DropzoneJsEbWidget { * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler service. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, EventDispatcherInterface $event_dispatcher, EntityManagerInterface $entity_manager, DropzoneJsUploadSaveInterface $dropzonejs_upload_save, AccountProxyInterface $current_user, ModuleHandlerInterface $module_handler) { - parent::__construct($configuration, $plugin_id, $plugin_definition, $event_dispatcher, $entity_manager, $dropzonejs_upload_save, $current_user); + public function __construct(array $configuration, $plugin_id, $plugin_definition, EventDispatcherInterface $event_dispatcher, EntityTypeManagerInterface $entity_type_manager, WidgetValidationManager $validation_manager, DropzoneJsUploadSaveInterface $dropzonejs_upload_save, AccountProxyInterface $current_user, ModuleHandlerInterface $module_handler) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $event_dispatcher, $entity_type_manager, $validation_manager, $dropzonejs_upload_save, $current_user); $this->moduleHandler = $module_handler; } @@ -72,7 +80,8 @@ class MediaEntityDropzoneJsEbWidget extends DropzoneJsEbWidget { $plugin_id, $plugin_definition, $container->get('event_dispatcher'), - $container->get('entity.manager'), + $container->get('entity_type.manager'), + $container->get('plugin.manager.entity_browser.widget_validation'), $container->get('dropzonejs.upload_save'), $container->get('current_user'), $container->get('module_handler') @@ -95,8 +104,13 @@ class MediaEntityDropzoneJsEbWidget extends DropzoneJsEbWidget { * @return \Drupal\media_entity\MediaBundleInterface */ protected function getBundle() { - return $this->entityManager->getStorage('media_bundle') - ->load($this->configuration['media_entity_bundle']); + if (!$this->bundle) { + $this->bundle = $this->entityTypeManager + ->getStorage('media_bundle') + ->load($this->configuration['media_entity_bundle']); + } + + return $this->bundle; } /** @@ -117,7 +131,7 @@ class MediaEntityDropzoneJsEbWidget extends DropzoneJsEbWidget { $form['media_entity_bundle']['#default_value'] = $bundle->id(); } - $bundles = $this->entityManager->getStorage('media_bundle')->loadMultiple(); + $bundles = $this->entityTypeManager->getStorage('media_bundle')->loadMultiple(); if (!empty($bundles)) { foreach ($bundles as $bundle) { @@ -143,6 +157,7 @@ class MediaEntityDropzoneJsEbWidget extends DropzoneJsEbWidget { // Depend on the media bundle this widget creates. $bundle = $this->getBundle(); $dependencies[$bundle->getConfigDependencyKey()][] = $bundle->getConfigDependencyName(); + $dependencies['module'][] = 'media_entity'; return $dependencies; } @@ -150,44 +165,37 @@ class MediaEntityDropzoneJsEbWidget extends DropzoneJsEbWidget { /** * {@inheritdoc} */ + public function prepareEntities(array $form, FormStateInterface $form_state) { + $entities = []; + + foreach (parent::prepareEntities($form, $form_state) as $file) { + $entities[] = $this->entityTypeManager->getStorage('media')->create([ + 'bundle' => $this->getBundle()->id(), + $this->getBundle()->getTypeConfiguration()['source_field'] => $file, + 'uid' => $this->currentUser->id(), + 'status' => TRUE, + 'type' => $this->getBundle()->getType()->getPluginId(), + ]); + } + + return $entities; + } + + /** + * {@inheritdoc} + */ public function submit(array &$element, array &$form, FormStateInterface $form_state) { - $media_entities = []; - $upload = $form_state->getValue('upload'); - if (isset($upload['uploaded_files']) && is_array($upload['uploaded_files'])) { - - $config = $this->getConfiguration(); - $user = $this->currentUser; - $bundle = $this->getBundle(); - - // First save the file. - foreach ($upload['uploaded_files'] as $uploaded_file) { - $file = $this->dropzoneJsUploadSave->saveFile($uploaded_file['path'], $config['settings']['upload_location'], $config['settings']['extensions'], $user); - - if ($file) { - $file->setPermanent(); - $file->save(); - - // Now save the media entity. - if ($this->moduleHandler->moduleExists('media_entity')) { - /** @var \Drupal\media_entity\MediaInterface $media_entity */ - $media_entity = $this->entityManager->getStorage('media')->create([ - 'bundle' => $bundle->id(), - $bundle->getTypeConfiguration()['source_field'] => $file, - 'uid' => $user->id(), - 'status' => TRUE, - 'type' => $bundle->getType()->getPluginId(), - ]); - $event = $this->eventDispatcher->dispatch(Events::MEDIA_ENTITY_CREATE, new DropzoneMediaEntityCreateEvent($media_entity, $file, $form, $form_state, $element)); - $media_entity = $event->getMediaEntity(); - - $media_entity->save(); - $media_entities[] = $media_entity; - } - else { - drupal_set_message(t('The media entity was not saved, because the media_entity module is not enabled.')); - } - } - } + $media_entities = $this->prepareEntities($form, $form_state); + $source_field = $this->getBundle()->getTypeConfiguration()['source_field']; + + foreach ($media_entities as &$media_entity) { + $file = $media_entity->$source_field->entity; + // This saves the file. + $file = file_move($file, $this->getUploadLocation(), FILE_EXISTS_RENAME); + $file = $media_entity->$source_field->entity = $file; + $event = $this->eventDispatcher->dispatch(Events::MEDIA_ENTITY_CREATE, new DropzoneMediaEntityCreateEvent($media_entity, $file, $form, $form_state, $element)); + $media_entity = $event->getMediaEntity(); + $media_entity->save(); } if (!empty(array_filter($media_entities))) { @@ -195,4 +203,11 @@ class MediaEntityDropzoneJsEbWidget extends DropzoneJsEbWidget { $this->clearFormValues($element, $form_state); } } + + /** + * {@inheritdoc} + */ + public function __sleep() { + return array_diff(parent::__sleep(), ['bundle']); + } }