diff --git a/src/Plugin/Field/FieldWidget/LayoutBuilderCopyWidget.php b/src/Plugin/Field/FieldWidget/LayoutBuilderCopyWidget.php index 7b2d9bb..5d9719e 100644 --- a/src/Plugin/Field/FieldWidget/LayoutBuilderCopyWidget.php +++ b/src/Plugin/Field/FieldWidget/LayoutBuilderCopyWidget.php @@ -257,9 +257,8 @@ class LayoutBuilderCopyWidget extends WidgetBase { /** @var \Drupal\block_content\BlockContentInterface $block */ /** @var \Drupal\block_content\BlockContentInterface $replicated_block */ $block = \Drupal::service('entity_type.manager')->getStorage('block_content')->loadRevision($configuration['block_revision_id']); - $replicated_block = $this->cloneEntity('block_content', $block->id()); + $replicated_block = $this->cloneEntity('block_content', $block->id(), $entity); if ($replicated_block) { - $replicated_block->set('langcode', $entity->language()->getId()); $replicated_block->save(); $configuration = $this->updateComponentConfiguration($configuration, $replicated_block); $cloned_component->setConfiguration($configuration); @@ -295,10 +294,11 @@ class LayoutBuilderCopyWidget extends WidgetBase { * * @param $entity_type_id * @param $entity_id + * @param ContentEntityInterface $layout_entity * * @return \Drupal\Core\Entity\EntityInterface|NULL */ - protected function cloneEntity($entity_type_id, $entity_id) { + protected function cloneEntity($entity_type_id, $entity_id, ContentEntityInterface $layout_entity) { $clone = NULL; try { @@ -306,33 +306,23 @@ class LayoutBuilderCopyWidget extends WidgetBase { /** @var \Drupal\Core\Entity\EntityInterface $clone */ $entity = \Drupal::service('entity_type.manager')->getStorage($entity_type_id)->load($entity_id); $clone = $entity->createDuplicate(); + $clone->set('langcode', $layout_entity->language()->getId()); /** @var \Drupal\Core\Field\FieldDefinitionInterface[] $field_definitions */ $field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle()); foreach ($field_definitions as $definition) { - - // Support for Entity reference revisions. - if ($definition->getFieldStorageDefinition()->getType() == 'entity_reference_revisions') { - $new_values = []; - $target_type = $definition->getFieldStorageDefinition()->getSetting('target_type'); - $values = $clone->get($definition->getName())->getValue(); - if (!empty($values)) { - foreach ($values as $value) { - /** @var \Drupal\Core\Entity\EntityInterface $reference */ - /** @var \Drupal\Core\Entity\EntityInterface $reference_clone */ - $reference = \Drupal::service('entity_type.manager')->getStorage($target_type)->load($value['target_id']); - $reference_clone = $reference->createDuplicate(); - $reference_clone->save(); - $new_values[] = [ - 'target_id' => $reference_clone->id(), - 'target_revision_id' => $reference_clone->getRevisionId(), - ]; - } - - if (!empty($new_values)) { - $clone->set($definition->getName(), $new_values); + switch ($definition->getFieldStorageDefinition()->getType()) { + case 'entity_reference_revisions': + // Support for Entity reference revisions. + $this->handleEntityReferenceRevisions($clone, $definition); + break; + + case 'entity_reference': + // Support for Entity reference fields that target inline blocks. + if ($definition->getSetting('target_type') == 'block_content') { + $this->handleInlineBlockEntityReferences($clone, $definition, $layout_entity); } - } + break; } } } @@ -369,4 +359,84 @@ class LayoutBuilderCopyWidget extends WidgetBase { $configuration["block_revision_id"] = $replicated_block->getRevisionId(); return $configuration; } + + /** + * Clone the targets of entity reference revision fields. + * + * @param Drupal\Core\Entity\EntityInterface $clone + * The cloned entity, which still has the same entity reference revision + * targets as the original. + * @param Drupal\Core\Field\FieldDefinitionInterface $definition + * The field definition of type entity_reference_revisions. + */ + protected function handleEntityReferenceRevisions($clone, $definition) { + $target_type = $definition->getFieldStorageDefinition()->getSetting('target_type'); + $values = $clone->get($definition->getName())->getValue(); + if (empty($values)) { + return; + } + + $new_values = []; + foreach ($values as $value) { + /** @var \Drupal\Core\Entity\EntityInterface $reference */ + /** @var \Drupal\Core\Entity\EntityInterface $reference_clone */ + $reference = \Drupal::service('entity_type.manager')->getStorage($target_type)->load($value['target_id']); + $reference_clone = $reference->createDuplicate(); + $reference_clone->save(); + $new_values[] = [ + 'target_id' => $reference_clone->id(), + 'target_revision_id' => $reference_clone->getRevisionId(), + ]; + } + + if (!empty($new_values)) { + $clone->set($definition->getName(), $new_values); + } + } + + /** + * Clone the targets of entity reference fields if they are inline blocks. + * + * @param Drupal\Core\Entity\EntityInterface $clone + * The cloned entity, which still has the same entity reference targets as + * the original. + * @param Drupal\Core\Field\FieldDefinitionInterface $definition + * The field definition of type entity_reference. + * @param ContentEntityInterface $layout_entity + * Then entity with a layout that will include $clone. + */ + protected function handleInlineBlockEntityReferences($clone, $definition, $layout_entity) { + $values = $clone->get($definition->getName())->getValue(); + if (empty($values)) { + return; + } + + $block_storage = \Drupal::service('entity_type.manager')->getStorage('block_content'); + $new_values = []; + foreach ($values as $value) { + /** @var \Drupal\Core\Entity\EntityInterface $nested_block */ + /** @var \Drupal\Core\Entity\EntityInterface $nested_clone */ + $nested_block = $block_storage->load($value['target_id']); + if (empty($nested_block) || $nested_block->isReusable()) { + $new_values[] = [ + 'target_id' => $value['target_id'], + ]; + continue; + } + $nested_clone = $this->cloneEntity('block_content', $nested_block->id(), $layout_entity); + if (empty($nested_clone)) { + continue; + } + $nested_clone->save(); + \Drupal::service('inline_block.usage')->addUsage($nested_clone->id(), $layout_entity); + $new_values[] = [ + 'target_id' => $nested_clone->id(), + ]; + } + + if (!empty($new_values)) { + $clone->set($definition->getName(), $new_values); + } + } + }