diff --git a/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php b/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php index 1025c35..25efb48 100644 --- a/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php +++ b/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php @@ -4,7 +4,7 @@ namespace Drupal\paragraphs\Plugin\Field\FieldWidget; use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\Html; -use Drupal\Core\Entity\Entity; +use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\RevisionableInterface; @@ -234,47 +234,19 @@ class InlineParagraphsWidget extends WidgetBase { } } - /** - * Localised Paragraphs. - * - * If the parent field is marked as translatable, assume paragraphs - * to be localized (host entity expects different paragraphs for - * different languages) - */ - else if ($items->getFieldDefinition()->isTranslatable()) { - // Get the paragraph item as an array of values. - $paragraph_array = $paragraphs_entity->toArray(); - // Get entity type if has not been previously fetched. - if (!isset($entity_type)) { - $entity_type = $entity_manager->getDefinition($target_type); - $bundle_key = $entity_type->getKey('bundle'); - } - - // Create a new paragraph entity for this language. - $new_paragraph = array( - $bundle_key => $paragraphs_entity->bundle(), - 'langcode' => $langcode - ); - - // Loop through all fields in the paragraph and add to new entity. - foreach ($paragraphs_entity->getFieldDefinitions() as $key => $field) { - // Check that the value is a field config and not empty. - if ($field instanceof FieldConfig && !empty($paragraph_array[$key])) { - $new_paragraph[$key] = $paragraph_array[$key]; - } - } - // Set the current entity to the new paragraph entity. - $paragraphs_entity = $entity_manager->getStorage($target_type)->create($new_paragraph); + // Localised Paragraphs. + // If the parent field is marked as translatable, assume paragraphs + // to be localized (host entity expects different paragraphs for + // different languages) + elseif ($items->getFieldDefinition()->isTranslatable()) { + $paragraphs_entity = $this->cloneReferencedEntity($paragraphs_entity, $langcode); } - /** - * Translated Paragraphs - * - * If the parent field is not translatable, assume the paragraph - * entity itself (rather the fields within it) are marked as - * translatable. (host entity expects same paragraphs in different - * languages). - */ + // Translated Paragraphs + // If the parent field is not translatable, assume the paragraph + // entity itself (rather the fields within it) are marked as + // translatable. (host entity expects same paragraphs in different + // languages). else { // Add translation if missing for the target language. if (!$paragraphs_entity->hasTranslation($langcode)) { @@ -776,7 +748,7 @@ class InlineParagraphsWidget extends WidgetBase { foreach ($bundles as $machine_name => $bundle) { if ($dragdrop_settings || (!count($this->getSelectionHandlerSetting('target_bundles')) - || in_array($machine_name, $this->getSelectionHandlerSetting('target_bundles')))) { + || in_array($machine_name, $this->getSelectionHandlerSetting('target_bundles')))) { $options[$machine_name] = $bundle['label']; if ($access_control_handler->createAccess($machine_name)) { @@ -873,7 +845,7 @@ class InlineParagraphsWidget extends WidgetBase { ); if ($drop_button) { $elements['add_more']['add_more_button_' . $machine_name]['#prefix'] = '
  • '; - $elements['add_more']['add_more_button_' . $machine_name]['#suffix'] = '
  • '; + $elements['add_more']['add_more_button_' . $machine_name]['#suffix'] = '
  • '; } } } @@ -1125,9 +1097,8 @@ class InlineParagraphsWidget extends WidgetBase { /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $display */ $display = $widget_state['paragraphs'][$item['_original_delta']]['display']; - if ($widget_state['paragraphs'][$delta]['mode'] == 'edit') { - $display->extractFormValues($paragraphs_entity, $element[$item['_original_delta']]['subform'], $form_state); - } + $display->extractFormValues($paragraphs_entity, $element[$item['_original_delta']]['subform'], $form_state); + $paragraphs_entity->setNewRevision($new_revision); // A content entity form saves without any rebuild. It needs to set the // language to update it in case of language change. @@ -1232,4 +1203,63 @@ class InlineParagraphsWidget extends WidgetBase { } return $element; } -} + + /** + * Clones Paragraphs (and field_collections) recursively, preparing them to be + * passed to the translated paragraph widget. + * + * @param \Drupal\Core\Entity\ContentEntityInterface $entity_to_clone The Entity + * to clone + * @param string $langcode language code for all the clone entities created. + * @return \Drupal\Core\Entity\ContentEntityInterface New entity object which + * has the same data as the original $entity_to_clone, Note this entity is not + * saved. + */ + protected function cloneReferencedEntity(ContentEntityInterface $entity_to_clone, $langcode) { + $entity_manager = \Drupal::entityTypeManager(); + + // Get the paragraph item as an array of values. + $paragraph_array = $entity_to_clone->toArray(); + $target_type = $entity_to_clone->getEntityTypeId(); + $entity_type = $entity_manager->getDefinition($target_type); + $bundle_key = $entity_type->getKey('bundle'); + + // Create a new entity for this language. + $new_entity = array( + $bundle_key => $entity_to_clone->bundle(), + 'langcode' => $langcode + ); + + // Loop through all fields in the paragraph and add to new entity. + foreach ($entity_to_clone->getFieldDefinitions() as $field_name => $field_definition) { + // Check that the value is a field config and not empty. + if ($field_definition instanceof FieldConfig && !empty($paragraph_array[$field_name])) { + if ($this->checkEntityTypeCloneable($field_definition->getSetting('target_type'))) { + /** @var [EntityInterface] $entities */ + $entities = $entity_to_clone->get($field_name)->referencedEntities(); + $cloned_entites = []; + foreach ($entities as $entity){ + $cloned_entites[] = $this->cloneReferencedEntity($entity, $langcode); + } + $new_entity[$field_name] = $cloned_entites; + } + else { + $new_entity[$field_name] = $paragraph_array[$field_name]; + } + } + } + return $entity_manager->getStorage($target_type)->create($new_entity); + } + + /** + * Checks whether we support cloning a certain entity type or not. + * + * @param string $entity_type_id the entity type ID to check whether it's cloneable + * @return bool + */ + protected function checkEntityTypeCloneable($entity_type_id){ + // @todo: maybe this list should be moved to widget configs with some sensible + // default? + return in_array($entity_type_id, ['field_collection_item', 'paragraph']); + } +} \ No newline at end of file