3 namespace Drupal\dropzonejs_eb_widget\Plugin\EntityBrowser\Widget;
5 use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
6 use Drupal\Core\Entity\EntityTypeManagerInterface;
7 use Drupal\Core\Extension\ModuleHandlerInterface;
8 use Drupal\Core\Form\FormStateInterface;
9 use Drupal\Core\Render\Element;
10 use Drupal\Core\Session\AccountProxyInterface;
11 use Drupal\Core\Utility\Token;
12 use Drupal\dropzonejs\DropzoneJsUploadSaveInterface;
13 use Drupal\dropzonejs\Events\DropzoneMediaEntityCreateEvent;
14 use Drupal\dropzonejs\Events\Events;
15 use Drupal\entity_browser\WidgetBase;
16 use Drupal\entity_browser\WidgetValidationManager;
17 use Drupal\inline_entity_form\Element\InlineEntityForm;
18 use Symfony\Component\DependencyInjection\ContainerInterface;
19 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
22 * Provides an Entity Browser widget that uploads and edit new files.
24 * @EntityBrowserWidget(
25 * id = "dropzonejs_media_entity_inline_entity_form",
26 * label = @Translation("Media Entity DropzoneJS with edit"),
27 * description = @Translation("Adds DropzoneJS upload integration that saves Media entities and allows to edit them."),
31 class InlineEntityFormMediaWidget extends MediaEntityDropzoneJsEbWidget {
34 * The entity display repository.
36 * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
38 protected $entityDisplayRepository;
41 * Constructs widget plugin.
43 * @param array $configuration
44 * A configuration array containing information about the plugin instance.
45 * @param string $plugin_id
46 * The plugin_id for the plugin instance.
47 * @param mixed $plugin_definition
48 * The plugin implementation definition.
49 * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
50 * Event dispatcher service.
51 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
52 * The entity type manager service.
53 * @param \Drupal\entity_browser\WidgetValidationManager $validation_manager
54 * The Widget Validation Manager service.
55 * @param \Drupal\dropzonejs\DropzoneJsUploadSaveInterface $dropzonejs_upload_save
56 * The upload saving dropzonejs service.
57 * @param \Drupal\Core\Session\AccountProxyInterface $current_user
58 * The current user service.
59 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
60 * The module handler service.
61 * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
62 * The entity display repository service.
64 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, Token $token, ModuleHandlerInterface $module_handler, EntityDisplayRepositoryInterface $entity_display_repository) {
65 parent::__construct($configuration, $plugin_id, $plugin_definition, $event_dispatcher, $entity_type_manager, $validation_manager, $dropzonejs_upload_save, $current_user, $token, $module_handler);
67 $this->entityDisplayRepository = $entity_display_repository;
73 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
78 $container->get('event_dispatcher'),
79 $container->get('entity_type.manager'),
80 $container->get('plugin.manager.entity_browser.widget_validation'),
81 $container->get('dropzonejs.upload_save'),
82 $container->get('current_user'),
83 $container->get('token'),
84 $container->get('module_handler'),
85 $container->get('entity_display.repository')
92 public function defaultConfiguration() {
94 'form_mode' => 'default',
95 ] + parent::defaultConfiguration();
101 public function getForm(array &$original_form, FormStateInterface $form_state, array $additional_widget_parameters) {
102 $form = parent::getForm($original_form, $form_state, $additional_widget_parameters);
104 // @todo Remove this when/if EB provides a way to define dependencies.
105 if (!$this->moduleHandler->moduleExists('inline_entity_form')) {
107 '#type' => 'container',
109 '#markup' => $this->t('Missing requirement: in order to use this widget you have to install Inline entity form module first'),
114 $form['#attached']['library'][] = 'dropzonejs_eb_widget/ief_edit';
117 '#value' => $this->t('Edit'),
119 'class' => ['js-hide'],
122 'wrapper' => 'ief-dropzone-upload',
123 'callback' => [static::class, 'onEdit'],
127 [$this, 'submitEdit'],
131 $form['entities']['#prefix'] = '<div id="ief-dropzone-upload">';
132 $form['entities']['#suffix'] = '</div>';
134 $form += ['entities' => []];
135 if ($entities = $form_state->get('uploaded_entities')) {
136 foreach ($entities as $entity) {
137 /** @var \Drupal\Core\Entity\EntityInterface $entity */
138 $form['entities'][$entity->uuid()] = [
139 '#type' => 'inline_entity_form',
140 '#entity_type' => $entity->getEntityTypeId(),
141 '#bundle' => $entity->bundle(),
142 '#default_value' => $entity,
143 '#form_mode' => $this->configuration['form_mode'],
148 if (!empty(Element::children($form['entities']))) {
149 // Make it possible to select those submitted entities.
150 $pos = array_search('dropzonejs-disable-submit', $original_form['#attributes']['class']);
151 if ($pos !== FALSE) {
152 unset($original_form['#attributes']['class'][$pos]);
156 $form['actions']['submit'] += ['#submit' => []];
162 * Submit callback for the edit button.
166 * @param \Drupal\Core\Form\FormStateInterface $form_state
169 public function submitEdit(array $form, FormStateInterface $form_state) {
170 $form_state->setRebuild(TRUE);
172 // Files have to saved before they can be viewed in the IEF form.
173 $media_entities = $this->prepareEntities($form, $form_state);
174 $source_field = $this->getBundle()->getTypeConfiguration()['source_field'];
175 foreach ($media_entities as $media_entity) {
176 /** @var \Drupal\file\Entity\File $file */
177 $file = $media_entity->$source_field->entity;
179 $media_entity->$source_field->target_id = $file->id();
182 $form_state->set('uploaded_entities', $media_entities);
186 * Ajax callback triggered when hitting the edit button.
192 * Returns the entire form.
194 public static function onEdit(array $form) {
195 return $form['widget']['entities'];
201 public function validate(array &$form, FormStateInterface $form_state) {
202 // Skip the DropzoneJsEbWidget specific validations.
203 WidgetBase::validate($form, $form_state);
207 * Prepares entities from the form.
211 * @param \Drupal\Core\Form\FormStateInterface $form_state
214 * @return \Drupal\media_entity\MediaInterface[]
215 * The prepared media entities.
217 protected function prepareEntitiesFromForm(array $form, FormStateInterface $form_state) {
218 $media_entities = [];
219 foreach (Element::children($form['widget']['entities']) as $key) {
220 /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
221 $entity = $form['widget']['entities'][$key]['#entity'];
222 $inline_entity_form_handler = InlineEntityForm::getInlineFormHandler($entity->getEntityTypeId());
223 $inline_entity_form_handler->entityFormSubmit($form['widget']['entities'][$key], $form_state);
224 $media_entities[] = $entity;
226 return $media_entities;
232 public function submit(array &$element, array &$form, FormStateInterface $form_state) {
233 $media_entities = $this->prepareEntitiesFromForm($form, $form_state);
234 $source_field = $this->getBundle()->getTypeConfiguration()['source_field'];
236 foreach ($media_entities as $media_entity) {
237 $file = $media_entity->{$source_field}->entity;
238 /** @var \Drupal\dropzonejs\Events\DropzoneMediaEntityCreateEvent $event */
239 $event = $this->eventDispatcher->dispatch(Events::MEDIA_ENTITY_CREATE, new DropzoneMediaEntityCreateEvent($media_entity, $file, $form, $form_state, $element));
240 $media_entity = $event->getMediaEntity();
241 $media_entity->save();
244 if (!empty(array_filter($media_entities))) {
245 $this->selectEntities($media_entities, $form_state);
246 $this->clearFormValues($element, $form_state);
253 protected function clearFormValues(array &$element, FormStateInterface $form_state) {
254 parent::clearFormValues($element, $form_state);
255 // Clear uploaded_entities to get a clean form in multi-step selection.
256 $form_state->set('uploaded_entities', []);
262 public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
263 $form = parent::buildConfigurationForm($form, $form_state);
264 $form['form_mode'] = [
266 '#title' => $this->t('Form mode'),
267 '#options' => $this->entityDisplayRepository->getFormModeOptions('media'),
268 '#default_value' => $this->configuration['form_mode'],