See #3218222: Cloning Entities with Layout Paragraphs (1.x) breaks structure and moves subparagraphs into Disabled Items - This was for Layout Paragraphs 1.x!

Problem/Motivation

https://www.drupal.org/project/layout_paragraphs is becoming more and more popular. Using Quick Node Clone to clone a node containing a layout paragraph results in broken structure as the contained paragraphs are moved into "Disabled Items" region.

Same with entity clone:
The absolutely same thing happens in https://www.drupal.org/project/entity_clone so if we find the reason, we should fix it in both modules. See the related issue: #3218223: Cloning Entities with Layout Paragraphs breaks structure and moves subparagraphs into Disabled Items

#3183249: Nested paragraph support might be related, but the patch didn't fix anything for me.

Steps to reproduce

Use layout_paragraphs (1.x) in an entity
Clone the entity
See the paragraph elements in "Disabled" instead of their parent paragraph (broken structure)

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

Anybody created an issue. See original summary.

anybody’s picture

Title: Cloning Layout Paragraphs breaks structure and moves subparagraphs into Disabled Items » Cloning Entities with Layout Paragraphs breaks structure and moves subparagraphs into Disabled Items
Issue summary: View changes
Related issues: +#3183249: Nested paragraph support
anybody’s picture

anybody’s picture

Issue summary: View changes
anybody’s picture

Issue summary: View changes
anybody’s picture

anybody’s picture

Ok I finally found a hack to make this work and documented in the related layout_paragraphs issue to discuss how to solve this cleanly (in layout_paragraphs). Best would be to have a hook on

/**
   * Clone the paragraphs of an entity.
   *
   * If we do not clone the paragraphs attached to the entity, the linked
   * paragraphs would be linked to two entities which is not ideal.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity to clone paragraphs for.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity with cloned paragraph fields.
   */
  public function cloneParagraphs(ContentEntityInterface $entity) {
    foreach ($entity->getFieldDefinitions() as $field_definition) {
      $field_storage_definition = $field_definition->getFieldStorageDefinition();
      $field_settings = $field_storage_definition->getSettings();
      $field_name = $field_storage_definition->getName();
      if (isset($field_settings['target_type']) && $field_settings['target_type'] == "paragraph") {
        if (!$entity->get($field_name)->isEmpty()) {
          // TODO: Layout Paragraphs integration:
          // TODO: See https://www.drupal.org/project/layout_paragraphs/issues/3218226#comment-14129846
          // TODO: See https://www.drupal.org/project/quick_node_clone/issues/3218222
          // TODO: All the Steps 1-6 don't belong here in a perfect world but belong to layout_paragraphs
          // 1. Create helper array to store old / new uuids from all paragraphs
          // to update parent_uuids from all children later here:
          $uuidOldNewMap = [];

          foreach ($entity->get($field_name) as $value) {
            if ($value->entity) {
              // 2. Store the old uuid of this paragraph:
              $oldUuid = $value->entity->uuid();
              $value->entity = $value->entity->createDuplicate();
              // 3. Store the new uuid of this paragraph:
              $newUuid = $value->entity->uuid();
              // 4. Save old => new uuid relations in array to replace the old one later:
              $uuidOldNewMap[$oldUuid] = $newUuid;

              foreach ($value->entity->getFieldDefinitions() as $field_definition) {
                $field_storage_definition = $field_definition->getFieldStorageDefinition();
                $pfield_settings = $field_storage_definition->getSettings();
                $pfield_name = $field_storage_definition->getName();

                // Check whether this field is excluded and if so unset.
                if ($this->excludeParagraphField($pfield_name, $value->entity->bundle())) {
                  unset($value->entity->{$pfield_name});
                }

                $this->moduleHandler->alter('cloned_node_paragraph_field', $value->entity, $pfield_name, $pfield_settings);

                if (isset($pfield_settings['target_type']) && $pfield_settings['target_type'] == "paragraph" && !empty($value->entity->{$pfield_name})) {
                  // Do the same for any nested paragraphs.
                  self::cloneParagraphs($value->entity);
                }
              }

              // 5. Update children paragraphs parent_uuid's to the new uuids from
              // the cloned paragraphs:
              $behavior_settings = $value->entity->getAllBehaviorSettings();
              if(!empty($behavior_settings['layout_paragraphs']['parent_uuid'])){
                $oldParentUuid = $behavior_settings['layout_paragraphs']['parent_uuid'];
                if(!empty($uuidOldNewMap[$oldParentUuid])){
                  $newParentUuid = $uuidOldNewMap[$oldParentUuid];
                  $behavior_settings['layout_paragraphs']['parent_uuid'] = $newParentUuid;
                  // kint([$oldParentUuid, $newParentUuid]);
                  $value->entity->setBehaviorSettings('layout_paragraphs', $behavior_settings['layout_paragraphs']);
                }
              }

              // 6. TODO: All steps 1-5 don't belong here but
            }
          }
        }
      }
    }

    return $entity;
  }

