--- /dev/null
+<?php
+
+namespace Drupal\layout_builder\Form;
+
+use Drupal\Core\DependencyInjection\ClassResolverInterface;
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Form\SubformState;
+use Drupal\Core\Layout\LayoutInterface;
+use Drupal\Core\Plugin\PluginFormFactoryInterface;
+use Drupal\Core\Plugin\PluginFormInterface;
+use Drupal\Core\Plugin\PluginWithFormsInterface;
+use Drupal\layout_builder\Controller\LayoutRebuildTrait;
+use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
+use Drupal\layout_builder\Section;
+use Drupal\layout_builder\SectionStorageInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a form for configuring a layout section.
+ *
+ * @internal
+ */
+class ConfigureSectionForm extends FormBase {
+
+ use AjaxFormHelperTrait;
+ use LayoutRebuildTrait;
+
+ /**
+ * The layout tempstore repository.
+ *
+ * @var \Drupal\layout_builder\LayoutTempstoreRepositoryInterface
+ */
+ protected $layoutTempstoreRepository;
+
+ /**
+ * The plugin being configured.
+ *
+ * @var \Drupal\Core\Layout\LayoutInterface|\Drupal\Core\Plugin\PluginFormInterface
+ */
+ protected $layout;
+
+ /**
+ * The plugin form manager.
+ *
+ * @var \Drupal\Core\Plugin\PluginFormFactoryInterface
+ */
+ protected $pluginFormFactory;
+
+ /**
+ * The section storage.
+ *
+ * @var \Drupal\layout_builder\SectionStorageInterface
+ */
+ protected $sectionStorage;
+
+ /**
+ * The field delta.
+ *
+ * @var int
+ */
+ protected $delta;
+
+ /**
+ * Indicates whether the section is being added or updated.
+ *
+ * @var bool
+ */
+ protected $isUpdate;
+
+ /**
+ * Constructs a new ConfigureSectionForm.
+ *
+ * @param \Drupal\layout_builder\LayoutTempstoreRepositoryInterface $layout_tempstore_repository
+ * The layout tempstore repository.
+ * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
+ * The class resolver.
+ * @param \Drupal\Core\Plugin\PluginFormFactoryInterface $plugin_form_manager
+ * The plugin form manager.
+ */
+ public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore_repository, ClassResolverInterface $class_resolver, PluginFormFactoryInterface $plugin_form_manager) {
+ $this->layoutTempstoreRepository = $layout_tempstore_repository;
+ $this->classResolver = $class_resolver;
+ $this->pluginFormFactory = $plugin_form_manager;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container) {
+ return new static(
+ $container->get('layout_builder.tempstore_repository'),
+ $container->get('class_resolver'),
+ $container->get('plugin_form.factory')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFormId() {
+ return 'layout_builder_configure_section';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, $delta = NULL, $plugin_id = NULL) {
+ $this->sectionStorage = $section_storage;
+ $this->delta = $delta;
+ $this->isUpdate = is_null($plugin_id);
+
+ if ($this->isUpdate) {
+ $section = $this->sectionStorage->getSection($this->delta);
+ }
+ else {
+ $section = new Section($plugin_id);
+ }
+ $this->layout = $section->getLayout();
+
+ $form['#tree'] = TRUE;
+ $form['layout_settings'] = [];
+ $subform_state = SubformState::createForSubform($form['layout_settings'], $form, $form_state);
+ $form['layout_settings'] = $this->getPluginForm($this->layout)->buildConfigurationForm($form['layout_settings'], $subform_state);
+
+ $form['actions']['submit'] = [
+ '#type' => 'submit',
+ '#value' => $this->isUpdate ? $this->t('Update') : $this->t('Add section'),
+ '#button_type' => 'primary',
+ ];
+ if ($this->isAjax()) {
+ $form['actions']['submit']['#ajax']['callback'] = '::ajaxSubmit';
+ }
+
+ return $form;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateForm(array &$form, FormStateInterface $form_state) {
+ $subform_state = SubformState::createForSubform($form['layout_settings'], $form, $form_state);
+ $this->getPluginForm($this->layout)->validateConfigurationForm($form['layout_settings'], $subform_state);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ // Call the plugin submit handler.
+ $subform_state = SubformState::createForSubform($form['layout_settings'], $form, $form_state);
+ $this->getPluginForm($this->layout)->submitConfigurationForm($form['layout_settings'], $subform_state);
+
+ $plugin_id = $this->layout->getPluginId();
+ $configuration = $this->layout->getConfiguration();
+
+ if ($this->isUpdate) {
+ $this->sectionStorage->getSection($this->delta)->setLayoutSettings($configuration);
+ }
+ else {
+ $this->sectionStorage->insertSection($this->delta, new Section($plugin_id, $configuration));
+ }
+
+ $this->layoutTempstoreRepository->set($this->sectionStorage);
+ $form_state->setRedirectUrl($this->sectionStorage->getLayoutBuilderUrl());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state) {
+ return $this->rebuildAndClose($this->sectionStorage);
+ }
+
+ /**
+ * Retrieves the plugin form for a given layout.
+ *
+ * @param \Drupal\Core\Layout\LayoutInterface $layout
+ * The layout plugin.
+ *
+ * @return \Drupal\Core\Plugin\PluginFormInterface
+ * The plugin form for the layout.
+ */
+ protected function getPluginForm(LayoutInterface $layout) {
+ if ($layout instanceof PluginWithFormsInterface) {
+ return $this->pluginFormFactory->createInstance($layout, 'configure');
+ }
+
+ if ($layout instanceof PluginFormInterface) {
+ return $layout;
+ }
+
+ throw new \InvalidArgumentException(sprintf('The "%s" layout does not provide a configuration form', $layout->getPluginId()));
+ }
+
+}