From 3324f140bb12a4489865c8895148de453dc63d9a Mon Sep 17 00:00:00 2001
From: Lee Rowlands <lee.rowlands@previousnext.com.au>
Date: Tue, 27 Jun 2023 08:28:58 +1000
Subject: [PATCH] Issue #2991772 by nuez, smustgrave, ravi.shankar, sanfair:
 Field layouts doen't seem to work for embedded forms

---
 .../field_layout/src/FieldLayoutBuilder.php   |  7 ++-
 .../field_layout_test.routing.yml             |  7 +++
 .../src/Form/EmbeddedForm.php                 | 55 +++++++++++++++++++
 .../FunctionalJavascript/FieldLayoutTest.php  |  5 ++
 4 files changed, 73 insertions(+), 1 deletion(-)
 create mode 100644 core/modules/field_layout/tests/modules/field_layout_test/src/Form/EmbeddedForm.php

diff --git a/core/modules/field_layout/src/FieldLayoutBuilder.php b/core/modules/field_layout/src/FieldLayoutBuilder.php
index fdbefd5e8d38..d78e0cb170a2 100644
--- a/core/modules/field_layout/src/FieldLayoutBuilder.php
+++ b/core/modules/field_layout/src/FieldLayoutBuilder.php
@@ -107,7 +107,12 @@ public function buildForm(array &$build, EntityDisplayWithLayoutInterface $displ
         // moving the field in the form structure. If a #group is already set,
         // do not overwrite it.
         if (isset($regions[$field['region']]) && !isset($build[$name]['#group'])) {
-          $build[$name]['#group'] = $field['region'];
+          if (!empty($build['#parents'])) {
+            $build[$name]['#group'] = implode('][', array_merge($build['#parents'], ['_field_layout', $field['region']]));
+          }
+          else {
+            $build[$name]['#group'] = $field['region'];
+          }
         }
       }
       // Ensure this will not conflict with any existing array elements by
diff --git a/core/modules/field_layout/tests/modules/field_layout_test/field_layout_test.routing.yml b/core/modules/field_layout/tests/modules/field_layout_test/field_layout_test.routing.yml
index bcea2888f0c6..51d44022e825 100644
--- a/core/modules/field_layout/tests/modules/field_layout_test/field_layout_test.routing.yml
+++ b/core/modules/field_layout/tests/modules/field_layout_test/field_layout_test.routing.yml
@@ -5,3 +5,10 @@ entity.entity_test.test_view_mode:
     _title: 'Test test view mode'
   requirements:
     _entity_access: 'entity_test.view'
+field_layout_test.embedded_form:
+  path: '/field-layout-embedded-form'
+  defaults:
+    _form: 'Drupal\field_layout_test\Form\EmbeddedForm'
+    _title: 'Embedded entity form'
+  requirements:
+    _permission: 'access administration pages'
diff --git a/core/modules/field_layout/tests/modules/field_layout_test/src/Form/EmbeddedForm.php b/core/modules/field_layout/tests/modules/field_layout_test/src/Form/EmbeddedForm.php
new file mode 100644
index 000000000000..f52f91b0569e
--- /dev/null
+++ b/core/modules/field_layout/tests/modules/field_layout_test/src/Form/EmbeddedForm.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace Drupal\field_layout_test\Form;
+
+use Drupal\Core\Entity\Entity\EntityFormDisplay;
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Form\SubformState;
+use Drupal\entity_test\Entity\EntityTest;
+use Drupal\field_layout\FieldLayoutBuilder;
+
+/**
+ * Provides the EmbeddedForm class.
+ *
+ * @package Drupal\field_layout_test\Form
+ */
+class EmbeddedForm extends FormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'field_layout_test_embedded_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $form['foo'] = [
+      '#type' => 'fieldset',
+      '#title' => $this->t('Wrapper'),
+      '#tree' => TRUE,
+      '#parents' => ['foo'],
+    ];
+    $entity = EntityTest::load(1);
+    if ($entity) {
+      if ($entity) {
+        $display = EntityFormDisplay::collectRenderDisplay($entity, 'default');
+        $subform_state = SubformState::createForSubform($form['foo'], $form, $form_state);
+        $display->buildForm($entity, $form['foo'], $subform_state);
+        \Drupal::classResolver(FieldLayoutBuilder::class)->buildForm($form['foo'], $display, $subform_state);
+      }
+    }
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    // Do nothing.
+  }
+
+}
diff --git a/core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php b/core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php
index f5f3ec1c6602..8e1c990c0783 100644
--- a/core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php
+++ b/core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php
@@ -127,6 +127,11 @@ public function testEntityForm() {
     $this->assertSession()->elementExists('css', '.layout__region--second .field--name-field-test-text');
     $this->assertFieldInRegion('field_test_text[0][value]', 'second');
 
+    // Tests if this layout works in an embedded context.
+    $this->drupalGet('/field-layout-embedded-form');
+    $this->assertSession()->elementExists('css', '.layout__region--second .field--name-field-test-text');
+    $this->assertFieldInRegion('foo[field_test_text][0][value]', 'second');
+
     // Move the field to the second region without tabledrag.
     $this->drupalGet('entity_test/structure/entity_test/form-display');
     $this->getSession()->getPage()->pressButton('Show row weights');
-- 
GitLab