@Maintainer: Shell we create an encapsulated fix in Quick Node Clone until this is possible?

anybody’s picture

This issue also needs MR1 from #3183249: Nested paragraph support - I included it in my MR here now to make it easier to test and review. We may have to reroll it once that issue has been fixed.

damienmckenna’s picture

Status: Active » Needs review
damienmckenna’s picture

Just to mention it - the latest MR works great with Layout Paragraphs v1, thanks Anybody!

damienmckenna’s picture

StatusFileSize
new4.85 KB

Here's the MR in patch format.

anybody’s picture

Status: Needs review » Needs work

Thanks @Damien! :) Finally (for Quick Node Clone maintainers) we should try to find out, what's (and if) still needed for layout_paragraphs:^2 and leave a note here.

layout_paragraphs:^2 is definitely the future, so I think this issue may never be committed, but kept as working workaround for layout_paragraphs:^1 users.

For that reason I'm setting this back to "Needs work" - for such documentation and testing here.

yonailo’s picture

Hello,

It seems that the latest patch does not work with the latest Layout Paragraphs 2.0.1

I would like to use this patch because the patch proposed in #3218226 : Cloning Entities containing Layout Paragraphs breaks structure does not seem to work with translations.

Looking at the patch here, I do not understand why it does not work with Layout Paragraphs 2.x.x, it seems to do all that is needed (for every node translation), I mean, updating UUID references, behaviors, etc.

Any clues are welcome.
Thanks in advance.

yonailo’s picture

Sorry I was using an old version of this patch, with the latest version of Damien it works well, even for translations !!
Thanks !!

anybody’s picture

As layout_paragraphs 2 is out and stable now, it would be great, if someone could pick this up and finish it. :)

anybody’s picture

@DamienMcKenna is #14 meant for Layout Paragraphs 2?
We should clarify this here and which steps need to be taken to make this bulletproof.

Being able to clone entities is an essential feature for content editors.

EDIT:

Here's the MR in patch format.

Sorry! I now saw it's just a static copy of the MR! So forget about my question. Still I'm unsure if it's still needed for LP2?!

damienmckenna’s picture

#14 was for compatibility with Layout Paragraphs v1.

anybody’s picture

Thanks @DamienMcKenna and sorry for my dumb question. So does anyone know if this issue or #3183249: Nested paragraph support is still required for Paragraphs or Layout Paragraphs 2?

Would be super nice to close this chapter.

damienmckenna’s picture

I don't have access to the site that needed the patch, so I don't know if this patch is still needed. However, we weren't using nested paragraphs so didn't run into the other issue.

jrochate’s picture

Using this versions:
- Drupal 10.1.7
- Quick Node Clone 1.16
- Layout Paragraphs 2.0.4
- Paragraphs 1.16

I have patched with #3183249 but still didn't get paragraphs do be clone inside the LP paragraph.
When applied the page's #14 patch, I concluded that they can't be applied simultaneously.

But....

When applying ONLY this page's #14 patch, the clone function works like expected.

So, thanks to @DamienMcKenna and @Anybody. I think this could be merged, but it colides with #3183249 that is marked as RTBC.

hebl’s picture

Status: Needs work » Reviewed & tested by the community

I can confirm what @jrochate said above.

Using these versions:
- Drupal 10.2.2
- Quick Node Clone 1.17
- Layout Paragraphs 2.0.4
- Paragrapghs 1.17

...Patch #14 by @DamienMcKenna works, and paragraphs within sections are now being cloned correctly.

I'm not sure what the next steps are here regarding getting it merged. The code in the patch suggests it should ideally live in the layout_paragraphs module

Thanks to @DamienMcKenna for the patch :)

pbabin’s picture

Came across this issue today or at least I came across this today to address an issue where our setup is not cloning the content.

Using the following:
- Drupal 10.3.1
- Quick Node Clone 1.18
- Layout Paragraphs 2.0.8
- Paragraphs 1.17
- Mercury Editor 2.1.1

Patch #14 by @DamienMckenna works; however, for the brief moment that I looked at this patch it doesn't integrate well with Mercury Editor on the node creation page meaning that the content is not using the Mercury Editor inline editor.

@Hebl calls out a good fact and it looks like they are working on something https://www.drupal.org/project/layout_paragraphs/issues/3306081

