Skip to content
Snippets Groups Projects
Commit df1c9084 authored by Pravin Gaikwad's avatar Pravin Gaikwad
Browse files

Revert "Issue #3050027 by carolpettirossi, tim-diels, Rajeshreeputra,...

Revert "Issue #3050027 by carolpettirossi, tim-diels, Rajeshreeputra, mohammedOdeh, podarok: Inline Blocks on Layout Builder Fail to Clone Correctly"

This reverts commit aaa4d9a0.
parent 5cbfafdb
No related branches found
No related tags found
No related merge requests found
......@@ -2,7 +2,6 @@
namespace Drupal\entity_clone\EntityClone\Content;
use Drupal\block_content\BlockContentInterface;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\content_moderation\Entity\ContentModerationState;
use Drupal\content_moderation\Plugin\Field\ModerationStateFieldItemList;
......@@ -10,20 +9,15 @@ use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityChangedInterface;
use Drupal\Core\Entity\EntityHandlerInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Entity\TranslatableInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Field\FieldConfigInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\entity_clone\EntityClone\EntityCloneInterface;
use Drupal\entity_clone\EntityCloneClonableFieldInterface;
use Drupal\layout_builder\InlineBlockUsageInterface;
use Drupal\layout_builder\Section;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -66,13 +60,6 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
*/
protected $currentUser;
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Constructs a new ContentEntityCloneBase.
*
......@@ -86,21 +73,17 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
* The current user.
* @param \Drupal\entity_clone\EntityCloneClonableFieldInterface $entity_clone_clonable_field
* The entity clone clonable field service.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler service.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager,
$entity_type_id,
TimeInterface $time_service,
AccountProxyInterface $current_user,
EntityCloneClonableFieldInterface $entity_clone_clonable_field,
ModuleHandlerInterface $module_handler) {
EntityCloneClonableFieldInterface $entity_clone_clonable_field) {
$this->entityTypeManager = $entity_type_manager;
$this->entityTypeId = $entity_type_id;
$this->timeService = $time_service;
$this->currentUser = $current_user;
$this->entityCloneClonableField = $entity_clone_clonable_field;
$this->moduleHandler = $module_handler;
}
/**
......@@ -113,8 +96,7 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
$entity_type->id(),
$container->get('datetime.time'),
$container->get('current_user'),
$container->get('entity_clone.clonable_field'),
$container->get('module_handler')
$container->get('entity_clone.clonable_field')
);
}
......@@ -124,19 +106,11 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
public function cloneEntity(EntityInterface $entity, EntityInterface $cloned_entity, array $properties = [], array &$already_cloned = []) {
// Clone referenced entities.
$already_cloned[$entity->getEntityTypeId()][$entity->id()] = $cloned_entity;
$languages = $cloned_entity->getTranslationLanguages(TRUE);
if ($cloned_entity instanceof FieldableEntityInterface && $entity instanceof FieldableEntityInterface) {
foreach ($cloned_entity->getFieldDefinitions() as $field_id => $field_definition) {
if ($cloning_method = $this->getCloneCallback($field_definition)) {
foreach ($languages as $language) {
$cloned_translation = $cloned_entity->getTranslation($language->getId());
$entity_translation = $entity->getTranslation($language->getId());
$field = $entity_translation->get($field_id);
/** @var \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem $value */
if ($field->count() > 0) {
$cloned_translation->set($field_id, $this->$cloning_method($field, $field_definition, $properties, $already_cloned));
}
}
$field = $entity->get($field_id);
if ($this->entityCloneClonableField->isClonable($field_definition, $field)) {
$cloned_entity->set($field_id, $this->cloneReferencedEntities($field, $field_definition, $properties, $already_cloned));
}
}
}
......@@ -146,6 +120,7 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
$cloned_entity->setOwnerId($this->currentUser->id());
// Set owner on translations:
$languages = $cloned_entity->getTranslationLanguages();
foreach ($languages as $langcode => $language) {
$translation = $cloned_entity->getTranslation($langcode);
$translation->setOwnerId($this->currentUser->id());
......@@ -161,7 +136,7 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
// translation gets its publishing status updated according to the
// moderation state. After the entity is saved, we kick in the creation
// of translations of created moderation state entity.
foreach ($languages as $language) {
foreach ($cloned_entity->getTranslationLanguages(TRUE) as $language) {
$translation = $cloned_entity->getTranslation($language->getId());
$translation->set('moderation_state', $cloned_entity->get('moderation_state')->value);
}
......@@ -177,34 +152,9 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
$this->setTranslationModerationState($entity, $cloned_entity);
}
// Set inline block usage after setting the field otherwise there will be
// access issue.
$this->checkAndUpdateInlineBlockUsage($cloned_entity);
return $cloned_entity;
}
/**
* Gets the clone callback.
*
* @return bool
* The clone method, or FALSE when not cloneable.
*/
protected function getCloneCallback(FieldDefinitionInterface $field_definition) {
$cloneable_field_types = [
'entity_reference' => 'cloneReferencedEntities',
'entity_reference_revisions' => 'cloneReferencedEntities',
'layout_section' => 'cloneInlineBlockEntities',
];
$type_is_cloneable = isset($cloneable_field_types[$field_definition->getType()]);
if (($field_definition instanceof FieldConfigInterface) && $type_is_cloneable) {
return $cloneable_field_types[$field_definition->getType()];
}
return FALSE;
}
/**
* Sets the cloned entity's label.
*
......@@ -233,57 +183,6 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
}
}
/**
* Update inline block usage.
*
* @param \Drupal\Core\Entity\EntityInterface $cloned_entity
* The entity.
*/
protected function checkAndUpdateInlineBlockUsage(EntityInterface $cloned_entity) {
if ($this->moduleHandler->moduleExists('layout_builder')
&& $cloned_entity->hasField('layout_builder__layout')) {
// We cannot inject this one.
/** @var \Drupal\layout_builder\InlineBlockUsageInterface $inline_block_usage */
$inline_block_usage = \Drupal::service('inline_block.usage');
$block_content_storage = $this->entityTypeManager->getStorage('block_content');
$this->updateInlineBlockUsage($cloned_entity, $inline_block_usage, $block_content_storage);
}
}
/**
* Update inline block usage.
*
* @param \Drupal\Core\Entity\EntityInterface $cloned_entity
* The entity.
* @param \Drupal\layout_builder\InlineBlockUsageInterface $inline_block_usage
* The inline block usage service.
* @param \Drupal\Core\Entity\EntityStorageInterface $block_content_storage
* The block content's storage.
*/
protected function updateInlineBlockUsage(EntityInterface $cloned_entity, InlineBlockUsageInterface $inline_block_usage, EntityStorageInterface $block_content_storage) {
$sections = $cloned_entity->get('layout_builder__layout');
foreach ($sections as $value) {
$section = $value->section;
$components = $section->getComponents();
/** @var \Drupal\layout_builder\SectionComponent $component */
foreach ($components as $component) {
if (!isset($component->toArray()['configuration']['block_revision_id'])) {
continue;
}
$componentAsArray = $component->toArray();
$referenced_block = $block_content_storage->loadRevision($componentAsArray['configuration']['block_revision_id']);
if ($referenced_block) {
$inline_block_usage->addUsage($referenced_block->id(), $cloned_entity);
}
}
}
}
/**
* Clones referenced entities.
*
......@@ -360,83 +259,6 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
return $child_properties;
}
/**
* Clone inline block entities.
*
* @param \Drupal\Core\Field\FieldItemListInterface $field
* The field item.
* @param \Drupal\Core\Field\FieldConfigInterface $field_definition
* The field definition.
* @param array $properties
* All new properties to replace old.
* @param array $already_cloned
* List of all already cloned entities, used for circular references.
*
* @return array
* Referenced entities.
*/
protected function cloneInlineBlockEntities(FieldItemListInterface $field, FieldConfigInterface $field_definition, array $properties, array &$already_cloned) {
$referenced_entities = [];
foreach ($field as $sid => $value) {
if ($value->isEmpty()) {
continue;
}
$section = $value->section;
if (!$section) {
continue;
}
$components = $section->getComponents();
$section_array = $section->toArray();
foreach ($components as $component) {
// If it is not a revisionable block, skip.
if (!isset($component->toArray()['configuration']) || !isset($component->toArray()['configuration']['block_revision_id'])) {
continue;
}
$component_array = $component->toArray();
$configuration = $component_array['configuration'];
$referenced_entity = $this->entityTypeManager
->getStorage('block_content')
->loadRevision($configuration['block_revision_id']);
if ($referenced_entity instanceof BlockContentInterface) {
$child_properties = $this->getChildProperties($properties, $field_definition, $referenced_entity);
$component_array['configuration'] = $this->cloneInlineBlock($referenced_entity, $configuration, $child_properties['children'], $already_cloned);
$section_array['components'][$component_array['uuid']] = $component_array;
}
}
$cloned_section = Section::fromArray($section_array);
$referenced_entities[$sid] = $cloned_section;
}
return $referenced_entities;
}
/**
* Clone inline block.
*
* @param \Drupal\block_content\BlockContentInterface $referenced_entity
* The referenced block.
* @param array $block_configuration
* The configuration of the block.
* @param array $properties
* The entity clone properties.
* @param array $already_cloned
* Already cloned entities.
*
* @return array
* The modified block configuration.
*/
protected function cloneInlineBlock(BlockContentInterface $referenced_entity, array $block_configuration, array $properties, array &$already_cloned) {
$cloned_reference = $referenced_entity->createDuplicate();
/** @var \Drupal\entity_clone\EntityClone\EntityCloneInterface $entity_clone_handler */
$entity_clone_handler = $this->entityTypeManager->getHandler($referenced_entity->getEntityTypeId(), 'entity_clone');
$entity_clone_handler->cloneEntity($referenced_entity, $cloned_reference, $properties, $already_cloned);
$block_configuration['block_revision_id'] = $cloned_reference->getRevisionId();
return $block_configuration;
}
/**
* Create moderation_state translations for the cloned entities.
*
......
......@@ -3,7 +3,6 @@
namespace Drupal\entity_clone\EntityClone\Content;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\block_content\BlockContentInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityHandlerInterface;
use Drupal\Core\Entity\EntityInterface;
......@@ -17,7 +16,6 @@ use Drupal\Core\StringTranslation\TranslationManager;
use Drupal\entity_clone\EntityClone\EntityCloneFormInterface;
use Drupal\entity_clone\EntityCloneClonableFieldInterface;
use Drupal\entity_clone\EntityCloneSettingsManager;
use Drupal\layout_builder\SectionListInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -123,12 +121,6 @@ class ContentEntityCloneFormBase implements EntityHandlerInterface, EntityCloneF
if ($this->entityCloneClonableField->isClonable($field_definition, $field)) {
$form['recursive'] = array_merge($form['recursive'], $this->getRecursiveFormElement($field_definition, $field_id, $field, $discovered_entities));
}
if ($field_definition instanceof FieldConfigInterface && $field_definition->getType() === 'layout_section') {
$field = $entity->get($field_id);
if ($field->count() > 0) {
$form['recursive'] = array_merge($form['recursive'], $this->getRecursiveLayoutFormElement($field_definition, $field_id, $field, $discovered_entities));
}
}
}
if ($parent) {
......@@ -235,87 +227,6 @@ class ContentEntityCloneFormBase implements EntityHandlerInterface, EntityCloneF
return $form_element;
}
/**
* Get the recursive Inline Blocks form element.
*
* @param \Drupal\Core\Field\FieldConfigInterface $field_definition
* The field definition.
* @param string $field_id
* The field ID.
* @param \Drupal\layout_builder\SectionListInterface $field
* The field item.
* @param array $discovered_entities
* List of all entities already discovered.
*
* @return array
* The form element for a recursive clone.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
protected function getRecursiveLayoutFormElement(FieldConfigInterface $field_definition, $field_id, SectionListInterface $field, array &$discovered_entities) {
$form_element = [
'#tree' => TRUE,
];
$target = $field_definition->getFieldStorageDefinition()->getSetting('target_type');
if ($target !== NULL) {
$fieldset_access = !$this->entityCloneSettingsManager->getHiddenValue($target);
}
else {
$fieldset_access = !$this->entityCloneSettingsManager->getLayoutReferencesSetting();
}
$form_element[$field_definition->id()] = [
'#type' => 'fieldset',
'#title' => $this->translationManager->translate('Entities referenced by field <em>@label (@field_id)</em>.', [
'@label' => $field_definition->label(),
'@field_id' => $field_id,
]),
'#description' => $this->translationManager->translate('Layout builder blocks always have to be cloned in order to preserve the integrity of the system.'),
'#access' => $fieldset_access,
'#description_should_be_shown' => $fieldset_access,
];
foreach ($field as $value) {
if ($value->isEmpty()) {
continue;
}
$section = $value->section;
if (!$section) {
continue;
}
$components = $section->getComponents();
foreach ($components as $component) {
// If it is not a revisionable block, skip.
if (!isset($component->toArray()['configuration']) || !isset($component->toArray()['configuration']['block_revision_id'])) {
continue;
}
$configuration = $component->toArray()['configuration'];
$referenced_entity = \Drupal::entityTypeManager()->getStorage('block_content')->loadRevision($configuration['block_revision_id']);
if ($referenced_entity instanceof BlockContentInterface && $referenced_entity->id()) {
$form_element[$field_definition->id()]['references'][$referenced_entity->id()]['clone'] = [
'#type' => 'checkbox',
'#title' => $this->translationManager->translate('Clone entity <strong>ID:</strong> <em>@entity_id</em>, <strong>Type:</strong> <em>@entity_type - @bundle</em>, <strong>Label:</strong> <em>@entity_label</em>', [
'@entity_id' => $referenced_entity->id(),
'@entity_type' => $referenced_entity->getEntityTypeId(),
'@bundle' => $referenced_entity->bundle(),
'@entity_label' => $referenced_entity->label(),
]),
'#default_value' => TRUE,
'#disabled' => TRUE,
'#access' => $referenced_entity->access('view label'),
];
}
if ($referenced_entity instanceof ContentEntityInterface) {
$form_element[$field_definition->id()]['references'][$referenced_entity->id()]['children'] = $this->getChildren($referenced_entity, $discovered_entities);
}
}
}
return $form_element;
}
/**
* Fetches clonable children from a field.
*
......
......@@ -180,21 +180,4 @@ class EntityCloneSettingsManager {
return $this->config->get('no_suffix') ?? FALSE;
}
/**
* Set the layout builder references setting.
*
* @param int $setting
* The settings from the form.
*/
public function setLayoutReferencesSettings(int $setting) {
$this->editableConfig->set('hide_layout_builder_referenced_entities', $setting)->save();
}
/**
* Get the layout builder references settings.
*/
public function getLayoutReferencesSetting() {
return $this->config->get('hide_layout_builder_referenced_entities') ?? FALSE;
}
}
......@@ -125,13 +125,6 @@ class EntityCloneSettingsForm extends ConfigFormBase implements ContainerInjecti
'#default_value' => $this->entityCloneSettingsManager->getExcludeClonedSetting(),
];
$form['hide_layout_builder_referenced_entities'] = [
'#type' => 'checkbox',
'#title' => $this->t('Hide Layout builder referenced entities checkboxes'),
'#description' => $this->t('Whether the "Entities referenced by field Layout" information should be shown on the entity clone form.'),
'#default_value' => $this->entityCloneSettingsManager->getLayoutReferencesSetting(),
];
return parent::buildForm($form, $form_state);
}
......@@ -142,7 +135,6 @@ class EntityCloneSettingsForm extends ConfigFormBase implements ContainerInjecti
$this->entityCloneSettingsManager->setFormSettings($form_state->getValue('form_settings'));
$this->entityCloneSettingsManager->setTakeOwnershipSettings($form_state->getValue('take_ownership'));
$this->entityCloneSettingsManager->setExcludeClonedSetting($form_state->getValue('no_suffix'));
$this->entityCloneSettingsManager->setLayoutReferencesSettings($form_state->getValue('hide_layout_builder_referenced_entities'));
parent::submitForm($form, $form_state);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment