diff --git a/entity_browser.module b/entity_browser.module index b3b7dd0..51a064e 100644 --- a/entity_browser.module +++ b/entity_browser.module @@ -56,6 +56,7 @@ function entity_browser_form_alter(&$form, FormStateInterface &$form_state) { 'options' => [ 'query' => [ 'details_id' => \Drupal::request()->query->get('details_id'), + 'langcode' => \Drupal::request()->query->get('langcode'), ], ], ]; diff --git a/js/entity_browser.common.js b/js/entity_browser.common.js index d28e176..5fec959 100644 --- a/js/entity_browser.common.js +++ b/js/entity_browser.common.js @@ -143,4 +143,23 @@ } }; + // AJAX beforeSubmit callback. + var ajaxBeforeSubmitOriginal = Drupal.Ajax.prototype.beforeSubmit; + Drupal.Ajax.prototype.beforeSubmit = function(form_values, element, options) { + if (this.$form) { + + // If there is a langcode select element on the form, use its value in the + // AJAX call. + var langcodeSelectElementName = $(this.element).data('entity-browser-langcode-select-element-name'); + if (langcodeSelectElementName) { + var $langcode = this.$form.find('select[name="' + langcodeSelectElementName + '"]'); + if ($langcode.length) { + options.url = options.url.replace(/([?&]langcode=)[^&]+/, '$1' + $langcode.val() + '$2'); + } + } + } + + ajaxBeforeSubmitOriginal.call(this, form_values, element, options); + }; + }(jQuery, Drupal, drupalSettings)); diff --git a/src/Controllers/EntityBrowserController.php b/src/Controllers/EntityBrowserController.php index aebb4be..fbc3daf 100644 --- a/src/Controllers/EntityBrowserController.php +++ b/src/Controllers/EntityBrowserController.php @@ -8,6 +8,7 @@ use Drupal\Core\Ajax\OpenDialogCommand; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Form\FormState; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\TypedData\TranslatableInterface; use Drupal\entity_browser\Ajax\ValueUpdatedCommand; use Symfony\Component\HttpFoundation\Request; @@ -31,10 +32,43 @@ class EntityBrowserController extends ControllerBase { public function entityBrowserEdit(EntityInterface $entity, Request $request) { // Build the entity edit form. $form_object = $this->entityTypeManager()->getFormObject($entity->getEntityTypeId(), 'edit'); - $form_object->setEntity($entity); $form_state = (new FormState()) ->setFormObject($form_object) ->disableRedirect(); + + // Prepare an entity translation in the parent form language. + if ($entity instanceof TranslatableInterface && $entity->isTranslatable()) { + $langcode = $request->query->get('langcode'); + if (is_string($langcode)) { + try { + if (!$entity->hasTranslation($langcode)) { + // Get the selected translation of the entity. + $entity_langcode = $entity->language()->getId(); + $source = $form_state->get(['content_translation', 'source']); + $source_langcode = $source ? $source->getId() : $entity_langcode; + $entity = $entity->getTranslation($source_langcode); + // The entity has no content translation source field if + // no entity field is translatable, even if the host is. + if ($entity->hasField('content_translation_source')) { + // Initialise the translation with source language values. + $entity->addTranslation($langcode, $entity->toArray()); + $translation = $entity->getTranslation($langcode); + $manager = \Drupal::service('content_translation.manager'); + $manager->getTranslationMetadata($translation)->setSource($entity->language()->getId()); + } + } + $form_state->set('langcode', $langcode); + } + catch (\InvalidArgumentException $e) { + // It could be that the parent form language is inappropriate for + // translations. Do not change form langcode in this case. Let it + // fallback to the default behavior - edit entity in its original + // language. + } + } + } + + $form_object->setEntity($entity); // Building the form also submits. $form = $this->formBuilder()->buildForm($form_object, $form_state); diff --git a/src/Plugin/Field/FieldWidget/EntityReferenceBrowserWidget.php b/src/Plugin/Field/FieldWidget/EntityReferenceBrowserWidget.php index 0ac85bc..bd2ab2d 100644 --- a/src/Plugin/Field/FieldWidget/EntityReferenceBrowserWidget.php +++ b/src/Plugin/Field/FieldWidget/EntityReferenceBrowserWidget.php @@ -2,6 +2,7 @@ namespace Drupal\entity_browser\Plugin\Field\FieldWidget; +use Drupal\Core\Entity\EntityFormInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\entity_browser\Element\EntityBrowserElement; use Symfony\Component\Validator\ConstraintViolationInterface; @@ -373,7 +374,7 @@ class EntityReferenceBrowserWidget extends WidgetBase implements ContainerFactor $field_parents = $element['#field_parents']; - $element['current'] = $this->displayCurrentSelection($details_id, $field_parents, $entities); + $element['current'] = $this->displayCurrentSelection($details_id, $field_parents, $entities, $form_state->get('langcode')); return $element; } @@ -477,7 +478,7 @@ class EntityReferenceBrowserWidget extends WidgetBase implements ContainerFactor * @return array * The render array for the current selection. */ - protected function displayCurrentSelection($details_id, $field_parents, $entities) { + protected function displayCurrentSelection($details_id, $field_parents, $entities, $langcode = NULL) { $field_widget_display = $this->fieldDisplayManager->createInstance( $this->getSetting('field_widget_display'), @@ -488,7 +489,7 @@ class EntityReferenceBrowserWidget extends WidgetBase implements ContainerFactor '#theme_wrappers' => ['container'], '#attributes' => ['class' => ['entities-list']], 'items' => array_map( - function (ContentEntityInterface $entity, $row_id) use ($field_widget_display, $details_id, $field_parents) { + function (ContentEntityInterface $entity, $row_id) use ($field_widget_display, $details_id, $field_parents, $langcode) { $display = $field_widget_display->view($entity); $edit_button_access = $this->getSetting('field_widget_edit'); if ($entity->getEntityTypeId() == 'file') { @@ -537,9 +538,11 @@ class EntityReferenceBrowserWidget extends WidgetBase implements ContainerFactor 'options' => [ 'query' => [ 'details_id' => $details_id, + 'langcode' => $langcode, ], ], ], + '#after_build' => [[$this, 'ajaxEditButtonAfterBuild']], '#access' => $edit_button_access, ], ]; @@ -751,4 +754,24 @@ class EntityReferenceBrowserWidget extends WidgetBase implements ContainerFactor return FALSE; } + /** + * After build callback for the AJAX "Edit" buttons. + */ + public function ajaxEditButtonAfterBuild(array $element, FormStateInterface $form_state) { + $form_object = $form_state->getFormObject(); + if ($form_object instanceof EntityFormInterface) { + $form = $form_state->getCompleteForm(); + $langcode_key = $form_object->getEntity()->getEntityType()->getKey('langcode'); + + // If there is a langcode select element on the form - pass its name as + // data attribute for further use in JS. + if ($langcode_key && isset($form[$langcode_key]['widget'])) { + $path = array_merge($form[$langcode_key]['widget']['#field_parents'], [$langcode_key, 0, 'value']); + $name = array_shift($path) . '[' . implode('][', $path) . ']'; + $element['#attributes']['data-entity-browser-langcode-select-element-name'] = $name; + } + } + return $element; + } + } diff --git a/src/Plugin/Field/FieldWidget/FileBrowserWidget.php b/src/Plugin/Field/FieldWidget/FileBrowserWidget.php index 7d87645..4df7c3e 100644 --- a/src/Plugin/Field/FieldWidget/FileBrowserWidget.php +++ b/src/Plugin/Field/FieldWidget/FileBrowserWidget.php @@ -196,7 +196,7 @@ class FileBrowserWidget extends EntityReferenceBrowserWidget { /** * {@inheritdoc} */ - protected function displayCurrentSelection($details_id, $field_parents, $entities) { + protected function displayCurrentSelection($details_id, $field_parents, $entities, $langcode = NULL) { $field_type = $this->fieldDefinition->getType(); $field_settings = $this->fieldDefinition->getSettings(); $field_machine_name = $this->fieldDefinition->getName(); @@ -344,7 +344,13 @@ class FileBrowserWidget extends EntityReferenceBrowserWidget { '#value' => $this->t('Edit'), '#ajax' => [ 'url' => Url::fromRoute('entity_browser.edit_form', ['entity_type' => $entity->getEntityTypeId(), 'entity' => $entity_id]), - 'options' => ['query' => ['details_id' => $details_id]], + 'options' => [ + 'query' => [ + 'details_id' => $details_id, + 'langcode' => $langcode, + ], + ], + '#after_build' => [[$this, 'ajaxEditButtonAfterBuild']], ], '#attributes' => [ 'data-entity-id' => $entity->getEntityTypeId() . ':' . $entity->id(),