I've applied the patch from layout_paragraphs and installed the layout_paragraphs_quick_node_clone submodule and it works without an issue. However, like @godotislate mentions our setup is relatively simple and does not include translations. Additionally, on the node clone create page the inline editor for Mercury Editor is displaying. So while patch #14 works, I'd advocate for the adopting the Layout Paragraphs submodule approach if you have a similar issue of cloned content not appearing when using layout paragraphs and quick node clone.

anybody’s picture

Patch #14 does not apply anymore with latest quick_node_clone. So should we maybe close this and switch over to #3306081: Support cloning of paragraphs by integrating with popular contributed clone/replicate modules?

tibur88’s picture

StatusFileSize
new4.71 KB

I checked the changes in version 8.x-1.20 and why the patch is no longer applied.
I have modified patch #14 to match the latest version, which seems to work.

I also plan to create the MR when I have some free time.

anybody’s picture

Just ran into this again and can confirm that this patch is still needed to work with (layout) paragraphs! So would be great, if the maintainer could decide how to proceed finally. This is an issue since many years... Thanks!

grevil’s picture

Status: Reviewed & tested by the community » Needs work

MR doesn't apply to latest 8.x-1.x anymore.

grevil’s picture

Status: Needs work » Needs review
StatusFileSize
new5.08 KB

Done. Unfortunately, I can't remove the "Draft" state.

Current rebased MR as patch is attached.

joelwinzer’s picture

StatusFileSize
new5.32 KB

Since it no longer works with version 8.x-1.22, I have adapted the patch from #14.

fl-49’s picture

Using the patch from #30 worked well for me with Drupal 10.5. After updating to Drupal 11.2.4 it no longer works. Paragraphs nested in Layout Paragraphs sections mostly do not clone, though the Layout Sections do (they are empty).
The patch in #31 does result in Paragraphs nested one level down being cloned, but they are not in their proper sections, and Paragraphs nested deeper than one level are still missing.

fl-49’s picture

I do not have a solution. I realize the complexity for cloning Paragraphs in particular.

But I did find that the below invokeAll lines added in core (D11.2) seem to be breaking Quick Node Clone with Paragraphs. With these lines, the results of getAllBehaviorSettings() on the original Paragraph are quite different than without these invokeAll lines, including different uuid. To experiment, I commented these lines, and the cloning appears to work fine.

In core, ContentEntityBase.php, lines 1220-1223:
// Modules might need to add or change the data initially held by the new
// entity object, for instance to fill-in default values.
\Drupal::moduleHandler()->invokeAll($this->getEntityTypeId() . '_duplicate', [$duplicate, $this]);
\Drupal::moduleHandler()->invokeAll('entity_duplicate', [$duplicate, $this]);

fl-49’s picture

My apologies. After looking deeper I realized my comment belongs with issue 3546997. I've posted my comments there.

arthur.baghdasar’s picture

Patch in #31 fixes the issue for me

arthur.baghdasar’s picture

Getting warning on entities without layout paragraphs

Warning: Undefined array key "layout_paragraphs" in Drupal\quick_node_clone\Entity\QuickNodeCloneEntityFormBuilder->cloneParagraphs() (line 240 of modules/contrib/quick_node_clone/src/Entity/QuickNodeCloneEntityFormBuilder.php).

grevil’s picture

@joelwinzer can we work on the MR please and only use patches as static representations of the MR's state? Also, why would you expand on an old patch???

@arthur.baghdasar this probably happens because the patch you mentioned expands on an old version of this issue's fix.

anybody’s picture

anybody’s picture

StatusFileSize
new4.99 KB

@grevil: Could you finish the work here please? I removed the draft state. Maybe you could also try contacting the maintainer on Slack if the fix is fine, so we can finally get this committed?

@thomas.frobieter can tell from TT if this works as expected.

Latest rebase from MR!3 attached as static patch!

Sadly have to confirm the patch doesn't work any more, the LB layouts are cloned, but shown empty.

Update:
For anyone using Layout Paragraphs 2.x or 3.x - forget about this issue and the patches here.
See #3218226: Cloning Entities containing Layout Paragraphs breaks structure and help pushing things forward!

anybody’s picture

Title: Cloning Entities with Layout Paragraphs breaks structure and moves subparagraphs into Disabled Items » Cloning Entities with Layout Paragraphs (1.x) breaks structure and moves subparagraphs into Disabled Items
Status: Needs review » Closed (outdated)

As I think not many people are using LB 1.x any more, we should probably close this and focus on a clean solution in layout_paragraphs:

FYI: New hooks hook_entity_duplicate() and hook_ENTITY_TYPE_duplicate() have been committed to Drupal core and will be available in Drupal 11.2. A universal approach that works for all the cloning modules might be possible using those hooks, when sites are running 11.2+.

See #31 in #3218226: Cloning Entities containing Layout Paragraphs breaks structure

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

anybody’s picture

Issue summary: View changes